On 01/21/18 12:59, Pedro Giffuni wrote:
Hi;


On 01/21/18 11:56, Mark Millard wrote:
[May be an __alloc_size2(n,s) should be added and used?]

On 2018-Jan-20, at 5:05 PM, Pedro Giffuni <p...@freebsd.org> wrote:

Very interesting , thanks for running such tests ...


On 01/20/18 18:59, Mark Millard wrote:
[Noting a typo in the program source, and
so in the output text: the 2nd occurance of: "my_calloc_alt0
should have been: "my_calloc_alt1
. Hand edited corrections below for clarity.]

On 2018-Jan-20, at 3:27 PM, Mark Millard <marklmi26-f...@yahoo.com> wrote:
[Bugzilla 225197 indirectly lead to this.
Avoiding continuing there.]

I decided to compare some alternate uses of
__attribute__((alloc_size(. . .))) compiled
and run under clang 5.0.1 and gcc7. I did not
get what I expected based on prior discussion
material.

This is an FYI since I do not know how important
the distinctions that I found are.

Here is the quick program:

# more alloc_size_attr_test.c
#include <stdlib.h>
#include <stdio.h>

__attribute__((alloc_size(1,2)))
void* my_calloc_alt0(size_t n, size_t s)
{
   void* p = calloc(n,s);
   printf("calloc __builtin_object_size 0,1,2,3: %ld, %ld, %ld, %ld\n"
         ,(long) __builtin_object_size(p, 0)
         ,(long) __builtin_object_size(p, 1)
         ,(long) __builtin_object_size(p, 2)
         ,(long) __builtin_object_size(p, 3)
         );
   return p;
}

__attribute__((alloc_size(1))) __attribute__((alloc_size(2)))
void* my_calloc_alt1(size_t n, size_t s)
{
   void* p = calloc(n,s);
   printf("calloc __builtin_object_size 0,1,2,3: %ld, %ld, %ld, %ld\n"
         ,(long) __builtin_object_size(p, 0)
         ,(long) __builtin_object_size(p, 1)
         ,(long) __builtin_object_size(p, 2)
         ,(long) __builtin_object_size(p, 3)
         );
   return p;
}

int main()
{
   void* p = my_calloc_alt0(2,7);
   printf("my_calloc_alt0 __builtin_object_size 0,1,2,3: %ld, %ld, %ld, %ld\n"
         ,(long) __builtin_object_size(p, 0)
         ,(long) __builtin_object_size(p, 1)
         ,(long) __builtin_object_size(p, 2)
         ,(long) __builtin_object_size(p, 3)
         );
   void* q = my_calloc_alt1(2,7);
   printf("my_calloc_alt0 __builtin_object_size 0,1,2,3: %ld, %ld, %ld, %ld\n"
The above line should have been:

printf("my_calloc_alt1 __builtin_object_size 0,1,2,3: %ld, %ld, %ld, %ld\n"
         ,(long) __builtin_object_size(q, 0)
         ,(long) __builtin_object_size(q, 1)
         ,(long) __builtin_object_size(q, 2)
         ,(long) __builtin_object_size(q, 3)
         );
}

# uname -apKU
FreeBSD FBSDFSSD 12.0-CURRENT FreeBSD 12.0-CURRENT r327485M  amd64 amd64 1200054 1200054
The system-clang 5.0.1 result was:

# clang -O2 alloc_size_attr_test.c
The later outputs are edited for clarity:

# ./a.out
calloc __builtin_object_size 0,1,2,3: 14, 14, 14, 0
my_calloc_alt0 __builtin_object_size 0,1,2,3: 14, 14, 14, 0
calloc __builtin_object_size 0,1,2,3: 14, 14, 14, 0
my_calloc_alt1 __builtin_object_size 0,1,2,3: 14, 14, 14, 0
The lang/gcc7 result was:

# gcc7 -O2 alloc_size_attr_test.c

# ./a.out
calloc __builtin_object_size 0,1,2,3: -1, -1, 0, 0
my_calloc_alt0 __builtin_object_size 0,1,2,3: 14, 14, 14, 14
calloc __builtin_object_size 0,1,2,3: -1, -1, 0, 0
my_calloc_alt1 __builtin_object_size 0,1,2,3: 14, 7, 14, 14
I'll ignore that gcc does not provide actual sizes
via __builtin_object_size for calloc use.

Pairing the other lines for easy comparison, with
some notes mixed in:

__attribute__((alloc_size(1,2))) style:
my_calloc_alt0 __builtin_object_size 0,1,2,3: 14, 14, 14, 0  (system clang)
my_calloc_alt0 __builtin_object_size 0,1,2,3: 14, 14, 14, 14 (gcc7)

__attribute__((alloc_size(1))) __attribute__((alloc_size(2))) style:
my_calloc_alt1 __builtin_object_size 0,1,2,3: 14, 14, 14, 0 (system clang)
my_calloc_alt1 __builtin_object_size 0,1,2,3: 14, 7, 14, 14 (gcc7)
So on GCC7 it appears
  __attribute__((alloc_size(1,2))) != __attribute__((alloc_size(1))) __attribute__((alloc_size(2)))
This is not good as it was the base for r280801 .. related to the 
old discussion about deprecating old compilers that don't accept 
VA_ARGS.
I am unsure if its a regression but it appears that for clang it is 
the same thing though.
May be there should be a __alloc_size2(n,s) that translates to
__attribute__((alloc_size(n,s))) when it is not a no-op. This
avoids the VA_ARGS issue and gcc's documentation makes no mention
of a more than 2 argument variant of
__attribute__((alloc_size(. . .))) .

Looking up glib it has:

G_GNUC_ALLOC_SIZE(x)
G_GNUC_ALLOC_SIZE2(x,y)

but none for any other count of arguments.

Yes, that would work fine for alloc_array. It would work for the nonnull attribute but that is deprecated on FreeBSD :).

Concept patch attached.
And of course there was a bug.

Pedro.
Index: include/stdlib.h
===================================================================
--- include/stdlib.h	(revision 328218)
+++ include/stdlib.h	(working copy)
@@ -92,7 +92,7 @@
 void	*bsearch(const void *, const void *, size_t,
 	    size_t, int (*)(const void * _Nonnull, const void *));
 void	*calloc(size_t, size_t) __malloc_like __result_use_check
-	     __alloc_size(1) __alloc_size(2);
+	     __alloc_size2(1, 2);
 div_t	 div(int, int) __pure2;
 _Noreturn void	 exit(int);
 void	 free(void *);
@@ -302,8 +302,8 @@
 	    int (*)(void *, const void *, const void *));
 int	 radixsort(const unsigned char **, int, const unsigned char *,
 	    unsigned);
-void	*reallocarray(void *, size_t, size_t) __result_use_check __alloc_size(2)
-	    __alloc_size(3);
+void	*reallocarray(void *, size_t, size_t) __result_use_check
+	    __alloc_size2(2, 3);
 void	*reallocf(void *, size_t) __result_use_check __alloc_size(2);
 int	 rpmatch(const char *);
 void	 setprogname(const char *);
Index: sys/sys/cdefs.h
===================================================================
--- sys/sys/cdefs.h	(revision 328218)
+++ sys/sys/cdefs.h	(working copy)
@@ -230,8 +230,10 @@
 #endif
 #if __GNUC_PREREQ__(4, 3) || __has_attribute(__alloc_size__)
 #define	__alloc_size(x)	__attribute__((__alloc_size__(x)))
+#define	__alloc_size2(n, x)	__attribute__((__alloc_size__(n, x)))
 #else
 #define	__alloc_size(x)
+#define	__alloc_size2(n, x)
 #endif
 #if __GNUC_PREREQ__(4, 9) || __has_attribute(__alloc_align__)
 #define	__alloc_align(x)	__attribute__((__alloc_align__(x)))
Index: sys/sys/malloc.h
===================================================================
--- sys/sys/malloc.h	(revision 328218)
+++ sys/sys/malloc.h	(working copy)
@@ -188,7 +188,7 @@
 	    __malloc_like __result_use_check __alloc_size(1);
 void	*mallocarray(size_t nmemb, size_t size, struct malloc_type *type,
 	    int flags) __malloc_like __result_use_check
-	    __alloc_size(1) __alloc_size(2);
+	    __alloc_size2(1, 2);
 void	malloc_init(void *);
 int	malloc_last_fail(void);
 void	malloc_type_allocated(struct malloc_type *type, unsigned long size);
_______________________________________________
freebsd-toolchain@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-toolchain
To unsubscribe, send any mail to "freebsd-toolchain-unsubscr...@freebsd.org"

Reply via email to