nullptr.cpp created this revision.
nullptr.cpp requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D92936
Files:
clang/lib/Sema/SemaInit.cpp
clang/lib/Sema/SemaStmt.cpp
clang/test/CXX/class/class.init/class.copy.elision/p3.cpp
Index: clang/test/CXX/class/class.init/class.copy.elision/p3.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/class/class.init/class.copy.elision/p3.cpp
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=cxx20 %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fcxx-exceptions -verify=cxx11_14_17 %s
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -fcxx-exceptions -verify=cxx11_14_17 %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify=cxx11_14_17 %s
+
+namespace test_delete_function {
+struct A1 {
+ A1();
+ A1(const A1&);
+ A1(A1&&) = delete;
+ // cxx11_14_17-note@-1 {{'A1' has been explicitly marked deleted here}}
+ // cxx20-note@-2 {{'A1' has been explicitly marked deleted here}}
+};
+A1 test1() {
+ A1 a;
+ return a;
+ // cxx11_14_17-error@-1 {{call to deleted constructor of 'test_delete_function::A1'}}
+ // cxx20-error@-2 {{call to deleted constructor of 'test_delete_function::A1'}}
+}
+
+struct A2 {
+ A2();
+ A2(const A2&);
+private:
+ A2(A2&&);
+ // cxx11_14_17-note@-1 {{declared private here}}
+ // cxx20-note@-2 {{declared private here}}
+};
+A2 test2() {
+ A2 a;
+ return a;
+ // cxx11_14_17-error@-1 {{calling a private constructor of class 'test_delete_function::A2'}}
+ // cxx20-error@-2 {{calling a private constructor of class 'test_delete_function::A2'}}
+}
+
+
+struct C {};
+
+struct B1 {
+ B1(C&);
+ B1(C&&) = delete;
+ // cxx11_14_17-note@-1 {{'B1' has been explicitly marked deleted here}}
+ // cxx20-note@-2 {{'B1' has been explicitly marked deleted here}}
+};
+B1 test3() {
+ C c;
+ return c;
+ // cxx11_14_17-error@-1 {{conversion function from 'test_delete_function::C' to 'test_delete_function::B1' invokes a deleted function}}
+ // cxx20-error@-2 {{conversion function from 'test_delete_function::C' to 'test_delete_function::B1' invokes a deleted function}}
+}
+
+struct B2 {
+ B2(C&);
+private:
+ B2(C&&);
+ // cxx11_14_17-note@-1 {{declared private here}}
+ // cxx20-note@-2 {{declared private here}}
+};
+B2 test4() {
+ C c;
+ return c;
+ // cxx11_14_17-error@-1 {{calling a private constructor of class 'test_delete_function::B2'}}
+ // cxx20-error@-2 {{calling a private constructor of class 'test_delete_function::B2'}}
+}
+} // namespace test_delete_function
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3106,11 +3106,14 @@
/// If move-initialization is not possible, such that we must fall back to
/// treating the operand as an lvalue, we will leave Res in its original
/// invalid state.
-static void TryMoveInitialization(Sema& S,
- const InitializedEntity &Entity,
+///
+/// \returns Whether need to do the second overload resolution. If the first
+/// overload resolution fails, or if the first overload resolution success but
+/// the selected constructor/operator doesn't match the additional criteria, we
+/// need to do the second overload resolution.
+static bool TryMoveInitialization(Sema &S, const InitializedEntity &Entity,
const VarDecl *NRVOCandidate,
- QualType ResultType,
- Expr *&Value,
+ QualType ResultType, Expr *&Value,
bool ConvertingConstructorsOnly,
ExprResult &Res) {
ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
@@ -3123,8 +3126,10 @@
InitializationSequence Seq(S, Entity, Kind, InitExpr);
- if (!Seq)
- return;
+ bool NeedSecondOverload = true;
+ if (!Seq && Seq.getFailedOverloadResult() != OR_Deleted) {
+ return NeedSecondOverload;
+ }
for (const InitializationSequence::Step &Step : Seq.steps()) {
if (Step.Kind != InitializationSequence::SK_ConstructorInitialization &&
@@ -3167,6 +3172,7 @@
}
}
+ NeedSecondOverload = false;
// Promote "AsRvalue" to the heap, since we now need this
// expression node to persist.
Value =
@@ -3177,6 +3183,8 @@
// using the constructor we found.
Res = Seq.Perform(S, Entity, Kind, Value);
}
+
+ return NeedSecondOverload;
}
/// Perform the initialization of a potentially-movable value, which
@@ -3201,6 +3209,7 @@
// select the constructor for the copy is first performed as if the object
// were designated by an rvalue.
ExprResult Res = ExprError();
+ bool NeedSecondOverload = true;
if (AllowNRVO) {
bool AffectedByCWG1579 = false;
@@ -3217,11 +3226,11 @@
}
if (NRVOCandidate) {
- TryMoveInitialization(*this, Entity, NRVOCandidate, ResultType, Value,
- true, Res);
+ NeedSecondOverload = TryMoveInitialization(*this, Entity, NRVOCandidate,
+ ResultType, Value, true, Res);
}
- if (!Res.isInvalid() && AffectedByCWG1579) {
+ if (!NeedSecondOverload && AffectedByCWG1579) {
QualType QT = NRVOCandidate->getType();
if (QT.getNonReferenceType()
.getUnqualifiedType()
@@ -3244,7 +3253,7 @@
Diag(Value->getExprLoc(), diag::note_add_std_move_in_cxx11)
<< FixItHint::CreateReplacement(Value->getSourceRange(), Str);
}
- } else if (Res.isInvalid() &&
+ } else if (NeedSecondOverload &&
!getDiagnostics().isIgnored(diag::warn_return_std_move,
Value->getExprLoc())) {
const VarDecl *FakeNRVOCandidate =
@@ -3285,7 +3294,7 @@
// Either we didn't meet the criteria for treating an lvalue as an rvalue,
// above, or overload resolution failed. Either way, we need to try
// (again) now with the return value expression as written.
- if (Res.isInvalid())
+ if (NeedSecondOverload)
Res = PerformCopyInitialization(Entity, SourceLocation(), Value);
return Res;
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -4119,7 +4119,11 @@
InitializationSequence::FK_ListConstructorOverloadFailed :
InitializationSequence::FK_ConstructorOverloadFailed,
Result);
- return;
+
+ // delete function also need the initialization sequence.
+ // TODO: which FailureKind?
+ if (Result != OR_Deleted)
+ return;
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@@ -5260,7 +5264,8 @@
Sequence.SetOverloadFailure(
InitializationSequence::FK_UserConversionOverloadFailed,
Result);
- return;
+ if (Result != OR_Deleted)
+ return;
}
FunctionDecl *Function = Best->Function;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits