Add hook to add attributes to function declarations that we know
about, whether they are builtins or not. Use this to add the
appropriate "format" attribute to NSLog, NSLogv, asprintf, and
vasprintf, and to translate builtin attributes (from Builtins.def)
into actual attributes on the function declaration.

Use the "printf" format attribute on function declarations to
determine whether we should do format string checking, rather than
looking at an ad hoc list of builtins and "known" function names.

Be a bit more careful about when we consider a function a "builtin" in
C++.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64561 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 13b40e8..ca1fa0c 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -259,15 +259,33 @@
 /// will be 0 for functions that do not correspond to a builtin, a
 /// value of type \c Builtin::ID if in the target-independent range 
 /// \c [1,Builtin::First), or a target-specific builtin value.
-unsigned FunctionDecl::getBuiltinID() const {
-  if (getIdentifier() && 
-      (getDeclContext()->isTranslationUnit() ||
-       (isa<LinkageSpecDecl>(getDeclContext()) &&
-        cast<LinkageSpecDecl>(getDeclContext())->getLanguage() 
-          == LinkageSpecDecl::lang_c)))
-    return getIdentifier()->getBuiltinID();
-    
-  // Not a builtin.
+unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const {
+  if (!getIdentifier() || !getIdentifier()->getBuiltinID())
+    return 0;
+
+  unsigned BuiltinID = getIdentifier()->getBuiltinID();
+  if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
+    return BuiltinID;
+
+  // This function has the name of a known C library
+  // function. Determine whether it actually refers to the C library
+  // function or whether it just has the same name.
+
+  // If this function is at translation-unit scope and we're not in
+  // C++, it refers to the C library function.
+  if (!Context.getLangOptions().CPlusPlus &&
+      getDeclContext()->isTranslationUnit())
+    return BuiltinID;
+
+  // If the function is in an extern "C" linkage specification and is
+  // not marked "overloadable", it's the real function.
+  if (isa<LinkageSpecDecl>(getDeclContext()) &&
+      cast<LinkageSpecDecl>(getDeclContext())->getLanguage() 
+        == LinkageSpecDecl::lang_c &&
+      !getAttr<OverloadableAttr>())
+    return BuiltinID;
+
+  // Not a builtin
   return 0;
 }
 
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 7063b76..7a04ffc 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -173,7 +173,7 @@
 
 /// isBuiltinCall - If this is a call to a builtin, return the builtin ID.  If
 /// not, return 0.
-unsigned CallExpr::isBuiltinCall() const {
+unsigned CallExpr::isBuiltinCall(ASTContext &Context) const {
   // All simple function calls (e.g. func()) are implicitly cast to pointer to
   // function. As a result, we try and obtain the DeclRefExpr from the 
   // ImplicitCastExpr.
@@ -192,7 +192,7 @@
   if (!FDecl->getIdentifier())
     return 0;
 
-  return FDecl->getBuiltinID();
+  return FDecl->getBuiltinID(Context);
 }
 
 
@@ -922,7 +922,7 @@
     
     // If this is a call to a builtin function, constant fold it otherwise
     // reject it.
-    if (CE->isBuiltinCall()) {
+    if (CE->isBuiltinCall(Ctx)) {
       EvalResult EvalResult;
       if (CE->Evaluate(EvalResult, Ctx)) {
         assert(!EvalResult.HasSideEffects && 
@@ -1205,7 +1205,7 @@
     // expression, and it is fully evaluated.  This is an important GNU
     // extension.  See GCC PR38377 for discussion.
     if (const CallExpr *CallCE = dyn_cast<CallExpr>(Cond->IgnoreParenCasts()))
-      if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) {
+      if (CallCE->isBuiltinCall(Ctx) == Builtin::BI__builtin_constant_p) {
         EvalResult EVResult;
         if (!Evaluate(EVResult, Ctx) || EVResult.HasSideEffects)
           return false;
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index c7cc854..3a3b152 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -350,7 +350,8 @@
 }  
 
 APValue PointerExprEvaluator::VisitCallExpr(CallExpr *E) {
-  if (E->isBuiltinCall() == Builtin::BI__builtin___CFStringMakeConstantString)
+  if (E->isBuiltinCall(Info.Ctx) == 
+        Builtin::BI__builtin___CFStringMakeConstantString)
     return APValue(E, 0);
   return APValue();
 }
@@ -646,7 +647,7 @@
 bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
   Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
   
-  switch (E->isBuiltinCall()) {
+  switch (E->isBuiltinCall(Info.Ctx)) {
   default:
     return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
   case Builtin::BI__builtin_classify_type:
@@ -1173,7 +1174,7 @@
 }
 
 bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
-  switch (E->isBuiltinCall()) {
+  switch (E->isBuiltinCall(Info.Ctx)) {
   default: return false;
   case Builtin::BI__builtin_huge_val:
   case Builtin::BI__builtin_huge_valf: