forked from OSchip/llvm-project
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:
parent
9955f14aaf
commit
0f5dbfd29a
|
@ -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
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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'}}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue