aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2011-07-10 03:47:27 +0000
committerChris Lattner <sabre@nondot.org>2011-07-10 03:47:27 +0000
commitf0a8679b6e6635117533b89894646f1450cea25b (patch)
tree0524a1b5ef9d8052c6bc846d6614c8c187fa05c6 /lib/CodeGen
parent12569fb55db2a8181711ac134b7479155db4f838 (diff)
Fix the clang bootstrap and Jay's testcase from llvm-dev by being completely
conservative when converting a functiontype to IR when in a "pointer within a struct" context. This has the unfortunate sideeffect of compiling all function pointers inside of structs into "{}*" which, though correct, is ugly. This has the positive side effect of being correct, and it is pretty straight-forward to improve on this. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134861 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp33
1 files changed, 30 insertions, 3 deletions
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index f304df917b..59c632f0d7 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -104,6 +104,7 @@ bool CodeGenTypes::isFuncTypeArgumentConvertible(QualType Ty){
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;
@@ -158,8 +159,14 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) {
return;
}
+ // If we completed a RecordDecl that we previously used and converted to an
+ // anonymous type, then go ahead and complete it now.
const RecordDecl *RD = cast<RecordDecl>(TD);
- if (!RD->isDependentType())
+ if (RD->isDependentType()) return;
+
+ // Only complete it if we converted it already. If we haven't converted it
+ // yet, we'll just do it lazily.
+ // if (RecordDeclTypes.count(Context.getTagDeclType(RD).getTypePtr()))
ConvertRecordDeclType(RD);
}
@@ -333,13 +340,20 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
// 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 (!isFuncTypeConvertible(cast<FunctionType>(Ty))) {
+ if (RecursionState == RS_StructPointer ||
+ !isFuncTypeConvertible(cast<FunctionType>(Ty))) {
// This function's type depends on an incomplete tag type.
// Return a placeholder type.
ResultType = llvm::StructType::get(getLLVMContext());
break;
}
+ // While we're converting the argument types for a function, we don't want
+ // to recursively convert any pointed-to structs. Converting directly-used
+ // structs is ok though.
+ RecursionStateTy SavedRecursionState = RecursionState;
+ RecursionState = RS_Struct;
+
// The function type can be built; call the appropriate routines to
// build it.
const CGFunctionInfo *FI;
@@ -354,8 +368,15 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT, 0)));
isVariadic = true;
}
-
+
ResultType = GetFunctionType(*FI, isVariadic);
+
+ // Restore our recursion state.
+ RecursionState = SavedRecursionState;
+
+ if (RecursionState == RS_Normal)
+ while (!DeferredRecords.empty())
+ ConvertRecordDeclType(DeferredRecords.pop_back_val());
break;
}
@@ -463,10 +484,16 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) {
CGRecordLayout *Layout = ComputeRecordLayout(RD, Ty);
CGRecordLayouts[Key] = Layout;
+ // If this struct blocked a FunctionType conversion, then recompute whatever
+ // was derived from that.
+ // FIXME: This is hugely overconservative.
+ TypeCache.clear();
+
// Restore our recursion state. If we're done converting the outer-most
// record, then convert any deferred structs as well.
RecursionState = SavedRecursionState;
+
if (RecursionState == RS_Normal)
while (!DeferredRecords.empty())
ConvertRecordDeclType(DeferredRecords.pop_back_val());