Adopt a more principled approach to invalid declarations:
  - If a declaration is an invalid redeclaration of an existing name,
    complain about the invalid redeclaration then avoid adding it to
    the AST (we can still parse the definition or initializer, if any).
  - If the declaration is invalid but there is no prior declaration
    with that name, introduce the invalid declaration into the AST
    (for later error recovery).
  - If the declaration is an invalid redeclaration of a builtin that
    starts with __builtin_, we produce an error and drop the
    redeclaration. If it is an invalid redeclaration of a library
    builtin (e.g., malloc, printf), warn (don't error!) and drop the
    redeclaration.

If a user attempts to define a builtin, produce an error and (if it's
a library builtin like malloc) suggest -ffreestanding.

This addresses <rdar://problem/6097585> and PR2892. However, PR3588 is
still going to cause some problems when builtins are redeclared
without a prototype.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64639 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Sema/implicit-builtin-decl.c b/test/Sema/implicit-builtin-decl.c
index e9b0556..892e372 100644
--- a/test/Sema/implicit-builtin-decl.c
+++ b/test/Sema/implicit-builtin-decl.c
@@ -2,13 +2,13 @@
 void f() {
   int *ptr = malloc(sizeof(int) * 10); // expected-warning{{implicitly declaring C library function 'malloc' with type}} \
   // expected-note{{please include the header <stdlib.h> or explicitly provide a declaration for 'malloc'}} \
-  // expected-note{{'malloc' was implicitly declared here with type 'void *}}
+  // expected-note{{'malloc' is a builtin with type 'void *}}
 }
 
 void *alloca(__SIZE_TYPE__); // redeclaration okay
 
-int *calloc(__SIZE_TYPE__, __SIZE_TYPE__); // expected-error{{conflicting types for 'calloc'}} \
-                    // expected-note{{'calloc' was implicitly declared here with type 'void *}}
+int *calloc(__SIZE_TYPE__, __SIZE_TYPE__); // expected-warning{{incompatible redeclaration of library function 'calloc' will be ignored}} \
+                    // expected-note{{'calloc' is a builtin with type 'void *}}
 
 
 void g(int malloc) { // okay: these aren't functions
@@ -16,11 +16,29 @@
 }
 
 void h() {
-  int malloc(int); // expected-error{{conflicting types for 'malloc'}}
-  int strcpy(int); // expected-error{{conflicting types for 'strcpy'}} \
-  // expected-note{{'strcpy' was implicitly declared here with type 'char *(char *, char const *)'}}
+  int malloc(int); // expected-warning{{incompatible redeclaration of library function 'malloc' will be ignored}}
+  int strcpy(int); // expected-warning{{incompatible redeclaration of library function 'strcpy' will be ignored}} \
+  // expected-note{{'strcpy' is a builtin with type 'char *(char *, char const *)'}}
 }
 
 void f2() {
   fprintf(0, "foo"); // expected-error{{implicit declaration of 'fprintf' requires inclusion of the header <stdio.h>}}
 }
+
+// PR2892
+void __builtin_object_size(); // expected-error{{conflicting types}} \
+// expected-note{{'__builtin_object_size' is a builtin with type}}
+
+int a[10];
+
+int f0() {
+  return __builtin_object_size(&a); // expected-error {{too few arguments to function}}
+}
+
+void * realloc(void *p, int size) { // expected-warning{{incompatible redeclaration of library function 'realloc' will be ignored}} \
+// expected-note{{'realloc' is a builtin with type 'void *(void *, unsigned long)'}} \
+// expected-error{{definition of library function 'realloc' in a hosted implementation}} \
+  // expected-note{{use -ffreestanding to compile as a freestanding implementation}}
+  return p;
+}
+
diff --git a/test/Sema/predefined-function.c b/test/Sema/predefined-function.c
index 2a254cc..bce6355 100644
--- a/test/Sema/predefined-function.c
+++ b/test/Sema/predefined-function.c
@@ -11,7 +11,7 @@
 int foo()
 {
     int eli(int (int)); // expected-error {{conflicting types for 'eli'}}
-    eli(b);
+    eli(b); // expected-error{{incompatible type passing}}
 	return 0;	
 }
 
@@ -25,13 +25,11 @@
 	return 0;
 }
 
-#if 0
 int foobar(int); // note {{previous declaration is here}}
 int foobar() // error {{conflicting types for 'foobar'}}
 {
 	return 0;
 }
-#endif
 
 int wibble(); // expected-note {{previous declaration is here}}
 float wibble() // expected-error {{conflicting types for 'wibble'}}
diff --git a/test/Sema/tentative-decls.c b/test/Sema/tentative-decls.c
index 0e4b13a..12ce181 100644
--- a/test/Sema/tentative-decls.c
+++ b/test/Sema/tentative-decls.c
@@ -1,4 +1,4 @@
-// RUN: clang %s -verify -fsyntax-only
+// RUN: clang %s -fsyntax-only -verify
 
 const int a [1] = {1};
 extern const int a[];
@@ -10,12 +10,14 @@
 const int c[];
 
 int i1 = 1; // expected-note {{previous definition is here}}
-int i1 = 2; // expected-error {{redefinition of 'i1'}} // expected-note {{previous definition is here}}
+int i1 = 2; // expected-error {{redefinition of 'i1'}}
 int i1;
 int i1;
 extern int i1; // expected-note {{previous definition is here}}
-static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}} expected-note {{previous definition is here}}
-int i1 = 3; // expected-error{{redefinition of 'i1'}} expected-error{{non-static declaration of 'i1' follows static declaration}}
+static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}}
+
+static int i2 = 5; // expected-note 2 {{previous definition is here}}
+int i2 = 3; // expected-error{{redefinition of 'i2'}} expected-error{{non-static declaration of 'i2' follows static declaration}}
 
 __private_extern__ int pExtern;
 int pExtern = 0;
diff --git a/test/Sema/typedef-redef.c b/test/Sema/typedef-redef.c
index d6962f1..48c4863 100644
--- a/test/Sema/typedef-redef.c
+++ b/test/Sema/typedef-redef.c
@@ -1,4 +1,4 @@
-// RUN: clang < %s -fsyntax-only -verify
+// RUN: clang -fsyntax-only -verify %s
 
 // size_t coming from a system header.
 #include <stddef.h>
@@ -7,7 +7,11 @@
 
 
 typedef const int x; // expected-note {{previous definition is here}}
-extern x a; // expected-note {{previous definition is here}}
+extern x a;
 typedef int x;  // expected-error {{typedef redefinition with different types}}
-extern x a; // expected-error{{redefinition of 'a' with a different type}}
+extern x a;
 
+// <rdar://problem/6097585>
+int y; // expected-note 2 {{previous definition is here}}
+float y; // expected-error{{redefinition of 'y' with a different type}}
+double y; // expected-error{{redefinition of 'y' with a different type}}
diff --git a/test/SemaObjC/class-def-test-1.m b/test/SemaObjC/class-def-test-1.m
index 50493f1..2c625fa 100644
--- a/test/SemaObjC/class-def-test-1.m
+++ b/test/SemaObjC/class-def-test-1.m
@@ -14,10 +14,10 @@
 
 @interface INTF1 : OBJECT @end // expected-error {{duplicate interface definition for class 'INTF1'}}
 
-typedef int OBJECT; // expected-note {{previous definition is here}}  \
-		       expected-error {{redefinition of 'OBJECT' as different kind of symbol}}
+typedef int OBJECT; // expected-error {{redefinition of 'OBJECT' as different kind of symbol}}
 
-@interface INTF2 : OBJECT @end // expected-error {{redefinition of 'OBJECT' as different kind of symbol}}
+typedef int OBJECT2; // expected-note {{previous definition is here}}
+@interface INTF2 : OBJECT2 @end // expected-error {{redefinition of 'OBJECT2' as different kind of symbol}}
 
 
 @protocol PROTO;