Revert D123909 "[Clang] Use of decltype(capture) in parameter-declaration-clause"

This reverts commit daa6d7b250.

It breaks valid code like https://reviews.llvm.org/D123909#3461716
This commit is contained in:
Fangrui Song 2022-04-20 10:32:41 -07:00
parent 9955f14aaf
commit 0f5dbfd29a
7 changed files with 12 additions and 93 deletions

View File

@ -281,8 +281,6 @@ C++2b Feature Support
- Implemented `P2036R3: Change scope of lambda trailing-return-type <https://wg21.link/P2036R3>`_. - Implemented `P2036R3: Change scope of lambda trailing-return-type <https://wg21.link/P2036R3>`_.
This proposal modifies how variables captured in lambdas can appear in trailing return type This proposal modifies how variables captured in lambdas can appear in trailing return type
expressions and how their types are deduced therein, in all C++ language versions. expressions and how their types are deduced therein, in all C++ language versions.
`CWG2569 <https://cplusplus.github.io/CWG/issues/2569.html>`_ is also partially implemented so that
`[x](decltype(x)){}` doesn't become ill-formed with the adoption of P2036R3.
CUDA Language Changes in Clang CUDA Language Changes in Clang
------------------------------ ------------------------------

View File

@ -1861,8 +1861,6 @@ private:
Token &Replacement); Token &Replacement);
ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
ExprResult ParseCXXMaybeMutableAgnosticExpression();
bool areTokensAdjacent(const Token &A, const Token &B); bool areTokensAdjacent(const Token &A, const Token &B);
void CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectTypePtr, void CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectTypePtr,

View File

@ -787,23 +787,6 @@ public:
/// context. /// context.
unsigned FunctionScopesStart = 0; unsigned FunctionScopesStart = 0;
/// Whether we are currently in the context of a mutable agnostic identifier
/// as described by CWG2569.
/// We are handling the unqualified-id of a decltype or noexcept expression.
bool InMutableAgnosticContext = false;
/// RAII object used to change the value of \c InMutableAgnosticContext
/// within a \c Sema object.
class MutableAgnosticContextRAII {
Sema &SemaRef;
public:
MutableAgnosticContextRAII(Sema &S) : SemaRef(S) {
SemaRef.InMutableAgnosticContext = true;
}
~MutableAgnosticContextRAII() { SemaRef.InMutableAgnosticContext = false; }
};
ArrayRef<sema::FunctionScopeInfo*> getFunctionScopes() const { ArrayRef<sema::FunctionScopeInfo*> getFunctionScopes() const {
return llvm::makeArrayRef(FunctionScopes.begin() + FunctionScopesStart, return llvm::makeArrayRef(FunctionScopes.begin() + FunctionScopesStart,
FunctionScopes.end()); FunctionScopes.end());
@ -5287,9 +5270,6 @@ public:
CorrectionCandidateCallback *CCC = nullptr, CorrectionCandidateCallback *CCC = nullptr,
bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr); bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
ExprResult ActOnMutableAgnosticIdExpression(Scope *S, CXXScopeSpec &SS,
UnqualifiedId &Id);
void DecomposeUnqualifiedId(const UnqualifiedId &Id, void DecomposeUnqualifiedId(const UnqualifiedId &Id,
TemplateArgumentListInfo &Buffer, TemplateArgumentListInfo &Buffer,
DeclarationNameInfo &NameInfo, DeclarationNameInfo &NameInfo,

View File

@ -1054,7 +1054,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
Sema::ExpressionEvaluationContextRecord::EK_Decltype); Sema::ExpressionEvaluationContextRecord::EK_Decltype);
Result = Actions.CorrectDelayedTyposInExpr( Result = Actions.CorrectDelayedTyposInExpr(
ParseCXXMaybeMutableAgnosticExpression(), /*InitDecl=*/nullptr, ParseExpression(), /*InitDecl=*/nullptr,
/*RecoverUncorrectedTypos=*/false, /*RecoverUncorrectedTypos=*/false,
[](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; }); [](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; });
if (Result.isInvalid()) { if (Result.isInvalid()) {

View File

@ -685,34 +685,6 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
return Result; return Result;
} }
/// ParseCXXMaybeMutableAgnosticExpression - Handle expressions inside of
/// sizeof, decltype, noexcept
/// - unqualified-id
/// - expression
/// This serves to silence errors about captured variable referred in lambda
/// parameter list, if they are used as the unqualified-id of a decltype,
/// sizeof, or noexcept expression.
ExprResult Parser::ParseCXXMaybeMutableAgnosticExpression() {
if (!getLangOpts().CPlusPlus11)
return ParseExpression();
if (Tok.is(tok::identifier) && NextToken().is(tok::r_paren)) {
UnqualifiedId Name;
CXXScopeSpec SS;
if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
/*ObjectHadErrors=*/false,
/*EnteringContext=*/false,
/*AllowDestructorName=*/false,
/*AllowConstructorName=*/false,
/*AllowDeductionGuide=*/false,
/*TemplateKWLoc=*/nullptr, Name))
return ExprError();
return Actions.ActOnMutableAgnosticIdExpression(getCurScope(), SS, Name);
}
return ParseExpression();
}
/// ParseLambdaExpression - Parse a C++11 lambda expression. /// ParseLambdaExpression - Parse a C++11 lambda expression.
/// ///
/// lambda-expression: /// lambda-expression:

