[cfe-commits] r153849 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Initialization.h lib/Sema/SemaInit.cpp test/SemaCXX/cxx0x-initializer-constructor.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Sun Apr 1 12:54:59 PDT 2012
Author: cornedbee
Date: Sun Apr 1 14:54:59 2012
New Revision: 153849
URL: http://llvm.org/viewvc/llvm-project?rev=153849&view=rev
Log:
Properly handle explicit constructors in list-initialization. Fixes PR12120.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Initialization.h
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=153849&r1=153848&r2=153849&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Apr 1 14:54:59 2012
@@ -1189,6 +1189,10 @@
"an inaccessible constructor|find no viable constructor|find ambiguous "
"constructors|invoke a deleted constructor}0 in C++98">,
InGroup<CXX98CompatBindToTemporaryCopy>, DefaultIgnore;
+def err_selected_explicit_constructor : Error<
+ "chosen constructor is explicit in copy-initialization">;
+def note_constructor_declared_here : Note<
+ "constructor declared here">;
// C++11 decltype
def err_decltype_in_declarator : Error<
Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=153849&r1=153848&r2=153849&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Sun Apr 1 14:54:59 2012
@@ -719,7 +719,9 @@
FK_PlaceholderType,
/// \brief Failed to initialize a std::initializer_list because copy
/// construction of some element failed.
- FK_InitListElementCopyFailure
+ FK_InitListElementCopyFailure,
+ /// \brief List-copy-initialization chose an explicit constructor.
+ FK_ExplicitConstructor
};
private:
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=153849&r1=153848&r2=153849&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sun Apr 1 14:54:59 2012
@@ -2465,6 +2465,7 @@
case FK_VariableLengthArrayHasInitializer:
case FK_PlaceholderType:
case FK_InitListElementCopyFailure:
+ case FK_ExplicitConstructor:
return false;
case FK_ReferenceInitOverloadFailed:
@@ -2896,7 +2897,7 @@
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
- bool AllowExplicit = Kind.AllowExplicit();
+ bool AllowExplicit = Kind.AllowExplicit() || InitListSyntax;
bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy;
// - Otherwise, if T is a class type, constructors are considered. The
@@ -2961,10 +2962,18 @@
return;
}
+ // C++11 [over.match.list]p1:
+ // In copy-list-initialization, if an explicit constructor is chosen, the
+ // initializer is ill-formed.
+ CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+ if (InitListSyntax && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
+ Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
+ return;
+ }
+
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
bool HadMultipleCandidates = (CandidateSet.size() > 1);
- CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
Sequence.AddConstructorInitializationStep(CtorDecl,
Best->FoundDecl.getAccess(),
DestType, HadMultipleCandidates,
@@ -5729,6 +5738,18 @@
}
break;
}
+
+ case FK_ExplicitConstructor: {
+ S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor)
+ << Args[0]->getSourceRange();
+ OverloadCandidateSet::iterator Best;
+ OverloadingResult Ovl
+ = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
+ assert(Ovl == OR_Success && "Inconsistent overload resolution");
+ CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+ S.Diag(CtorDecl->getLocation(), diag::note_constructor_declared_here);
+ break;
+ }
}
PrintInitLocationNote(S, Entity);
@@ -5843,6 +5864,10 @@
case FK_InitListElementCopyFailure:
OS << "copy construction of initializer list element failed";
break;
+
+ case FK_ExplicitConstructor:
+ OS << "list copy initialization chose explicit constructor";
+ break;
}
OS << '\n';
return;
Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp?rev=153849&r1=153848&r2=153849&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp Sun Apr 1 14:54:59 2012
@@ -38,7 +38,7 @@
namespace objects {
struct X1 { X1(int); };
- struct X2 { explicit X2(int); }; // expected-note 2 {{candidate constructor}}
+ struct X2 { explicit X2(int); }; // expected-note {{constructor declared here}}
template <int N>
struct A {
@@ -94,7 +94,7 @@
{ X1 x{0}; }
{ X1 x = {0}; }
{ X2 x{0}; }
- { X2 x = {0}; } // expected-error {{no matching constructor}}
+ { X2 x = {0}; } // expected-error {{constructor is explicit}}
}
struct C {
@@ -153,9 +153,9 @@
G(std::initializer_list<int>, T ...); // expected-note 3 {{not viable}}
};
- struct H { // expected-note 8 {{not viable}}
- explicit H(int, int); // expected-note 3 {{not viable}}
- H(int, void*); // expected-note 4 {{not viable}}
+ struct H { // expected-note 6 {{not viable}}
+ explicit H(int, int); // expected-note 3 {{not viable}} expected-note {{declared here}}
+ H(int, void*); // expected-note 3 {{not viable}}
};
void edge_cases() {
@@ -191,7 +191,7 @@
H h1{1, nullptr};
H h2 = {1, nullptr};
H h3{1, 1};
- H h4 = {1, 1}; // expected-error {{no matching constructor}}
+ H h4 = {1, 1}; // expected-error {{constructor is explicit}}
};
}
@@ -259,3 +259,11 @@
// 4 levels: init list, gen_pair, command_map via init list, command_pair
const std::initializer_list<generator_pair> y = {{{{1, 2}}}};
}
+
+namespace PR12120 {
+ struct A { explicit A(int); A(float); }; // expected-note {{declared here}}
+ A a = { 0 }; // expected-error {{constructor is explicit}}
+
+ struct B { explicit B(short); B(long); }; // expected-note 2 {{candidate}}
+ B b = { 0 }; // expected-error {{ambiguous}}
+}
More information about the cfe-commits
mailing list