]> granicus.if.org Git - clang/commitdiff
PR42513: Enter the proper DeclContext before substituting into an
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 24 Aug 2019 02:30:00 +0000 (02:30 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 24 Aug 2019 02:30:00 +0000 (02:30 +0000)
default template argument expression.

We already did this for type template parameters and template template
parameters, but apparently forgot to do so for non-type template
parameters. This causes the substituted default argument expression to
be substituted in the proper context, and in particular to properly mark
its subexpressions as odr-used.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@369834 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplate.cpp
test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
test/SemaTemplate/temp_arg_nontype_cxx11.cpp

index a73c5d3f9bc678e389453e53cee76d73bb440e45..d230ec90d7771db51bed980e66ecf56d38a5402c 100644 (file)
@@ -4693,6 +4693,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
   for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
     TemplateArgLists.addOuterTemplateArguments(None);
 
+  Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
   EnterExpressionEvaluationContext ConstantEvaluated(
       SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
   return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists);
index c5deb9fe91950193092a0defc076786ef9eeef0e..85312cf1049fa668073e8a61fb2ebbb4c644cbf6 100644 (file)
@@ -268,13 +268,16 @@ namespace tuple_tests {
   // Don't get caught by surprise when X<...> doesn't even exist in the
   // selected specialization!
   namespace libcxx_2 {
-    template<class ...T> struct tuple { // expected-note {{candidate}}
+    template<class ...T> struct tuple {
       template<class ...Args> struct X { static const bool value = false; };
+      // Substitution into X<U...>::value succeeds but produces the
+      // value-dependent expression
+      //   tuple<T...>::X<>::value
+      // FIXME: Is that the right behavior?
       template<class ...U, bool Y = X<U...>::value> tuple(U &&...u);
-      // expected-note@-1 {{substitution failure [with T = <>, U = <int, int, int>]: cannot reference member of primary template because deduced class template specialization 'tuple<>' is an explicit specialization}}
     };
     template <> class tuple<> {};
-    tuple a = {1, 2, 3}; // expected-error {{no viable constructor or deduction guide}}
+    tuple a = {1, 2, 3}; // expected-error {{excess elements in struct initializer}}
   }
 
   namespace libcxx_3 {
index 313114e2cb8ee043b5b03aea89a50317469ec0ed..460b6def5d6f386fa7d178ed05c6e4146398482b 100644 (file)
@@ -48,3 +48,20 @@ void Useage() {
 }
 }
 
+namespace PR42513 {
+  template<typename X, int Ret = WidgetCtor((X*)nullptr)> void f();
+  constexpr int WidgetCtor(struct X1*);
+
+  struct X1 {
+    friend constexpr int WidgetCtor(X1*);
+  };
+  template<typename X1>
+  struct StandardWidget {
+    friend constexpr int WidgetCtor(X1*) {
+      return 0;
+    }
+  };
+  template struct StandardWidget<X1>;
+
+  void use() { f<X1>(); }
+}