@@ -3330,7 +3330,8 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
3330
3330
// / \returns An aggregate which contains the Candidate and isMoveEligible
3331
3331
// / and isCopyElidable methods. If Candidate is non-null, it means
3332
3332
// / isMoveEligible() would be true under the most permissive language standard.
3333
- Sema::NamedReturnInfo Sema::getNamedReturnInfo (Expr *&E, bool ForceCXX2b) {
3333
+ Sema::NamedReturnInfo Sema::getNamedReturnInfo (Expr *&E,
3334
+ SimplerImplicitMoveMode Mode) {
3334
3335
if (!E)
3335
3336
return NamedReturnInfo ();
3336
3337
// - in a return statement in a function [where] ...
@@ -3342,13 +3343,10 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E, bool ForceCXX2b) {
3342
3343
if (!VD)
3343
3344
return NamedReturnInfo ();
3344
3345
NamedReturnInfo Res = getNamedReturnInfo (VD);
3345
- // FIXME: We supress simpler implicit move here (unless ForceCXX2b is true)
3346
- // in msvc compatibility mode just as a temporary work around,
3347
- // as the MSVC STL has issues with this change.
3348
- // We will come back later with a more targeted approach.
3349
3346
if (Res.Candidate && !E->isXValue () &&
3350
- (ForceCXX2b ||
3351
- (getLangOpts ().CPlusPlus2b && !getLangOpts ().MSVCCompat ))) {
3347
+ (Mode == SimplerImplicitMoveMode::ForceOn ||
3348
+ (Mode != SimplerImplicitMoveMode::ForceOff &&
3349
+ getLangOpts ().CPlusPlus2b ))) {
3352
3350
E = ImplicitCastExpr::Create (Context, VD->getType ().getNonReferenceType (),
3353
3351
CK_NoOp, E, nullptr , VK_XValue,
3354
3352
FPOptionsOverride ());
@@ -3488,15 +3486,10 @@ VerifyInitializationSequenceCXX98(const Sema &S,
3488
3486
// / This routine implements C++20 [class.copy.elision]p3, which attempts to
3489
3487
// / treat returned lvalues as rvalues in certain cases (to prefer move
3490
3488
// / construction), then falls back to treating them as lvalues if that failed.
3491
- ExprResult
3492
- Sema::PerformMoveOrCopyInitialization (const InitializedEntity &Entity,
3493
- const NamedReturnInfo &NRInfo,
3494
- Expr *Value) {
3495
- // FIXME: We force P1825 implicit moves here in msvc compatibility mode
3496
- // because we are disabling simpler implicit moves as a temporary
3497
- // work around, as the MSVC STL has issues with this change.
3498
- // We will come back later with a more targeted approach.
3499
- if ((!getLangOpts ().CPlusPlus2b || getLangOpts ().MSVCCompat ) &&
3489
+ ExprResult Sema::PerformMoveOrCopyInitialization (
3490
+ const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value,
3491
+ bool SupressSimplerImplicitMoves) {
3492
+ if ((!getLangOpts ().CPlusPlus2b || SupressSimplerImplicitMoves) &&
3500
3493
NRInfo.isMoveEligible ()) {
3501
3494
ImplicitCastExpr AsRvalue (ImplicitCastExpr::OnStack, Value->getType (),
3502
3495
CK_NoOp, Value, VK_XValue, FPOptionsOverride ());
@@ -3537,7 +3530,8 @@ static bool hasDeducedReturnType(FunctionDecl *FD) {
3537
3530
// /
3538
3531
StmtResult Sema::ActOnCapScopeReturnStmt (SourceLocation ReturnLoc,
3539
3532
Expr *RetValExp,
3540
- NamedReturnInfo &NRInfo) {
3533
+ NamedReturnInfo &NRInfo,
3534
+ bool SupressSimplerImplicitMoves) {
3541
3535
// If this is the first return we've seen, infer the return type.
3542
3536
// [expr.prim.lambda]p4 in C++11; block literals follow the same rules.
3543
3537
CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction ());
@@ -3668,7 +3662,8 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
3668
3662
// the C version of which boils down to CheckSingleAssignmentConstraints.
3669
3663
InitializedEntity Entity = InitializedEntity::InitializeResult (
3670
3664
ReturnLoc, FnRetType, NRVOCandidate != nullptr );
3671
- ExprResult Res = PerformMoveOrCopyInitialization (Entity, NRInfo, RetValExp);
3665
+ ExprResult Res = PerformMoveOrCopyInitialization (
3666
+ Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves);
3672
3667
if (Res.isInvalid ()) {
3673
3668
// FIXME: Cleanup temporaries here, anyway?
3674
3669
return StmtError ();
@@ -3878,15 +3873,37 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
3878
3873
return R;
3879
3874
}
3880
3875
3876
+ static bool CheckSimplerImplicitMovesMSVCWorkaround (const Sema &S,
3877
+ const Expr *E) {
3878
+ if (!E || !S.getLangOpts ().CPlusPlus2b || !S.getLangOpts ().MSVCCompat )
3879
+ return false ;
3880
+ const Decl *D = E->getReferencedDeclOfCallee ();
3881
+ if (!D || !S.SourceMgr .isInSystemHeader (D->getLocation ()))
3882
+ return false ;
3883
+ for (const DeclContext *DC = D->getDeclContext (); DC; DC = DC->getParent ()) {
3884
+ if (DC->isStdNamespace ())
3885
+ return true ;
3886
+ }
3887
+ return false ;
3888
+ }
3889
+
3881
3890
StmtResult Sema::BuildReturnStmt (SourceLocation ReturnLoc, Expr *RetValExp) {
3882
3891
// Check for unexpanded parameter packs.
3883
3892
if (RetValExp && DiagnoseUnexpandedParameterPack (RetValExp))
3884
3893
return StmtError ();
3885
3894
3886
- NamedReturnInfo NRInfo = getNamedReturnInfo (RetValExp);
3895
+ // HACK: We supress simpler implicit move here in msvc compatibility mode
3896
+ // just as a temporary work around, as the MSVC STL has issues with
3897
+ // this change.
3898
+ bool SupressSimplerImplicitMoves =
3899
+ CheckSimplerImplicitMovesMSVCWorkaround (*this , RetValExp);
3900
+ NamedReturnInfo NRInfo = getNamedReturnInfo (
3901
+ RetValExp, SupressSimplerImplicitMoves ? SimplerImplicitMoveMode::ForceOff
3902
+ : SimplerImplicitMoveMode::Normal);
3887
3903
3888
3904
if (isa<CapturingScopeInfo>(getCurFunction ()))
3889
- return ActOnCapScopeReturnStmt (ReturnLoc, RetValExp, NRInfo);
3905
+ return ActOnCapScopeReturnStmt (ReturnLoc, RetValExp, NRInfo,
3906
+ SupressSimplerImplicitMoves);
3890
3907
3891
3908
QualType FnRetType;
3892
3909
QualType RelatedRetType;
@@ -4077,8 +4094,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
4077
4094
// we have a non-void function with an expression, continue checking
4078
4095
InitializedEntity Entity = InitializedEntity::InitializeResult (
4079
4096
ReturnLoc, RetType, NRVOCandidate != nullptr );
4080
- ExprResult Res =
4081
- PerformMoveOrCopyInitialization ( Entity, NRInfo, RetValExp);
4097
+ ExprResult Res = PerformMoveOrCopyInitialization (
4098
+ Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves );
4082
4099
if (Res.isInvalid ()) {
4083
4100
// FIXME: Clean up temporaries here anyway?
4084
4101
return StmtError ();
0 commit comments