[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #6 from manu at gcc dot gnu dot org 2009-07-07 10:25 --- (In reply to comment #5) Thus code is undefined you have an acess of a char array as a struct. Yes you are only taking the address of an element but it is still considered an acess by the standards. I see that users repeatedly fall for this. Could we detect what type is accessed as what and provide an informative note? Something like: warning: dereferencing type-punned pointer might break strict-aliasing rules note: accessing 'char *' as 'structure *' is undefined Andrew, do you think this would be difficult to implement? -- manu at gcc dot gnu dot org changed: What|Removed |Added CC||manu at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #7 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 16:31 --- extern int c; int a(void) { return *(short *)(void *)c; } This is a very bad example of a false positive as you are acessing an int as a short; that is undefined. I will look at your code later on, my laptop for home is currently broken. Whether it is a false positive or not depends on the context. For example, if I call function a() from function b(): int b(void) { c = 0x12345678; __asm__ volatile (:::memory); return a(); } the code is valid and the function b() must return a fixed value depending on the endianity of the machine. That __asm__ statement works as a barrier that prevents the compiler from reordering two accesses to c. So I am not against the warning. The warning is good. The problem is that there is no way to shut up the warning. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #9 from pinskia at gcc dot gnu dot org 2009-07-07 16:54 --- So you say that converting the char * pointer to struct * pointer is understood as accessing the stored value by the standard? No. Let's look at the code: char buffer[512]; (void *)((struct structure *)(void *)buffer)-x You are accessing a character array via a struct structure and then taking the address. This why it is undefined. Even though it does not look like an access in the assembly as it is a-b is an addition, it is an access according to the C/C++ standard. Also aliasing is not transitive, that is you can access anything via a character type but you cannot access a character by everything (only character types themselves). the code is valid and the function b() must return a fixed value depending on the endianity of the machine. That __asm__ statement works as a barrier that prevents the compiler from reordering two accesses to c. Actually even with the memory barrier is still undefined according to the C/C++ standards, it does not mean we won't do what you expect but it means we don't have to do what you expect it to do. This is why we warn about it. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #8 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 16:45 --- Thus code is undefined you have an acess of a char array as a struct. Yes you are only taking the address of an element but it is still considered an acess by the standards. Why is it undefined? An object shall have its store value accessed only by an lvalue that has one of the following types ... * a character type So you say that converting the char * pointer to struct * pointer is understood as accessing the stored value by the standard? The only possible problem could be some hypothetical computer that cannot hold misaligned pointers to structs (common computers allow unaligned pointers and trap only on dereferencing unaligned pointers, not on generating them). But once I know that I have a computer that allows unaligned pointers to structs, there should be a method how to shut the warning up (with (void *) cast). -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #10 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 18:07 --- So you mean that that -x operator is invalid and break the standard? Anyway the standard means if you write your code according to the standard = the code will run correctly, but the inverse implication doesn't apply. It is sometimes required to break the C standard. For example, you write unsigned char *framebuffer = vga_getgraphmem(); and now you want to access the framebuffer. According to the standard, you could only do it by bytes. But that means one bus cycle to the videocard for every byte transfered. So people understand that common processors allow aligned accesses to 2, 4 or 8 bytes and that common videocards have their framebuffer base address aligned on same larger boundary --- and they simply cast the pointer to u_int32_t or u_int64_t and access the videoram faster. Each time you watch some video, remember those undefined memory accesses that are hapenning for you to get faster performance :) Another example --- the C standard says how it's not allowed to even produce a pointer that points before the allocated array or more than one entry after the last entry of the array and how it's not allowed to subtract two pointers from different arrays. It is perfectly rational --- unless you are writing the memory allocator itself! Then you inevitably must do some operations that are considered undefined by the standard. Regarding that int * to short * cast --- obviously, the code may run on some computer that has tagged memory and traps if access with invalid type is done. But common computers don't have tagged memory and the programmer should be allowed to do such casts if he understands the implications (for example, if its done only in arch-specific part of an operating system, it is perfectly legal). So there should be a method to silence the warning. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #11 from pinskia at gcc dot gnu dot org 2009-07-07 18:18 --- (In reply to comment #10) For example, you write unsigned char *framebuffer = vga_getgraphmem(); and now you want to access the framebuffer. According to the standard, you could only do it by bytes. But that means one bus cycle to the videocard for every byte transfered. So people understand that common processors allow aligned accesses to 2, 4 or 8 bytes and that common videocards have their framebuffer base address aligned on same larger boundary --- and they simply cast the pointer to u_int32_t or u_int64_t and access the videoram faster. Each time you watch some video, remember those undefined memory accesses that are hapenning for you to get faster performance :) Not fully, you missed part of the standard that takes about the effective type. Basically if there is no declared type for an object, the effective type is the type which is used for storing and then only that can be read back with that type or character type or the other cases the standard mentions. The effective type changes when another store happens. In both of original cases in this bug report, there is a declared type which is also the effective type. And it is not about the cast between the pointer types which causes it to be undefined but rather the accesses. -- pinskia at gcc dot gnu dot org changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution||INVALID http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #12 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 19:40 --- So if there was char *buffer = malloc(512) instead of char buffer[512], would it be correct to cast it to the pointer to structure? And it is not about the cast between the pointer types which causes it to be undefined but rather the accesses. What is considered the access in that code? Is it the - operator? operator? = operator? Cast operator? Or anything else? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #13 from pinskia at gcc dot gnu dot org 2009-07-07 20:24 --- (In reply to comment #12) So if there was char *buffer = malloc(512) instead of char buffer[512], would it be correct to cast it to the pointer to structure? Yes. And it is not about the cast between the pointer types which causes it to be undefined but rather the accesses. What is considered the access in that code? Is it the - operator? operator? = operator? Cast operator? Or anything else? The following three operators are causes an access to happen even if is used afterwards: -, ., and * Thanks, Andrew PInski -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #1 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 01:22 --- Created an attachment (id=18145) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18145action=view) a bug in -Wstrict-aliasing=3 This is an example of a flaw in -Wstrict-aliasing=3 (this mode is very bad, produces many false positives on my project and I'm wondering why is it default?) Gcc man page says that -Wstrict-aliasing=3 produces less false positives than -Wstrict-aliasing=2. This is counterexample, it produces type-punned warning in -Wstrict-aliasing=3 mode and doesn't warn in -Wstrict-aliasing=2. I added (void *) casts everywhere, but they don't quash the warning. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #2 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 01:34 --- Created an attachment (id=18146) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18146action=view) a bug in -Wstrict-aliasing=3 This is an example of a flaw in -Wstrict-aliasing=3 (this mode is very bad, produces many false positives on my project and I'm wondering why is it default?) Gcc man page says that -Wstrict-aliasing=3 produces less false positives than -Wstrict-aliasing=2. This is counterexample, it produces type-punned warning in -Wstrict-aliasing=3 mode and doesn't warn in -Wstrict-aliasing=2. I added (void *) casts everywhere, but they don't quash the warning. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #3 from pinskia at gmail dot com 2009-07-07 03:44 --- Subject: Re: New: dereferencing type-punned pointer warnings cannot be disabled Sent from my iPhone On Jul 6, 2009, at 6:12 PM, mikulas at artax dot karlin dot mff dot cuni dot cz gcc-bugzi...@gcc.gnu.org wrote: Gcc became recently (4.4) very bad regarding false positive type- punned warnings. In previous versions, the warnings could be suppressed by casting to (void *), in 3.x and 4.1 it worked perfectly, in 4.3 it still worked somehow (except in -Wstrict-aliasing=3 mode), in 4.4 there are cases where it doesn't work at all. I don't want to completely disable the warnings with -Wno-strict- aliasing (this could leave bugs unnotified), but I need a method to disable them on case-by-case basis once I verified that the code in question is correct. Simple example, compile with -O2 -Wall: extern int c; int a(void) { return *(short *)(void *)c; } This is a very bad example of a false positive as you are acessing an int as a short; that is undefined. I will look at your code later on, my laptop for home is currently broken. In 4.4 the warning can't be disabled at all! The (void *) cast doesn't suppress the warning and none of three options to -Wstrict-aliasing helps. In 4.3 the cast to (void *) suppressed the warning in -Wstrict-aliasing 1,2 modes (and didn't suppress it in the default mode 3), in 4.4 the warning can't be suppressed at all. Gcc developers tried to made these warnings more intelligent with less false positives, but unfortunatelly they completely broke the method to disable them in the specific case. For me, false positives are not a major problem --- when I get a false positive, I just read the code, check it and if I conclude that it's OK, I disable the warning with (void *). But if there's no way to disable false positives, it makes the warnings completely useless. -- Summary: dereferencing type-punned pointer warnings cannot be disabled Product: gcc Version: 4.4.1 Status: UNCONFIRMED Severity: major Priority: P3 Component: regression AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: mikulas at artax dot karlin dot mff dot cuni dot cz GCC build triplet: i686-pc-linux-gnu GCC host triplet: i686-pc-linux-gnu GCC target triplet: i686-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665 -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
Re: [Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
Sent from my iPhone On Jul 6, 2009, at 6:34 PM, mikulas at artax dot karlin dot mff dot cuni dot cz gcc-bugzi...@gcc.gnu.org wrote: --- Comment #2 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 01:34 --- Created an attachment (id=18146) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18146action=view) a bug in -Wstrict-aliasing=3 This is an example of a flaw in -Wstrict-aliasing=3 (this mode is very bad, produces many false positives on my project and I'm wondering why is it default?) Gcc man page says that -Wstrict-aliasing=3 produces less false positives than -Wstrict-aliasing=2. This is counterexample, it produces type- punned warning in -Wstrict-aliasing=3 mode and doesn't warn in -Wstrict-aliasing=2. I added (void *) casts everywhere, but they don't quash the warning. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #4 from pinskia at gmail dot com 2009-07-07 03:48 --- Subject: Re: dereferencing type-punned pointer warnings cannot be disabled Sent from my iPhone On Jul 6, 2009, at 6:34 PM, mikulas at artax dot karlin dot mff dot cuni dot cz gcc-bugzi...@gcc.gnu.org wrote: --- Comment #2 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 01:34 --- Created an attachment (id=18146) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18146action=view) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18146action=view) a bug in -Wstrict-aliasing=3 This is an example of a flaw in -Wstrict-aliasing=3 (this mode is very bad, produces many false positives on my project and I'm wondering why is it default?) Gcc man page says that -Wstrict-aliasing=3 produces less false positives than -Wstrict-aliasing=2. This is counterexample, it produces type- punned warning in -Wstrict-aliasing=3 mode and doesn't warn in -Wstrict-aliasing=2. I added (void *) casts everywhere, but they don't quash the warning. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665 -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
Re: [Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
Thus code is undefined you have an acess of a char array as a struct. Yes you are only taking the address of an element but it is still considered an acess by the standards. Sent from my iPhone On Jul 6, 2009, at 6:34 PM, mikulas at artax dot karlin dot mff dot cuni dot cz gcc-bugzi...@gcc.gnu.org wrote: --- Comment #2 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 01:34 --- Created an attachment (id=18146) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18146action=view) a bug in -Wstrict-aliasing=3 This is an example of a flaw in -Wstrict-aliasing=3 (this mode is very bad, produces many false positives on my project and I'm wondering why is it default?) Gcc man page says that -Wstrict-aliasing=3 produces less false positives than -Wstrict-aliasing=2. This is counterexample, it produces type- punned warning in -Wstrict-aliasing=3 mode and doesn't warn in -Wstrict-aliasing=2. I added (void *) casts everywhere, but they don't quash the warning. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665
[Bug regression/40665] dereferencing type-punned pointer warnings cannot be disabled
--- Comment #5 from pinskia at gmail dot com 2009-07-07 03:50 --- Subject: Re: dereferencing type-punned pointer warnings cannot be disabled Thus code is undefined you have an acess of a char array as a struct. Yes you are only taking the address of an element but it is still considered an acess by the standards. Sent from my iPhone On Jul 6, 2009, at 6:34 PM, mikulas at artax dot karlin dot mff dot cuni dot cz gcc-bugzi...@gcc.gnu.org wrote: --- Comment #2 from mikulas at artax dot karlin dot mff dot cuni dot cz 2009-07-07 01:34 --- Created an attachment (id=18146) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18146action=view) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18146action=view) a bug in -Wstrict-aliasing=3 This is an example of a flaw in -Wstrict-aliasing=3 (this mode is very bad, produces many false positives on my project and I'm wondering why is it default?) Gcc man page says that -Wstrict-aliasing=3 produces less false positives than -Wstrict-aliasing=2. This is counterexample, it produces type- punned warning in -Wstrict-aliasing=3 mode and doesn't warn in -Wstrict-aliasing=2. I added (void *) casts everywhere, but they don't quash the warning. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665 -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40665