Make it possible for builtins to expression FILE* arguments, so that
we can define builtins such as fprintf, vfprintf, and
__builtin___fprintf_chk. Give a nice error message when we need to
implicitly declare a function like fprintf.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64526 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index e7ec137..e345898 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -87,6 +87,7 @@
 /// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
 /// pointer over the consumed characters.  This returns the resultant type.
 static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, 
+                                  Builtin::Context::GetBuiltinTypeError &Error,
                                   bool AllowTypeModifiers = true) {
   // Modifiers.
   bool Long = false, LongLong = false, Signed = false, Unsigned = false;
@@ -202,10 +203,23 @@
     
     Str = End;
     
-    QualType ElementType = DecodeTypeFromStr(Str, Context, false);
+    QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false);
     Type = Context.getVectorType(ElementType, NumElements);
     break;
   }
+  case 'P': {
+    IdentifierInfo *II = &Context.Idents.get("FILE");
+    DeclContext::lookup_result Lookup 
+      = Context.getTranslationUnitDecl()->lookup(II);
+    if (Lookup.first != Lookup.second && isa<TypeDecl>(*Lookup.first)) {
+      Type = Context.getTypeDeclType(cast<TypeDecl>(*Lookup.first));
+      break;
+    }
+    else {
+      Error = Builtin::Context::GE_Missing_FILE;
+      return QualType();
+    }
+  }
   }
   
   if (!AllowTypeModifiers)
@@ -231,16 +245,21 @@
 }
 
 /// GetBuiltinType - Return the type for the specified builtin.
-QualType Builtin::Context::GetBuiltinType(unsigned id,
-                                          ASTContext &Context) const {
+QualType Builtin::Context::GetBuiltinType(unsigned id, ASTContext &Context,
+                                          GetBuiltinTypeError &Error) const {
   const char *TypeStr = GetRecord(id).Type;
   
   llvm::SmallVector<QualType, 8> ArgTypes;
   
-  QualType ResType = DecodeTypeFromStr(TypeStr, Context);
+  Error = GE_None;
+  QualType ResType = DecodeTypeFromStr(TypeStr, Context, Error);
+  if (Error != GE_None)
+    return QualType();
   while (TypeStr[0] && TypeStr[0] != '.') {
-    QualType Ty = DecodeTypeFromStr(TypeStr, Context);
-    
+    QualType Ty = DecodeTypeFromStr(TypeStr, Context, Error);
+    if (Error != GE_None)
+      return QualType();
+
     // Do array -> pointer decay.  The builtin should use the decayed type.
     if (Ty->isArrayType())
       Ty = Context.getArrayDecayedType(Ty);