summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization/ASTReaderDecl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-02-06 02:42:59 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-02-06 02:42:59 +0000
commit5a4737cd6aac5c99248de6ee6865f057b7618494 (patch)
tree4578974f1165f4416d19d72769013ad6f6122d51 /clang/lib/Serialization/ASTReaderDecl.cpp
parent9bdea541cab4e540dc9c8d88edcb9c23f75d9595 (diff)
downloadbcm5719-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.cpp41
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.
OpenPOWER on IntegriCloud