summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2014-12-14 01:46:53 +0000
committerJohn McCall <rjmccall@apple.com>2014-12-14 01:46:53 +0000
commit578a1f8c6d275d2d3ffe327e72e4cbfed5bad7d8 (patch)
tree20958f18531da4727cde35208a636a9969ea59ce /clang/test
parent706f315e65841a964029c950e8569e6403f7793f (diff)
downloadbcm5719-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.cpp50
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);
+ }
+}
OpenPOWER on IntegriCloud