Author: rsmith Date: Fri Aug 23 19:30:00 2019 New Revision: 369834 URL: http://llvm.org/viewvc/llvm-project?rev=369834&view=rev Log: 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. Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx11.cpp Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=369834&r1=369833&r2=369834&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Aug 23 19:30:00 2019 @@ -4693,6 +4693,7 @@ SubstDefaultTemplateArgument(Sema &SemaR 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); Modified: cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp?rev=369834&r1=369833&r2=369834&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp Fri Aug 23 19:30:00 2019 @@ -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 { Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx11.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx11.cpp?rev=369834&r1=369833&r2=369834&view=diff ============================================================================== --- cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx11.cpp (original) +++ cfe/trunk/test/SemaTemplate/temp_arg_nontype_cxx11.cpp Fri Aug 23 19:30:00 2019 @@ -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>(); } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits