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;
+}
+