mizvekov created this revision.
Herald added subscribers: jansvoboda11, dexonsmith, lxfind, dang.
mizvekov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

WIP, not yet ready for review.

Small sample of things wrong with this patch:

- Have to remove some copypasta.
- Fix from D98971 <https://reviews.llvm.org/D98971> directly imported here
- Some further simplifications needed.
- Test suite not updated to test new mode.
- In fact, the test suite was not run at all...

Just some manual testing:

- return: moderate
- throw: light
- co_return: not tested yet

Signed-off-by: Matheus Izvekov <mizve...@gmail.com>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D99005

Files:
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Sema/SemaCoroutine.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaType.cpp

Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8839,6 +8839,10 @@
   if (E->isTypeDependent())
     return S.Context.DependentTy;
 
+  Expr *IDExpr = E;
+  if (auto ImplCastExpr = dyn_cast<ImplicitCastExpr>(E)) {
+    IDExpr = ImplCastExpr->getSubExpr();
+  }
   // C++11 [dcl.type.simple]p4:
   //   The type denoted by decltype(e) is defined as follows:
 
@@ -8849,7 +8853,7 @@
   // Note that this does not pick up the implicit 'const' for a template
   // parameter object. This rule makes no difference before C++20 so we apply
   // it unconditionally.
-  if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(E))
+  if (const auto *SNTTPE = dyn_cast<SubstNonTypeTemplateParmExpr>(IDExpr))
     return SNTTPE->getParameterType(S.Context);
 
   //     - if e is an unparenthesized id-expression or an unparenthesized class
@@ -8858,21 +8862,22 @@
   //       functions, the program is ill-formed;
   //
   // We apply the same rules for Objective-C ivar and property references.
-  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr)) {
     const ValueDecl *VD = DRE->getDecl();
     if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD))
       return TPO->getType().getUnqualifiedType();
     return VD->getType();
-  } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
+  } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(IDExpr)) {
     if (const ValueDecl *VD = ME->getMemberDecl())
       if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
         return VD->getType();
-  } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
+  } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(IDExpr)) {
     return IR->getDecl()->getType();
-  } else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
+  } else if (const ObjCPropertyRefExpr *PR =
+                 dyn_cast<ObjCPropertyRefExpr>(IDExpr)) {
     if (PR->isExplicitProperty())
       return PR->getExplicitProperty()->getType();
-  } else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
+  } else if (auto *PE = dyn_cast<PredefinedExpr>(IDExpr)) {
     return PE->getType();
   }
 
@@ -8885,8 +8890,8 @@
   //   entity.
   using namespace sema;
   if (S.getCurLambda()) {
-    if (isa<ParenExpr>(E)) {
-      if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
+    if (isa<ParenExpr>(IDExpr)) {
+      if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(IDExpr->IgnoreParens())) {
         if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
           QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
           if (!T.isNull())
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3041,6 +3041,8 @@
 /// NRVO, or NULL if there is no such candidate.
 VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, Expr *E,
                                        CopyElisionSemanticsKind CESK) {
+  if (auto ImplCastExpr = dyn_cast<ImplicitCastExpr>(E))
+    E = ImplCastExpr->getSubExpr();
   // - in a return statement in a function [where] ...
   // ... the expression is the name of a non-volatile automatic object ...
   DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens());
@@ -3086,15 +3088,14 @@
   if (VD->hasAttr<BlocksAttr>())
     return false;
 
-  // ...non-volatile...
-  if (VD->getType().isVolatileQualified())
-    return false;
-
-  // C++20 [class.copy.elision]p3:
-  // ...rvalue reference to a non-volatile...
-  if (VD->getType()->isRValueReferenceType() &&
-      (!(CESK & CES_AllowRValueReferenceType) ||
-       VD->getType().getNonReferenceType().isVolatileQualified()))
+  QualType VDNonRefType = VDType;
+  if (VDType->isReferenceType()) {
+    if (!(CESK & CES_AllowRValueReferenceType) ||
+        !VDType->isRValueReferenceType())
+      return false;
+    VDNonRefType = VDType.getNonReferenceType();
+  }
+  if (!VDNonRefType->isObjectType() || VDNonRefType.isVolatileQualified())
     return false;
 
   if (CESK & CES_AllowDifferentTypes)
@@ -3102,8 +3103,8 @@
 
   // Variables with higher required alignment than their type's ABI
   // alignment cannot use NRVO.
-  if (!VD->getType()->isDependentType() && VD->hasAttr<AlignedAttr>() &&
-      Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VD->getType()))
+  if (!VDNonRefType->isDependentType() && VD->hasAttr<AlignedAttr>() &&
+      Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VDNonRefType))
     return false;
 
   return true;
@@ -3221,15 +3222,16 @@
   ExprResult Res = ExprError();
   bool NeedSecondOverloadResolution = true;
 
-  if (AllowNRVO) {
-    CopyElisionSemanticsKind CESK = CES_Strict;
-    if (getLangOpts().CPlusPlus20) {
-      CESK = CES_ImplicitlyMovableCXX20;
-    } else if (getLangOpts().CPlusPlus11) {
-      CESK = CES_ImplicitlyMovableCXX11CXX14CXX17;
-    }
-
+  if (!(getLangOpts().CPlusPlus2b &&
+        getLangOpts().CPlusPlusSimplerImplicitMove) &&
+      AllowNRVO) {
     if (!NRVOCandidate) {
+      CopyElisionSemanticsKind CESK = CES_Strict;
+      if (getLangOpts().CPlusPlus20) {
+        CESK = CES_ImplicitlyMovableCXX20;
+      } else if (getLangOpts().CPlusPlus11) {
+        CESK = CES_ImplicitlyMovableCXX11CXX14CXX17;
+      }
       NRVOCandidate = getCopyElisionCandidate(ResultType, Value, CESK);
     }
 
@@ -3650,6 +3652,15 @@
   if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
     return StmtError();
 
+  if (getLangOpts().CPlusPlus2b && getLangOpts().CPlusPlusSimplerImplicitMove) {
+    if (VarDecl *VD = getCopyElisionCandidate(QualType{}, RetValExp,
+                                              CES_ImplicitlyMovableCXX20)) {
+      RetValExp = ImplicitCastExpr::Create(
+          Context, VD->getType().getNonReferenceType(), CK_NoOp, RetValExp,
+          nullptr, VK_XValue, FPOptionsOverride());
+    }
+  }
+
   if (isa<CapturingScopeInfo>(getCurFunction()))
     return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp);
 
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -851,6 +851,16 @@
     Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
 
   if (Ex && !Ex->isTypeDependent()) {
+    if (getLangOpts().CPlusPlus2b &&
+        getLangOpts().CPlusPlusSimplerImplicitMove) {
+      if (VarDecl *VD = getCopyElisionCandidate(QualType{}, Ex,
+                                                CES_ImplicitlyMovableCXX20)) {
+        Ex = ImplicitCastExpr::Create(
+            Context, VD->getType().getNonReferenceType(), CK_NoOp, Ex, nullptr,
+            VK_XValue, FPOptionsOverride());
+      }
+    }
+
     QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType());
     if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex))
       return ExprError();
Index: clang/lib/Sema/SemaCoroutine.cpp
===================================================================
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -999,10 +999,13 @@
     const VarDecl *NRVOCandidate = this->getCopyElisionCandidate(
         E->getType(), E, CES_ImplicitlyMovableCXX20);
     if (NRVOCandidate) {
+      QualType T = NRVOCandidate->getType();
+      E = ImplicitCastExpr::Create(Context, T.getNonReferenceType(), CK_NoOp, E,
+                                   nullptr, VK_XValue, FPOptionsOverride());
       InitializedEntity Entity =
-          InitializedEntity::InitializeResult(Loc, E->getType(), NRVOCandidate);
-      ExprResult MoveResult = this->PerformMoveOrCopyInitialization(
-          Entity, NRVOCandidate, E->getType(), E);
+          InitializedEntity::InitializeResult(Loc, T, NRVOCandidate);
+      ExprResult MoveResult =
+          this->PerformMoveOrCopyInitialization(Entity, NRVOCandidate, T, E);
       if (MoveResult.get())
         E = MoveResult.get();
     }
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -5837,6 +5837,12 @@
     CmdArgs.push_back("-fcoroutines-ts");
   }
 
+  if (Args.hasFlag(options::OPT_fsimpler_implicit_move,
+                   options::OPT_fno_simpler_implicit_move, false) &&
+      types::isCXX(InputType)) {
+    CmdArgs.push_back("-fsimpler-implicit-move");
+  }
+
   Args.AddLastArg(CmdArgs, options::OPT_fdouble_square_bracket_attributes,
                   options::OPT_fno_double_square_bracket_attributes);
 
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1069,6 +1069,12 @@
   PosFlag<SetTrue, [CC1Option], "Enable support for the C++ Coroutines TS">,
   NegFlag<SetFalse>>;
 
+// C++2b Simpler Implicit Move
+defm simpler_implicit_move : BoolFOption<"simpler-implicit-move",
+  LangOpts<"CPlusPlusSimplerImplicitMove">, DefaultFalse,
+  PosFlag<SetTrue, [CC1Option], "Enable support for C++2b simpler implicit move (P2266)">,
+  NegFlag<SetFalse>>;
+
 def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">,
     Group<f_Group>, Flags<[NoXarchOption, CC1Option, CC1AsOption]>, MetaVarName<"<option>">,
     HelpText<"Embed LLVM bitcode (option: off, all, bitcode, marker)">,
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -144,6 +144,7 @@
 LANGOPT(NoMathBuiltin     , 1, 0, "disable math builtin functions")
 LANGOPT(GNUAsm            , 1, 1, "GNU-style inline assembly")
 LANGOPT(Coroutines        , 1, 0, "C++20 coroutines")
+LANGOPT(CPlusPlusSimplerImplicitMove, 1, 0, "C++2b simpler implicit move")
 LANGOPT(DllExportInlines  , 1, 1, "dllexported classes dllexport inline methods")
 LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments")
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to