aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseExprCXX.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/Parse/ParseExprCXX.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'clang/lib/Parse/ParseExprCXX.cpp')
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp198
1 files changed, 122 insertions, 76 deletions
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 9bd89eddb455..7f09120574a7 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
@@ -21,6 +22,7 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <numeric>
@@ -979,11 +981,10 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
InitKind = LambdaCaptureInitKind::DirectInit;
ExprVector Exprs;
- CommaLocsTy Commas;
if (Tentative) {
Parens.skipToEnd();
*Tentative = LambdaIntroducerTentativeParse::Incomplete;
- } else if (ParseExpressionList(Exprs, Commas)) {
+ } else if (ParseExpressionList(Exprs)) {
Parens.skipToEnd();
Init = ExprError();
} else {
@@ -1156,51 +1157,66 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro,
static void tryConsumeLambdaSpecifierToken(Parser &P,
SourceLocation &MutableLoc,
+ SourceLocation &StaticLoc,
SourceLocation &ConstexprLoc,
SourceLocation &ConstevalLoc,
SourceLocation &DeclEndLoc) {
assert(MutableLoc.isInvalid());
+ assert(StaticLoc.isInvalid());
assert(ConstexprLoc.isInvalid());
+ assert(ConstevalLoc.isInvalid());
// Consume constexpr-opt mutable-opt in any sequence, and set the DeclEndLoc
// to the final of those locations. Emit an error if we have multiple
// copies of those keywords and recover.
+ auto ConsumeLocation = [&P, &DeclEndLoc](SourceLocation &SpecifierLoc,
+ int DiagIndex) {
+ if (SpecifierLoc.isValid()) {
+ P.Diag(P.getCurToken().getLocation(),
+ diag::err_lambda_decl_specifier_repeated)
+ << DiagIndex
+ << FixItHint::CreateRemoval(P.getCurToken().getLocation());
+ }
+ SpecifierLoc = P.ConsumeToken();
+ DeclEndLoc = SpecifierLoc;
+ };
+
while (true) {
switch (P.getCurToken().getKind()) {
- case tok::kw_mutable: {
- if (MutableLoc.isValid()) {
- P.Diag(P.getCurToken().getLocation(),
- diag::err_lambda_decl_specifier_repeated)
- << 0 << FixItHint::CreateRemoval(P.getCurToken().getLocation());
- }
- MutableLoc = P.ConsumeToken();
- DeclEndLoc = MutableLoc;
- break /*switch*/;
- }
+ case tok::kw_mutable:
+ ConsumeLocation(MutableLoc, 0);
+ break;
+ case tok::kw_static:
+ ConsumeLocation(StaticLoc, 1);
+ break;
case tok::kw_constexpr:
- if (ConstexprLoc.isValid()) {
- P.Diag(P.getCurToken().getLocation(),
- diag::err_lambda_decl_specifier_repeated)
- << 1 << FixItHint::CreateRemoval(P.getCurToken().getLocation());
- }
- ConstexprLoc = P.ConsumeToken();
- DeclEndLoc = ConstexprLoc;
- break /*switch*/;
+ ConsumeLocation(ConstexprLoc, 2);
+ break;
case tok::kw_consteval:
- if (ConstevalLoc.isValid()) {
- P.Diag(P.getCurToken().getLocation(),
- diag::err_lambda_decl_specifier_repeated)
- << 2 << FixItHint::CreateRemoval(P.getCurToken().getLocation());
- }
- ConstevalLoc = P.ConsumeToken();
- DeclEndLoc = ConstevalLoc;
- break /*switch*/;
+ ConsumeLocation(ConstevalLoc, 3);
+ break;
default:
return;
}
}
}
+static void addStaticToLambdaDeclSpecifier(Parser &P, SourceLocation StaticLoc,
+ DeclSpec &DS) {
+ if (StaticLoc.isValid()) {
+ P.Diag(StaticLoc, !P.getLangOpts().CPlusPlus2b
+ ? diag::err_static_lambda
+ : diag::warn_cxx20_compat_static_lambda);
+ const char *PrevSpec = nullptr;
+ unsigned DiagID = 0;
+ DS.SetStorageClassSpec(P.getActions(), DeclSpec::SCS_static, StaticLoc,
+ PrevSpec, DiagID,
+ P.getActions().getASTContext().getPrintingPolicy());
+ assert(PrevSpec == nullptr && DiagID == 0 &&
+ "Static cannot have been set previously!");
+ }
+}
+
static void
addConstexprToLambdaDeclSpecifier(Parser &P, SourceLocation ConstexprLoc,
DeclSpec &DS) {
@@ -1231,6 +1247,24 @@ static void addConstevalToLambdaDeclSpecifier(Parser &P,
}
}
+static void DiagnoseStaticSpecifierRestrictions(Parser &P,
+ SourceLocation StaticLoc,
+ SourceLocation MutableLoc,
+ const LambdaIntroducer &Intro) {
+ if (StaticLoc.isInvalid())
+ return;
+
+ // [expr.prim.lambda.general] p4
+ // The lambda-specifier-seq shall not contain both mutable and static.
+ // If the lambda-specifier-seq contains static, there shall be no
+ // lambda-capture.
+ if (MutableLoc.isValid())
+ P.Diag(StaticLoc, diag::err_static_mutable_lambda);
+ if (Intro.hasLambdaCapture()) {
+ P.Diag(StaticLoc, diag::err_static_lambda_captures);
+ }
+}
+
/// ParseLambdaExpressionAfterIntroducer - Parse the rest of a lambda
/// expression.
ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
@@ -1256,7 +1290,22 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
if (getLangOpts().CUDA) {
// In CUDA code, GNU attributes are allowed to appear immediately after the
// "[...]", even if there is no "(...)" before the lambda body.
- MaybeParseGNUAttributes(D);
+ //
+ // Note that we support __noinline__ as a keyword in this mode and thus
+ // it has to be separately handled.
+ while (true) {
+ if (Tok.is(tok::kw___noinline__)) {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+ Attr.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ ParsedAttr::AS_Keyword);
+ } else if (Tok.is(tok::kw___attribute))
+ ParseGNUAttributes(Attr, nullptr, &D);
+ else
+ break;
+ }
+
+ D.takeAttributes(Attr);
}
// Helper to emit a warning if we see a CUDA host/device/global attribute
@@ -1330,14 +1379,18 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
// the mutable specifier to be compatible with MSVC.
MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attr);
- // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update
- // the DeclEndLoc.
+ // Parse lambda specifiers and update the DeclEndLoc.
SourceLocation MutableLoc;
+ SourceLocation StaticLoc;
SourceLocation ConstexprLoc;
SourceLocation ConstevalLoc;
- tryConsumeLambdaSpecifierToken(*this, MutableLoc, ConstexprLoc,
- ConstevalLoc, DeclEndLoc);
+ tryConsumeLambdaSpecifierToken(*this, MutableLoc, StaticLoc,
+ ConstexprLoc, ConstevalLoc, DeclEndLoc);
+
+ DiagnoseStaticSpecifierRestrictions(*this, StaticLoc, MutableLoc,
+ Intro);
+ addStaticToLambdaDeclSpecifier(*this, StaticLoc, DS);
addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS);
addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS);
// Parse exception-specification[opt].
@@ -1390,8 +1443,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
DynamicExceptions.size(),
NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,
/*ExceptionSpecTokens*/ nullptr,
- /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D,
- TrailingReturnType, TrailingReturnTypeLoc, &DS),
+ /*DeclsInPrototype=*/std::nullopt, LParenLoc, FunLocalRangeEnd,
+ D, TrailingReturnType, TrailingReturnTypeLoc, &DS),
std::move(Attr), DeclEndLoc);
};
@@ -1412,8 +1465,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
Actions.RecordParsingTemplateParameterDepth(
CurTemplateDepthTracker.getOriginalDepth());
- ParseParameterDeclarationClause(D.getContext(), Attr, ParamInfo,
- EllipsisLoc);
+ ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);
// For a generic lambda, each 'auto' within the parameter declaration
// clause creates a template type parameter, so increment the depth.
// If we've parsed any explicit template parameters, then the depth will
@@ -1433,10 +1485,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
if (Tok.is(tok::kw_requires))
ParseTrailingRequiresClause(D);
} else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute,
- tok::kw_constexpr, tok::kw_consteval,
+ tok::kw_constexpr, tok::kw_consteval, tok::kw_static,
tok::kw___private, tok::kw___global, tok::kw___local,
tok::kw___constant, tok::kw___generic,
- tok::kw_requires, tok::kw_noexcept) ||
+ tok::kw_groupshared, tok::kw_requires,
+ tok::kw_noexcept) ||
(Tok.is(tok::l_square) && NextToken().is(tok::l_square))) {
if (!getLangOpts().CPlusPlus2b)
// It's common to forget that one needs '()' before 'mutable', an
@@ -1520,7 +1573,8 @@ ExprResult Parser::ParseCXXCasts() {
// Parse the common declaration-specifiers piece.
DeclSpec DS(AttrFactory);
- ParseSpecifierQualifierList(DS);
+ ParseSpecifierQualifierList(DS, /*AccessSpecifier=*/AS_none,
+ DeclSpecContext::DSC_type_specifier);
// Parse the abstract-declarator, if present.
Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),
@@ -1874,7 +1928,6 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
PreferredType.enterTypeCast(Tok.getLocation(), TypeRep.get());
ExprVector Exprs;
- CommaLocsTy CommaLocs;
auto RunSignatureHelp = [&]() {
QualType PreferredType;
@@ -1887,7 +1940,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
};
if (Tok.isNot(tok::r_paren)) {
- if (ParseExpressionList(Exprs, CommaLocs, [&] {
+ if (ParseExpressionList(Exprs, [&] {
PreferredType.enterFunctionArgument(Tok.getLocation(),
RunSignatureHelp);
})) {
@@ -1905,8 +1958,6 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
if (!TypeRep)
return ExprError();
- assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
- "Unexpected number of commas!");
return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(),
Exprs, T.getCloseLocation(),
/*ListInitialization=*/false);
@@ -2318,8 +2369,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
/// type-specifier-seq: [C++ 8.1]
/// type-specifier type-specifier-seq[opt]
///
-bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
- ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_type_specifier);
+bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS, DeclaratorContext Context) {
+ ParseSpecifierQualifierList(DS, AS_none,
+ getDeclSpecContextFromDeclaratorContext(Context));
DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());
return false;
}
@@ -2735,7 +2787,8 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
// Parse the type-specifier-seq.
DeclSpec DS(AttrFactory);
- if (ParseCXXTypeSpecifierSeq(DS)) // FIXME: ObjectType?
+ if (ParseCXXTypeSpecifierSeq(
+ DS, DeclaratorContext::ConversionId)) // FIXME: ObjectType?
return true;
// Parse the conversion-declarator, which is merely a sequence of
@@ -2819,6 +2872,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
// identifier
// template-id (when it hasn't already been annotated)
if (Tok.is(tok::identifier)) {
+ ParseIdentifier:
// Consume the identifier.
IdentifierInfo *Id = Tok.getIdentifierInfo();
SourceLocation IdLoc = ConsumeToken();
@@ -3053,9 +3107,20 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
return false;
}
- Diag(Tok, diag::err_expected_unqualified_id)
- << getLangOpts().CPlusPlus;
- return true;
+ switch (Tok.getKind()) {
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
+ if (!NextToken().is(tok::l_paren)) {
+ Tok.setKind(tok::identifier);
+ Diag(Tok, diag::ext_keyword_as_ident)
+ << Tok.getIdentifierInfo()->getName() << 0;
+ goto ParseIdentifier;
+ }
+ [[fallthrough]];
+ default:
+ Diag(Tok, diag::err_expected_unqualified_id) << getLangOpts().CPlusPlus;
+ return true;
+ }
}
/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
@@ -3170,7 +3235,6 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
T.consumeOpen();
ConstructorLParen = T.getOpenLocation();
if (Tok.isNot(tok::r_paren)) {
- CommaLocsTy CommaLocs;
auto RunSignatureHelp = [&]() {
ParsedType TypeRep =
Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
@@ -3186,7 +3250,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
CalledSignatureHelp = true;
return PreferredType;
};
- if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] {
+ if (ParseExpressionList(ConstructorArgs, [&] {
PreferredType.enterFunctionArgument(Tok.getLocation(),
RunSignatureHelp);
})) {
@@ -3285,9 +3349,7 @@ bool Parser::ParseExpressionListOrTypeId(
}
// It's not a type, it has to be an expression list.
- // Discard the comma locations - ActOnCXXNew has enough parameters.
- CommaLocsTy CommaLocs;
- return ParseExpressionList(PlacementArgs, CommaLocs);
+ return ParseExpressionList(PlacementArgs);
}
/// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
@@ -3447,6 +3509,10 @@ ExprResult Parser::ParseRequiresExpression() {
Actions, Sema::ExpressionEvaluationContext::Unevaluated);
ParseScope BodyScope(this, Scope::DeclScope);
+ // Create a separate diagnostic pool for RequiresExprBodyDecl.
+ // Dependent diagnostics are attached to this Decl and non-depenedent
+ // diagnostics are surfaced after this parse.
+ ParsingDeclRAIIObject ParsingBodyDecl(*this, ParsingDeclRAIIObject::NoParent);
RequiresExprBodyDecl *Body = Actions.ActOnStartRequiresExpr(
RequiresKWLoc, LocalParameterDecls, getCurScope());
@@ -3684,6 +3750,7 @@ ExprResult Parser::ParseRequiresExpression() {
}
Braces.consumeClose();
Actions.ActOnFinishRequiresExpr();
+ ParsingBodyDecl.complete(Body);
return Actions.ActOnRequiresExpr(RequiresKWLoc, Body, LocalParameterDecls,
Requirements, Braces.getCloseLocation());
}
@@ -3724,14 +3791,6 @@ static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) {
}
}
-static unsigned TypeTraitArity(tok::TokenKind kind) {
- switch (kind) {
- default: llvm_unreachable("Not a known type trait");
-#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N;
-#include "clang/Basic/TokenKinds.def"
- }
-}
-
/// Parse the built-in type-trait pseudo-functions that allow
/// implementation of the TR1/C++11 type traits templates.
///
@@ -3745,7 +3804,6 @@ static unsigned TypeTraitArity(tok::TokenKind kind) {
///
ExprResult Parser::ParseTypeTrait() {
tok::TokenKind Kind = Tok.getKind();
- unsigned Arity = TypeTraitArity(Kind);
SourceLocation Loc = ConsumeToken();
@@ -3780,18 +3838,6 @@ ExprResult Parser::ParseTypeTrait() {
SourceLocation EndLoc = Parens.getCloseLocation();
- if (Arity && Args.size() != Arity) {
- Diag(EndLoc, diag::err_type_trait_arity)
- << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc);
- return ExprError();
- }
-
- if (!Arity && Args.empty()) {
- Diag(EndLoc, diag::err_type_trait_arity)
- << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc);
- return ExprError();
- }
-
return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc);
}