View File

@ -2699,18 +2699,6 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
return BuildDeclarationNameExpr(SS, R, ADL); return BuildDeclarationNameExpr(SS, R, ADL);
} }
ExprResult Sema::ActOnMutableAgnosticIdExpression(Scope *S, CXXScopeSpec &SS,
UnqualifiedId &Id) {
MutableAgnosticContextRAII Ctx(*this);
return ActOnIdExpression(S, SS, /*TemplateKwLoc*/
SourceLocation(), Id,
/*HasTrailingLParen*/ false,
/*IsAddressOfOperand*/ false,
/*CorrectionCandidateCallback*/ nullptr,
/*IsInlineAsmIdentifier*/ false,
/*KeywordReplacement*/ nullptr);
}
/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified /// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
/// declaration name, generally during template instantiation. /// declaration name, generally during template instantiation.
/// There's a large number of things which don't need to be done along /// There's a large number of things which don't need to be done along
@ -18561,11 +18549,6 @@ static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI,
static bool CheckCaptureUseBeforeLambdaQualifiers(Sema &S, VarDecl *Var, static bool CheckCaptureUseBeforeLambdaQualifiers(Sema &S, VarDecl *Var,
SourceLocation ExprLoc, SourceLocation ExprLoc,
LambdaScopeInfo *LSI) { LambdaScopeInfo *LSI) {
// Allow `[a = 1](decltype(a)) {}` as per CWG2569.
if (S.InMutableAgnosticContext)
return true;
if (Var->isInvalidDecl()) if (Var->isInvalidDecl())
return false; return false;
@ -18648,7 +18631,7 @@ bool Sema::tryCaptureVariable(
LSI = dyn_cast_or_null<LambdaScopeInfo>( LSI = dyn_cast_or_null<LambdaScopeInfo>(
FunctionScopes[FunctionScopesIndex]); FunctionScopes[FunctionScopesIndex]);
if (LSI && LSI->BeforeLambdaQualifiersScope) { if (LSI && LSI->BeforeLambdaQualifiersScope) {
if (isa<ParmVarDecl>(Var) && !Var->getDeclContext()->isFunctionOrMethod()) if (isa<ParmVarDecl>(Var))
return true; return true;
IsInLambdaBeforeQualifiers = true; IsInLambdaBeforeQualifiers = true;
if (!CheckCaptureUseBeforeLambdaQualifiers(*this, Var, ExprLoc, LSI)) { if (!CheckCaptureUseBeforeLambdaQualifiers(*this, Var, ExprLoc, LSI)) {

View File

@ -87,23 +87,23 @@ void err() {
int y, z; // expected-note 2{{declared here}} int y, z; // expected-note 2{{declared here}}
auto implicit_tpl = [=]( // expected-note {{variable 'y' is captured here}} auto implicit_tpl = [=]( // expected-note {{variable 'y' is captured here}}
decltype( decltype(
[&]<decltype((y))> { return 0; }) y) { // expected-error{{captured variable 'y' cannot appear here}} [&]<decltype(y)> { return 0; }) y) { //expected-error{{captured variable 'y' cannot appear here}}
return y; return y;
}; };
auto init_tpl = [x = 1]( // expected-note{{explicitly captured here}} auto init_tpl = [x = 1]( // expected-note{{explicitly captured here}}
decltype([&]<decltype((x))> { return 0; }) y) { // expected-error {{captured variable 'x' cannot appear here}} decltype([&]<decltype(x)> { return 0; }) y) { // expected-error {{captured variable 'x' cannot appear here}}
return x; return x;
}; };
auto implicit = [=]( // expected-note {{variable 'z' is captured here}} auto implicit = [=]( // expected-note {{variable 'z' is captured here}}
decltype( decltype(
[&](decltype((z))) { return 0; }) z) { // expected-error{{captured variable 'z' cannot appear here}} [&](decltype(z)) { return 0; }) z) { //expected-error{{captured variable 'z' cannot appear here}}
return z; return z;
}; };
auto init = [x = 1]( // expected-note{{explicitly captured here}} auto init = [x = 1]( // expected-note{{explicitly captured here}}
decltype([&](decltype((x))) { return 0; }) y) { // expected-error {{captured variable 'x' cannot appear here}} decltype([&](decltype(x)) { return 0; }) y) { // expected-error {{captured variable 'x' cannot appear here}}
return x; return x;
}; };
@ -141,20 +141,20 @@ void nested() {
decltype([&]( decltype([&](
decltype([=]( // expected-note {{variable 'x' is captured here}} decltype([=]( // expected-note {{variable 'x' is captured here}}
decltype([&]( decltype([&](
decltype([&](decltype((x))) {}) // expected-error{{captured variable 'x' cannot appear here}} decltype([&](decltype(x)) {}) // expected-error{{captured variable 'x' cannot appear here}}
) {})) {})) {})){}; ) {})) {})) {})){};
(void)[&]( (void)[&](
decltype([&]( decltype([&](
decltype([&]( decltype([&](
decltype([&]( decltype([&](
decltype([&](decltype((y))) {})) {})) {})) {})){}; decltype([&](decltype(y)) {})) {})) {})) {})){};
(void)[=]( (void)[=](
decltype([=]( decltype([=](
decltype([=]( decltype([=](
decltype([=]( // expected-note {{variable 'z' is captured here}} decltype([=]( // expected-note {{variable 'z' is captured here}}
decltype([&]<decltype((z))> {}) // expected-error{{captured variable 'z' cannot appear here}} decltype([&]<decltype(z)> {}) // expected-error{{captured variable 'z' cannot appear here}}
) {})) {})) {})){}; ) {})) {})) {})){};
} }
@ -202,15 +202,3 @@ void test_dependent() {
dependent_init_capture(0); dependent_init_capture(0);
dependent_variadic_capture(1, 2, 3, 4); dependent_variadic_capture(1, 2, 3, 4);
} }
void test_CWG2569_tpl(auto a) {
(void)[=]<typename T = decltype(a)>(decltype(a) b = decltype(a)()){};
}
void test_CWG2569() {
int a = 0;
(void)[=]<typename T = decltype(a)>(decltype(a) b = decltype(a)()){};
test_CWG2569_tpl(0);
(void)[=]<typename T = decltype(not_a_thing)>(decltype(not_a_thing)){}; // expected-error 2{{use of undeclared identifier 'not_a_thing'}}
}