Skip to content

Commit 717010b

Browse files
author
git apple-llvm automerger
committed
Merge commit '20555a15a596' from llvm.org/main into next
2 parents 57bc6d2 + 20555a1 commit 717010b

File tree

5 files changed

+200
-79
lines changed

5 files changed

+200
-79
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4827,20 +4827,24 @@ class Sema final {
48274827
bool isMoveEligible() const { return S != None; };
48284828
bool isCopyElidable() const { return S == MoveEligibleAndCopyElidable; }
48294829
};
4830-
NamedReturnInfo getNamedReturnInfo(Expr *&E, bool ForceCXX2b = false);
4830+
enum class SimplerImplicitMoveMode { ForceOff, Normal, ForceOn };
4831+
NamedReturnInfo getNamedReturnInfo(
4832+
Expr *&E, SimplerImplicitMoveMode Mode = SimplerImplicitMoveMode::Normal);
48314833
NamedReturnInfo getNamedReturnInfo(const VarDecl *VD);
48324834
const VarDecl *getCopyElisionCandidate(NamedReturnInfo &Info,
48334835
QualType ReturnType);
48344836

4835-
ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
4836-
const NamedReturnInfo &NRInfo,
4837-
Expr *Value);
4837+
ExprResult
4838+
PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
4839+
const NamedReturnInfo &NRInfo, Expr *Value,
4840+
bool SupressSimplerImplicitMoves = false);
48384841

48394842
StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
48404843
Scope *CurScope);
48414844
StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
48424845
StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
4843-
NamedReturnInfo &NRInfo);
4846+
NamedReturnInfo &NRInfo,
4847+
bool SupressSimplerImplicitMoves);
48444848

48454849
StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
48464850
bool IsVolatile, unsigned NumOutputs,

clang/lib/Frontend/InitPreprocessor.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
598598
}
599599
// C++2b features.
600600
if (LangOpts.CPlusPlus2b) {
601-
if (!LangOpts.MSVCCompat)
602-
Builder.defineMacro("__cpp_implicit_move", "202011L");
601+
Builder.defineMacro("__cpp_implicit_move", "202011L");
603602
Builder.defineMacro("__cpp_size_t_suffix", "202011L");
604603
}
605604
if (LangOpts.Char8)

clang/lib/Sema/SemaCoroutine.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
977977
VarDecl *Promise = FSI->CoroutinePromise;
978978
ExprResult PC;
979979
if (E && (isa<InitListExpr>(E) || !E->getType()->isVoidType())) {
980-
getNamedReturnInfo(E, /*ForceCXX2b=*/true);
980+
getNamedReturnInfo(E, SimplerImplicitMoveMode::ForceOn);
981981
PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);
982982
} else {
983983
E = MakeFullDiscardedValueExpr(E).get();

clang/lib/Sema/SemaStmt.cpp

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3330,7 +3330,8 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
33303330
/// \returns An aggregate which contains the Candidate and isMoveEligible
33313331
/// and isCopyElidable methods. If Candidate is non-null, it means
33323332
/// 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) {
33343335
if (!E)
33353336
return NamedReturnInfo();
33363337
// - in a return statement in a function [where] ...
@@ -3342,13 +3343,10 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E, bool ForceCXX2b) {
33423343
if (!VD)
33433344
return NamedReturnInfo();
33443345
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.
33493346
if (Res.Candidate && !E->isXValue() &&
3350-
(ForceCXX2b ||
3351-
(getLangOpts().CPlusPlus2b && !getLangOpts().MSVCCompat))) {
3347+
(Mode == SimplerImplicitMoveMode::ForceOn ||
3348+
(Mode != SimplerImplicitMoveMode::ForceOff &&
3349+
getLangOpts().CPlusPlus2b))) {
33523350
E = ImplicitCastExpr::Create(Context, VD->getType().getNonReferenceType(),
33533351
CK_NoOp, E, nullptr, VK_XValue,
33543352
FPOptionsOverride());
@@ -3488,15 +3486,10 @@ VerifyInitializationSequenceCXX98(const Sema &S,
34883486
/// This routine implements C++20 [class.copy.elision]p3, which attempts to
34893487
/// treat returned lvalues as rvalues in certain cases (to prefer move
34903488
/// 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) &&
35003493
NRInfo.isMoveEligible()) {
35013494
ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
35023495
CK_NoOp, Value, VK_XValue, FPOptionsOverride());
@@ -3537,7 +3530,8 @@ static bool hasDeducedReturnType(FunctionDecl *FD) {
35373530
///
35383531
StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
35393532
Expr *RetValExp,
3540-
NamedReturnInfo &NRInfo) {
3533+
NamedReturnInfo &NRInfo,
3534+
bool SupressSimplerImplicitMoves) {
35413535
// If this is the first return we've seen, infer the return type.
35423536
// [expr.prim.lambda]p4 in C++11; block literals follow the same rules.
35433537
CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction());
@@ -3668,7 +3662,8 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc,
36683662
// the C version of which boils down to CheckSingleAssignmentConstraints.
36693663
InitializedEntity Entity = InitializedEntity::InitializeResult(
36703664
ReturnLoc, FnRetType, NRVOCandidate != nullptr);
3671-
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRInfo, RetValExp);
3665+
ExprResult Res = PerformMoveOrCopyInitialization(
3666+
Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves);
36723667
if (Res.isInvalid()) {
36733668
// FIXME: Cleanup temporaries here, anyway?
36743669
return StmtError();
@@ -3878,15 +3873,37 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
38783873
return R;
38793874
}
38803875

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+
38813890
StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
38823891
// Check for unexpanded parameter packs.
38833892
if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
38843893
return StmtError();
38853894

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);
38873903

