<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Aug 14, 2009, at 3:38 PM, Eli Friedman wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; font-family: Helvetica; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; ">On Fri, Aug 14, 2009 at 3:30 PM, Chris Lattner<<a href="mailto:clattner@apple.com">clattner@apple.com</a>> wrote:<br><blockquote type="cite"><br></blockquote><blockquote type="cite">On Aug 14, 2009, at 3:20 PM, Eli Friedman wrote:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><blockquote type="cite">On Fri, Aug 14, 2009 at 3:12 PM, Ted Kremenek<<a href="mailto:kremenek@apple.com">kremenek@apple.com</a>> wrote:<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">Unless I'm mistaken, this breaks constructs like the following:<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">__attribute((malloc)) void *(*f)();<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">-Eli<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">I implemented handling of this case, but I noticed that GCC actually<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">rejects<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">attribute 'malloc' being applied to function pointers ("warning: 'malloc'<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">attribute ignored").  Should we do the same in Clang?  For function<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">pointers, the malloc attribute really a property of the pointer type, not<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">the declaration, but apparently GCC doesn't even reason about that.<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">I think it's better to be self-consistent here over being consistent<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">with gcc, as long as we don't break compatibility.  Function<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">attributes are confusing enough without making different attributes<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">act differently.<br></blockquote></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">The problem is that this attribute is really a decl attribute, not a type<br></blockquote><blockquote type="cite">attribute.  If I have two functions with the same prototype (but one is<br></blockquote><blockquote type="cite">attribute malloc) I should be able to assign them to the same function<br></blockquote><blockquote type="cite">pointer, no?  If we made it part of the type system, we'd have to consider<br></blockquote><blockquote type="cite">the attribute for assignment compatibility etc.<br></blockquote><br>How is malloc different from noreturn in this regard?</span></blockquote></div><br><div>There are two points here.  First, the 'malloc' attribute is a GCC-extension, and if that attribute only applies to function declarations that is at least self-consistent.  Limiting, but self-consistent.  Other than generalizing the attribute (which might be nice from a programming language theory point of view) there is no code out there that uses more functionality on that attribute than GCC provides.</div><div><br></div><div>As for 'noreturn', Clang's handling of it is incorrect.  Consider:</div><div><br></div><div><div>$ cat t.c</div><div>__attribute((noreturn)) void *(*fptr)();</div><div>void *(*gptr)();</div><div><br></div><div>void bar() {</div><div>  gptr = fptr;</div><div>}</div><div><br></div><div>$ gcc -fsyntax-only t.c</div><div><div>t.c: In function ‘bar’:</div><div>t.c:5: warning: assignment makes qualified function pointer from unqualified</div><div><br></div><div>$ clang -fsyntax-only t.c</div><div>(nothing)</div><div><br></div><div>I'm not certain what GCC is doing under the hood, but it appears that (unlike Clang) GCC is reasoning about 'noreturn' as a qualifier on the type.  That doesn't appear to be the case with 'malloc'.  Perhaps that's just how it was implemented in GCC, and perhaps they both should be handled as qualifiers.  The upshot is that while Clang eats code where 'noreturn' is attached to a function pointer, it doesn't handle it correctly.</div></div></div></body></html>