Author: vvassilev
Date: Thu Jan 12 03:16:26 2017
New Revision: 291753

URL: http://llvm.org/viewvc/llvm-project?rev=291753&view=rev
Log:
PR31469: Don't add friend template class decls to redecl chain in dependent 
contexts.
    
Fixes a crash in modules where the template class decl becomes the most recent
decl in the redeclaration chain and forcing the template instantiator try to
instantiate the friend declaration, rather than the template definition.
    
In practice, A::list<int> produces a TemplateSpecializationType
A::__1::list<int, allocator<type-parameter-0-0> >' failing to replace to
subsitute the default argument to allocator<int>.
    
Kudos Richard Smith (D28399).

Added:
    cfe/trunk/test/Modules/Inputs/PR31469/
    cfe/trunk/test/Modules/Inputs/PR31469/empty.h
    cfe/trunk/test/Modules/Inputs/PR31469/module.modulemap
    cfe/trunk/test/Modules/Inputs/PR31469/textual.h
    cfe/trunk/test/Modules/Inputs/PR31469/textual_file_shadow.h
    cfe/trunk/test/Modules/pr31469.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/Misc/ast-dump-decl.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=291753&r1=291752&r2=291753&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Thu Jan 12 03:16:26 2017
@@ -2028,8 +2028,7 @@ public:
                                    SourceLocation L,
                                    DeclarationName Name,
                                    TemplateParameterList *Params,
-                                   NamedDecl *Decl,
-                                   ClassTemplateDecl *PrevDecl);
+                                   NamedDecl *Decl);
 
   /// \brief Create an empty class template node.
   static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=291753&r1=291752&r2=291753&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Jan 12 03:16:26 2017
@@ -4671,8 +4671,7 @@ Decl *ASTNodeImporter::VisitClassTemplat
 
   ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), 
DC, 
                                                     Loc, Name, TemplateParams, 
-                                                    D2Templated, 
-                                                    /*PrevDecl=*/nullptr);
+                                                    D2Templated);
   D2Templated->setDescribedClassTemplate(D2);    
   
   D2->setAccess(D->getAccess());

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=291753&r1=291752&r2=291753&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Thu Jan 12 03:16:26 2017
@@ -297,12 +297,10 @@ ClassTemplateDecl *ClassTemplateDecl::Cr
                                              SourceLocation L,
                                              DeclarationName Name,
                                              TemplateParameterList *Params,
-                                             NamedDecl *Decl,
-                                             ClassTemplateDecl *PrevDecl) {
+                                             NamedDecl *Decl) {
   AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
   ClassTemplateDecl *New = new (C, DC) ClassTemplateDecl(C, DC, L, Name,
                                                          Params, Decl);
-  New->setPreviousDecl(PrevDecl);
   return New;
 }
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=291753&r1=291752&r2=291753&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jan 12 03:16:26 2017
@@ -1224,9 +1224,17 @@ Sema::CheckClassTemplate(Scope *S, unsig
     }
   }
 
+  // If this is a templated friend in a dependent context we should not put it
+  // on the redecl chain. In some cases, the templated friend can be the most
+  // recent declaration tricking the template instantiator to make 
substitutions
+  // there.
+  // FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious
+  bool ShouldAddRedecl
+    = !(TUK == TUK_Friend && CurContext->isDependentContext());
+
   CXXRecordDecl *NewClass =
     CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
-                          PrevClassTemplate?
+                          PrevClassTemplate && ShouldAddRedecl ?
                             PrevClassTemplate->getTemplatedDecl() : nullptr,
                           /*DelayTypeCreation=*/true);
   SetNestedNameSpecifier(NewClass, SS);
@@ -1245,7 +1253,11 @@ Sema::CheckClassTemplate(Scope *S, unsig
   ClassTemplateDecl *NewTemplate
     = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
                                 DeclarationName(Name), TemplateParams,
-                                NewClass, PrevClassTemplate);
+                                NewClass);
+
+  if (ShouldAddRedecl)
+    NewTemplate->setPreviousDecl(PrevClassTemplate);
+
   NewClass->setDescribedClassTemplate(NewTemplate);
 
   if (ModulePrivateLoc.isValid())

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=291753&r1=291752&r2=291753&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Jan 12 03:16:26 2017
@@ -1219,8 +1219,10 @@ Decl *TemplateDeclInstantiator::VisitCla
 
   ClassTemplateDecl *Inst
     = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(),
-                                D->getIdentifier(), InstParams, RecordInst,
-                                PrevClassTemplate);
+                                D->getIdentifier(), InstParams, RecordInst);
+  assert(!(isFriend && Owner->isDependentContext()));
+  Inst->setPreviousDecl(PrevClassTemplate);
+
   RecordInst->setDescribedClassTemplate(Inst);
 
   if (isFriend) {

Modified: cfe/trunk/test/Misc/ast-dump-decl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-decl.cpp?rev=291753&r1=291752&r2=291753&view=diff
==============================================================================
--- cfe/trunk/test/Misc/ast-dump-decl.cpp (original)
+++ cfe/trunk/test/Misc/ast-dump-decl.cpp Thu Jan 12 03:16:26 2017
@@ -336,7 +336,6 @@ namespace testCanonicalTemplate {
   // CHECK-NEXT:       ClassTemplateDecl{{.*}} TestClassTemplate
   // CHECK-NEXT:         TemplateTypeParmDecl
   // CHECK-NEXT:         CXXRecordDecl{{.*}} class TestClassTemplate
-  // CHECK-NEXT:         ClassTemplateSpecialization{{.*}} 'TestClassTemplate'
   // CHECK-NEXT:   ClassTemplateSpecializationDecl{{.*}} class 
TestClassTemplate
   // CHECK-NEXT:     TemplateArgument{{.*}}A
   // CHECK-NEXT:     CXXRecordDecl{{.*}} class TestClassTemplate

Added: cfe/trunk/test/Modules/Inputs/PR31469/empty.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR31469/empty.h?rev=291753&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/PR31469/empty.h (added)
+++ cfe/trunk/test/Modules/Inputs/PR31469/empty.h Thu Jan 12 03:16:26 2017
@@ -0,0 +1 @@
+// This file is triggers loading of module M.

Added: cfe/trunk/test/Modules/Inputs/PR31469/module.modulemap
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR31469/module.modulemap?rev=291753&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/PR31469/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/PR31469/module.modulemap Thu Jan 12 03:16:26 
2017
@@ -0,0 +1,5 @@
+module M {
+  module "textual_shadow" { header "textual_file_shadow.h" export *}
+  module "trigger" { header "empty.h" export * }
+  export *
+}

Added: cfe/trunk/test/Modules/Inputs/PR31469/textual.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR31469/textual.h?rev=291753&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/PR31469/textual.h (added)
+++ cfe/trunk/test/Modules/Inputs/PR31469/textual.h Thu Jan 12 03:16:26 2017
@@ -0,0 +1,17 @@
+namespace A {
+inline
+namespace __1 {
+  template <class _Tp> class allocator;
+  template <class _Tp, class _Alloc = allocator<_Tp>> class list;
+  template <class _VoidPtr> class __list_iterator {
+    //template <class> friend class list; // causes another crash in 
ASTDeclReader::attachPreviousDecl
+    template <class, class> friend class list;
+  };
+  template <class _Tp, class _Alloc> class __list_imp {};
+  template <class _Tp, class _Alloc> class list : __list_imp<_Tp, _Alloc> {
+  public:
+    list() {}
+  };
+  template <class _Tp> void f(list<_Tp>);
+}
+}

Added: cfe/trunk/test/Modules/Inputs/PR31469/textual_file_shadow.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR31469/textual_file_shadow.h?rev=291753&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/PR31469/textual_file_shadow.h (added)
+++ cfe/trunk/test/Modules/Inputs/PR31469/textual_file_shadow.h Thu Jan 12 
03:16:26 2017
@@ -0,0 +1,2 @@
+#include "textual.h"
+

Added: cfe/trunk/test/Modules/pr31469.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/pr31469.cpp?rev=291753&view=auto
==============================================================================
--- cfe/trunk/test/Modules/pr31469.cpp (added)
+++ cfe/trunk/test/Modules/pr31469.cpp Thu Jan 12 03:16:26 2017
@@ -0,0 +1,15 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -std=c++11 -I%S/Inputs/PR31469 -verify %s
+// RUN: %clang_cc1 -std=c++11 -I%S/Inputs/PR31469 -fmodules 
-fmodules-local-submodule-visibility \
+// RUN:    -fimplicit-module-maps -fmodules-cache-path=%t  -verify %s
+
+#include "textual.h"
+#include "empty.h"
+
+namespace A {
+  template <class _Tp> void f();
+}
+
+A::list<int> use;
+
+// expected-no-diagnostics


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to