Provide a custom diagnostic when code tries to use an unknown builtin

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83014 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 44b582d..1d4e003 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -148,6 +148,7 @@
 def err_builtin_definition : Error<"definition of builtin function %0">;
 def err_types_compatible_p_in_cplusplus : Error<
   "__builtin_types_compatible_p is not valid in C++">;
+def warn_builtin_unknown : Warning<"use of unknown builtin %0">, DefaultError;
 
 /// main()
 // static/inline main() are not errors in C, just in C++.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 7f3f24e..5df4dca 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -32,6 +32,7 @@
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include <algorithm>
+#include <cstring>
 #include <functional>
 #include <queue>
 using namespace clang;
@@ -3925,15 +3926,15 @@
   }
 
   // Extension in C99.  Legal in C90, but warn about it.
-  if (getLangOptions().C99)
+  static const unsigned int BuiltinLen = strlen("__builtin_");
+  if (II.getLength() > BuiltinLen &&
+      std::equal(II.getName(), II.getName() + BuiltinLen, "__builtin_"))
+    Diag(Loc, diag::warn_builtin_unknown) << &II;
+  else if (getLangOptions().C99)
     Diag(Loc, diag::ext_implicit_function_decl) << &II;
   else
     Diag(Loc, diag::warn_implicit_function_decl) << &II;
 
-  // FIXME: handle stuff like:
-  // void foo() { extern float X(); }
-  // void bar() { X(); }  <-- implicit decl for X in another scope.
-
   // Set a Declarator for the implicit definition: int foo();
   const char *Dummy;
   DeclSpec DS;
diff --git a/test/Sema/builtins.c b/test/Sema/builtins.c
index 912a6b3..e133d62 100644
--- a/test/Sema/builtins.c
+++ b/test/Sema/builtins.c
@@ -67,3 +67,7 @@
 void test12(void) {
   __builtin_trap();  // no warning because trap is noreturn.
 }
+
+void test_unknown_builtin(int a, int b) {
+  __builtin_foo(a, b); // expected-error{{use of unknown builtin}}
+}