diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-02-06 02:42:59 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-02-06 02:42:59 +0000 |
commit | 5a4737cd6aac5c99248de6ee6865f057b7618494 (patch) | |
tree | 4578974f1165f4416d19d72769013ad6f6122d51 /clang/lib/Serialization/ASTReaderDecl.cpp | |
parent | 9bdea541cab4e540dc9c8d88edcb9c23f75d9595 (diff) | |
download | bcm5719-llvm-5a4737cd6aac5c99248de6ee6865f057b7618494.tar.gz bcm5719-llvm-5a4737cd6aac5c99248de6ee6865f057b7618494.zip |
[modules] If a module declares an entity and then imports another declaration
of that entity, ensure that the redeclaration chain is reordered properly on
reload. Otherwise, the result of name lookup for that entity may point to an
entity that is too old; if that's an injected friend name or the like, that
can result in the name not being found at all.
llvm-svn: 228371
Diffstat (limited to 'clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 56506073af2..970ec84e042 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -124,6 +124,7 @@ namespace clang { class RedeclarableResult { ASTReader &Reader; GlobalDeclID FirstID; + Decl *MergeWith; mutable bool Owning; Decl::Kind DeclKind; @@ -131,13 +132,14 @@ namespace clang { public: RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID, - Decl::Kind DeclKind) - : Reader(Reader), FirstID(FirstID), Owning(true), DeclKind(DeclKind) { } + Decl *MergeWith, Decl::Kind DeclKind) + : Reader(Reader), FirstID(FirstID), MergeWith(MergeWith), + Owning(true), DeclKind(DeclKind) {} RedeclarableResult(const RedeclarableResult &Other) - : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) , - DeclKind(Other.DeclKind) - { + : Reader(Other.Reader), FirstID(Other.FirstID), + MergeWith(Other.MergeWith), Owning(Other.Owning), + DeclKind(Other.DeclKind) { Other.Owning = false; } @@ -149,7 +151,11 @@ namespace clang { /// \brief Retrieve the first ID. GlobalDeclID getFirstID() const { return FirstID; } - + + /// \brief Get a known declaration that this should be merged with, if + /// any. + Decl *getKnownMergeTarget() const { return MergeWith; } + /// \brief Do not introduce this declaration ID into the set of pending /// declaration chains. void suppress() { @@ -2077,15 +2083,23 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) { } template <typename T> -ASTDeclReader::RedeclarableResult +ASTDeclReader::RedeclarableResult ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { DeclID FirstDeclID = ReadDeclID(Record, Idx); - + Decl *MergeWith = nullptr; + // 0 indicates that this declaration was the only declaration of its entity, // and is used for space optimization. if (FirstDeclID == 0) FirstDeclID = ThisDeclID; - + else if (Record[Idx++]) { + // We need to merge with FirstDeclID. Read it now to ensure that it is + // before us in the redecl chain, then forget we saw it so that we will + // merge with it. + MergeWith = Reader.GetDecl(FirstDeclID); + FirstDeclID = ThisDeclID; + } + T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID)); if (FirstDecl != D) { // We delay loading of the redeclaration chain to avoid deeply nested calls. @@ -2100,7 +2114,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { // The result structure takes care to note that we need to load the // other declaration chains for this ID. - return RedeclarableResult(Reader, FirstDeclID, + return RedeclarableResult(Reader, FirstDeclID, MergeWith, static_cast<T *>(D)->getKind()); } @@ -2127,7 +2141,10 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, if (!Reader.getContext().getLangOpts().Modules) return; - if (FindExistingResult ExistingRes = findExisting(D)) + if (auto *Existing = Redecl.getKnownMergeTarget()) + // We already know of an existing declaration we should merge with. + mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID); + else if (FindExistingResult ExistingRes = findExisting(D)) if (T *Existing = ExistingRes) mergeRedeclarable(D, Existing, Redecl, TemplatePatternID); } @@ -2148,7 +2165,7 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, auto *DPattern = D->getTemplatedDecl(); auto *ExistingPattern = Existing->getTemplatedDecl(); RedeclarableResult Result(Reader, DPattern->getCanonicalDecl()->getGlobalID(), - DPattern->getKind()); + /*MergeWith*/ExistingPattern, DPattern->getKind()); if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) { // Merge with any existing definition. |