]> granicus.if.org Git - clang/commitdiff
Merging r369834:
authorHans Wennborg <hans@hanshq.net>
Tue, 27 Aug 2019 10:38:25 +0000 (10:38 +0000)
committerHans Wennborg <hans@hanshq.net>
Tue, 27 Aug 2019 10:38:25 +0000 (10:38 +0000)
------------------------------------------------------------------------
r369834 | rsmith | 2019-08-24 04:30:00 +0200 (Sat, 24 Aug 2019) | 8 lines

PR42513: Enter the proper DeclContext before substituting into an
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/branches/release_90@370038 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 ec4b63a2e508dcce15b5d02897323db19cc7ee91..135ca2b25cbe4ef516e751cd6ba20489ab72134a 100644 (file)
@@ -4692,6 +4692,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>(); }
+}