diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/Parse/ParseExprCXX.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'clang/lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 198 |
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); } |