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