Modified:
cfe/trunk/include/clang/Serialization/ASTWriter.h
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/test/Modules/cxx-templates.cpp
Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=245779&r1=245778&r2=245779&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Fri Aug 21 20:47:18 2015
@@ -405,6 +405,10 @@ private:
/// \brief The set of declarations that may have redeclaration chains that
/// need to be serialized.
llvm::SmallVector<const Decl *, 16> Redeclarations;
+
+ /// \brief A cache of the first local declaration for "interesting"
+ /// redeclaration chains.
+ llvm::DenseMap<const Decl *, const Decl *> FirstLocalDeclCache;
/// \brief Statements that we've encountered while serializing a
/// declaration or type.
@@ -676,6 +680,10 @@ public:
const ASTTemplateArgumentListInfo *ASTTemplArgList,
RecordDataImpl &Record);
+ /// \brief Find the first local declaration of a given local redeclarable
+ /// decl.
+ const Decl *getFirstLocalDecl(const Decl *D);
+
/// \brief Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordDataImpl &Record);
@@ -857,12 +865,6 @@ public:
void CompletedTagDefinition(const TagDecl *D) override;
void AddedVisibleDecl(const DeclContext *DC, const Decl *D) override;
void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D)
override;
- void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
- const ClassTemplateSpecializationDecl *D)
override;
- void AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
- const VarTemplateSpecializationDecl *D)
override;
- void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
- const FunctionDecl *D) override;
void ResolvedExceptionSpec(const FunctionDecl *FD) override;
void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType)
override;
void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=245779&r1=245778&r2=245779&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Aug 21 20:47:18 2015
@@ -8123,11 +8123,8 @@ void ASTReader::finishPendingActions() {
PendingIncompleteDeclChains.clear();
// Load pending declaration chains.
- for (unsigned I = 0; I != PendingDeclChains.size(); ++I) {
- PendingDeclChainsKnown.erase(PendingDeclChains[I]);
+ for (unsigned I = 0; I != PendingDeclChains.size(); ++I)
loadPendingDeclChain(PendingDeclChains[I]);
- }
- assert(PendingDeclChainsKnown.empty());
PendingDeclChains.clear();
assert(RedeclsDeserialized.empty() && "some redecls not wired up");
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=245779&r1=245778&r2=245779&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Aug 21 20:47:18 2015
@@ -147,12 +147,6 @@ namespace clang {
}
~RedeclarableResult() {
- if (FirstID && Owning &&
- isRedeclarableDeclKind(LoadedDecl->getKind())) {
- auto Canon = Reader.GetDecl(FirstID)->getCanonicalDecl();
- if (Reader.PendingDeclChainsKnown.insert(Canon).second)
- Reader.PendingDeclChains.push_back(Canon);
- }
}
/// \brief Note that a RedeclarableDecl is not actually redeclarable.
@@ -2186,23 +2180,33 @@ ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
DeclID FirstDeclID = ReadDeclID(Record, Idx);
Decl *MergeWith = nullptr;
+
bool IsKeyDecl = ThisDeclID == FirstDeclID;
+ bool IsFirstLocalDecl = false;
// 0 indicates that this declaration was the only declaration of its entity,
// and is used for space optimization.
if (FirstDeclID == 0) {
FirstDeclID = ThisDeclID;
IsKeyDecl = true;
+ IsFirstLocalDecl = true;
} else if (unsigned N = Record[Idx++]) {
- IsKeyDecl = false;
+ // This declaration was the first local declaration, but may have imported
+ // other declarations.
+ IsKeyDecl = N == 1;
+ IsFirstLocalDecl = true;
// We have some declarations that must be before us in our redeclaration
// chain. Read them now, and remember that we ought to merge with one of
// them.
// FIXME: Provide a known merge target to the second and subsequent such
// declaration.
- for (unsigned I = 0; I != N; ++I)
+ for (unsigned I = 0; I != N - 1; ++I)
MergeWith = ReadDecl(Record, Idx/*, MergeWith*/);
+ } else {
+ // This declaration was not the first local declaration. Read the first
+ // local declaration now, to trigger the import of other redeclarations.
+ (void)ReadDecl(Record, Idx);
}
T *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
@@ -2214,13 +2218,21 @@ ASTDeclReader::VisitRedeclarable(Redecla
D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl);
D->First = FirstDecl->getCanonicalDecl();
}
-
+
// Note that this declaration has been deserialized.
- Reader.RedeclsDeserialized.insert(static_cast<T *>(D));
-
+ T *DAsT = static_cast<T*>(D);
+ Reader.RedeclsDeserialized.insert(DAsT);
+
+ // Note that we need to load local redeclarations of this decl and build a
+ // decl chain for them. This must happen *after* we perform the preloading
+ // above; this ensures that the redeclaration chain is built in the correct
+ // order.
+ if (IsFirstLocalDecl)
+ Reader.PendingDeclChains.push_back(DAsT);
+
// The result structure takes care to note that we need to load the
// other declaration chains for this ID.
- return RedeclarableResult(Reader, FirstDeclID, static_cast<T *>(D),
MergeWith,
+ return RedeclarableResult(Reader, FirstDeclID, DAsT, MergeWith,
IsKeyDecl);
}
@@ -2330,11 +2342,8 @@ void ASTDeclReader::mergeRedeclarable(Re
TemplatePatternID, Redecl.isKeyDecl());
// If this declaration is a key declaration, make a note of that.
- if (Redecl.isKeyDecl()) {
+ if (Redecl.isKeyDecl())
Reader.KeyDecls[ExistingCanon].push_back(Redecl.getFirstID());
- if (Reader.PendingDeclChainsKnown.insert(ExistingCanon).second)
- Reader.PendingDeclChains.push_back(ExistingCanon);
- }
}
}
@@ -3424,15 +3433,12 @@ namespace {
ASTReader &Reader;
SmallVectorImpl<DeclID> &SearchDecls;
llvm::SmallPtrSetImpl<Decl *> &Deserialized;
- GlobalDeclID CanonID;
SmallVector<Decl *, 4> Chain;
public:
RedeclChainVisitor(ASTReader &Reader, SmallVectorImpl<DeclID>
&SearchDecls,
- llvm::SmallPtrSetImpl<Decl *> &Deserialized,
- GlobalDeclID CanonID)
- : Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized),
- CanonID(CanonID) {
+ llvm::SmallPtrSetImpl<Decl *> &Deserialized)
+ : Reader(Reader), SearchDecls(SearchDecls), Deserialized(Deserialized) {
assert(std::is_sorted(SearchDecls.begin(), SearchDecls.end()));
}
@@ -3518,10 +3524,10 @@ namespace {
break;
}
- if (LocalSearchDeclID && LocalSearchDeclID != CanonID) {
+ assert(LocalSearchDeclID);
+ if (LocalSearchDeclID) {
// If the search decl was from this module, add it to the chain.
// Note, the chain is sorted from newest to oldest, so this goes last.
- // We exclude the canonical declaration; it implicitly goes at the end.
addToChain(Reader.GetDecl(LocalSearchDeclID));
}
@@ -3531,26 +3537,14 @@ namespace {
};
}
-void ASTReader::loadPendingDeclChain(Decl *CanonDecl) {
- // The decl might have been merged into something else after being added to
- // our list. If it was, just skip it.
- if (!CanonDecl->isCanonicalDecl())
- return;
-
+void ASTReader::loadPendingDeclChain(Decl *FirstLocal) {
// Determine the set of declaration IDs we'll be searching for.
- SmallVector<DeclID, 16> SearchDecls;
- GlobalDeclID CanonID = CanonDecl->getGlobalID();
- if (CanonID)
- SearchDecls.push_back(CanonDecl->getGlobalID()); // Always first.
- KeyDeclsMap::iterator KeyPos = KeyDecls.find(CanonDecl);
- if (KeyPos != KeyDecls.end())
- SearchDecls.append(KeyPos->second.begin(), KeyPos->second.end());
- llvm::array_pod_sort(SearchDecls.begin(), SearchDecls.end());
+ SmallVector<DeclID, 1> SearchDecls;
+ SearchDecls.push_back(FirstLocal->getGlobalID());
// Build up the list of redeclarations.
- RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized, CanonID);
- ModuleMgr.visit(Visitor);
- RedeclsDeserialized.erase(CanonDecl);
+ RedeclChainVisitor Visitor(*this, SearchDecls, RedeclsDeserialized);
+ Visitor(*getOwningModuleFile(FirstLocal));
// Retrieve the chains.
ArrayRef<Decl *> Chain = Visitor.getChain();
@@ -3561,11 +3555,14 @@ void ASTReader::loadPendingDeclChain(Dec
//
// FIXME: We have three different dispatches on decl kind here; maybe
// we should instead generate one loop per kind and dispatch up-front?
+ Decl *CanonDecl = FirstLocal->getCanonicalDecl();
Decl *MostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
if (!MostRecent)
MostRecent = CanonDecl;
for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
auto *D = Chain[N - I - 1];
+ if (D == CanonDecl)
+ continue;
ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl);
MostRecent = D;
}
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=245779&r1=245778&r2=245779&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Aug 21 20:47:18 2015
@@ -3799,41 +3799,39 @@ void ASTWriter::WriteRedeclarations() {
SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap;
for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) {
- const Decl *Key = Redeclarations[I];
- assert((Chain ? Chain->getKeyDeclaration(Key) == Key
- : Key->isFirstDecl()) &&
- "not the key declaration");
+ const Decl *FirstLocal = Redeclarations[I];
+ assert(!FirstLocal->isFromASTFile() &&
+ (!FirstLocal->getPreviousDecl() ||
+ FirstLocal->getPreviousDecl()->isFromASTFile() ||
+ getDeclID(FirstLocal->getPreviousDecl()) < NUM_PREDEF_DECL_IDS) &&
+ "not the first local declaration");
+ assert(getDeclID(FirstLocal) >= NUM_PREDEF_DECL_IDS &&
+ "should not have predefined decl as first decl");
- const Decl *First = Key->getCanonicalDecl();
- const Decl *MostRecent = First->getMostRecentDecl();
-
- assert((getDeclID(First) >= NUM_PREDEF_DECL_IDS || First == Key) &&
- "should not have imported key decls for predefined decl");
-
- // If we only have a single declaration, there is no point in storing
- // a redeclaration chain.
- if (First == MostRecent)
- continue;
-
unsigned Offset = LocalRedeclChains.size();
unsigned Size = 0;
LocalRedeclChains.push_back(0); // Placeholder for the size.
// Collect the set of local redeclarations of this declaration, from newest
// to oldest.
- for (const Decl *Prev = MostRecent; Prev;
- Prev = Prev->getPreviousDecl()) {
- if (!Prev->isFromASTFile() && Prev != Key) {
+ for (const Decl *Prev = FirstLocal->getMostRecentDecl(); Prev !=
FirstLocal;
+ Prev = Prev->getPreviousDecl()) {
+ if (!Prev->isFromASTFile()) {
AddDeclRef(Prev, LocalRedeclChains);
++Size;
}
}
+ // If we only have a single local declaration, there is no point in storing
+ // a redeclaration chain.
+ if (LocalRedeclChains.size() == 1)
+ continue;
+
LocalRedeclChains[Offset] = Size;
// Add the mapping from the first ID from the AST to the set of local
// declarations.
- LocalRedeclarationsInfo Info = { getDeclID(Key), Offset };
+ LocalRedeclarationsInfo Info = { getDeclID(FirstLocal), Offset };
LocalRedeclsMap.push_back(Info);
assert(N == Redeclarations.size() &&
@@ -4145,8 +4143,6 @@ void ASTWriter::WriteASTCore(Sema &SemaR
if (D) {
assert(D->isCanonicalDecl() && "predefined decl is not canonical");
DeclIDs[D] = ID;
- if (D->getMostRecentDecl() != D)
- Redeclarations.push_back(D);
}
};
RegisterPredefDecl(Context.getTranslationUnitDecl(),
@@ -5730,42 +5726,6 @@ void ASTWriter::AddedCXXImplicitMember(c
DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D));
}
-void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
- const ClassTemplateSpecializationDecl *D)
{
- // The specializations set is kept in the canonical template.
- TD = TD->getCanonicalDecl();
- if (!(!D->isFromASTFile() && TD->isFromASTFile()))
- return; // Not a source specialization added to a template from PCH.
-
- assert(!WritingAST && "Already writing the AST!");
- DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
- D));
-}
-
-void ASTWriter::AddedCXXTemplateSpecialization(
- const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {
- // The specializations set is kept in the canonical template.
- TD = TD->getCanonicalDecl();
- if (!(!D->isFromASTFile() && TD->isFromASTFile()))
- return; // Not a source specialization added to a template from PCH.
-
- assert(!WritingAST && "Already writing the AST!");
- DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
- D));
-}
-
-void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
- const FunctionDecl *D) {
- // The specializations set is kept in the canonical template.
- TD = TD->getCanonicalDecl();
- if (!(!D->isFromASTFile() && TD->isFromASTFile()))
- return; // Not a source specialization added to a template from PCH.
-
- assert(!WritingAST && "Already writing the AST!");
- DeclUpdates[TD].push_back(DeclUpdate(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
- D));
-}
-
void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");
if (!Chain) return;
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=245779&r1=245778&r2=245779&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Aug 21 20:47:18 2015
@@ -159,6 +159,19 @@ namespace clang {
Writer.AddStmt(FD->getBody());
}
+ /// Add to the record the first declaration from each module file that
+ /// provides a declaration of D. The intent is to provide a sufficient
+ /// set such that reloading this set will load all current redeclarations.
+ void AddFirstDeclFromEachModule(const Decl *D, bool IncludeLocal) {
+ llvm::MapVector<ModuleFile*, const Decl*> Firsts;
+ // FIXME: We can skip entries that we know are implied by others.
+ for (const Decl *R = D->getMostRecentDecl(); R; R = R->getPreviousDecl())
+ if (IncludeLocal || R->isFromASTFile())
+ Firsts[Writer.Chain->getOwningModuleFile(R)] = R;
+ for (const auto &F : Firsts)
+ Writer.AddDeclRef(F.second, Record);
+ }
+
/// Get the specialization decl from an entry in the specialization list.
template <typename EntryType>
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
@@ -194,20 +207,46 @@ namespace clang {
if (auto *LS = Common->LazySpecializations)
LazySpecializations = ArrayRef<DeclID>(LS + 1, LS + 1 + LS[0]);
- Record.push_back(Specializations.size() +
- PartialSpecializations.size() +
- LazySpecializations.size());
+ // Add a slot to the record for the number of specializations.
+ unsigned I = Record.size();
+ Record.push_back(0);
+
for (auto &Entry : Specializations) {
auto *D = getSpecializationDecl(Entry);
assert(D->isCanonicalDecl() && "non-canonical decl in set");
- Writer.AddDeclRef(D, Record);
+ AddFirstDeclFromEachModule(D, /*IncludeLocal*/true);
}
for (auto &Entry : PartialSpecializations) {
auto *D = getSpecializationDecl(Entry);
assert(D->isCanonicalDecl() && "non-canonical decl in set");
- Writer.AddDeclRef(D, Record);
+ AddFirstDeclFromEachModule(D, /*IncludeLocal*/true);
}
Record.append(LazySpecializations.begin(), LazySpecializations.end());
+
+ // Update the size entry we added earlier.
+ Record[I] = Record.size() - I - 1;
+ }
+
+ /// Ensure that this template specialization is associated with the
specified
+ /// template on reload.
+ void RegisterTemplateSpecialization(const Decl *Template,
+ const Decl *Specialization) {
+ Template = Template->getCanonicalDecl();
+
+ // If the canonical template is local, we'll write out this
specialization
+ // when we emit it.
+ // FIXME: We can do the same thing if there is any local declaration of
+ // the template, to avoid emitting an update record.
+ if (!Template->isFromASTFile())
+ return;
+
+ // We only need to associate the first local declaration of the
+ // specialization. The other declarations will get pulled in by it.
+ if (Writer.getFirstLocalDecl(Specialization) != Specialization)
+ return;
+
+ Writer.DeclUpdates[Template].push_back(ASTWriter::DeclUpdate(
+ UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, Specialization));
}
};
}
@@ -479,6 +518,9 @@ void ASTDeclWriter::VisitFunctionDecl(Fu
case FunctionDecl::TK_FunctionTemplateSpecialization: {
FunctionTemplateSpecializationInfo *
FTSInfo = D->getTemplateSpecializationInfo();
+
+ RegisterTemplateSpecialization(FTSInfo->getTemplate(), D);
+
Writer.AddDeclRef(FTSInfo->getTemplate(), Record);
Record.push_back(FTSInfo->getTemplateSpecializationKind());
@@ -1249,6 +1291,8 @@ void ASTDeclWriter::VisitClassTemplateDe
void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl
*D) {
+ RegisterTemplateSpecialization(D->getSpecializedTemplate(), D);
+
VisitCXXRecordDecl(D);
llvm::PointerUnion<ClassTemplateDecl *,
@@ -1308,6 +1352,8 @@ void ASTDeclWriter::VisitVarTemplateDecl
void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
VarTemplateSpecializationDecl *D) {
+ RegisterTemplateSpecialization(D->getSpecializedTemplate(), D);
+
VisitVarDecl(D);
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
@@ -1478,48 +1524,61 @@ void ASTDeclWriter::VisitDeclContext(Dec
Record.push_back(VisibleOffset);
}
-/// Determine whether D is the first declaration in its redeclaration chain that
-/// is not from an AST file.
-template <typename T>
-static bool isFirstLocalDecl(Redeclarable<T> *D) {
- assert(D && !static_cast<T*>(D)->isFromASTFile());
- do
- D = D->getPreviousDecl();
- while (D && static_cast<T*>(D)->isFromASTFile());
- return !D;
+/// \brief Is this a local declaration (that is, one that will be written to
+/// our AST file)? This is the case for declarations that are neither imported
+/// from another AST file nor predefined.
+static bool isLocalDecl(ASTWriter &W, const Decl *D) {
+ if (D->isFromASTFile())
+ return false;
+ return W.getDeclID(D) >= NUM_PREDEF_DECL_IDS;
+}
+
+const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) {
+ assert(isLocalDecl(*this, D) && "expected a local declaration");
+
+ const Decl *Canon = D->getCanonicalDecl();
+ if (isLocalDecl(*this, Canon))
+ return Canon;
+
+ const Decl *&CacheEntry = FirstLocalDeclCache[Canon];
+ if (CacheEntry)
+ return CacheEntry;
+
+ for (const Decl *Redecl = D; Redecl; Redecl = Redecl->getPreviousDecl())
+ if (isLocalDecl(*this, Redecl))
+ D = Redecl;
+ return CacheEntry = D;
}
template <typename T>
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
T *First = D->getFirstDecl();
T *MostRecent = First->getMostRecentDecl();
+ T *DAsT = static_cast<T *>(D);
if (MostRecent != First) {
- assert(isRedeclarableDeclKind(static_cast<T *>(D)->getKind()) &&
+ assert(isRedeclarableDeclKind(DAsT->getKind()) &&
"Not considered redeclarable?");
Writer.AddDeclRef(First, Record);
- // In a modules build, emit a list of all imported key declarations
- // (excluding First, if it was imported), so that we can be sure that all
- // redeclarations visible to this module are before D in the redecl chain.
- unsigned I = Record.size();
- Record.push_back(0);
- if (Context.getLangOpts().Modules && Writer.Chain) {
- if (isFirstLocalDecl(D)) {
- Writer.Chain->forEachImportedKeyDecl(First, [&](const Decl *D) {
- if (D != First)
- Writer.AddDeclRef(D, Record);
- });
- Record[I] = Record.size() - I - 1;
-
- // Write a redeclaration chain, attached to the first key decl.
-
Writer.Redeclarations.push_back(Writer.Chain->getKeyDeclaration(First));
- }
- } else if (D == First || D->getPreviousDecl()->isFromASTFile()) {
- assert(isFirstLocalDecl(D) && "imported decl after local decl");
-
- // Write a redeclaration chain attached to the first decl.
- Writer.Redeclarations.push_back(First);
+ // Write out a list of local redeclarations of this declaration if it's the
+ // first local declaration in the chain.
+ const Decl *FirstLocal = Writer.getFirstLocalDecl(DAsT);
+ if (DAsT == FirstLocal) {
+ Writer.Redeclarations.push_back(DAsT);
+
+ // Emit a list of all imported first declarations so that we can be sure
+ // that all redeclarations visible to this module are before D in the
+ // redecl chain.
+ unsigned I = Record.size();
+ Record.push_back(0);
+ if (Writer.Chain)
+ AddFirstDeclFromEachModule(DAsT, /*IncludeLocal*/false);
+ // This is the number of imported first declarations + 1.
+ Record[I] = Record.size() - I;
+ } else {
+ Record.push_back(0);
+ Writer.AddDeclRef(FirstLocal, Record);
}
// Make sure that we serialize both the previous and the most-recent
Modified: cfe/trunk/test/Modules/cxx-templates.cpp
URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-templates.cpp?rev=245779&r1=245778&r2=245779&view=diff
==============================================================================
--- cfe/trunk/test/Modules/cxx-templates.cpp (original)
+++ cfe/trunk/test/Modules/cxx-templates.cpp Fri Aug 21 20:47:18 2015
@@ -187,10 +187,10 @@ namespace Std {
// CHECK-DUMP: ClassTemplateDecl {{.*}} <{{.*[/\\]}}cxx-templates-common.h:1:1, {{.*}}> col:{{.*}} in cxx_templates_common SomeTemplate
// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}}
SomeTemplate
-// CHECK-DUMP-NEXT: TemplateArgument type 'char [2]'
-// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate
definition
-// CHECK-DUMP-NEXT: TemplateArgument type 'char [2]'
-// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}}
SomeTemplate
// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]'
// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate
definition
// CHECK-DUMP-NEXT: TemplateArgument type 'char [1]'
+// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} prev {{.*}}
SomeTemplate
+// CHECK-DUMP-NEXT: TemplateArgument type 'char [2]'
+// CHECK-DUMP: ClassTemplateSpecializationDecl {{.*}} SomeTemplate
definition
+// CHECK-DUMP-NEXT: TemplateArgument type 'char [2]'
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits