Author: Richard Smith
Date: 2020-06-23T14:43:04-07:00
New Revision: a6308c0ad954a08645d9abf0a5e77dc488b8ca28

URL: 
https://github.com/llvm/llvm-project/commit/a6308c0ad954a08645d9abf0a5e77dc488b8ca28
DIFF: 
https://github.com/llvm/llvm-project/commit/a6308c0ad954a08645d9abf0a5e77dc488b8ca28.diff

LOG: When performing a substitution into a dependent alias template, mark the
outer levels as retained rather than omitting their arguments.

This better reflects what's going on (we're performing a substitution
while still inside a template), and in theory is more correct, but I've
not found a testcase where it matters in practice (largely because we
don't allow alias templates to be declared inside a function).

Fixed AST dumping of SubstNonTypeTemplateParm[Pack]Expr to demonstrate
that we're properly substituting through dependent alias templates. (We
can't deduce properly through these yet, but we can at least produce the
right input to template argument deduction.)

No functionality change intended.

Added: 
    

Modified: 
    clang/include/clang/AST/ASTNodeTraverser.h
    clang/lib/Sema/SemaTemplate.cpp
    clang/test/AST/ast-dump-openmp-begin-declare-variant_template_1.cpp
    clang/test/SemaTemplate/alias-templates.cpp
    clang/test/SemaTemplate/deduction-guide.cpp
    clang/unittests/AST/ASTTraverserTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/ASTNodeTraverser.h 
b/clang/include/clang/AST/ASTNodeTraverser.h
index 7462120e3765..f1c98193df6c 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -680,6 +680,15 @@ class ASTNodeTraverser
         Visit(A);
   }
 
+  void VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr 
*E) {
+    Visit(E->getParameter());
+  }
+  void VisitSubstNonTypeTemplateParmPackExpr(
+      const SubstNonTypeTemplateParmPackExpr *E) {
+    Visit(E->getParameterPack());
+    Visit(E->getArgumentPack());
+  }
+
   void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
     if (const VarDecl *CatchParam = Node->getCatchParamDecl())
       Visit(CatchParam);

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 00003e8a7531..72bd35bea0c6 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3560,9 +3560,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
     // Only substitute for the innermost template argument list.
     MultiLevelTemplateArgumentList TemplateArgLists;
     TemplateArgLists.addOuterTemplateArguments(&StackTemplateArgs);
-    unsigned Depth = AliasTemplate->getTemplateParameters()->getDepth();
-    for (unsigned I = 0; I < Depth; ++I)
-      TemplateArgLists.addOuterTemplateArguments(None);
+    TemplateArgLists.addOuterRetainedLevels(
+        AliasTemplate->getTemplateParameters()->getDepth());
 
     LocalInstantiationScope Scope(*this);
     InstantiatingTemplate Inst(*this, TemplateLoc, Template);

diff  --git 
a/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_1.cpp 
b/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_1.cpp
index 6d36c1b90eb8..5916958b9462 100644
--- a/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_1.cpp
+++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_1.cpp
@@ -153,7 +153,8 @@ int test() {
 // CHECK-NEXT: |       `-PseudoObjectExpr [[ADDR_85:0x[a-z0-9]*]] <col:10, 
col:13> 'int'
 // CHECK-NEXT: |         |-CallExpr [[ADDR_86:0x[a-z0-9]*]] <col:10, col:13> 
'int'
 // CHECK-NEXT: |         | `-SubstNonTypeTemplateParmExpr 
[[ADDR_87:0x[a-z0-9]*]] <col:10> 'int (*)({{.*}})'
-// CHECK-NEXT: |         |   `-UnaryOperator [[ADDR_88:0x[a-z0-9]*]] <col:10> 
'int (*)({{.*}})' prefix '&' cannot overflow
+// CHECK-NEXT: |         |   |-NonTypeTemplateParmDecl {{.*}} referenced 
'Ty':'int (*)()' depth 0 index 0 fn
+// CHECK-NEXT: |         |   `-UnaryOperator [[ADDR_88:0x[a-z0-9]*]] 
<line:47:10> 'int (*)({{.*}})' prefix '&' cannot overflow
 // CHECK-NEXT: |         |     `-DeclRefExpr [[ADDR_89:0x[a-z0-9]*]] <col:10> 
'int ({{.*}})' {{.*}}Function [[ADDR_0]] 'also_before' 'int ({{.*}})'
 // CHECK-NEXT: |         `-CallExpr [[ADDR_90:0x[a-z0-9]*]] <line:21:1, 
line:47:13> 'int'
 // CHECK-NEXT: |           `-ImplicitCastExpr [[ADDR_91:0x[a-z0-9]*]] 
<line:21:1> 'int (*)({{.*}})' <FunctionToPointerDecay>

diff  --git a/clang/test/SemaTemplate/alias-templates.cpp 
b/clang/test/SemaTemplate/alias-templates.cpp
index 80678bf22985..6dffd9489294 100644
--- a/clang/test/SemaTemplate/alias-templates.cpp
+++ b/clang/test/SemaTemplate/alias-templates.cpp
@@ -265,3 +265,28 @@ namespace an_alias_template_is_not_a_class_template {
     int z = Bar(); // expected-error {{use of template template parameter 
'Bar' requires template arguments}}
   }
 }
+
+namespace resolved_nttp {
+  template <typename T> struct A {
+    template <int N> using Arr = T[N];
+    Arr<3> a;
+  };
+  using TA = decltype(A<int>::a);
+  using TA = int[3];
+
+  template <typename T> struct B {
+    template <int... N> using Fn = T(int(*...A)[N]);
+    Fn<1, 2, 3> *p;
+  };
+  using TB = decltype(B<int>::p);
+  using TB = int (*)(int (*)[1], int (*)[2], int (*)[3]);
+
+  template <typename T, int ...M> struct C {
+    template <T... N> using Fn = T(int(*...A)[N]);
+    Fn<1, M..., 4> *p; // expected-error-re 3{{evaluates to {{[234]}}, which 
cannot be narrowed to type 'bool'}}
+  };
+  using TC = decltype(C<int, 2, 3>::p);
+  using TC = int (*)(int (*)[1], int (*)[2], int (*)[3], int (*)[4]);
+
+  using TC2 = decltype(C<bool, 2, 3>::p); // expected-note {{instantiation of}}
+}

diff  --git a/clang/test/SemaTemplate/deduction-guide.cpp 
b/clang/test/SemaTemplate/deduction-guide.cpp
index 2a7d438ddadd..8a964903ebfc 100644
--- a/clang/test/SemaTemplate/deduction-guide.cpp
+++ b/clang/test/SemaTemplate/deduction-guide.cpp
@@ -1,7 +1,8 @@
-// RUN: %clang_cc1 -std=c++2a -verify -ast-dump -ast-dump-decl-types 
-ast-dump-filter "deduction guide" %s | FileCheck %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -std=c++2a -verify -ast-dump -ast-dump-decl-types 
-ast-dump-filter "deduction guide" %s | FileCheck %s --strict-whitespace
 
 template<auto ...> struct X {};
