aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGCall.cpp23
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp27
-rw-r--r--lib/CodeGen/CodeGenTypes.h6
-rw-r--r--test/CodeGen/decl.c15
4 files changed, 56 insertions, 15 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 29104424ac..c0c2a47207 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -251,18 +251,27 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
// If this is being called from the guts of the ConvertType loop, make sure
// to call ConvertTypeRecursive so we don't get into issues with cyclic
// pointer type structures.
- const llvm::Type *ArgType;
- if (IsRecursive)
- ArgType = ConvertTypeRecursive(*I);
- else
- ArgType = ConvertType(*I);
- PreferredArgTypes.push_back(ArgType);
+ PreferredArgTypes.push_back(ConvertTypeRecursive(*I));
}
-
+
// Compute ABI information.
getABIInfo().computeInfo(*FI, getContext(), TheModule.getContext(),
PreferredArgTypes.data(), PreferredArgTypes.size());
+ // If this is a top-level call and ConvertTypeRecursive hit unresolved pointer
+ // types, resolve them now. These pointers may point to this function, which
+ // we *just* filled in the FunctionInfo for.
+ if (!IsRecursive && !PointersToResolve.empty()) {
+ // Use PATypeHolder's so that our preferred types don't dangle under
+ // refinement.
+ llvm::SmallVector<llvm::PATypeHolder, 8> Handles(PreferredArgTypes.begin(),
+ PreferredArgTypes.end());
+ HandleLateResolvedPointers();
+ PreferredArgTypes.clear();
+ PreferredArgTypes.append(Handles.begin(), Handles.end());
+ }
+
+
return *FI;
}
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 7876e5aefc..d469b906fc 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -42,14 +42,11 @@ CodeGenTypes::~CodeGenTypes() {
delete &*I++;
}
-/// ConvertType - Convert the specified type to its LLVM form.
-const llvm::Type *CodeGenTypes::ConvertType(QualType T, bool IsRecursive) {
- const llvm::Type *RawResult = ConvertTypeRecursive(T);
-
- if (IsRecursive || PointersToResolve.empty())
- return RawResult;
-
- llvm::PATypeHolder Result = RawResult;
+/// HandleLateResolvedPointers - For top-level ConvertType calls, this handles
+/// pointers that are referenced but have not been converted yet. This is used
+/// to handle cyclic structures properly.
+void CodeGenTypes::HandleLateResolvedPointers() {
+ assert(!PointersToResolve.empty() && "No pointers to resolve!");
// Any pointers that were converted deferred evaluation of their pointee type,
// creating an opaque type instead. This is in order to avoid problems with
@@ -64,7 +61,21 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T, bool IsRecursive) {
const llvm::Type *NT = ConvertTypeForMemRecursive(P.first);
P.second->refineAbstractTypeTo(NT);
}
+}
+
+/// ConvertType - Convert the specified type to its LLVM form.
+const llvm::Type *CodeGenTypes::ConvertType(QualType T, bool IsRecursive) {
+ const llvm::Type *Result = ConvertTypeRecursive(T);
+
+ // If this is a top-level call to ConvertType and sub-conversions caused
+ // pointers to get lazily built as opaque types, resolve the pointers, which
+ // might cause Result to be merged away.
+ if (!IsRecursive && !PointersToResolve.empty()) {
+ llvm::PATypeHolder ResultHandle = Result;
+ HandleLateResolvedPointers();
+ Result = ResultHandle;
+ }
return Result;
}
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index bf55fc5369..c7f48e6c9d 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -94,6 +94,12 @@ private:
/// is available only for ConvertType(). CovertType() is preferred
/// interface to convert type T into a llvm::Type.
const llvm::Type *ConvertNewType(QualType T);
+
+ /// HandleLateResolvedPointers - For top-level ConvertType calls, this handles
+ /// pointers that are referenced but have not been converted yet. This is
+ /// used to handle cyclic structures properly.
+ void HandleLateResolvedPointers();
+
public:
CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD,
const ABIInfo &Info);
diff --git a/test/CodeGen/decl.c b/test/CodeGen/decl.c
index dcf120fd88..7a9971ee18 100644
--- a/test/CodeGen/decl.c
+++ b/test/CodeGen/decl.c
@@ -102,3 +102,18 @@ void init_error(void) {
global_dc->x = cp_diagnostic_starter;
}
+
+
+// rdar://8147692 - ABI crash in recursive struct-through-function-pointer.
+typedef struct {
+ int x5a;
+} x5;
+
+typedef struct x2 *x0;
+typedef long (*x1)(x0 x0a, x5 x6);
+struct x2 {
+ x1 x4;
+};
+long x3(x0 x0a, x5 a) {
+ return x0a->x4(x0a, a);
+}