Handle AST merges of incomplete class types.

llvm-svn: 95941
This commit is contained in:
Douglas Gregor 2010-02-12 00:09:27 +00:00
parent 90073804fb
commit 2579105c4e
3 changed files with 69 additions and 40 deletions

View File

@ -789,6 +789,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
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 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
}
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 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
}
// 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(),

View File

@ -34,3 +34,13 @@ struct S6 { int i : 8; unsigned j : 8; } x6;
// 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;

View File

@ -31,3 +31,12 @@ struct S6 { int i : 8; unsigned j; } x6;
// 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;