aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization
diff options
context:
space:
mode:
authorAxel Naumann <Axel.Naumann@cern.ch>2012-10-02 09:09:43 +0000
committerAxel Naumann <Axel.Naumann@cern.ch>2012-10-02 09:09:43 +0000
commit39d26c3e499470cd80a3e6f26f11ac681cd9712c (patch)
tree29e424007f5364bcd619aa1ecc53eaf0c58e35d7 /lib/Serialization
parentb7bafa94bc583af9b825b5049aed50359fdb844b (diff)
Merge pending instantiations instead of overwriting existing ones.
Check whether a pending instantiation needs to be instantiated (or whether an instantiation already exists). Verify the size of the PendingInstantiations record (was only checking size of existing PendingInstantiations). Migrate Obj-C++ part of redecl-merge into separate test, now that this is growing. templates.mm: test that CodeGen has seen exactly one definition of template instantiations. redecl-merge.m: use "@" specifier for expected-diagnostics. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164993 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization')
-rw-r--r--lib/Serialization/ASTReader.cpp16
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp59
2 files changed, 69 insertions, 6 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 639ef93fb6..a897d868e4 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2223,13 +2223,15 @@ ASTReader::ReadASTBlock(ModuleFile &F) {
case PENDING_IMPLICIT_INSTANTIATIONS:
if (PendingInstantiations.size() % 2 != 0) {
+ Error("Invalid existing PendingInstantiations");
+ return Failure;
+ }
+
+ if (Record.size() % 2 != 0) {
Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
return Failure;
}
-
- // Later lists of pending instantiations overwrite earlier ones.
- // FIXME: This is most certainly wrong for modules.
- PendingInstantiations.clear();
+
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++]));
PendingInstantiations.push_back(
@@ -5592,7 +5594,11 @@ void ASTReader::ReadPendingInstantiations(
ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));
SourceLocation Loc
= SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]);
- Pending.push_back(std::make_pair(D, Loc));
+
+ // For modules, find out whether an instantiation already exists
+ if (!getContext().getLangOpts().Modules
+ || needPendingInstantiation(D))
+ Pending.push_back(std::make_pair(D, Loc));
}
PendingInstantiations.clear();
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index fb4192f86a..85740de15b 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -2156,7 +2156,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
// loading, and some declarations may still be initializing.
if (isConsumerInterestedIn(D))
InterestingDecls.push_back(D);
-
+
return D;
}
@@ -2504,3 +2504,60 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
}
}
}
+
+/// \brief Return a template specialization of ND (should be a TemplateDecl)
+/// that matches FD or TD.
+static NamedDecl* findMatchingSpecialization(FunctionDecl* FD,
+ ClassTemplateSpecializationDecl*TD,
+ NamedDecl* ND) {
+ TemplateDecl* Templt = dyn_cast<TemplateDecl>(ND);
+ if (!Templt) return 0;
+ if (FD) {
+ FunctionTemplateDecl* FTD = dyn_cast<FunctionTemplateDecl>(Templt);
+ if (!FTD) return 0;
+ const TemplateArgumentList* TmpltArgs = FD->getTemplateSpecializationArgs();
+ assert(TmpltArgs || "Template without arguments");
+ void* InsertionPoint;
+ return FTD->findSpecialization(TmpltArgs->data(), TmpltArgs->size(),
+ InsertionPoint);
+ } else {
+ ClassTemplateDecl* CTD = dyn_cast<ClassTemplateDecl>(Templt);
+ if (!CTD) return 0;
+ const TemplateArgumentList& TmpltArgs = TD->getTemplateArgs();
+ void* InsertionPoint;
+ return CTD->findSpecialization(TmpltArgs.data(), TmpltArgs.size(),
+ InsertionPoint);
+ }
+ return 0;
+}
+
+/// \brief Find out whether an instantiation (outside the module) already exists
+bool ASTReader::needPendingInstantiation(ValueDecl* D) const {
+ DeclContext *DC = D->getDeclContext()->getRedeclContext();
+ DeclarationName Name = D->getDeclName();
+ assert(Name && "unnamed template");
+
+ FunctionDecl* FD = dyn_cast<FunctionDecl>(D);
+ ClassTemplateSpecializationDecl* CD
+ = FD ? 0 : dyn_cast<ClassTemplateSpecializationDecl>(D);
+
+ NamedDecl* FoundSpecialization = 0;
+ if (DC->isTranslationUnit() && SemaObj) {
+ IdentifierResolver &IdResolver = SemaObj->IdResolver;
+ for (IdentifierResolver::iterator I = IdResolver.begin(Name),
+ IEnd = IdResolver.end();
+ I != IEnd && !FoundSpecialization; ++I)
+ FoundSpecialization = findMatchingSpecialization(FD, CD, *I);
+ } else {
+ // templates are redeclarables, i.e. they must have been merged into
+ // the primary context. Use localUncachedLookup to not pick up template
+ // decls from modules again.
+ llvm::SmallVector<NamedDecl*, 6> Results;
+ DC->getPrimaryContext()->localUncachedLookup(Name, Results);
+ for (llvm::SmallVector<NamedDecl *, 6>::const_iterator
+ I = Results.begin(), E = Results.end();
+ I != E && FoundSpecialization; ++I)
+ FoundSpecialization = findMatchingSpecialization(FD, CD, *I);
+ }
+ return FoundSpecialization && isSameEntity(FoundSpecialization, D);
+}