]> granicus.if.org Git - clang/commitdiff
When we're deserializing a template parameter declaration, temporarily
authorDouglas Gregor <dgregor@apple.com>
Sat, 5 Mar 2011 01:35:54 +0000 (01:35 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 5 Mar 2011 01:35:54 +0000 (01:35 +0000)
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

lib/AST/DeclBase.cpp
lib/Serialization/ASTReaderDecl.cpp
test/PCH/cxx-templates.h

index 0642f423c6f34516ebaa431f0febb07d6b5b092e..8d6a5412a55b15cc96761ab69f2010d7be52379f 100644 (file)
@@ -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;
 }
 
index 1e4ff83d5fc3b5f765d6ff997dd927d9f2158c84..a49f909c6f011453b97e7c7ff367ee260bc23036 100644 (file)
@@ -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
index d2c820f877c6067e553dcad69893f2ef8400dcf7..c45e02dcb23c1718fe9931dc5b2b76e6fda0129d 100644 (file)
@@ -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; }
+}