Handle AST merges of incomplete class types.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95941 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index a7a7653..5993e9a 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -789,6 +789,7 @@
IDNS |= Decl::IDNS_Ordinary;
// We may already have a record of the same name; try to find and match it.
+ RecordDecl *AdoptDecl = 0;
if (!DC->isFunctionOrMethod() && SearchName) {
llvm::SmallVector<NamedDecl *, 4> ConflictingDecls;
for (DeclContext::lookup_result Lookup = DC->lookup(Name);
@@ -804,15 +805,21 @@
}
if (RecordDecl *FoundRecord = dyn_cast<RecordDecl>(Found)) {
- RecordDecl *FoundDef = FoundRecord->getDefinition();
- // FIXME: If we found something but there is no definition,
- // assume the types are the same and fill in the gaps.
- if (FoundDef && IsStructuralMatch(D, FoundDef)) {
- // The record types structurally match.
- // FIXME: For C++, we should also merge methods here.
- Importer.getImportedDecls()[D] = FoundDef;
- return FoundDef;
- }
+ if (RecordDecl *FoundDef = FoundRecord->getDefinition()) {
+ if (!D->isDefinition() || IsStructuralMatch(D, FoundDef)) {
+ // The record types structurally match, or the "from" translation
+ // unit only had a forward declaration anyway; call it the same
+ // function.
+ // FIXME: For C++, we should also merge methods here.
+ Importer.getImportedDecls()[D] = FoundDef;
+ return FoundDef;
+ }
+ } else {
+ // We have a forward declaration of this type, so adopt that forward
+ // declaration rather than building a new one.
+ AdoptDecl = FoundRecord;
+ continue;
+ }
}
ConflictingDecls.push_back(*Lookup.first);
@@ -826,47 +833,50 @@
}
// Create the record declaration.
- RecordDecl *ToRecord = 0;
- if (CXXRecordDecl *FromCXX = dyn_cast<CXXRecordDecl>(D)) {
- CXXRecordDecl *ToCXX = CXXRecordDecl::Create(Importer.getToContext(),
- D->getTagKind(),
- DC, Loc,
- Name.getAsIdentifierInfo(),
+ RecordDecl *ToRecord = AdoptDecl;
+ if (!ToRecord) {
+ if (CXXRecordDecl *FromCXX = dyn_cast<CXXRecordDecl>(D)) {
+ CXXRecordDecl *ToCXX = CXXRecordDecl::Create(Importer.getToContext(),
+ D->getTagKind(),
+ DC, Loc,
+ Name.getAsIdentifierInfo(),
Importer.Import(D->getTagKeywordLoc()));
- ToRecord = ToCXX;
-
- if (D->isDefinition()) {
- // Add base classes.
- llvm::SmallVector<CXXBaseSpecifier *, 4> Bases;
- for (CXXRecordDecl::base_class_iterator FromBase = FromCXX->bases_begin(),
- FromBaseEnd = FromCXX->bases_end();
- FromBase != FromBaseEnd;
- ++FromBase) {
- QualType T = Importer.Import(FromBase->getType());
- if (T.isNull())
- return 0;
-
- Bases.push_back(
- new (Importer.getToContext())
+ ToRecord = ToCXX;
+
+ if (D->isDefinition()) {
+ // Add base classes.
+ llvm::SmallVector<CXXBaseSpecifier *, 4> Bases;
+ for (CXXRecordDecl::base_class_iterator
+ FromBase = FromCXX->bases_begin(),
+ FromBaseEnd = FromCXX->bases_end();
+ FromBase != FromBaseEnd;
+ ++FromBase) {
+ QualType T = Importer.Import(FromBase->getType());
+ if (T.isNull())
+ return 0;
+
+ Bases.push_back(
+ new (Importer.getToContext())
CXXBaseSpecifier(Importer.Import(FromBase->getSourceRange()),
FromBase->isVirtual(),
FromBase->isBaseOfClass(),
FromBase->getAccessSpecifierAsWritten(),
T));
+ }
+ if (!Bases.empty())
+ ToCXX->setBases(Bases.data(), Bases.size());
}
- if (!Bases.empty())
- ToCXX->setBases(Bases.data(), Bases.size());
+ } else {
+ ToRecord = RecordDecl::Create(Importer.getToContext(), D->getTagKind(),
+ DC, Loc,
+ Name.getAsIdentifierInfo(),
+ Importer.Import(D->getTagKeywordLoc()));
}
- } else {
- ToRecord = RecordDecl::Create(Importer.getToContext(), D->getTagKind(),
- DC, Loc,
- Name.getAsIdentifierInfo(),
- Importer.Import(D->getTagKeywordLoc()));
+ ToRecord->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDecl(ToRecord);
}
- ToRecord->setLexicalDeclContext(LexicalDC);
Importer.getImportedDecls()[D] = ToRecord;
- LexicalDC->addDecl(ToRecord);
-
+
if (D->isDefinition()) {
ToRecord->startDefinition();
for (DeclContext::decl_iterator FromMem = D->decls_begin(),
diff --git a/test/ASTMerge/Inputs/struct1.c b/test/ASTMerge/Inputs/struct1.c
index 5743fe0..ff8fa0a 100644
--- a/test/ASTMerge/Inputs/struct1.c
+++ b/test/ASTMerge/Inputs/struct1.c
@@ -34,3 +34,13 @@
// Bit-field mismatch
struct S7 { int i : 8; unsigned j : 8; } x7;
+
+// Incomplete type
+struct S8 *x8;
+
+// Incomplete type
+struct S9 { int i; float f; } *x9;
+
+// Incomplete type
+struct S10 *x10;
+
diff --git a/test/ASTMerge/Inputs/struct2.c b/test/ASTMerge/Inputs/struct2.c
index a707ed2..d865eef 100644
--- a/test/ASTMerge/Inputs/struct2.c
+++ b/test/ASTMerge/Inputs/struct2.c
@@ -31,3 +31,12 @@
// Bit-field mismatch
struct S7 { int i : 8; unsigned j : 16; } x7;
+
+// Incomplete type
+struct S8 { int i; float f; } *x8;
+
+// Incomplete type
+struct S9 *x9;
+
+// Incomplete type
+struct S10 *x10;