Rename CGT::VerifyFuncTypeComplete to isFuncTypeConvertible since
it is a predicate, not an action.  Change the return type to be a bool,
not the incomplete member.  Enhace it to detect the recursive compilation
case, allowing us to compile Eli's testcase on llvmdev:

struct T {
 struct T (*p)(void);
} t;

into:

%struct.T = type { {}* }

@t = common global %struct.T zeroinitializer, align 8




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134853 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index a6f242f..7387fa7 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -704,16 +704,15 @@
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
   const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
 
-  if (!VerifyFuncTypeComplete(FPT)) {
-    const CGFunctionInfo *Info;
-    if (isa<CXXDestructorDecl>(MD))
-      Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
-    else
-      Info = &getFunctionInfo(MD);
-    return GetFunctionType(*Info, FPT->isVariadic());
-  }
-
-  return llvm::StructType::get(getLLVMContext());
+  if (!isFuncTypeConvertible(FPT))
+    return llvm::StructType::get(getLLVMContext());
+    
+  const CGFunctionInfo *Info;
+  if (isa<CXXDestructorDecl>(MD))
+    Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
+  else
+    Info = &getFunctionInfo(MD);
+  return GetFunctionType(*Info, FPT->isVariadic());
 }
 
 void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index e439b5f..c161b79 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -2937,7 +2937,8 @@
 
   // We can't emit thunks for member functions with incomplete types.
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
-  if (CGM.getTypes().VerifyFuncTypeComplete(MD->getType().getTypePtr()))
+  if (!CGM.getTypes().isFuncTypeConvertible(
+                                cast<FunctionType>(MD->getType().getTypePtr())))
     return;
 
   EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true);
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 9375410..ed44aec 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -93,19 +93,55 @@
 
 }
 
-// Code to verify a given function type is complete, i.e. the return type
-// and all of the argument types are complete.
-const TagType *CodeGenTypes::VerifyFuncTypeComplete(const Type* T) {
-  const FunctionType *FT = cast<FunctionType>(T);
-  if (const TagType* TT = FT->getResultType()->getAs<TagType>())
-    if (!TT->getDecl()->isDefinition())
-      return TT;
-  if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(T))
+/// isFuncTypeArgumentConvertible - Return true if the specified type in a 
+/// function argument or result position can be converted to an IR type at this
+/// point.  This boils down to being whether it is complete, as well as whether
+/// we've temporarily deferred expanding the type because we're in a recursive
+/// context.
+bool CodeGenTypes::isFuncTypeArgumentConvertible(QualType Ty){
+  // If this isn't a tagged type, we can convert it!
+  const TagType *TT = Ty->getAs<TagType>();
+  if (TT == 0) return true;
+  
+  // If it's a tagged type, but is a forward decl, we can't convert it.
+  if (!TT->getDecl()->isDefinition())
+    return false;
+  
+  // If we're not under a pointer under a struct, then we can convert it if
+  // needed.
+  if (RecursionState != RS_StructPointer)
+    return true;
+
+  // If this is an enum, then it is safe to convert.
+  const RecordType *RT = dyn_cast<RecordType>(TT);
+  if (RT == 0) return true;
+
+  // Otherwise, we have to be careful.  If it is a struct that we're in the
+  // process of expanding, then we can't convert the function type.  That's ok
+  // though because we must be in a pointer context under the struct, so we can
+  // just convert it to a dummy type.
+  //
+  // We decide this by checking whether ConvertRecordDeclType returns us an
+  // opaque type for a struct that we know is defined.
+  return !ConvertRecordDeclType(RT->getDecl())->isOpaque();
+}
+
+
+/// Code to verify a given function type is complete, i.e. the return type
+/// and all of the argument types are complete.  Also check to see if we are in
+/// a RS_StructPointer context, and if so whether any struct types have been
+/// pended.  If so, we don't want to ask the ABI lowering code to handle a type
+/// that cannot be converted to an IR type.
+bool CodeGenTypes::isFuncTypeConvertible(const FunctionType *FT) {
+  if (!isFuncTypeArgumentConvertible(FT->getResultType()))
+    return false;
+  
+  if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT))
     for (unsigned i = 0, e = FPT->getNumArgs(); i != e; i++)
-      if (const TagType *TT = FPT->getArgType(i)->getAs<TagType>())
-        if (!TT->getDecl()->isDefinition())
-          return TT;
-  return 0;
+      if (!isFuncTypeArgumentConvertible(FPT->getArgType(i)))
+        return false;
+
+  return true;
 }
 
 /// UpdateCompletedType - When we find the full definition for a TagDecl,
@@ -296,7 +332,7 @@
     // First, check whether we can build the full function type.  If the
     // function type depends on an incomplete type (e.g. a struct or enum), we
     // cannot lower the function type.
-    if (VerifyFuncTypeComplete(Ty)) {
+    if (!isFuncTypeConvertible(cast<FunctionType>(Ty))) {
       // This function's type depends on an incomplete tag type.
       // Return a placeholder type.
       ResultType = llvm::StructType::get(getLLVMContext());
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 755f87b..9878600 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -137,11 +137,12 @@
 
   llvm::FunctionType *GetFunctionType(GlobalDecl GD);
 
-  /// VerifyFuncTypeComplete - Utility to check whether a function type can
+  /// isFuncTypeConvertible - Utility to check whether a function type can
   /// be converted to an LLVM type (i.e. doesn't depend on an incomplete tag
   /// type).
-  static const TagType *VerifyFuncTypeComplete(const Type* T);
-
+  bool isFuncTypeConvertible(const FunctionType *FT);
+  bool isFuncTypeArgumentConvertible(QualType Ty);
+  
   /// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable,
   /// given a CXXMethodDecl. If the method to has an incomplete return type,
   /// and/or incomplete argument types, this will return the opaque type.
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index e6720c4..1192f32 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -537,7 +537,7 @@
     const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
     const llvm::Type *Ty;
     // Check whether the function has a computable LLVM signature.
-    if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
+    if (Types.isFuncTypeConvertible(FPT)) {
       // The function has a computable LLVM signature; use the correct type.
       Ty = Types.GetFunctionType(Types.getFunctionInfo(MD),
                                  FPT->isVariadic());