[Bug c/115095] New: [missed optimization] fixed processing on constant string
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115095 Bug ID: 115095 Summary: [missed optimization] fixed processing on constant string Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- Created attachment 58208 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58208=edit source code of https://godbolt.org/z/Meqvbj8GG I've found clang was able to compute the result of hashing a constant string at compile time. I would have hope GCC -O3 would be able to optimize such computation as well: static inline unsigned int hash(unsigned int h, const char *s) { while (*s) { h += *s; h *= *s++; } return h; } #define LOCATION() hash(hash(0, __FILE__), __func__) unsigned int location(void) { return LOCATION(); } is translated by clang to location: movl$1418535820, %eax retq but not by GCC, which doesn't compute the value of LOCATION() at compile time but emit code that compute the value at runtime. At first, I thought it was an issue with handling __FILE__ or __func__, but trying with other string constants, GCC is not computing the value at compile time. See https://godbolt.org/z/Meqvbj8GG
[Bug c/111025] New: attribute((malloc)) and posix_memalign() (and other functions that return newly allocated object address into an output parameter)
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111025 Bug ID: 111025 Summary: attribute((malloc)) and posix_memalign() (and other functions that return newly allocated object address into an output parameter) Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- Functions such as posix_memalign() don't return the pointer to the newly allocated memory as their return value, thus attribute((malloc)) cannot be used with them. It would be useful to have some form of attribute((malloc)) that could apply to function such as posix_memalign(). This new attribute((malloc)) form could also be used on asprintf() for example. With support for the attribute((malloc))'s deallocator specification, it could improve warnings at compile time and prevents developer mistake.
[Bug middle-end/110292] undefined value due to strict aliasing without warning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110292 --- Comment #5 from Yann Droneaud --- Hi, Thanks a lot for the quick analysis of my issue. (In reply to Andrew Pinski from comment #4) > Note -Wstrict-aliasing=1 actually does warn: OK, and -Wall enables -Wstrict-aliasing which defaults to -Wstrict-aliasing=3, I'm sorry I haven't tried to use lower values ... https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wstrict-aliasing (In reply to Andrew Pinski from comment #2) > aliasing violations are known not to be warned about nor have a runtime > sanitizer either. Is there any other tool that would reliably detect such issues ? Regards
[Bug c/110292] undefined value due to strict aliasing without warning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110292 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #1 from Yann Droneaud --- And it should be noted that using -fsanitize=undefined is making the issue vanish as 0 is written into j location on the stack ...
[Bug c/110292] New: undefined value due to strict aliasing without warning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110292 Bug ID: 110292 Summary: undefined value due to strict aliasing without warning Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- The following code (reduced with some help from cvise) doesn't trigger any warning from GCC 13+ $ cat test.c #include struct a { uint8_t b:6; }; struct c { uint64_t d:6; }; void e(uint64_t *f, uint64_t *g) { struct c *h = (struct c *)f; struct a i[8] = { [7] = { h -> d } }; __builtin___memcpy_chk (g, i, sizeof(i), __builtin_object_size (g, 0)); } int main(void) { uint64_t j = 0; uint64_t k; e(, ); if (k) __builtin_trap(); return 0; } But compiled under Fedora 39 (Rawhide, gcc 13.1.1-2, x86_64), it aborts, because j location on the stack is not set to 0 before its address is being passed to e() ... $ gcc -Wall -Wextra -O2 test.c -o test $ ./test Aborted (core dumped) Even if it doesn't abort (because the stack is cleared), there's a problem and valgrind reports: $ gcc -Wall -Wextra -O2 -g3 test.c -o test $ valgrind --track-origins=yes ./test ==63110== Memcheck, a memory error detector ==63110== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==63110== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info ==63110== Command: ./test ==63110== ==63110== Conditional jump or move depends on uninitialised value(s) ==63110==at 0x401047: main (test.c:22) ==63110== Uninitialised value was created by a stack allocation ==63110==at 0x401030: main (test.c:18) ... And, as one could see, line 18 doesn't match any of the variables that are allocated. Below, the assembly compiled by GCC: $ gcc -Wall -Wextra -O2 -g3 test.c -S $ cat test.s e: movzbl (%rdi), %eax andl$63, %eax salq$56, %rax movq%rax, (%rsi) ret main: subq$16, %rsp leaq8(%rsp), %rsi movq%rsp, %rdi calle cmpq$0, 8(%rsp) jne .L5 xorl%eax, %eax addq$16, %rsp ret .L5: ud2 Code available at https://godbolt.org/z/b8sn314K9 Is it an aliasing issue in the code and GCC doesn't reports a warning ? Or worse ?
[Bug c/71713] "initializer element is not constant" with nested casts
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71713 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #2 from Yann Droneaud --- May be it's possible with GCC 13, with -std=gnu2x, and using C2x constexpr storage qualifier.
[Bug c/109828] [13/14 Regression] static compound literal with flexible array in initializer leads to invalid size and ICE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109828 --- Comment #8 from Yann Droneaud --- (In reply to Yann Droneaud from comment #7) > I've also experimented compound literal initialization at block level > instead of file level. Except in case it's not supported, it shows the same > issue at block level as file level. > > https://godbolt.org/z/vn5Pn7hTx > > Unrelated, I've noted it's not possible to initialize the flexible array if > the initializer is not having a static storage. I would have expected this > restriction to be lifted by now. I've opened bug #109863
[Bug c/109863] New: RFE: more consistent flex array initialization: lift static storage requirement in gnu2x
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109863 Bug ID: 109863 Summary: RFE: more consistent flex array initialization: lift static storage requirement in gnu2x Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- I've noted some discrepancies in the flex array initialization support: /* https://godbolt.org/z/9er5G9G15 */ struct s { char i; char c[]; }; extern void t(const struct s*); void f(void) { // ERROR: non-static initialization of a flexible array member const struct s c0 = { .c = "0", }; t(); // ERROR: non-static initialization of a flexible array member const struct s *const c1 = &(const struct s) { .c = "1", }; t(c1); // OK const struct s *const c2 = &(constexpr struct s) { .c = "2", }; t(c2); // ERROR: initializer element is not constant static const struct s *const c3 = &(constexpr struct s) { .c = "3", }; t(c3); // OK static const struct s *const c4 = &(static constexpr struct s) { .c = "4", }; t(c4); } AFAICT constexpr is not supposed to also mean static storage at the block level, so flex array in c2 is initialized in a non-static way ... Then I would be happy if GCC could be enhanced to not reject c0 and c1 initialization. But I fear the opposite will happen, and GCC will reject c2 initialization too :)
[Bug c/109828] [13/14 Regression] static compound literal with flexible array in initializer leads to invalid size and ICE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109828 --- Comment #7 from Yann Droneaud --- I've also experimented compound literal initialization at block level instead of file level. Except in case it's not supported, it shows the same issue at block level as file level. https://godbolt.org/z/vn5Pn7hTx Unrelated, I've noted it's not possible to initialize the flexible array if the initializer is not having a static storage. I would have expected this restriction to be lifted by now.
[Bug c/109828] [13/14 Regression] C2x:static compound literal (with flexible array) in initializer leads to invalid size and ICE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109828 --- Comment #4 from Yann Droneaud --- I'm still playing with this, for example https://godbolt.org/z/dfjr8veh5, and I've noticed the size of the compound_initializer is incorrect too: struct s { char i; char c[]; }; const struct s *const s = &(static const struct s) { .c = "1", }; Compile too: .quad __compound_literal.4 .type __compound_literal.4, @object .size __compound_literal.4, 1 __compound_literal.4: .zero 1 .string "1" .zero 18446744073709551613 .zero 1 I would have have expected .size to be 3, not 1. Maybe it's the result of computing the size as 3 + -3 + 1, but it's far fetched.
[Bug c/109828] C2x:static compound literal (with flexible array) in initializer leads to invalid size and ICE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109828 --- Comment #2 from Yann Droneaud --- (In reply to Yann Droneaud from comment #0) > The following code is badly compiled by GCC 13.1: > > struct s { int i; char c[]; }; > > const struct s s = { .c = "0", }; > const struct s *r = &(constexpr struct s) { .c = "1", }; > const struct s *t = &(static struct s) { .c = "2", }; > > Targetting x86-64 / amd64, compiling this with gcc -std=gnu2x -S, produces > surprising large .zero directive: > > s: > .zero 4 > .string "0" > __compound_literal.0: > .zero 4 > .string "1" > .zero 18446744073709551613 > .zero 1 > r: > .quad __compound_literal.0 > __compound_literal.1: > .zero 4 > .string "2" > .zero 18446744073709551613 > .zero 1 > t: > .quad __compound_literal.1 > > When asked to assemble that, binutils' as complains: $ gcc -std=gnu2x nice.c -c /tmp/ccZEWv73.s: Assembler messages: /tmp/ccZEWv73.s:17: Warning: .space repeat count is zero, ignored /tmp/ccZEWv73.s:32: Warning: .space repeat count is zero, ignored
[Bug c/109828] C2x:static compound literal (with flexible array) in initializer leads to invalid size and ICE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109828 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #1 from Yann Droneaud --- I should mention GCC trunk (gcc 14.0.0 20230510 on godbolt.org) is experiencing ICE without the need to call __builtin_object_size().
[Bug c/109828] New: C2x:static compound literal (with flexible array) in initializer leads to invalid size and ICE
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109828 Bug ID: 109828 Summary: C2x:static compound literal (with flexible array) in initializer leads to invalid size and ICE Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- The following code is badly compiled by GCC 13.1: struct s { int i; char c[]; }; const struct s s = { .c = "0", }; const struct s *r = &(constexpr struct s) { .c = "1", }; const struct s *t = &(static struct s) { .c = "2", }; Targetting x86-64 / amd64, compiling this with gcc -std=gnu2x -S, produces surprising large .zero directive: s: .zero 4 .string "0" __compound_literal.0: .zero 4 .string "1" .zero 18446744073709551613 .zero 1 r: .quad __compound_literal.0 __compound_literal.1: .zero 4 .string "2" .zero 18446744073709551613 .zero 1 t: .quad __compound_literal.1 Adding a call to __builtin_object_size() and compiling with optimization triggers an ICE size_t ice(void) { return __builtin_object_size(t, 0); } $ gcc -std=gnu2x -O2 -S ice.c ice.c: In function ‘ice’: ice.c:11:12: internal compiler error: Segmentation fault 11 | return __builtin_object_size(t, 0); |^~~ 0xc4dc6f crash_signal ../../gcc/toplev.cc:317 0x7f39935907cf ??? /usr/src/debug/glibc-2.37.9000-9.fc39.x86_64/signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0 0xb1023e tree_fits_poly_int64_p(tree_node const*) ../../gcc/tree.cc:6378 0xb1023e tree_to_poly_int64(tree_node const*) ../../gcc/tree.cc:3285 0x83b5bb component_ref_size(tree_node*, special_array_member*) ../../gcc/tree.cc:13199 0x8096ed decl_init_size(tree_node*, bool) ../../gcc/tree-object-size.cc:493 0xc7f08b addr_object_size ../../gcc/tree-object-size.cc:568 0x6d0248 fold_builtin_object_size ../../gcc/builtins.cc:10808 0x6d0248 fold_builtin_2 ../../gcc/builtins.cc:9841 0x6d0248 fold_builtin_n(unsigned int, tree_node*, tree_node*, tree_node**, int, bool) [clone .isra.0] ../../gcc/builtins.cc:9949 0x12084a6 gimplify_call_expr ../../gcc/gimplify.cc:3824 0x12084a6 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc/gimplify.cc:16348 0x1207508 gimplify_modify_expr ../../gcc/gimplify.cc:6153 0x1207508 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc/gimplify.cc:16376 0x1206dfc gimplify_stmt(tree_node**, gimple**) ../../gcc/gimplify.cc:7219 0x1699436 gimplify_and_add(tree_node*, gimple**) ../../gcc/gimplify.cc:492 0x1699436 gimplify_return_expr ../../gcc/gimplify.cc:1680 0x1208676 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) ../../gcc/gimplify.cc:16638 0x1206dfc gimplify_stmt(tree_node**, gimple**) ../../gcc/gimplify.cc:7219 0x1698c04 gimplify_bind_expr ../../gcc/gimplify.cc:1430 See https://godbolt.org/z/fnnW5T8TG
[Bug c/109516] warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'const long unsigned int:48' [-Wformat=]
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109516 --- Comment #7 from Yann Droneaud --- (In reply to Andrew Pinski from comment #6) > > > > And I failed to comprehend how unsigned long int:48 can be passed to a > > variadic function without being promoted to plain unsigned long int ... > > Oh yes, there is no way for an user to get the value back via va_arg really. > But this is just how C has an implementation defined behavior here really. I understand, but can't refrain myself from thinking it's an unfortunate discrepancy having a warning when formatting the uint64_t:48 case but not for uint32_t:24 one. Anyway, thanks for all the explanation. Regards.
[Bug c/109516] warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'const long unsigned int:48' [-Wformat=]
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109516 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #4 from Yann Droneaud --- (In reply to Andrew Pinski from comment #1) > > Basically GCC decided that the type of the bitfield uint48 has a type of > unsigned:48 and since it is larger size than int, it does not get promoted > to int and in this cases gets passed to the variadic function as that type. I wouldn't have expected bitfield type to be "visible" outside of its structure. And I failed to comprehend how unsigned long int:48 can be passed to a variadic function without being promoted to plain unsigned long int ... Anyway, I will have to add a cast to silence the warning. > While clang decided that the type is still unsigned long long. AFAICT, there's no unsigned long long involved in my example.
[Bug c/109516] New: warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'const long unsigned int:48' [-Wformat=]
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109516 Bug ID: 109516 Summary: warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'const long unsigned int:48' [-Wformat=] Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- I've discovered today an unexpected format related warning when asking to print a bitfield over unsigned long: $ cat > fmt-bitfield.c < #include #include struct struct24 { uint32_t uint24:24; }; void print24(const struct struct24 *s) { printf("%" PRIx32 "\n", s->uint24); } struct struct48 { uint64_t uint48:48; }; void print48(const struct struct48 *s) { printf("%" PRIx64 "\n", s->uint48); } EOF $ gcc -Wformat -c fmt-bitfield.c fmt-bitfield.c: In function 'print48': fmt-bitfield.c:13:10: warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'long unsigned int:48' [-Wformat=] 13 | { printf("%" PRIx64 "\n", s->uint48); } | ^~~ ~ || |long unsigned int:48 In file included from fmt-bitfield.c:1: /usr/include/inttypes.h:121:41: note: format string is defined here 121 | # define PRIx64 __PRI64_PREFIX "x" See https://godbolt.org/z/r44e5rfnh I understood that, according to C standard, bitfield over type other that int or bool is an implementation defined behavior. But GCC is expected to support bitfield over long as well: https://gcc.gnu.org/onlinedocs/gcc/Structures-unions-enumerations-and-bit-fields-implementation.html - Allowable bit-field types other than _Bool, signed int, and unsigned int (C99 and C11 6.7.2.1). Other integer types, such as long int, and enumerated types are permitted even in strictly conforming mode. So I believe the warning is spurious, and formatting a value whose type is a bitfield over long should not trigger the warning when using %l format modifier. (For the record, clang doesn't report such warning).
[Bug preprocessor/109183] [regression?] since GCC 11.1, -MM -MMD generates "a-" prefixed dependency files
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109183 --- Comment #4 from Yann Droneaud --- (In reply to Alexandre Oliva from comment #3) > dump files now consistently take the base name from the output name, when > not overridden > > since in this case gcc is called for (compiling and) linking, and the final > output name is a.* (.out or .exe, depending on the platform), That the issue at hand, `gcc -MM -MMD test.c` does not compile nor link anything: it preprocess and extract dependencies, nothing more. Thus using "a.out" as the output is not expected.
[Bug preprocessor/109183] [regression?] since GCC 11.1, -MM -MMD generates "a-" prefixed dependency files
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109183 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #2 from Yann Droneaud --- gcc -MM -MMD seems to behave like gcc -dumpbase a -MM -MMD test.c or gcc -dumpdir a- -MM -MMD test.c
[Bug preprocessor/109183] New: [regression?] since GCC 11.1, -MM -MMD generates "a-" prefixed dependency files
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109183 Bug ID: 109183 Summary: [regression?] since GCC 11.1, -MM -MMD generates "a-" prefixed dependency files Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: preprocessor Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- I've found a rather surprising behavior change when using GCC >= 11.1 to build some project using custom build environment. How to reproduce: : > test.c gcc -MM -MMD test.c test -e a-test.d && echo "unexpected dependency file name" I've git-bisect-ed between GCC 11.1 and GCC 10.1 and the behavior change did happen as the result of this commit: commit 1dedc12d186a110854537e1279b4e6c29f2df35a Author: Alexandre Oliva Date: Tue May 26 04:30:15 2020 -0300 revamp dump and aux output names https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1dedc12d186a110854537e1279b4e6c29f2df35a I didn't find an explanation there for this behavior change. It's not noted in the documentation either https://gcc.gnu.org/onlinedocs/gcc-11.3.0/gcc/Preprocessor-Options.html So this make me believe it's some kind of regression for a corner case. I understand the correct usage of -MMD is to be associated with some processing, -E, -S, -c, etc, while -MM imply -E, so perhaps -MM and -MMD are mutually exclusive and should not be allowed together. I dunno. But generating "a-" prefixed dependency files is rather unexpected.
[Bug tree-optimization/108398] tree-object-size trips up with pointer arithmetic if an intermediate result is an invalid pointer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108398 --- Comment #10 from Yann Droneaud --- (In reply to Jakub Jelinek from comment #8) > -fsanitize=undefined with no diagnostics doesn't mean code is UB free. This is a pity, it would have help users do diagnose the issue in their code.
[Bug tree-optimization/108398] tree-object-size trips up with pointer arithmetic if an intermediate result is an invalid pointer
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108398 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #6 from Yann Droneaud --- c-reduce comes up with the following reproducer: #include typedef struct { int a; } b; typedef struct { b c[2]; } d; d e; int f = 2; int main() { b *g; for (g = e.c; f; g++) switch (g->a) { case 0: memmove(g, g + 1, sizeof(b)); f--; g--; } } gcc -fsanitize=undefined doesn't catch any issue ...
[Bug other/55899] GCC should provide built-ins in data types flavor/version/variation
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55899 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #2 from Yann Droneaud --- I stumbled upon this issue again when dealing with uint64_t as sometimes it's defined as unsigned long, sometimes it's defined as unsigned long long depending on the ABI. Having __builtin_ffs64(), __builtin_clz64(), __builtin_ctz64(), etc. would ease me making my code portable to unpleasant ABI such as Microsoft Windows ones without having to use GCC's __builtin_types_compatible_p() (which is not supported when compiling C++), or C11 _Generic() ...
[Bug c++/107104] semantics of __builtin_constant_p within static_assert and return value
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107104 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #3 from Yann Droneaud --- I'm experiencing the same issue: #include void a(int v) { static_assert(__builtin_constant_p(v) && v == -1, "failure"); } GCC 13 and below complains: : In function 'a': :16:43: error: expression in static assertion is not constant 16 | static_assert(__builtin_constant_p(v) && v == -1, "failure"); | ^~ Compiler returned: 1 clang current trunk, eg above 15.0, seems to finally get it right: :16:5: error: static assertion failed due to requirement '__builtin_constant_p(v) && v == -1': failure static_assert(__builtin_constant_p(v) && v == -1, "failure"); ^ ~~ /usr/include/assert.h:143:24: note: expanded from macro 'static_assert' # define static_assert _Static_assert ^ 1 error generated. Compiler returned: 1 see https://godbolt.org/z/KKn6xTG8a
[Bug ipa/106061] [13 Regression] during GIMPLE pass: einline ICE: verify_cgraph_node failed (edge points to wrong declaration) with -Og since r13-1204-gd68d366425369649
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106061 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #6 from Yann Droneaud --- I'm reaching this bug too, compiling the following smaller reproducer: extern void a(void); inline void b(int c) { if (c) a(); } void d(void) { b(0); }
[Bug tree-optimization/107618] Incorrect diagnostics when using -Og, builtin_expect(), and function attribute "warning" or "error"
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107618 --- Comment #6 from Yann Droneaud --- (In reply to Richard Biener from comment #5) > Should be fixed for GCC 13, it doesn't seem to be a regression. I've tested with a fresh rebuild of GCC's trunk, and the warning is no more reported at -Og level. Thanks.
[Bug middle-end/107618] Incorrect diagnostics when using -Og, builtin_expect(), and function attribute "warning" or "error"
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107618 --- Comment #2 from Yann Droneaud --- I was wondering what GCC expects __builtin_object_size(0, 0) to be, and used the following: void a_1 (void) __attribute__((__warning__("-1"))); void a0 (void) __attribute__((__warning__("0"))); void a1 (void) __attribute__((__warning__("1"))); void a2 (void) __attribute__((__warning__("2"))); void a3 (void) __attribute__((__warning__("3"))); void a4 (void) __attribute__((__warning__("4"))); int main(void) { unsigned long b = __builtin_object_size(0, 0); if (__builtin_expect(b == (unsigned long)-1, 0)) a_1(); if (__builtin_expect(b == 0, 0)) a0(); if (__builtin_expect(b == 1, 0)) a1(); if (__builtin_expect(b == 2, 0)) a2(); if (__builtin_expect(b == 3, 0)) a3(); if (__builtin_expect(b == 4, 0)) a4(); } It works as expected for any level above 0, except -Og: $ gcc -O1 -S warning.c warning.c: In function ‘main’: warning.c:11:5: warning: call to ‘a_1’ declared with attribute warning: -1 [-Wattribute-warning] 11 | a_1(); | ^ It's quite reassuring that __builtin_object_size(0, 0) returns -1, hence the emitted call to a_1(): $ cat warning.s .file"warning.c" .text .globlmain .typemain, @function main: endbr64 subq$8, %rsp calla_1@PLT movl$0, %eax addq$8, %rsp ret For -Og, there's a firework of warnings (shockingly they're the same than -O0 level): $ gcc -Og -S warning.c warning.c: In function ‘main’: warning.c:11:5: warning: call to ‘a_1’ declared with attribute warning: -1 [-Wattribute-warning] 11 | a_1(); | ^ warning.c:13:5: warning: call to ‘a0’ declared with attribute warning: 0 [-Wattribute-warning] 13 | a0(); | ^~~~ warning.c:15:5: warning: call to ‘a1’ declared with attribute warning: 1 [-Wattribute-warning] 15 | a1(); | ^~~~ warning.c:17:5: warning: call to ‘a2’ declared with attribute warning: 2 [-Wattribute-warning] 17 | a2(); | ^~~~ warning.c:19:5: warning: call to ‘a3’ declared with attribute warning: 3 [-Wattribute-warning] 19 | a3(); | ^~~~ warning.c:21:5: warning: call to ‘a4’ declared with attribute warning: 4 [-Wattribute-warning] 21 | a4(); | ^~~~ Generated assembly for -Og is the same than for levels above 0: a call to a_1() function is emitted, which mean GCC, at some point, knows __builtin_object_size(0, 0) is -1 here. Thus most of the warnings are not very useful. $ cat warning.s .file"warning.c" .text .globlmain .typemain, @function main: endbr64 subq$8, %rsp calla_1@PLT movl$0, %eax addq$8, %rsp ret
[Bug middle-end/107618] Incorrect diagnostics when using -Og, builtin_expect(), and function attribute "warning" or "error"
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107618 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #1 from Yann Droneaud --- A smallest reproducer (generated with some help from C-reduce): void a(void) __attribute__((__warning__(""))); int main(void) { unsigned long b = __builtin_object_size(0, 0); if (__builtin_expect(b < 1, 0)) a(); } Works at all level above -00, except -Og: $ gcc -Og warning.c warning.c: In function ‘main’: warning.c:5:5: warning: call to ‘a’ declared with attribute warning: [-Wattribute-warning] 5 | a(); | ^~~
[Bug other/107618] New: Incorrect diagnostics when using -Og, builtin_expect(), and function attribute "warning" or "error"
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107618 Bug ID: 107618 Summary: Incorrect diagnostics when using -Og, builtin_expect(), and function attribute "warning" or "error" Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: other Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- Created attachment 53872 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53872=edit reproducer for -Og, __builtin_expect(), and function __attribute__((warning(""))) The code below compiled with -Og triggers a warning message that is not mandated: $ gcc -Og warning.c warning.c: In function ‘test_expect’: warning.c:26:17: warning: call to ‘size_mismatch_expect’ declared with attribute warning: size mismatch (builtin_expect) [-Wattribute-warning] 26 | size_mismatch_expect(); | ^~ $ cat warning.c #include #include #include extern void size_mismatch_nonexpect(void) __attribute__((__warning__("size mismatch"))); static bool test_nonexpect(const void *addr, size_t len) { size_t sz = __builtin_object_size(addr, 0); if (sz != (size_t)-1 && sz < len) { size_mismatch_nonexpect(); return false; } return true; } extern void size_mismatch_expect(void) __attribute__((__warning__("size mismatch (builtin_expect)"))); static bool test_expect(const void *addr, size_t len) { size_t sz = __builtin_object_size(addr, 0); if (__builtin_expect(sz != (size_t)-1 && sz < len, 0)) { size_mismatch_expect(); return false; } return true; } int main(void) { int i = 0; if (!test_nonexpect(, sizeof(i))) return EXIT_FAILURE; if (!test_expect(, sizeof(i))) return EXIT_FAILURE; return EXIT_SUCCESS; } The warning at -Og level is not expected because there's no call to the size_mismatch_expect() in the generated assembler (for x86-64): $ head warning.s .file"warning.c" .text .typetest_nonexpect, @function test_nonexpect: movl$1, %eax ret .sizetest_nonexpect, .-test_nonexpect .typetest_expect, @function test_expect: movl$1, %eax ret .sizetest_expect, .-test_expect .globlmain .typemain, @function main: endbr64 subq$24, %rsp movq%fs:40, %rax movq%rax, 8(%rsp) xorl%eax, %eax movl$0, 4(%rsp) leaq4(%rsp), %rdi movl$4, %esi calltest_nonexpect testb%al, %al jne.L11 movl$1, %eax .L5: movq8(%rsp), %rdx subq%fs:40, %rdx jne.L12 addq$24, %rsp ret .L11: leaq4(%rsp), %rdi movl$4, %esi calltest_expect testb%al, %al je.L9 movl$0, %eax jmp.L5 .L9: movl$1, %eax jmp.L5 See also https://godbolt.org/z/KEsaavhvG Compiling at optimization level s, z, 1, 2, or 3 doesn't produce that warning. (but compiling with -O0 does produces two warnings, as expected, since calls to the two functions are emitted). Having the warning at debug optimization level makes using -Og in some complex code base challenging for no good reason when __attribute__((error(""))) is used (or -Werror=attribute-warning). It should also be noted clang doesn't generate the warning for optimization level above 0.
[Bug middle-end/99578] [11 Regression] gcc-11 -Warray-bounds or -Wstringop-overread warning when accessing a pointer from integer literal
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578 --- Comment #43 from Yann Droneaud --- (In reply to Jakub Jelinek from comment #37) > Fixed on the trunk so far, temporarily by differentiating between < 4KB > addresses which are still handled like GCC 11 did for warning purposes, and > >= 4KB addresses where we won't warn anymore. As noted by Andrew Pinski in bug #106699, comment #1, one has "to use --param=min-pagesize=0 if the first 4k is valid memory" to inhibit warnings for addresses below 4096.
[Bug c/106699] New: Since gcc 12, deferencing constant literal addresses triggers -Warray-bounds warning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106699 Bug ID: 106699 Summary: Since gcc 12, deferencing constant literal addresses triggers -Warray-bounds warning Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- Since GCC 12.1, compiling memtest86+ triggers the following warning: In function 'find_rsdp', inlined from 'acpi_init' at ../system/acpi.c:329:29: ../system/acpi.c:185:29: warning: array subscript 0 is outside array bounds of 'uint16_t[0]' {aka 'short unsigned int[]'} [-Warray-bounds] 185 | uintptr_t address = *(uint16_t *)0x40E << 4; | ^~ ../system/hwctrl.c: In function 'reboot': ../system/hwctrl.c:76:9: warning: array subscript 0 is outside array bounds of 'uint16_t[0]' {aka 'short unsigned int[]'} [-Warray-bounds] 76 | *((uint16_t *)0x472) = 0x1234; | ^~~~ In function 'find_cpus_in_floating_mp_struct', inlined from 'smp_init' at ../system/smp.c:543:39: ../system/smp.c:346:29: warning: array subscript 0 is outside array bounds of 'uint16_t[0]' {aka 'short unsigned int[]'} [-Warray-bounds] 346 | uintptr_t address = *(uint16_t *)0x40E << 4; | ^~ Sure using integer literal as a pointer is a recipe for disaster in most cases. But it's for a freestanding environment, a bootloader, a kernel. So -Warray-bounds should not infer an address points to a empty array. A minimal test case: #include void write(void) { *((uint16_t *)0x472) = 0x1234; } uint16_t read(void) { return *(uint16_t *)0x40E << 4; } https://godbolt.org/z/c9993xx41
[Bug rtl-optimization/81501] mulitple calls to __tls_get_addr() with -fPIC
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81501 --- Comment #7 from Yann Droneaud --- (In reply to Roy Jacobson from comment #6) > We recently upgraded our toolchain from GCC9 to GCC11, and we're seeing > __tls_get_addr take up to 10% of total runtime under some workloads, where > it was 1-2% before. > > It seems that some changes to the optimization passes in 10 or 11 have > significantly increased the impact of this problem. In bug #82803, comment #12, (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82803#c12), I've shown a workaround I used, which might be useful until GCC handle __tls_get_addr() as returning a constant addresses that doesn't need to be looked up multiple times in a function.
[Bug c/82283] Wrong warning with -Wmissing-field-initializers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82283 --- Comment #16 from Yann Droneaud --- (In reply to Marek Polacek from comment #13) > I have a patch which fixes all the testcases here. I've checked my test cases using godbolt gcc trunk, and, yeah, thanks a lot !
[Bug c/82283] Wrong warning with -Wmissing-field-initializers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82283 --- Comment #8 from Yann Droneaud --- See also this stack overflow question https://stackoverflow.com/questions/49081541/compound-literal-and-designated-initializer-warning-from-gcc-but-not-clang
[Bug c/82283] Wrong warning with -Wmissing-field-initializers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82283 --- Comment #7 from Yann Droneaud --- See also bug #84685 which is a very likely duplicate of this one.
[Bug c/84685] Designated initializers warning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84685 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #3 from Yann Droneaud --- Likely a duplicate of bug #82283
[Bug c/82283] Wrong warning with -Wmissing-field-initializers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82283 --- Comment #6 from Yann Droneaud --- Found this one on stack overflow[1], and I find it a bit embarrassing: struct { struct { int a; int b; } c[1]; } d = { .c[0].a = 1, .c[0].b = 1, }; Results in the following warning: :7:8: error: missing initializer for field 'b' of 'struct ' [-Werror=missing-field-initializers] 7 |.c[0].b = 1, |^ :4:9: note: 'b' declared here 4 | int b; | ^ cc1: all warnings being treated as errors Compiler returned: 1 See https://godbolt.org/z/zGqM7C GCC emits a warning about a field missing an initializer despite being obviously explicitly initialized. If the present but missing initialization is removed: struct { struct { int a; int b; } c[1]; } d = { .c[0].a = 1, }; GCC complains, incorrectly, about a missing initializer, as described in previous comments: :8:1: error: missing initializer for field 'b' of 'struct ' [-Werror=missing-field-initializers] 8 | }; | ^ :4:9: note: 'b' declared here 4 | int b; | ^ cc1: all warnings being treated as errors Compiler returned: 1 See https://godbolt.org/z/8NRwo5 [1] https://stackoverflow.com/questions/22194935/wmissing-field-initializer-when-using-designated-initializers
[Bug c/82283] Wrong warning with -Wmissing-field-initializers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82283 --- Comment #5 from Yann Droneaud --- For a full combo, here's the almost original code that trigger the two errors above with GLibc < 2.28, only one with newer Glibc. #define _GNU_SOURCE 1 #include #include #include int test(int fd) { static const char message[] = "Hello world"; struct sockaddr_in addr = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK), .sin_port = htons(12345), }; struct iovec vec = { .iov_base = (void *)message, .iov_len = sizeof(message), }; struct mmsghdr mmsghdr = { .msg_hdr = (struct msghdr) { .msg_name = , .msg_namelen = sizeof(addr), .msg_iov = , .msg_iovlen = 1, }, }; return sendmmsg(fd, , 1, 0); } see https://godbolt.org/z/pwXyzE
[Bug c/82283] Wrong warning with -Wmissing-field-initializers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82283 --- Comment #4 from Yann Droneaud --- Also with the ({}) GCC extension: struct a { int b; int c; }; void d(struct a *); void e(void) { struct a f = { .b = ({ int g = 0; g; }) }; d(); } It produces the warning: : In function 'e': :10:17: error: missing initializer for field 'c' of 'struct a' [-Werror=missing-field-initializers] 10 | })}; | ^ :3:7: note: 'c' declared here 3 | int c; | ^ cc1: all warnings being treated as errors Compiler returned: 1 See https://godbolt.org/z/VJAuv4 (Note: this example and the one above were reduced by c-reduce https://embed.cs.utah.edu/creduce/ )
[Bug c/82283] Wrong warning with -Wmissing-field-initializers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82283 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #3 from Yann Droneaud --- I'm experiencing the same issue in multiple cases, even with latest GCC trunk (10.x). I believe the following code is C99 conformant, but still trigger an unexpected warning: struct a { int b; }; struct c { struct a d; int e; }; void f(struct c *); void g(void) { struct c h = {.d = (struct a){0}}; f(); } It produces the following warning: : In function 'g': :10:30: error: missing initializer for field 'e' of 'struct c' [-Weror=missing-field-initializers] 10 | struct c h = {.d = (struct a){0}}; | ^ :6:7: note: 'e' declared here 6 | int e; | ^ cc1: all warnings being treated as errors Compiler returned: 1 See https://godbolt.org/z/vQLYRX
[Bug tree-optimization/82803] Wildly excessive calls to __tls_get_addr with optimizations enabled.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82803 --- Comment #12 from Yann Droneaud --- (In reply to Yann Droneaud from comment #8) > Created attachment 46903 [details] > An artificial test case for gcc to emit 17 calls to __tls_get_addr() > It's possible to "workaround" this issue by using some __asm__ statement such as OPTIMIZER_HIDE_VAR() from Linux kernel, see https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/compiler.h?h=v5.3#n169 __asm__ ("" : "=r" (var) : "0" (var)) As base line, an artificial benchmark using attachment #46903 in an ELF shared library, have following results when run through perf: Performance counter stats for './case' (100 runs): 932,83 msec task-clock:u #0,999 CPUs utilized ( +- 0,38% ) 0 context-switches:u #0,000 K/sec 0 cpu-migrations:u #0,000 K/sec 51 page-faults:u #0,054 K/sec ( +- 0,19% ) 2 528 214 520 cycles:u #2,710 GHz ( +- 0,30% ) 4 150 148 436 instructions:u #1,64 insn per cycle ( +- 0,00% ) 1 530 031 707 branches:u # 1640,205 M/sec ( +- 0,00% ) 51 236 branch-misses:u#0,00% of all branches ( +- 7,24% ) 0,93364 +- 0,00359 seconds time elapsed ( +- 0,38% ) Applying the following change to attachment #46903 --- case.c~ 2019-09-20 15:39:41.852356614 +0200 +++ case.c2019-09-25 21:38:47.620696710 +0200 @@ -1,8 +1,15 @@ int process(int *); +#define HIDE_VAR(v) __asm__ ("" : "=r" (v) : "0" (v)) + static int *state(void) { - static __thread int s[16]; + static __thread int __s[16]; + int *s = __s; + + HIDE_VAR(s); + return s; } And running the benchmark again through perf, the results are: Performance counter stats for './case' (100 runs): 540,54 msec task-clock:u #0,999 CPUs utilized ( +- 0,22% ) 0 context-switches:u #0,000 K/sec 0 cpu-migrations:u #0,000 K/sec 50 page-faults:u #0,093 K/sec ( +- 0,17% ) 1 469 494 111 cycles:u #2,719 GHz ( +- 0,12% ) 1 530 148 010 instructions:u #1,04 insn per cycle ( +- 0,00% ) 730 031 281 branches:u # 1350,554 M/sec ( +- 0,00% ) 74 613 branch-misses:u#0,01% of all branches ( +- 18,61% ) 0,54102 +- 0,00119 seconds time elapsed ( +- 0,22% ) With the workaround, the benchmark took 42% less time. It's 1.72x faster.
[Bug rtl-optimization/82803] Wildly excessive calls to __tls_get_addr with optimizations enabled.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82803 --- Comment #10 from Yann Droneaud --- Some more snippets, generated with creduce: -8< void a(long *); int b(void); void c(void); long d(void) { static __thread long e; a(); if (b()) c(); return e; } --8< int a(void); void b(long *); void c(void) { static __thread long d; if (d || a()) d = 0; b(); } --8< void a(int *); int b(int *); int c(void) { static __thread int d; a(); while (b()); return 0; } --8< void b(int *); int c(int *); int d(void) { static __thread int a; if (a) while (c()); b(); return 0; } --8< int b(void); void c(void); void d(int *); int e(void) { static __thread int a[2]; d(a); do { d(a); if (b()) c(); } while (a[0] && a[1]); d(a); return 0; } --8< Those make gcc emits 2 or more calls to __tls_get_addr().
[Bug rtl-optimization/82803] Wildly excessive calls to __tls_get_addr with optimizations enabled.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82803 --- Comment #9 from Yann Droneaud --- This issue is also reported as bug #81501
[Bug rtl-optimization/81501] Unneccessary calls to __tls_get_addr() in simple thread-singleton pattern
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81501 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #3 from Yann Droneaud --- See also bug #82803.
[Bug rtl-optimization/82803] Wildly excessive calls to __tls_get_addr with optimizations enabled.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82803 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #8 from Yann Droneaud --- Created attachment 46903 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46903=edit An artificial test case for gcc to emit 17 calls to __tls_get_addr() Using Thread Local Storage (TLS) is a pain: the issue reported here still apply on latest GCC. I've code such as static struct state *state(void) __attribute__((pure)); static struct state *state(void) { static __thread struct state s; return } int do(void) { struct state * const s = state(); int res; /* do something */ return res; } Once compiled, code for my real function contains 6 calls to __tls_get_addr(). Which is far more than expected. And far more than necessary. Clang compile the same code and emit a single call to __tls_get_addr(). Both on Linux amd64, -O3 -fPIC. The attached testcase is an example which is designed to trigger 17 calls to __tls_get_addr(). As you will see, there's about one per conditional + function call pair. Once again, clang is able to emit code with a single call to __tls_get_addr(). You can check for yourself: https://godbolt.org/z/QVGjka
[Bug c/86647] Test on constant expression (unsigned) -1 < 0 triggers a spurious -Wtype-limits warning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86647 --- Comment #5 from Yann Droneaud --- I've reproduced the issue with bool test(void) { return ((unsigned int)0 - 1) < 0; } See https://godbolt.org/z/b1QqIC
[Bug c/86647] Test on constant expression (unsigned) -1 < 0 triggers a spurious -Wtype-limits warning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86647 --- Comment #4 from Yann Droneaud --- *** Bug 91685 has been marked as a duplicate of this bug. ***
[Bug c/91685] -Wtype-limits warns for constant expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91685 Yann Droneaud changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED CC||yann at droneaud dot fr Resolution|--- |DUPLICATE --- Comment #1 from Yann Droneaud --- My issue is the same as bug #86647. *** This bug has been marked as a duplicate of bug 86647 ***
[Bug c++/81642] -Wtype-limits should not trigger for defined numbers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81642 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #3 from Yann Droneaud --- See also bug #86647 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86647
[Bug c/86647] Test on constant expression (unsigned) -1 < 0 triggers a spurious -Wtype-limits warning
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86647 Yann Droneaud changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #3 from Yann Droneaud --- See also bug #81642 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81642
[Bug c/91685] New: -Wtype-limits warns for constant expression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91685 Bug ID: 91685 Summary: -Wtype-limits warns for constant expression Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Target Milestone: --- I'm was trying to implement a test for socklen_t type signedness, because on some platform it's signed and some it's unsigned. For signed socklen_t, I wanted to rejected negative values. I found following code triggers a warning: $ cat test.c #include bool test_unsigned(void) { return ((unsigned int)0 - 1) < 0; } $ gcc -O2 -Wall -Wextra -c test.c warning: comparison of unsigned expression in '< 0' is always false [-Wtype-limits] According to the documentation for -Wtype-limits, this warning should not be produced, because expression is constant: > Warn if a comparison is always true or always false due to the limited range > of the data type, but do not warn for constant expressions. For example, warn > if an unsigned variable is compared against zero with < or >=. This warning > is also enabled by -Wextra. https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/Warning-Options.html#index-Wtype-limits I've made some tests on godbolt, see https://godbolt.org/z/b1QqIC and found clang doesn't trigger the warning. Perhaps warning here is welcomed and documentation should be updated ? In the mean time, I still looking for a portable way to test if socklen_t is negative on platform where it's signed ...
[Bug c++/90885] GCC should warn about 2^16 and 2^32 and 2^64
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90885 --- Comment #7 from Yann Droneaud --- The issue was noted on twitter by John Regehr, in https://twitter.com/johnregehr/status/1139295920997068800 and following messages. The warning was suggest again by John Regehr in https://twitter.com/johnregehr/status/1139302389612077056
[Bug middle-end/90037] [9 Regression] -Wnull-dereference false positive after r269302
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90037 Yann Droneaud changed: What|Removed |Added Attachment #46138|0 |1 is obsolete|| --- Comment #4 from Yann Droneaud --- Created attachment 46139 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46139=edit Reduced reproducer sample (In reply to Yann Droneaud from comment #3) > Created attachment 46138 [details] > Reduced reproducer sample > > I've used creduce[1][2] to generate a smaller reproducer sample, see > https://godbolt.org/z/Ae2x_h > I've used an improved "interestingness script" to generate a reproducer sample which trigger less unrelated warnings. See https://godbolt.org/z/542lS0
[Bug middle-end/90037] [9 Regression] -Wnull-dereference false positive after r269302
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90037 --- Comment #3 from Yann Droneaud --- Created attachment 46138 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46138=edit Reduced reproducer sample I've used creduce[1][2] to generate a smaller reproducer sample, see https://godbolt.org/z/Ae2x_h [1] http://embed.cs.utah.edu/creduce/ [2] https://github.com/csmith-project/creduce
[Bug c/60722] New: __builtin_choose_expr() does not allow 'CONST_EXP' using const variable
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60722 Bug ID: 60722 Summary: __builtin_choose_expr() does not allow 'CONST_EXP' using const variable Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Created attachment 32498 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=32498action=edit testcase Hi, I'm trying to use __builtin_choose_expr() with a test against a const variable: #define VALUE 123 int test(void) { const int value = VALUE; int v1, v2; v1 = __builtin_choose_expr(__builtin_constant_p(VALUE), (__builtin_choose_expr(VALUE = 10, 2, (__builtin_choose_expr(VALUE = 0, 1, 0, -1); v1 = __builtin_choose_expr(__builtin_constant_p(value), (__builtin_choose_expr(value = 10, 2, (__builtin_choose_expr(value = 0, 1, 0, -1); return v1 - v2; } The first expression is considering a constant defined as a macro. And the second expression is considering a constant variable. With gcc 4.9.0 20140313 (experimental), I'm facing the following error: $ /opt/gcc/bin/gcc -O2 -c test.c test.c: In function ‘test’: test.c:21:11: erreur: first argument to ‘__builtin_choose_expr’ not a constant (__builtin_choose_expr(value = 0, ^ test.c:19:9: erreur: first argument to ‘__builtin_choose_expr’ not a constant (__builtin_choose_expr(value = 10, ^ (Note: with gcc 4.8, I'm also having the issue with _builtin_constant_p(value), as bug #19449) It's a pity gcc is not able to consider (value = 0) as a constant expression while its obvious that 'value' is a constant variable (!). It makes usage of __builtin_choose_expr() not applicable in my case.
[Bug c/58872] New: RFC: more builtins for bit manipulation
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58872 Bug ID: 58872 Summary: RFC: more builtins for bit manipulation Product: gcc Version: unknown Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Current bit manipulation builtins can be found in documentation: http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#Other-Builtins GCC could benefit of more bit manipulation builtins, for example: - rotate bit right: __builtin_ror8(uint8_t v, int count) __builtin_ror16(uint16_t v, int count) __builtin_ror32(uint32_t v, int count) __builtin_ror64(uint64_t v, int count) - rotate bit left: __builtin_rol8(uint8_t v, int count) __builtin_rol16(uint16_t v, int count) __builtin_rol32(uint32_t v, int count) __builtin_rol64(uint64_t v, int count) - reverse bit string (bit swap): __builtin_brev8(uint8_t v, int index, int count) __builtin_brev16(uint16_t v, int index, int count) __builtin_brev32(uint32_t v, int index, int count) __builtin_brev64(uint64_t v, int index, int count)
[Bug c/58872] RFC: more builtins for bit manipulation
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58872 Yann Droneaud yann at droneaud dot fr changed: What|Removed |Added CC||yann at droneaud dot fr --- Comment #2 from Yann Droneaud yann at droneaud dot fr --- (In reply to Marc Glisse from comment #1) What do the arguments of brev mean? Related to PR 50481. The prototype for the reverse bit string builtin was designed to be useful to reverse bits in a subset of a integer value, starting at index with count bits. The general use case is likely to reverse all bits in a variable, (uint64_t for example): uint64_t v; __builtin_brev64(v, 0, sizeof(v) * 8); But I thought it might be interesting to have a more general purpose builtin. Actually, the builtin arguments for reverse should probably match what's currently available on modern hardware.
[Bug c/57908] New: alignment of arrays allocated stack on amd64/x86_64: 16 bytes ?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57908 Bug ID: 57908 Summary: alignment of arrays allocated stack on amd64/x86_64: 16 bytes ? Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr According to System V Application Binary Interface, AMD64 Architecture Processor Supplement, Draft Version 0.90 Aggregates and Unions - An array uses the same alignment as its elements, except that a local or global array variable that requires at least 16 bytes, or a C99 local or global variable-length array variable, always has alignment of at least 16 bytes.[4] No other changes required. [4] The alignment requirement allows the use of SSE instructions when operating on the array. The compiler cannot in general calculate the size of a variable-length array (VLA), but it is expected that most VLAs will require at least 16 bytes, so it is logical to mandate that VLAs have at least a 16-byte alignment. As I understand the ABI specifications, arrays allocated on stack must be aligned on 16 bytes boundaries, whatever its length is: eg. an array of 7 bytes get aligned on 16 bytes boundaries. A test program seems to verify that, with gcc version 4.8.1 20130603 (Red Hat 4.8.1-1) (GCC) : kind name address size alignment required Arrays object | u8 | 0x7fffefdd486f |1 | 1 |1 object | u8_0 | 0x7fffefdd4860 |8 |32 |1 object | u8_1 | 0x7fffefdd4850 |7 |16 |1 object | u8_2 | 0x7fffefdd4840 |6 |64 |1 object | u8_3 | 0x7fffefdd4830 |5 |16 |1 object | u8_4 | 0x7fffefdd4820 |4 |32 |1 object | u8_5 | 0x7fffefdd4810 |3 |16 |1 object | u8_6 | 0x7fffefdd4800 |2 | 2048 |1 object | u8_7 | 0x7fffefdd47ff |1 | 1 |1 object | u8_8 | 0x7fffefdd47fe |1 | 2 |1 IMHO it's a waste of memory and this behavor is inconsistent regarding structure layout: eg. arrays in structure are not aligned on 16 bytes boundary. But let's say the specification mandate such stack allocation, aligned on 16 bytes boundary. Then enter LLVM/Clang clang version 3.3 (tags/RELEASE_33/rc3): kind name address size alignment required Arrays object | u8 | 0x7fff45f4154f |1 | 1 |1 object | u8_0 | 0x7fff45f41547 |8 | 1 |1 object | u8_1 | 0x7fff45f41540 |7 |64 |1 object | u8_2 | 0x7fff45f4153a |6 | 2 |1 object | u8_3 | 0x7fff45f41535 |5 | 1 |1 object | u8_4 | 0x7fff45f41531 |4 | 1 |1 object | u8_5 | 0x7fff45f4152e |3 | 2 |1 object | u8_6 | 0x7fff45f4152c |2 | 4 |1 object | u8_7 | 0x7fff45f4152b |1 | 1 |1 object | u8_8 | 0x7fff45f4152a |1 | 2 |1 It seems that Clang is not aligning arrays on stack to 16 bytes boundary. Note: for both compiler, tested on Fedora 19, the results were produced with a test program compiled with default optimisation flag, with -O3, the results are quite the same. The source code of the test is available here: https://gitorious.org/opteya/alignment/blobs/master/stack-alignment.c
[Bug c/57908] alignment of arrays allocated stack on amd64/x86_64: 16 bytes ?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57908 --- Comment #1 from Yann Droneaud yann at droneaud dot fr --- Additionally, for ARM target (ARMv7), it seems GCC align arrays on stack to 4 bytes boundary ... but I don't found the ABI specification that require such alignment. kind name address size alignment required Arrays object | u8 | 0xf6fff017 |1 | 1 |1 object | u8_0 | 0xf6fff00c |8 | 4 |1 object | u8_1 | 0xf6fff004 |7 | 4 |1 object | u8_2 | 0xf6ffeffc |6 | 4 |1 object | u8_3 | 0xf6ffeff4 |5 | 4 |1 object | u8_4 | 0xf6ffeff0 |4 |16 |1 object | u8_5 | 0xf6ffefec |3 | 4 |1 object | u8_6 | 0xf6ffefe8 |2 | 8 |1 object | u8_7 | 0xf6ffefe4 |1 | 4 |1 object | u8_8 | 0xf6ffefe3 |1 | 1 |1
[Bug target/57908] alignment of arrays allocated stack on amd64/x86_64: 16 bytes ?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57908 --- Comment #4 from Yann Droneaud yann at droneaud dot fr --- (In reply to Andrew Pinski from comment #2) Your test program is not fully testing things correctly. kind name address size alignment required object | u8_5 | 0x7fffefdd4810 |3 |16 |1 object | u8_6 | 0x7fffefdd4800 |2 | 2048 |1 object | u8_7 | 0x7fffefdd47ff |1 | 1 |1 Shows why. There are two variables right next to each other but the alignment recorded is 2048 but that was just accidental. The alignment of u8_6 is 16 due to the next variable at 10. Have you noticed that u8_7 is an array of 1 element only ? Array of 1 element (bytes) only are not aligned on 16 bytes boundary. Array of 2 bytes and greater get aligned on 16 bytes boundary. Should I show another test case ?
[Bug target/57908] alignment of arrays allocated stack on amd64/x86_64: 16 bytes ?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57908 Yann Droneaud yann at droneaud dot fr changed: What|Removed |Added Status|RESOLVED|UNCONFIRMED Resolution|INVALID |--- --- Comment #5 from Yann Droneaud yann at droneaud dot fr --- (In reply to Yann Droneaud from comment #4) (In reply to Andrew Pinski from comment #2) Your test program is not fully testing things correctly. kind name address size alignment required object | u8_5 | 0x7fffefdd4810 |3 |16 |1 object | u8_6 | 0x7fffefdd4800 |2 | 2048 |1 object | u8_7 | 0x7fffefdd47ff |1 | 1 |1 Shows why. There are two variables right next to each other but the alignment recorded is 2048 but that was just accidental. The alignment of u8_6 is 16 due to the next variable at 10. Have you noticed that u8_7 is an array of 1 element only ? Array of 1 element (bytes) only are not aligned on 16 bytes boundary. Array of 2 bytes and greater get aligned on 16 bytes boundary. Should I show another test case ? kind name address size alignment required type |uint8_t |N/A |1 | N/A |1 type | uint8_t[2] |N/A |2 | N/A |1 Arrays object | u8_0 | 0x7fff7671e25f |1 | 1 |1 object | u8_1 | 0x7fff7671e250 |3 |16 |1 object | u8_2 | 0x7fff7671e240 |7 |64 |1 object | u8_3 | 0x7fff7671e230 |5 |16 |1 object | u8_4 | 0x7fff7671e220 |2 |32 |1 object | u8_5 | 0x7fff7671e21f |1 | 1 |1 object | u8_6 | 0x7fff7671e210 |3 |16 |1 object | u8_7 | 0x7fff7671e200 |5 | 512 |1 object | u8_8 | 0x7fff7671e1f0 |7 |16 |1 object | u8_9 | 0x7fff7671e1e0 |2 |32 |1 object | u8_10 | 0x7fff7671e1d0 | 11 |16 |1 object | u8_11 | 0x7fff7671e1c0 |3 |64 |1 object | u8_12 | 0x7fff7671e1b0 | 13 |16 |1 object | u8_13 | 0x7fff7671e1a0 |2 |32 |1 object | u8_14 | 0x7fff7671e19f |1 | 1 |1 object | u8_15 | 0x7fff7671e190 |2 |16 |1
[Bug target/57908] alignment of arrays allocated stack on amd64/x86_64: 16 bytes ?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57908 --- Comment #6 from Yann Droneaud yann at droneaud dot fr --- Created attachment 30512 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=30512action=edit Demonstrate stack allocation of array aligned on 16 bytes
[Bug target/57908] alignment of arrays allocated stack on amd64/x86_64: 16 bytes ?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57908 --- Comment #8 from Yann Droneaud yann at droneaud dot fr --- Using -Os show different results: Arrays object | u8_0 | 0x7fff9b4c05bc |1 | 4 |1 object | u8_1 | 0x7fff9b4c05c7 |3 | 1 |1 object | u8_2 | 0x7fff9b4c05da |7 | 2 |1 object | u8_3 | 0x7fff9b4c05d0 |5 |16 |1 object | u8_4 | 0x7fff9b4c05bf |2 | 1 |1 object | u8_5 | 0x7fff9b4c05bd |1 | 1 |1 object | u8_6 | 0x7fff9b4c05ca |3 | 2 |1 object | u8_7 | 0x7fff9b4c05d5 |5 | 1 |1 object | u8_8 | 0x7fff9b4c05e1 |7 | 1 |1 object | u8_9 | 0x7fff9b4c05c1 |2 | 1 |1 object | u8_10 | 0x7fff9b4c05e8 | 11 | 8 |1 object | u8_11 | 0x7fff9b4c05cd |3 | 1 |1 object | u8_12 | 0x7fff9b4c05f3 | 13 | 1 |1 object | u8_13 | 0x7fff9b4c05c3 |2 | 1 |1 object | u8_14 | 0x7fff9b4c05be |1 | 2 |1 object | u8_15 | 0x7fff9b4c05c5 |2 | 1 |1 So GCC is using 16 bytes to align array allocated on stack by default but it's not enforcing such alignment. I guess it's all about optimisation ... but wasting up to 14 bytes to get an array of 2 bytes aligned might be overkill. Could someone comment on which optimisation is achieved by aligning such small arrays ? Regards.
[Bug target/57908] alignment of arrays allocated stack on amd64/x86_64: 16 bytes ?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57908 --- Comment #10 from Yann Droneaud yann at droneaud dot fr --- (In reply to Andrew Pinski from comment #9) (In reply to Yann Droneaud from comment #8) Could someone comment on which optimisation is achieved by aligning such small arrays ? The simple answer is so each array is more likely to fit into a cache line: One use of this macro is to increase alignment of medium-size data to make it all fit in fewer cache lines. */ Thanks for the investigation. Initially I thought it would be better to pack such arrays to fit whole cache line: fewer cache lines will be used and most of the arrays would be already in cache lines. But according to http://stackoverflow.com/a/7281770: On x86 cache lines are 64 bytes, however, to prevent false sharing, you need to follow the guidelines of the processor you are targeting (intel has some special notes on its netburst based processors), generally you need to align to 64 bytes for this (intel states that you should also avoid crossing 16 byte boundries). This start to make sense to me. I'm likely buying the argument for global variables but for local variables, I think they are probably not going to be shared a lot across CPUs. But I haven't data for this so I won't continue that way. Thanks a lot for answer my question.
[Bug target/57911] New: alignment of arrays allocated stack on ARM : 4 bytes ?
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57911 Bug ID: 57911 Summary: alignment of arrays allocated stack on ARM : 4 bytes ? Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Hi Following discussion in bug #57908, especially bug #57908 comment #1, on ARMv7, I'm very surprised that array of bytes are aligned on 4 bytes boundary when allocated on stack. Using attachment #30512, I'm able to produce the following results using GCC arm-none-linux-gnueabi-gcc (Sourcery CodeBench Lite 2013.05-24) 4.7.3. Another custom GCC 4.7.2 produces same results. with default option: kind name address size alignment required type |uint8_t |N/A |1 | N/A |1 type | uint8_t[2] |N/A |2 | N/A |1 Arrays object | u8_0 | 0xf6fff00c |1 | 4 |1 object | u8_1 | 0xf6fff008 |3 | 8 |1 object | u8_2 | 0xf6fff000 |7 | 4096 |1 object | u8_3 | 0xf6ffeff8 |5 | 8 |1 object | u8_4 | 0xf6ffeff4 |2 | 4 |1 object | u8_5 | 0xf6ffeff0 |1 |16 |1 object | u8_6 | 0xf6ffefec |3 | 4 |1 object | u8_7 | 0xf6ffefe4 |5 | 4 |1 object | u8_8 | 0xf6ffefdc |7 | 4 |1 object | u8_9 | 0xf6ffefd8 |2 | 8 |1 object | u8_10 | 0xf6ffefcc | 11 | 4 |1 object | u8_11 | 0xf6ffefc8 |3 | 8 |1 object | u8_12 | 0xf6ffefb8 | 13 | 8 |1 object | u8_13 | 0xf6ffefb4 |2 | 4 |1 object | u8_14 | 0xf6ffefb0 |1 |16 |1 object | u8_15 | 0xf6ffefac |2 | 4 |1 with -Os: kind name address size alignment required type |uint8_t |N/A |1 | N/A |1 type | uint8_t[2] |N/A |2 | N/A |1 Arrays object | u8_0 | 0xf6ffef9c |1 | 4 |1 object | u8_1 | 0xf6ffefb8 |3 | 8 |1 object | u8_2 | 0xf6ffefd4 |7 | 4 |1 object | u8_3 | 0xf6ffefc4 |5 | 4 |1 object | u8_4 | 0xf6ffefa8 |2 | 8 |1 object | u8_5 | 0xf6ffefa0 |1 |32 |1 object | u8_6 | 0xf6ffefbc |3 | 4 |1 object | u8_7 | 0xf6ffefcc |5 | 4 |1 object | u8_8 | 0xf6ffefdc |7 | 4 |1 object | u8_9 | 0xf6ffefac |2 | 4 |1 object | u8_10 | 0xf6ffefe4 | 11 | 4 |1 object | u8_11 | 0xf6ffefc0 |3 |64 |1 object | u8_12 | 0xf6ffeff0 | 13 |16 |1 object | u8_13 | 0xf6ffefb0 |2 |16 |1 object | u8_14 | 0xf6ffefa4 |1 | 4 |1 object | u8_15 | 0xf6ffefb4 |2 | 4 |1 I'm reading AAPCS (IHI0042E) and I don't found any requirement for array allocated on stack to be aligned on 4 bytes. It's a pity that -Os, as suggested by Andrew Pinski in bug #57908 comment #7, doesn't align the array on 1 bytes boundary.
[Bug c/57889] New: Improvement: builtin to return a string from a type (type to string builtin)
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57889 Bug ID: 57889 Summary: Improvement: builtin to return a string from a type (type to string builtin) Product: gcc Version: unknown Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: yann at droneaud dot fr Hi, It might be of interest to have a builtin to convert a type name to a string. Given a type or a variable, the builtin would return the type of it as a string. It could be used to build debug messages: #define ASSERT_NULL(p) do { \ if ((p) == NULL) \ printf(%s * %s == NULL\n, __builtin_typestringof(*p), #p); \ } while(0); Regards.
[Bug other/55899] New: GCC should provide built-ins in stdint.h data types flavor/version/variation
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55899 Bug #: 55899 Summary: GCC should provide built-ins in stdint.h data types flavor/version/variation Classification: Unclassified Product: gcc Version: unknown Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: other AssignedTo: unassig...@gcc.gnu.org ReportedBy: y...@droneaud.fr Built-in functions such as __builtin_clz(unsigned int x) __builtin_ctz(unsigned int x) __builtin_ffs(unsigned int x) etc. are lacking variant based on C99 stdint.h data type. Currently there's __builtin_clzl(unsigned long x) __builtin_clzll(unsigned long long x) I'd like to have: __builtin_clz32(uint32_t x) __builtin_clz64(uint64_t x) This would help to hard code the number of bits when using such construct to know the number of bit needed to hold a value: (8 * sizeof(unsigned int)) - __builtin_clz(value) when value is of type uint32_t: 32 - __builtin_clz32(value) Note: there's already __builtin_bswap32(int32_t x) and __builtin_bswap64(int64_t x)
[Bug c/51579] New: GCC should be able report a warning for usage of parameters marked with __attribute__((unused))
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51579 Bug #: 51579 Summary: GCC should be able report a warning for usage of parameters marked with __attribute__((unused)) Classification: Unclassified Product: gcc Version: 4.6.2 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: c AssignedTo: unassig...@gcc.gnu.org ReportedBy: y...@droneaud.fr I would like to see GCC emit a warning when a parameter marked as unused is in fact used in the function. The warning option could be something like -Wunused-parameter-used For example, the following code doesn't produce any warning. int foo (int *ptr, int val __attribute__((unused))) { int res; res = *ptr + val; return res; } It would be interesting to have a warning like this: test.c: In function 'foo': test.c:5:21: warning: parameter 'val' is used but marked as unused in declaration [-Wunused-parameter-used] Same thing could apply to function, type and variable specified with __attribute__((unused)) Additionally, a new attribute warn_use could be introduced to enforce the unused attribute, since unused attribute is not meant to prevent usage: - This attribute, attached to a function, means that the function is meant to be possibly unused - When attached to a type (including a union or a struct), this attribute means that variables of that type are meant to appear possibly unused - This attribute, attached to a variable, means that the variable is meant to be possibly unused
[Bug c/51579] GCC should be able report a warning for usage of parameters marked with __attribute__((unused))
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51579 --- Comment #2 from Yann Droneaud yann at droneaud dot fr 2011-12-16 15:25:41 UTC --- (In reply to comment #1) I don't think we should start warning each time an __attribute__((unused)) parameter is actually used. In my experience that's absolutely common and pervasive. That's why it must not be the default behavor, so I'm not asking for inclusion in -Wunused. If the parameter is meant to *never* be used, should be completely removed, no? Sometimes you cannot remove the parameter, since the function signature is provided by, for example for a callback in some graphic toolkit. What's the point of specifying that something is not used if your going to use it anyway :) If there's no penalty to put __attribute__((unused)), one mad developer could put __attribute__((unused)) on all functions arguments, just in case. (but in the end, it's easier to disable warning with -Wno-unused). Having the warning could help programmer remember to remove the attribute which is now, in turn, not used. This would enforce some contract between the function declaration and its own implementation. Or maybe what you are really asking for are unnamed parameters, like in C++, which indeed can be handy sometimes when dealing with ABI stability issues, etc? Seems something different, however. Having the C++ unnamed parameter behavor could help, but would require some preprocessor magic to be fully portable, for example. #if defined(__GNUC__) || defined(__cplusplus) # define UNUSED(name) #else # define UNUSED(name) unused_ ## name #endif int foo (int *ptr, int UNUSED(var)) { } Currently, one can do: #if defined(__GNUC__) # define UNUSED __attribute__((unused)) #else # define UNUSED #endif int foo (int *ptr, int UNUSED var) { }