+template<template<typename X, X> typename> struct Y {};
+template<typename ...> struct Z {};
 
 template<typename T, typename ...Ts> struct A {
   template<Ts ...Ns, T *...Ps> A(X<Ps...>, Ts (*...qs)[Ns]);
@@ -12,7 +13,7 @@ A a(X<&arr1, &arr2>{}, &arr1, &arr2, &arr3);
 using AT = decltype(a);
 using AT = A<int[3], int, int, short>;
 
-// CHECK: Dumping <deduction guide for A>:
+// CHECK-LABEL: Dumping <deduction guide for A>:
 // CHECK: FunctionTemplateDecl
 // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 T
 // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 1 ... Ts
@@ -61,7 +62,7 @@ B b(X<nullptr, 'x'>{});
 using BT = decltype(b);
 using BT = B<char, 'x'>;
 
-// CHECK: Dumping <deduction guide for B>:
+// CHECK-LABEL: Dumping <deduction guide for B>:
 // CHECK: FunctionTemplateDecl
 // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 T
 // CHECK: |-NonTypeTemplateParmDecl {{.*}} 'T' depth 0 index 1 V
@@ -83,7 +84,6 @@ using BT = B<char, 'x'>;
 // CHECK:   `-TemplateArgument expr
 // CHECK:     `-DeclRefExpr {{.*}} 'T' NonTypeTemplateParm {{.*}} 'V' 'T'
 
-template<template<typename X, X> typename> struct Y {};
 template<typename A> struct C {
   template<template<typename X, X> typename T, typename U, U V = 0> C(A, Y<T>, 
U);
 };
@@ -91,7 +91,7 @@ C c(1, Y<B>{}, 2);
 using CT = decltype(c);
 using CT = C<int>;
 
-// CHECK: Dumping <deduction guide for C>:
+// CHECK-LABEL: Dumping <deduction guide for C>:
 // CHECK: FunctionTemplateDecl
 // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 A
 // CHECK: |-TemplateTemplateParmDecl {{.*}} depth 0 index 1 T
@@ -100,7 +100,7 @@ using CT = C<int>;
 // CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 2 U
 // CHECK: |-NonTypeTemplateParmDecl {{.*}} 'type-parameter-0-2' depth 0 index 
3 V
 // CHECK: | `-TemplateArgument expr
-// CHECK: | `-IntegerLiteral {{.*}} 'int' 0
+// CHECK: |   `-IntegerLiteral {{.*}} 'int' 0
 // CHECK: |-CXXDeductionGuideDecl {{.*}} 'auto (A, Y<>, type-parameter-0-2) -> 
C<A>'
 // CHECK: | |-ParmVarDecl {{.*}} 'A'
 // CHECK: | |-ParmVarDecl {{.*}} 'Y<>'
@@ -120,3 +120,89 @@ using CT = C<int>;
 // CHECK: |-TemplateSpecializationType {{.*}} 'Y<>' dependent Y
 // CHECK: | `-TemplateArgument template 
 // CHECK: `-TemplateTypeParmType {{.*}} 'type-parameter-0-2' dependent depth 0 
index 2
+
+template<typename ...T> struct D { // expected-note {{candidate}}
+  template<typename... U> using B = int(int (*...p)(T, U));
+  template<typename U1, typename U2> D(B<U1, U2>*); // expected-note 
{{candidate}}
+};
+int f(int(int, int), int(int, int));
+// FIXME: We can't deduce this because we can't deduce through a
+// SubstTemplateTypeParmPackType.
+D d = f; // expected-error {{no viable}}
+using DT = decltype(d);
+using DT = D<int, int>;
+
+// CHECK-LABEL: Dumping <deduction guide for D>:
+// CHECK: FunctionTemplateDecl
+// CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 ... T
+// CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 1 U1
+// CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 2 U2
+// CHECK: `-CXXDeductionGuideDecl {{.*}} 'auto (B<type-parameter-0-1, 
type-parameter-0-2> *) -> D<T...>'  
+// CHECK:   `-ParmVarDecl {{.*}} 'B<type-parameter-0-1, type-parameter-0-2> *'
+// CHECK: FunctionProtoType {{.*}} 'auto (B<type-parameter-0-1, 
type-parameter-0-2> *) -> D<T...>' dependent trailing_return
+// CHECK: |-InjectedClassNameType {{.*}} 'D<T...>' dependent
+// CHECK: `-PointerType {{.*}} 'B<type-parameter-0-1, type-parameter-0-2> *' 
dependent
+// CHECK:   `-TemplateSpecializationType {{.*}} 'B<type-parameter-0-1, 
type-parameter-0-2>' sugar dependent alias B
+// CHECK:     |-TemplateArgument type 'type-parameter-0-1'
+// CHECK:     |-TemplateArgument type 'type-parameter-0-2'
+// CHECK:     `-FunctionProtoType {{.*}} 'int (int (*)(T, U)...)' dependent 
cdecl
+// CHECK:       |-BuiltinType {{.*}} 'int'
+// CHECK:       `-PackExpansionType {{.*}} 'int (*)(T, U)...' dependent 
expansions 2
+// CHECK:         `-PointerType {{.*}} 'int (*)(T, U)' dependent 
contains_unexpanded_pack
+// CHECK:           `-ParenType {{.*}} 'int (T, U)' sugar dependent 
contains_unexpanded_pack
+// CHECK:             `-FunctionProtoType {{.*}} 'int (T, U)' dependent 
contains_unexpanded_pack cdecl
+// CHECK:               |-BuiltinType {{.*}} 'int'
+// CHECK:               |-TemplateTypeParmType {{.*}} 'T' dependent 
contains_unexpanded_pack depth 0 index 0 pack
+// CHECK:               | `-TemplateTypeParm {{.*}} 'T'
+// CHECK:               `-SubstTemplateTypeParmPackType {{.*}} 'U' dependent 
contains_unexpanded_pack
+// CHECK:                 |-TemplateTypeParmType {{.*}} 'U' dependent 
contains_unexpanded_pack depth 1 index 0 pack
+// CHECK:                 | `-TemplateTypeParm {{.*}} 'U'
+// CHECK:                 `-TemplateArgument pack
+// CHECK:                   |-TemplateArgument type 'type-parameter-0-1'
+// CHECK-NOT: Subst
+// CHECK:                   | `-TemplateTypeParmType
+// CHECK:                   `-TemplateArgument type 'type-parameter-0-2'
+// CHECK-NOT: Subst
+// CHECK:                     `-TemplateTypeParmType
+
+template<int ...N> struct E { // expected-note {{candidate}}
+  template<int ...M> using B = Z<X<N, M>...>;
+  template<int M1, int M2> E(B<M1, M2>); // expected-note {{candidate}}
+};
+// FIXME: We can't deduce this because we can't deduce through a
+// SubstNonTypeTemplateParmPackExpr.
+E e = Z<X<1, 2>, X<3, 4>>(); // expected-error {{no viable}}
+using ET = decltype(e);
+using ET = E<1, 3>;
+
+// CHECK-LABEL: Dumping <deduction guide for E>:
+// CHECK: FunctionTemplateDecl
+// CHECK: |-NonTypeTemplateParmDecl [[N:0x[0-9a-f]*]] {{.*}} 'int' depth 0 
index 0 ... N
+// CHECK: |-NonTypeTemplateParmDecl [[M1:0x[0-9a-f]*]] {{.*}} 'int' depth 0 
index 1 M1
+// CHECK: |-NonTypeTemplateParmDecl [[M2:0x[0-9a-f]*]] {{.*}} 'int' depth 0 
index 2 M2
+// CHECK: `-CXXDeductionGuideDecl {{.*}} 'auto (B<M1, M2>) -> E<N...>'
+// CHECK:   `-ParmVarDecl {{.*}} 'B<M1, M2>':'Z<X<N, M>...>'
+// CHECK: FunctionProtoType {{.*}} 'auto (B<M1, M2>) -> E<N...>' dependent 
trailing_return
+// CHECK: |-InjectedClassNameType {{.*}} 'E<N...>' dependent
+// CHECK: `-TemplateSpecializationType {{.*}} 'B<M1, M2>' sugar dependent 
alias B
+// CHECK:   |-TemplateArgument expr
+// CHECK:   | `-DeclRefExpr {{.*}} 'int' NonTypeTemplateParm {{.*}} 'M1' 'int'
+// CHECK:   |-TemplateArgument expr
+// CHECK:   | `-DeclRefExpr {{.*}} 'int' NonTypeTemplateParm {{.*}} 'M2' 'int'
+// CHECK:   `-TemplateSpecializationType {{.*}} 'Z<X<N, M>...>' dependent Z
+// CHECK:     `-TemplateArgument type 'X<N, M>...'
+// CHECK:       `-PackExpansionType {{.*}} 'X<N, M>...' dependent expansions 2
+// CHECK:         `-TemplateSpecializationType {{.*}} 'X<N, M>' dependent 
contains_unexpanded_pack X
+// CHECK:           |-TemplateArgument expr
+// CHECK-NOT: Subst
+// CHECK:           | `-DeclRefExpr {{.*}} 'int' NonTypeTemplateParm [[N]] 'N' 
'int'
+// CHECK:           `-TemplateArgument expr
+// CHECK:             `-SubstNonTypeTemplateParmPackExpr {{.*}} 'int'
+// CHECK:               |-NonTypeTemplateParmDecl {{.*}} referenced 'int' 
depth 1 index 0 ... M
+// CHECK:               `-TemplateArgument pack
+// CHECK:                 |-TemplateArgument expr
+// CHECK-NOT: Subst
+// CHECK:                 | `-DeclRefExpr {{.*}} 'int' NonTypeTemplateParm 
[[M1]] 'M1' 'int'
+// CHECK:                 `-TemplateArgument expr
+// CHECK-NOT: Subst
+// CHECK:                   `-DeclRefExpr {{.*}} 'int' NonTypeTemplateParm 
[[M2]] 'M2' 'int'

diff  --git a/clang/unittests/AST/ASTTraverserTest.cpp 
b/clang/unittests/AST/ASTTraverserTest.cpp
index 6d3d83318032..2f131c3fd04f 100644
--- a/clang/unittests/AST/ASTTraverserTest.cpp
+++ b/clang/unittests/AST/ASTTraverserTest.cpp
@@ -431,6 +431,7 @@ VarDecl 'c1'
 StaticAssertDecl
 |-ImplicitCastExpr
 | `-SubstNonTypeTemplateParmExpr
+|   |-NonTypeTemplateParmDecl 'alignment'
 |   `-IntegerLiteral
 `-StringLiteral
 )cpp");


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

Reply via email to