summaryrefslogtreecommitdiffstats
path: root/clang/test/SemaTemplate/temp_arg_template.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-04-13 21:37:24 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-04-13 21:37:24 +0000
commit1389418e18407da990cc5c503eb78d1bc8532fc8 (patch)
treecd200dff8f7e3e8eec47769e84a53a642b68ea88 /clang/test/SemaTemplate/temp_arg_template.cpp
parentd0e9481c55e1edca268a240359d3acc4c2a212fa (diff)
downloadbcm5719-llvm-1389418e18407da990cc5c503eb78d1bc8532fc8.tar.gz
bcm5719-llvm-1389418e18407da990cc5c503eb78d1bc8532fc8.zip
PR32185: Revert r291512 and add a testcase for PR32185.
This reverts an attempt to check that types match when matching a dependently-typed non-type template parameter. (This comes up when matching the parameters of a template template parameter against the parameters of a template template argument.) The matching rules here are murky at best. Our behavior after this revert is definitely wrong for certain C++17 features (for 'auto' template parameter types within the parameter list of a template template argument in particular), but our behavior before this revert is wrong for some pre-existing testcases, so reverting to our prior behavior seems like our best option. llvm-svn: 300262
Diffstat (limited to 'clang/test/SemaTemplate/temp_arg_template.cpp')
-rw-r--r--clang/test/SemaTemplate/temp_arg_template.cpp41
1 files changed, 38 insertions, 3 deletions
diff --git a/clang/test/SemaTemplate/temp_arg_template.cpp b/clang/test/SemaTemplate/temp_arg_template.cpp
index b0df9149c6e..8f59dd724cc 100644
--- a/clang/test/SemaTemplate/temp_arg_template.cpp
+++ b/clang/test/SemaTemplate/temp_arg_template.cpp
@@ -102,7 +102,42 @@ void foo() {
}
namespace CheckDependentNonTypeParamTypes {
- template<template<typename T, typename U, T v> class> struct A {}; // expected-note {{previous}}
- template<typename T, typename U, U v> struct B {}; // expected-note {{different type}}
- A<B> ab; // expected-error {{different template parameters}}
+ template<template<typename T, typename U, T v> class X> struct A {
+ void f() {
+ X<int, void*, 3> x; // expected-error {{does not refer to any declaration}}
+ }
+ void g() {
+ X<int, long, 3> x;
+ }
+ void h() {
+ // FIXME: If we accept A<B> at all, it's not obvious what should happen
+ // here. While parsing the template, we form
+ // X<unsigned char, int, (unsigned char)1234>
+ // but in the final instantiation do we get
+ // B<unsigned char, int, (int)1234>
+ // or
+ // B<unsigned char, int, (int)(unsigned char)1234>
+ // ?
+ X<unsigned char, int, 1234> x;
+ int check[x.value == 1234 ? 1 : -1];
+ }
+ };
+
+ template<typename T, typename U, U v> struct B { // expected-note {{parameter}}
+ static const U value = v;
+ };
+
+ // FIXME: This should probably be rejected, but the rules are at best unclear.
+ A<B> ab;
+
+ void use() {
+ ab.f(); // expected-note {{instantiation of}}
+ ab.g();
+ ab.h();
+ }
+}
+
+namespace PR32185 {
+ template<template<typename T, T> class U> struct A {};
+ template<template<typename T, T> class U> struct B : A<U> {};
}
OpenPOWER on IntegriCloud