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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to