summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-08-24 02:30:00 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-08-24 02:30:00 +0000
commit3a4eadc9fc677db3fb3303c749e88315e9d658b7 (patch)
tree93b4cc4c9a5543a0365b421a2c4b8f3e731ff7e2
parentec57b202e7c266df2f81c8e37316d0564878c179 (diff)
downloadclang-3a4eadc9fc677db3fb3303c749e88315e9d658b7.tar.gz
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/trunk@369834 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaTemplate.cpp1
-rw-r--r--test/SemaCXX/cxx1z-class-template-argument-deduction.cpp9
-rw-r--r--test/SemaTemplate/temp_arg_nontype_cxx11.cpp17
3 files changed, 24 insertions, 3 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index a73c5d3f9b..d230ec90d7 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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);
diff --git a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index c5deb9fe91..85312cf104 100644
--- a/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -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 {
diff --git a/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
index 313114e2cb..460b6def5d 100644
--- a/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
+++ b/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
@@ -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>(); }
+}