diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-04-13 21:37:24 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-04-13 21:37:24 +0000 |
commit | 1389418e18407da990cc5c503eb78d1bc8532fc8 (patch) | |
tree | cd200dff8f7e3e8eec47769e84a53a642b68ea88 /clang/test/SemaTemplate/temp_arg_template.cpp | |
parent | d0e9481c55e1edca268a240359d3acc4c2a212fa (diff) | |
download | bcm5719-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.cpp | 41 |
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> {}; } |