v.g.vassilev removed rL LLVM as the repository for this revision.
v.g.vassilev updated this revision to Diff 83936.
v.g.vassilev marked an inline comment as done.
v.g.vassilev added a comment.

Address comments.


https://reviews.llvm.org/D28399

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

Index: test/Modules/pr31469.cpp
===================================================================
--- /dev/null
+++ test/Modules/pr31469.cpp
@@ -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
Index: test/Modules/Inputs/PR31469/textual_file_shadow.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/PR31469/textual_file_shadow.h
@@ -0,0 +1,2 @@
+#include "textual.h"
+
Index: test/Modules/Inputs/PR31469/textual.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/PR31469/textual.h
@@ -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>);
+}
+}
Index: test/Modules/Inputs/PR31469/module.modulemap
===================================================================
--- /dev/null
+++ test/Modules/Inputs/PR31469/module.modulemap
@@ -0,0 +1,5 @@
+module M {
+  module "textual_shadow" { header "textual_file_shadow.h" export *}
+  module "trigger" { header "empty.h" export * }
+  export *
+}
Index: test/Modules/Inputs/PR31469/empty.h
===================================================================
--- /dev/null
+++ test/Modules/Inputs/PR31469/empty.h
@@ -0,0 +1 @@
+// This file is triggers loading of module M.
Index: test/Misc/ast-dump-decl.cpp
===================================================================
--- test/Misc/ast-dump-decl.cpp
+++ test/Misc/ast-dump-decl.cpp
@@ -336,7 +336,6 @@
   // 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
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1193,8 +1193,10 @@
 
   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) {
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -1224,9 +1224,17 @@
     }
   }
 
+  // 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 @@
   ClassTemplateDecl *NewTemplate
     = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
                                 DeclarationName(Name), TemplateParams,
-                                NewClass, PrevClassTemplate);
+                                NewClass);
+
+  if (ShouldAddRedecl)
+    NewTemplate->setPreviousDecl(PrevClassTemplate);
+
   NewClass->setDescribedClassTemplate(NewTemplate);
 
   if (ModulePrivateLoc.isValid())
Index: lib/AST/DeclTemplate.cpp
===================================================================
--- lib/AST/DeclTemplate.cpp
+++ lib/AST/DeclTemplate.cpp
@@ -297,12 +297,10 @@
                                              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;
 }
 
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -4671,8 +4671,7 @@
 
   ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, 
                                                     Loc, Name, TemplateParams, 
-                                                    D2Templated, 
-                                                    /*PrevDecl=*/nullptr);
+                                                    D2Templated);
   D2Templated->setDescribedClassTemplate(D2);    
   
   D2->setAccess(D->getAccess());
Index: include/clang/AST/DeclTemplate.h
===================================================================
--- include/clang/AST/DeclTemplate.h
+++ include/clang/AST/DeclTemplate.h
@@ -2028,8 +2028,7 @@
                                    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);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to