aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AST/DeclBase.cpp3
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp26
-rw-r--r--test/PCH/cxx-templates.h12
3 files changed, 36 insertions, 5 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 0642f423c6..8d6a5412a5 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -173,9 +173,6 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
Decl::~Decl() { }
void Decl::setDeclContext(DeclContext *DC) {
- if (isOutOfSemaDC())
- delete getMultipleDC();
-
DeclCtx = DC;
}
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 1e4ff83d5f..a49f909c6f 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -38,6 +38,9 @@ namespace clang {
const RecordData &Record;
unsigned &Idx;
TypeID TypeIDForTypeDecl;
+
+ DeclID DeclContextIDForTemplateParmDecl;
+ DeclID LexicalDeclContextIDForTemplateParmDecl;
uint64_t GetCurrentCursorOffset();
SourceLocation ReadSourceLocation(const RecordData &R, unsigned &I) {
@@ -175,13 +178,32 @@ void ASTDeclReader::Visit(Decl *D) {
// FunctionDecl's body was written last after all other Stmts/Exprs.
if (Record[Idx++])
FD->setLazyBody(GetCurrentCursorOffset());
+ } else if (D->isTemplateParameter()) {
+ // If we have a fully initialized template parameter, we can now
+ // set its DeclContext.
+ D->setDeclContext(
+ cast_or_null<DeclContext>(
+ Reader.GetDecl(DeclContextIDForTemplateParmDecl)));
+ D->setLexicalDeclContext(
+ cast_or_null<DeclContext>(
+ Reader.GetDecl(LexicalDeclContextIDForTemplateParmDecl)));
}
}
void ASTDeclReader::VisitDecl(Decl *D) {
- D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
- D->setLexicalDeclContext(
+ if (D->isTemplateParameter()) {
+ // We don't want to deserialize the DeclContext of a template
+ // parameter immediately, because the template parameter might be
+ // used in the formulation of its DeclContext. Use the translation
+ // unit DeclContext as a placeholder.
+ DeclContextIDForTemplateParmDecl = Record[Idx++];
+ LexicalDeclContextIDForTemplateParmDecl = Record[Idx++];
+ D->setDeclContext(Reader.getContext()->getTranslationUnitDecl());
+ } else {
+ D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
+ D->setLexicalDeclContext(
cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
+ }
D->setLocation(ReadSourceLocation(Record, Idx));
D->setInvalidDecl(Record[Idx++]);
if (Record[Idx++]) { // hasAttrs
diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h
index d2c820f877..c45e02dcb2 100644
--- a/test/PCH/cxx-templates.h
+++ b/test/PCH/cxx-templates.h
@@ -193,3 +193,15 @@ namespace ZeroLengthExplicitTemplateArgs {
template<typename T> void g2(T);
};
}
+
+namespace NonTypeTemplateParmContext {
+ template<typename T, int inlineCapacity = 0> class Vector { };
+
+ struct String {
+ template<int inlineCapacity>
+ static String adopt(Vector<char, inlineCapacity>&);
+ };
+
+ template<int inlineCapacity>
+ inline bool equalIgnoringNullity(const Vector<char, inlineCapacity>& a, const String& b) { return false; }
+}