aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-03-05 01:35:54 +0000
committerDouglas Gregor <dgregor@apple.com>2011-03-05 01:35:54 +0000
commit67da6f6f0c20dbfebb1c383a3efaf85d925ad33e (patch)
tree311c0f10a746fc0b89ba7cb7b63d54ad0d37b32a
parentb1c86492f9a9bef01a4567408c22f961bbd604fe (diff)
When we're deserializing a template parameter declaration, temporarily
use the translation unit as its declaration context, then deserialize the actual lexical and semantic DeclContexts after the template parameter is complete. This avoids problems when the DeclContext itself (e.g., a class template) is dependent on the template parameter (e.g., for the injected-class-name). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127056 91177308-0d34-0410-b5e6-96231b3b80d8
-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; }
+}