diff options
| author | John McCall <rjmccall@apple.com> | 2014-12-14 01:46:53 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2014-12-14 01:46:53 +0000 |
| commit | 578a1f8c6d275d2d3ffe327e72e4cbfed5bad7d8 (patch) | |
| tree | 20958f18531da4727cde35208a636a9969ea59ce /clang/test | |
| parent | 706f315e65841a964029c950e8569e6403f7793f (diff) | |
| download | bcm5719-llvm-578a1f8c6d275d2d3ffe327e72e4cbfed5bad7d8.tar.gz bcm5719-llvm-578a1f8c6d275d2d3ffe327e72e4cbfed5bad7d8.zip | |
If a non-template constructor instantiated to X(X),
ignore it during overload resolution when initializing
X from a value of type cv X.
Previously, our rule here only ignored specializations
of constructor templates. That's probably because the
standard says that constructors are outright ill-formed
if their first parameter is literally X and they're
callable with one argument. However, Clang only
enforces that prohibition against non-implicit
instantiations; I'm not sure why, but it seems to be
deliberate. Given that, the most sensible thing to
do is to just ignore the "illegal" constructor
regardless of where it came from.
Also, stop ignoring such constructors silently:
print a note explaining why they're being ignored.
Fixes <rdar://19199836>.
llvm-svn: 224205
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/SemaTemplate/constructor-template.cpp | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/clang/test/SemaTemplate/constructor-template.cpp b/clang/test/SemaTemplate/constructor-template.cpp index cf3fdfb7c1e..c5306a6e32f 100644 --- a/clang/test/SemaTemplate/constructor-template.cpp +++ b/clang/test/SemaTemplate/constructor-template.cpp @@ -54,7 +54,7 @@ struct B { A<int> x; B(B& a) : x(a.x) {} }; struct X2 { X2(); // expected-note{{candidate constructor}} X2(X2&); // expected-note {{candidate constructor}} - template<typename T> X2(T); + template<typename T> X2(T); // expected-note {{candidate template ignored: instantiation would take its own class type by value}} }; X2 test(bool Cond, X2 x2) { @@ -126,3 +126,51 @@ namespace PR8182 { } } + +// Don't blow out the stack trying to call an illegal constructor +// instantiation. We intentionally allow implicit instantiations to +// exist, so make sure they're unusable. +// +// rdar://19199836 +namespace self_by_value { + template <class T, class U> struct A { + A() {} + A(const A<T,U> &o) {} + A(A<T,T> o) {} + }; + + void helper(A<int,float>); + + void test1(A<int,int> a) { + helper(a); + } + void test2() { + helper(A<int,int>()); + } +} + +namespace self_by_value_2 { + template <class T, class U> struct A { + A() {} // expected-note {{not viable: requires 0 arguments}} + A(A<T,U> &o) {} // expected-note {{not viable: expects an l-value}} + A(A<T,T> o) {} // expected-note {{ignored: instantiation takes its own class type by value}} + }; + + void helper_A(A<int,int>); // expected-note {{passing argument to parameter here}} + void test_A() { + helper_A(A<int,int>()); // expected-error {{no matching constructor}} + } +} + +namespace self_by_value_3 { + template <class T, class U> struct A { + A() {} + A(A<T,U> &o) {} + A(A<T,T> o) {} + }; + + void helper_A(A<int,int>); + void test_A(A<int,int> b) { + helper_A(b); + } +} |

