r179482 - Handle incompatible redeclarations of library builtins better.

John McCall rjmccall at apple.com
Sun Apr 14 01:50:55 PDT 2013


Author: rjmccall
Date: Sun Apr 14 03:50:55 2013
New Revision: 179482

URL: http://llvm.org/viewvc/llvm-project?rev=179482&view=rev
Log:
Handle incompatible redeclarations of library builtins better.
Invalid redeclarations of valid explicit declarations shouldn't
take the same path as redeclarations of implicit declarations,
and invalid local extern declarations shouldn't foul things up
for everybody else.

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Sema/extern-redecl.c

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=179482&r1=179481&r2=179482&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Apr 14 03:50:55 2013
@@ -2697,21 +2697,31 @@ bool Sema::MergeFunctionDecl(FunctionDec
     // Fall through to diagnose conflicting types.
   }
 
-  // A function that has already been declared has been redeclared or defined
-  // with a different type- show appropriate diagnostic
-  if (unsigned BuiltinID = Old->getBuiltinID()) {
-    // The user has declared a builtin function with an incompatible
-    // signature.
+  // A function that has already been declared has been redeclared or
+  // defined with a different type; show an appropriate diagnostic.
+
+  // If the previous declaration was an implicitly-generated builtin
+  // declaration, then at the very least we should use a specialized note.
+  unsigned BuiltinID;
+  if (Old->isImplicit() && (BuiltinID = Old->getBuiltinID())) {
+    // If it's actually a library-defined builtin function like 'malloc'
+    // or 'printf', just warn about the incompatible redeclaration.
     if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) {
-      // The function the user is redeclaring is a library-defined
-      // function like 'malloc' or 'printf'. Warn about the
-      // redeclaration, then pretend that we don't know about this
-      // library built-in.
       Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New;
       Diag(Old->getLocation(), diag::note_previous_builtin_declaration)
         << Old << Old->getType();
-      New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin);
-      Old->setInvalidDecl();
+
+      // If this is a global redeclaration, just forget hereafter
+      // about the "builtin-ness" of the function.
+      //
+      // Doing this for local extern declarations is problematic.  If
+      // the builtin declaration remains visible, a second invalid
+      // local declaration will produce a hard error; if it doesn't
+      // remain visible, a single bogus local redeclaration (which is
+      // actually only a warning) could break all the downstream code.
+      if (!New->getDeclContext()->isFunctionOrMethod())
+        New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin);
+
       return false;
     }
 

Modified: cfe/trunk/test/Sema/extern-redecl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/extern-redecl.c?rev=179482&r1=179481&r2=179482&view=diff
==============================================================================
--- cfe/trunk/test/Sema/extern-redecl.c (original)
+++ cfe/trunk/test/Sema/extern-redecl.c Sun Apr 14 03:50:55 2013
@@ -42,3 +42,23 @@ void test4() {
   }
   int x = sizeof(test4_array); // expected-error {{invalid application of 'sizeof' to an incomplete type 'int []'}}
 }
+
+// Test that invalid local extern declarations of library
+// builtins behave reasonably.
+extern void abort(void); // expected-note 2 {{previous declaration is here}}
+extern float *calloc(); // expected-warning {{incompatible redeclaration of library function}} expected-note {{is a builtin}} expected-note 2 {{previous declaration is here}}
+void test5a() {
+  int abort(); // expected-error {{conflicting types}}
+  float *malloc(); // expected-warning {{incompatible redeclaration of library function}} expected-note 2 {{is a builtin}}
+  int *calloc(); // expected-error {{conflicting types}}
+}
+void test5b() {
+  int abort(); // expected-error {{conflicting types}}
+  float *malloc(); // expected-warning {{incompatible redeclaration of library function}}
+  int *calloc(); // expected-error {{conflicting types}}
+}
+void test5c() {
+  void (*_abort)(void) = &abort;
+  void *(*_malloc)() = &malloc;
+  float *(*_calloc)() = &calloc;
+}





More information about the cfe-commits mailing list