(original) (raw)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 004f78f22ac36..8bae0d6e99ae0 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -293,6 +293,7 @@ Bug Fixes to Attribute Support Bug Fixes to C++ Support ^^^^^^^^^^^^^^^^^^^^^^^^ +- Clang now diagnoses copy constructors taking the class by value in template instantiations. (#GH130866) - Clang is now better at keeping track of friend function template instance contexts. (#GH55509) - Clang now prints the correct instantiation context for diagnostics suppressed by template argument deduction. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 96aac7871db1e..1c62a551ee732 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -10921,8 +10921,8 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { // parameters have default arguments. if (!Constructor->isInvalidDecl() && Constructor->hasOneParamOrDefaultArgs() && - Constructor->getTemplateSpecializationKind() != - TSK_ImplicitInstantiation) { + !Constructor->isFunctionTemplateSpecialization() + ) { QualType ParamType = Constructor->getParamDecl(0)->getType(); QualType ClassTy = Context.getTagDeclType(ClassDecl); if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { diff --git a/clang/test/SemaCXX/copy-ctor-template.cpp b/clang/test/SemaCXX/copy-ctor-template.cpp new file mode 100644 index 0000000000000..c58bd7c0c5e10 --- /dev/null +++ b/clang/test/SemaCXX/copy-ctor-template.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template+struct A{ + A(); // expected-note{{candidate constructor not viable: requires 0 arguments, but 1 was provided}} + A(A&); // expected-note{{candidate constructor not viable: expects an lvalue for 1st argument}} + A(A<v, t="">); // expected-error{{copy constructor must pass its first argument by reference}} +}; + +void f() { + A<int, int=""> a = A<int, int="">(); // expected-note{{in instantiation of template class 'A<int, int="">'}} + A<int, double=""> a1 = A<double, int="">(); // No error (not a copy constructor) +} + +// Test rvalue-to-lvalue conversion in copy constructor +A<int, int=""> &&a(void); +void g() { + A<int, int=""> a2 = a(); // expected-error{{no matching constructor}} +} + +template+struct B{ + B(); + template B(U); // No error (templated constructor) +}; + +void h() { + B<int, int=""> b = B<int, int="">(); // should use implicit copy constructor +} diff --git a/clang/test/SemaTemplate/constructor-template.cpp b/clang/test/SemaTemplate/constructor-template.cpp index a89dc60cfa347..13f00beb1ffc5 100644 --- a/clang/test/SemaTemplate/constructor-template.cpp +++ b/clang/test/SemaTemplate/constructor-template.cpp @@ -73,7 +73,7 @@ struct X3 { template X3(T); }; -template<> X3::X3(X3); // expected-error{{must pass its first argument by reference}} +template<> X3::X3(X3); // No error (template constructor) struct X4 { X4(); @@ -139,12 +139,12 @@ namespace self_by_value { template struct A { A() {} A(const A<t,u> &o) {} - A(A<t,t> o) {} + A(A<t,t> o) {} // expected-error{{copy constructor must pass its first argument by reference}} }; void helper(A<int,float>); - void test1(A<int,int> a) { + void test1(A<int,int> a) { // expected-note{{in instantiation of template class 'self_by_value::A<int, int="">'}} helper(a); } void test2() { @@ -156,12 +156,13 @@ namespace self_by_value_2 { template struct A { A() {} // precxx17-note {{not viable: requires 0 arguments}} A(A<t,u> &o) {} // precxx17-note {{not viable: expects an lvalue}} - A(A<t,t> o) {} // precxx17-note {{ignored: instantiation takes its own class type by value}} + A(A<t,t> o) {} // expected-error{{copy constructor must pass its first argument by reference}} }; void helper_A(A<int,int>); // precxx17-note {{passing argument to parameter here}} void test_A() { - helper_A(A<int,int>()); // precxx17-error {{no matching constructor}} + helper_A(A<int,int>()); // precxx17-error {{no matching constructor}} \ + // expected-note{{in instantiation of template class 'self_by_value_2::A<int, int="">'}} } } @@ -169,11 +170,11 @@ namespace self_by_value_3 { template struct A { A() {} A(A<t,u> &o) {} - A(A<t,t> o) {} + A(A<t,t> o) {} // expected-error{{copy constructor must pass its first argument by reference}} }; void helper_A(A<int,int>); - void test_A(A<int,int> b) { + void test_A(A<int,int> b) { // expected-note{{in instantiation of template class 'self_by_value_3::A<int, int="">'}} helper_A(b); } } </int,></int,int></int,int></int,int></t,t></t,t></t,u></int,></int,int></int,int></int,int></t,t></t,t></t,u></int,></int,int></int,int></int,float></t,t></t,t></t,u></int,></int,></int,></int,></double,></int,></int,></int,></int,></v,>