38883904
if (isa<CapturingScopeInfo>(getCurFunction()))
3889-
return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp, NRInfo);
3905+
return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp, NRInfo,
3906+
SupressSimplerImplicitMoves);
38903907

38913908
QualType FnRetType;
38923909
QualType RelatedRetType;
@@ -4077,8 +4094,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
40774094
// we have a non-void function with an expression, continue checking
40784095
InitializedEntity Entity = InitializedEntity::InitializeResult(
40794096
ReturnLoc, RetType, NRVOCandidate != nullptr);
4080-
ExprResult Res =
4081-
PerformMoveOrCopyInitialization(Entity, NRInfo, RetValExp);
4097+
ExprResult Res = PerformMoveOrCopyInitialization(
4098+
Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves);
40824099
if (Res.isInvalid()) {
40834100
// FIXME: Clean up temporaries here anyway?
40844101
return StmtError();
Lines changed: 150 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,153 @@
1-
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fcxx-exceptions -verify=new %s
2-
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fcxx-exceptions -fms-compatibility -verify=old %s
3-
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=old %s
1+
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify=cxx2b,new %s
2+
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -fms-compatibility -verify=cxx2b,old %s
3+
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=cxx20,old %s
44

55
// FIXME: This is a test for a temporary workaround where we disable simpler implicit moves
6-
// when compiling with -fms-compatibility, because the MSVC STL does not compile.
7-
// A better workaround is under discussion.
8-
// The test cases here are just a copy from `CXX/class/class.init/class.copy.elision/p3.cpp`,
9-
// so feel free to delete this file when the workaround is not needed anymore.
10-
11-
struct CopyOnly {
12-
CopyOnly(); // new-note {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
13-
// new-note@-1 {{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
14-
CopyOnly(CopyOnly &); // new-note {{candidate constructor not viable: expects an lvalue for 1st argument}}
15-
// new-note@-1 {{candidate constructor not viable: expects an lvalue for 1st argument}}
16-
};
17-
struct MoveOnly {
18-
MoveOnly();
19-
MoveOnly(MoveOnly &&);
6+
// in the STL when compiling with -fms-compatibility, because of issues with the
7+
// implementation there.
8+
// Feel free to delete this file when the workaround is not needed anymore.
9+
10+
#if __INCLUDE_LEVEL__ == 0
11+
12+
#if __cpluscplus > 202002L && __cpp_implicit_move < 202011L
13+
#error "__cpp_implicit_move not defined correctly"
14+
#endif
15+
16+
struct nocopy {
17+
nocopy(nocopy &&);
2018
};
21-
MoveOnly &&rref();
22-
23-
MoveOnly &&test1(MoveOnly &&w) {
24-
return w; // old-error {{cannot bind to lvalue of type}}
25-
}
26-
27-
CopyOnly test2(bool b) {
28-
static CopyOnly w1;
29-
CopyOnly w2;
30-
if (b) {
31-
return w1;
32-
} else {
33-
return w2; // new-error {{no matching constructor for initialization}}
34-
}
35-
}
36-
37-
template <class T> T &&test3(T &&x) { return x; } // old-error {{cannot bind to lvalue of type}}
38-
template MoveOnly &test3<MoveOnly &>(MoveOnly &);
39-
template MoveOnly &&test3<MoveOnly>(MoveOnly &&); // old-note {{in instantiation of function template specialization}}
40-
41-
MoveOnly &&test4() {
42-
MoveOnly &&x = rref();
43-
return x; // old-error {{cannot bind to lvalue of type}}
44-
}
45-
46-
void test5() try {
47-
CopyOnly x;
48-
throw x; // new-error {{no matching constructor for initialization}}
49-
} catch (...) {
50-
}
51-
52-
MoveOnly test6(MoveOnly x) { return x; }
19+
20+
int &&mt1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
21+
int &mt2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
22+
nocopy mt3(nocopy x) { return x; }
23+
24+
namespace {
25+
int &&mt1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
26+
int &mt2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
27+
nocopy mt3(nocopy x) { return x; }
28+
} // namespace
29+
30+
namespace foo {
31+
int &&mt1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
32+
int &mt2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
33+
namespace std {
34+
int &&mt1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
35+
int &mt2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
36+
nocopy mt3(nocopy x) { return x; }
37+
} // namespace std
38+
} // namespace foo
39+
40+
namespace std {
41+
42+
int &&mt1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
43+
int &mt2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
44+
nocopy mt3(nocopy x) { return x; }
45+
46+
namespace {
47+
int &&mt1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
48+
int &mt2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
49+
nocopy mt3(nocopy x) { return x; }
50+
} // namespace
51+
52+
namespace foo {
53+
int &&mt1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
54+
int &mt2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
55+
nocopy mt3(nocopy x) { return x; }
56+
} // namespace foo
57+
58+
} // namespace std
59+
60+
#include __FILE__
61+
62+
#define SYSTEM
63+
#include __FILE__
64+
65+
#elif !defined(SYSTEM)
66+
67+
int &&ut1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
68+
int &ut2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
69+
nocopy ut3(nocopy x) { return x; }
70+
71+
namespace {
72+
int &&ut1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
73+
int &ut2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
74+
nocopy ut3(nocopy x) { return x; }
75+
} // namespace
76+
77+
namespace foo {
78+
int &&ut1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
79+
int &ut2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
80+
nocopy ut3(nocopy x) { return x; }
81+
namespace std {
82+
int &&ut1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
83+
int &ut2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
84+
nocopy ut3(nocopy x) { return x; }
85+
} // namespace std
86+
} // namespace foo
87+
88+
namespace std {
89+
90+
int &&ut1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
91+
int &ut2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
92+
nocopy ut3(nocopy x) { return x; }
93+
94+
namespace {
95+
int &&ut1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
96+
int &ut2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
97+
nocopy ut3(nocopy x) { return x; }
98+
} // namespace
99+
100+
namespace foo {
101+
int &&ut1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
102+
int &ut2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
103+
nocopy ut3(nocopy x) { return x; }
104+
} // namespace foo
105+
106+
} // namespace std
107+
108+
#else
109+
110+
#pragma GCC system_header
111+
112+
int &&st1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
113+
int &st2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
114+
nocopy st3(nocopy x) { return x; }
115+
116+
namespace {
117+
int &&st1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
118+
int &st2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
119+
nocopy st3(nocopy x) { return x; }
120+
} // namespace
121+
122+
namespace foo {
123+
int &&st1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
124+
int &st2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
125+
nocopy st3(nocopy x) { return x; }
126+
namespace std {
127+
int &&st1(int &&x) { return x; } // cxx20-error {{cannot bind to lvalue}}
128+
int &st2(int &&x) { return x; } // cxx2b-error {{cannot bind to a temporary}}
129+
nocopy st3(nocopy x) { return x; }
130+
} // namespace std
131+
} // namespace foo
132+
133+
namespace std {
134+
135+
int &&st1(int &&x) { return x; } // old-error {{cannot bind to lvalue}}
136+
int &st2(int &&x) { return x; } // new-error {{cannot bind to a temporary}}
137+
nocopy st3(nocopy x) { return x; }
138+
139+
namespace {
140+
int &&st1(int &&x) { return x; } // old-error {{cannot bind to lvalue}}
141+
int &st2(int &&x) { return x; } // new-error {{cannot bind to a temporary}}
142+
nocopy st3(nocopy x) { return x; }
143+
} // namespace
144+
145+
namespace foo {
146+
int &&st1(int &&x) { return x; } // old-error {{cannot bind to lvalue}}
147+
int &st2(int &&x) { return x; } // new-error {{cannot bind to a temporary}}
148+
nocopy st3(nocopy x) { return x; }
149+
} // namespace foo
150+
151+
} // namespace std
152+
153+
#endif

0 commit comments

Comments
 (0)