diff options
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 40 | ||||
-rw-r--r-- | test/Modules/Inputs/redecl-merge-bottom.h | 3 | ||||
-rw-r--r-- | test/Modules/Inputs/redecl-merge-left.h | 17 | ||||
-rw-r--r-- | test/Modules/Inputs/redecl-merge-right.h | 12 | ||||
-rw-r--r-- | test/Modules/Inputs/redecl-merge-top.h | 4 | ||||
-rw-r--r-- | test/Modules/redecl-merge.m | 23 |
6 files changed, 97 insertions, 2 deletions
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 82f6fae4a0..4871a3049a 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -182,6 +182,10 @@ namespace clang { ~FindExistingResult(); + /// \brief Suppress the addition of this result into the known set of + /// names. + void suppress() { AddResult = false; } + operator NamedDecl*() const { return Existing; } template<typename T> @@ -412,20 +416,27 @@ void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { } void ASTDeclReader::VisitTagDecl(TagDecl *TD) { - VisitRedeclarable(TD); + // Record the declaration -> global ID mapping. + Reader.DeclToID[TD] = ThisDeclID; + + RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); + TD->IdentifierNamespace = Record[Idx++]; TD->setTagKind((TagDecl::TagKind)Record[Idx++]); TD->setCompleteDefinition(Record[Idx++]); TD->setEmbeddedInDeclarator(Record[Idx++]); TD->setFreeStanding(Record[Idx++]); TD->setRBraceLoc(ReadSourceLocation(Record, Idx)); + if (Record[Idx++]) { // hasExtInfo TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); TD->TypedefNameDeclOrQualifier = Info; } else TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx)); + + mergeRedeclarable(TD, Redecl); } void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { @@ -1547,6 +1558,14 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID()) == Merged.end()) Merged.push_back(Redecl.getFirstID()); + + // If ExistingCanon did not come from a module file, introduce the + // first declaration that *does* come from a module file is in the + // set of pending declaration chains, so that we merge this + // declaration. + if (!ExistingCanon->isFromASTFile() && + Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID())) + Reader.PendingDeclChains.push_back(Merged[0]); } } } @@ -1662,6 +1681,15 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X)) return true; + // Compatible tags match. + if (TagDecl *TagX = dyn_cast<TagDecl>(X)) { + TagDecl *TagY = cast<TagDecl>(Y); + if ((TagX->getTagKind() == TagY->getTagKind()) || + ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class)&& + (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class))) + return true; + } + // FIXME: Many other cases to implement. return false; } @@ -1679,13 +1707,21 @@ ASTDeclReader::FindExistingResult::~FindExistingResult() { } ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { + DeclarationName Name = D->getDeclName(); + if (!Name) { + // Don't bother trying to find unnamed declarations. + FindExistingResult Result(Reader, D, /*Existing=*/0); + Result.suppress(); + return Result; + } + DeclContext *DC = D->getDeclContext()->getRedeclContext(); if (!DC->isFileContext()) return FindExistingResult(Reader); if (DC->isTranslationUnit() && Reader.SemaObj) { IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver; - for (IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()), + for (IdentifierResolver::iterator I = IdResolver.begin(Name), IEnd = IdResolver.end(); I != IEnd; ++I) { if (isSameEntity(*I, D)) diff --git a/test/Modules/Inputs/redecl-merge-bottom.h b/test/Modules/Inputs/redecl-merge-bottom.h index a054cd2059..4e52a67247 100644 --- a/test/Modules/Inputs/redecl-merge-bottom.h +++ b/test/Modules/Inputs/redecl-merge-bottom.h @@ -13,6 +13,9 @@ @protocol P1; +struct S1; +struct S3; + void refers_to_C4(C4*); #ifdef __cplusplus diff --git a/test/Modules/Inputs/redecl-merge-left.h b/test/Modules/Inputs/redecl-merge-left.h index 82146f7ed5..b21271b146 100644 --- a/test/Modules/Inputs/redecl-merge-left.h +++ b/test/Modules/Inputs/redecl-merge-left.h @@ -15,6 +15,14 @@ - (void)protoMethod2; @end +struct S1; +struct S2 { + int field; +}; + +struct S1 *produce_S1(void); +void consume_S2(struct S2*); + // Test declarations in different modules with no common initial // declaration. @class C; @@ -39,6 +47,15 @@ struct explicit_struct; @protocol P3; +struct S3; +struct S3; +struct S4 { + int field; +}; + +struct S3 *produce_S3(void); +void consume_S4(struct S4*); + #ifdef __cplusplus template<typename T> class Vector; diff --git a/test/Modules/Inputs/redecl-merge-right.h b/test/Modules/Inputs/redecl-merge-right.h index b6dfe2f53c..686a96228a 100644 --- a/test/Modules/Inputs/redecl-merge-right.h +++ b/test/Modules/Inputs/redecl-merge-right.h @@ -21,6 +21,12 @@ @protocol P2; +struct S1; +struct S2; + +void consume_S1(struct S1*); +struct S2 *produce_S2(void); + // Test declarations in different modules with no common initial // declaration. @class C; @@ -47,6 +53,12 @@ struct explicit_struct; @protocol P3; @protocol P3; +struct S3; +struct S4; + +void consume_S3(struct S3*); +struct S4 *produce_S4(void); + #ifdef __cplusplus template<typename T> class Vector { public: diff --git a/test/Modules/Inputs/redecl-merge-top.h b/test/Modules/Inputs/redecl-merge-top.h index 64c0c92546..519254ca22 100644 --- a/test/Modules/Inputs/redecl-merge-top.h +++ b/test/Modules/Inputs/redecl-merge-top.h @@ -11,6 +11,10 @@ @protocol P2; @protocol P2; +struct S1; +struct S2; +struct S2; + #ifdef __cplusplus template<typename T> class Vector; #endif diff --git a/test/Modules/redecl-merge.m b/test/Modules/redecl-merge.m index dfbc25fe9e..c0e83e8a86 100644 --- a/test/Modules/redecl-merge.m +++ b/test/Modules/redecl-merge.m @@ -32,6 +32,29 @@ void testProtoMerge(id<P1> p1, id<P2> p2) { [p2 protoMethod2]; } +struct S1 { + int s1_field; +}; + +struct S3 { + int s3_field; +}; + +void testTagMerge() { + consume_S1(produce_S1()); + struct S2 s2; + s2.field = 0; + consume_S2(produce_S2()); + struct S1 s1; + s1.s1_field = 0; + consume_S3(produce_S3()); + struct S4 s4; + s4.field = 0; + consume_S4(produce_S4()); + struct S3 s3; + s3.s3_field = 0; +} + // Test redeclarations of entities in explicit submodules, to make // sure we're maintaining the declaration chains even when normal name // lookup can't see what we're looking for. |