Ensure we don't strip the ConstantExpr carrying a non-type template
authorRichard Smith <richard@metafoo.co.uk>
Tue, 19 Jan 2021 20:09:12 +0000 (12:09 -0800)
committerRichard Smith <richard@metafoo.co.uk>
Tue, 19 Jan 2021 20:48:39 +0000 (12:48 -0800)
argument's value off it during substitution.

clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp

index 7679063..7d7591a 100644 (file)
@@ -1597,7 +1597,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
 ExprResult
 TemplateInstantiator::TransformSubstNonTypeTemplateParmExpr(
                                           SubstNonTypeTemplateParmExpr *E) {
-  ExprResult SubstReplacement = TransformExpr(E->getReplacement());
+  ExprResult SubstReplacement = E->getReplacement();
+  if (!isa<ConstantExpr>(SubstReplacement.get()))
+    SubstReplacement = TransformExpr(E->getReplacement());
   if (SubstReplacement.isInvalid())
     return true;
   QualType SubstType = TransformType(E->getParameterType(getSema().Context));
index bc8a22e..4d61b9c 100644 (file)
@@ -511,3 +511,18 @@ namespace dependent_reference {
   // Ensure that we can instantiate the definition of S<...>.
   int n = *v.q + *w.q;
 }
+
+namespace decay {
+  template<typename T, typename C, const char *const A[(int)T::count]> struct X {
+    template<typename CC> void f(const X<T, CC, A> &v) {}
+  };
+  struct A {
+    static constexpr const char *arr[] = {"hello", "world"};
+    static constexpr int count = 2;
+  };
+  void f() {
+    X<A, int, A::arr> x1;
+    X<A, float, A::arr> x2;
+    x1.f(x2);
+  }
+}