diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp | 624 |
1 files changed, 368 insertions, 256 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp index f3d10b4a0889..d61f414406f0 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseExprCXX.cpp @@ -14,13 +14,16 @@ #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" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include <numeric> @@ -453,8 +456,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier( bool IsCorrectedToColon = false; bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr; if (Actions.ActOnCXXNestedNameSpecifier( - getCurScope(), IdInfo, EnteringContext, SS, false, - CorrectionFlagPtr, OnlyNamespace)) { + getCurScope(), IdInfo, EnteringContext, SS, CorrectionFlagPtr, + OnlyNamespace)) { // Identifier is not recognized as a nested name, but we can have // mistyped '::' instead of ':'. if (CorrectionFlagPtr && IsCorrectedToColon) { @@ -668,7 +671,7 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { // CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, - /*ObjectHadErrors=*/false, + /*ObjectHasErrors=*/false, /*EnteringContext=*/false); Token Replacement; @@ -722,7 +725,7 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { /// '&' identifier initializer /// /// lambda-declarator: -/// lambda-specifiers [C++2b] +/// lambda-specifiers [C++23] /// '(' parameter-declaration-clause ')' lambda-specifiers /// requires-clause[opt] /// @@ -979,11 +982,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 { @@ -1068,8 +1070,8 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // Ensure that any ellipsis was in the right place. SourceLocation EllipsisLoc; - if (std::any_of(std::begin(EllipsisLocs), std::end(EllipsisLocs), - [](SourceLocation Loc) { return Loc.isValid(); })) { + if (llvm::any_of(EllipsisLocs, + [](SourceLocation Loc) { return Loc.isValid(); })) { // The '...' should appear before the identifier in an init-capture, and // after the identifier otherwise. bool InitCapture = InitKind != LambdaCaptureInitKind::NoInit; @@ -1156,51 +1158,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().CPlusPlus23 + ? 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 +1248,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( @@ -1241,35 +1276,40 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc, "lambda expression parsing"); - - - // FIXME: Call into Actions to add any init-capture declarations to the - // scope while parsing the lambda-declarator and compound-statement. - // Parse lambda-declarator[opt]. DeclSpec DS(AttrFactory); - Declarator D(DS, DeclaratorContext::LambdaExpr); + Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::LambdaExpr); TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); + + ParseScope LambdaScope(this, Scope::LambdaScope | Scope::DeclScope | + Scope::FunctionDeclarationScope | + Scope::FunctionPrototypeScope); + Actions.PushLambdaScope(); + Actions.ActOnLambdaExpressionAfterIntroducer(Intro, getCurScope()); - ParsedAttributes Attr(AttrFactory); + ParsedAttributes Attributes(AttrFactory); 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(); + Attributes.addNew(AttrName, AttrNameLoc, /*ScopeName=*/nullptr, + AttrNameLoc, /*ArgsUnion=*/nullptr, + /*numArgs=*/0, tok::kw___noinline__); + } else if (Tok.is(tok::kw___attribute)) + ParseGNUAttributes(Attributes, /*LatePArsedAttrList=*/nullptr, &D); + else + break; + } - // Helper to emit a warning if we see a CUDA host/device/global attribute - // after '(...)'. nvcc doesn't accept this. - auto WarnIfHasCUDATargetAttr = [&] { - if (getLangOpts().CUDA) - for (const ParsedAttr &A : Attr) - if (A.getKind() == ParsedAttr::AT_CUDADevice || - A.getKind() == ParsedAttr::AT_CUDAHost || - A.getKind() == ParsedAttr::AT_CUDAGlobal) - Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position) - << A.getAttrName()->getName(); - }; + D.takeAttributes(Attributes); + } MultiParseScope TemplateParamScope(*this); if (Tok.is(tok::less)) { @@ -1300,7 +1340,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( } Actions.ActOnLambdaExplicitTemplateParameterList( - LAngleLoc, TemplateParams, RAngleLoc, RequiresClause); + Intro, LAngleLoc, TemplateParams, RAngleLoc, RequiresClause); ++CurTemplateDepthTracker; } } @@ -1310,109 +1350,39 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // or operator template declaration. We accept this as a conforming extension // in all language modes that support lambdas. if (isCXX11AttributeSpecifier()) { - Diag(Tok, getLangOpts().CPlusPlus2b + Diag(Tok, getLangOpts().CPlusPlus23 ? diag::warn_cxx20_compat_decl_attrs_on_lambda - : diag::ext_decl_attrs_on_lambda); + : diag::ext_decl_attrs_on_lambda) + << Tok.getIdentifierInfo() << Tok.isRegularKeywordAttribute(); MaybeParseCXX11Attributes(D); } TypeResult TrailingReturnType; SourceLocation TrailingReturnTypeLoc; + SourceLocation LParenLoc, RParenLoc; + SourceLocation DeclEndLoc; + bool HasParentheses = false; + bool HasSpecifiers = false; + SourceLocation MutableLoc; - auto ParseLambdaSpecifiers = - [&](SourceLocation LParenLoc, SourceLocation RParenLoc, - MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo, - SourceLocation EllipsisLoc) { - SourceLocation DeclEndLoc = RParenLoc; - - // GNU-style attributes must be parsed before the mutable specifier to - // be compatible with GCC. MSVC-style attributes must be parsed before - // 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. - SourceLocation MutableLoc; - SourceLocation ConstexprLoc; - SourceLocation ConstevalLoc; - tryConsumeLambdaSpecifierToken(*this, MutableLoc, ConstexprLoc, - ConstevalLoc, DeclEndLoc); - - addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS); - addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS); - // Parse exception-specification[opt]. - ExceptionSpecificationType ESpecType = EST_None; - SourceRange ESpecRange; - SmallVector<ParsedType, 2> DynamicExceptions; - SmallVector<SourceRange, 2> DynamicExceptionRanges; - ExprResult NoexceptExpr; - CachedTokens *ExceptionSpecTokens; - ESpecType = tryParseExceptionSpecification( - /*Delayed=*/false, ESpecRange, DynamicExceptions, - DynamicExceptionRanges, NoexceptExpr, ExceptionSpecTokens); - - if (ESpecType != EST_None) - DeclEndLoc = ESpecRange.getEnd(); - - // Parse attribute-specifier[opt]. - MaybeParseCXX11Attributes(Attr, &DeclEndLoc); - - // Parse OpenCL addr space attribute. - if (Tok.isOneOf(tok::kw___private, tok::kw___global, tok::kw___local, - tok::kw___constant, tok::kw___generic)) { - ParseOpenCLQualifiers(DS.getAttributes()); - ConsumeToken(); - } - - SourceLocation FunLocalRangeEnd = DeclEndLoc; - - // Parse trailing-return-type[opt]. - if (Tok.is(tok::arrow)) { - FunLocalRangeEnd = Tok.getLocation(); - SourceRange Range; - TrailingReturnType = ParseTrailingReturnType( - Range, /*MayBeFollowedByDirectInit*/ false); - TrailingReturnTypeLoc = Range.getBegin(); - if (Range.getEnd().isValid()) - DeclEndLoc = Range.getEnd(); - } + ParseScope Prototype(this, Scope::FunctionPrototypeScope | + Scope::FunctionDeclarationScope | + Scope::DeclScope); - SourceLocation NoLoc; - D.AddTypeInfo( - DeclaratorChunk::getFunction( - /*HasProto=*/true, - /*IsAmbiguous=*/false, LParenLoc, ParamInfo.data(), - ParamInfo.size(), EllipsisLoc, RParenLoc, - /*RefQualifierIsLvalueRef=*/true, - /*RefQualifierLoc=*/NoLoc, MutableLoc, ESpecType, ESpecRange, - DynamicExceptions.data(), DynamicExceptionRanges.data(), - DynamicExceptions.size(), - NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, - /*ExceptionSpecTokens*/ nullptr, - /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D, - TrailingReturnType, TrailingReturnTypeLoc, &DS), - std::move(Attr), DeclEndLoc); - }; + // Parse parameter-declaration-clause. + SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; + SourceLocation EllipsisLoc; if (Tok.is(tok::l_paren)) { - ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope | - Scope::FunctionDeclarationScope | - Scope::DeclScope); - BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - SourceLocation LParenLoc = T.getOpenLocation(); - - // Parse parameter-declaration-clause. - SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; - SourceLocation EllipsisLoc; + LParenLoc = T.getOpenLocation(); if (Tok.isNot(tok::r_paren)) { Actions.RecordParsingTemplateParameterDepth( CurTemplateDepthTracker.getOriginalDepth()); - ParseParameterDeclarationClause(D.getContext(), Attr, ParamInfo, - EllipsisLoc); + ParseParameterDeclarationClause(D, Attributes, 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 @@ -1423,35 +1393,127 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( } T.consumeClose(); + DeclEndLoc = RParenLoc = T.getCloseLocation(); + HasParentheses = true; + } - // Parse lambda-specifiers. - ParseLambdaSpecifiers(LParenLoc, /*DeclEndLoc=*/T.getCloseLocation(), - ParamInfo, EllipsisLoc); + HasSpecifiers = + Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute, + 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_groupshared, + tok::kw_requires, tok::kw_noexcept) || + Tok.isRegularKeywordAttribute() || + (Tok.is(tok::l_square) && NextToken().is(tok::l_square)); + + if (HasSpecifiers && !HasParentheses && !getLangOpts().CPlusPlus23) { + // It's common to forget that one needs '()' before 'mutable', an + // attribute specifier, the result type, or the requires clause. Deal with + // this. + Diag(Tok, diag::ext_lambda_missing_parens) + << FixItHint::CreateInsertion(Tok.getLocation(), "() "); + } - // Parse requires-clause[opt]. - 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___private, tok::kw___global, tok::kw___local, - tok::kw___constant, tok::kw___generic, - 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 - // attribute specifier, the result type, or the requires clause. Deal with - // this. - Diag(Tok, diag::ext_lambda_missing_parens) - << FixItHint::CreateInsertion(Tok.getLocation(), "() "); + if (HasParentheses || HasSpecifiers) { + // GNU-style attributes must be parsed before the mutable specifier to + // be compatible with GCC. MSVC-style attributes must be parsed before + // the mutable specifier to be compatible with MSVC. + MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attributes); + // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update + // the DeclEndLoc. + SourceLocation ConstexprLoc; + SourceLocation ConstevalLoc; + SourceLocation StaticLoc; + + tryConsumeLambdaSpecifierToken(*this, MutableLoc, StaticLoc, ConstexprLoc, + ConstevalLoc, DeclEndLoc); + + DiagnoseStaticSpecifierRestrictions(*this, StaticLoc, MutableLoc, Intro); + + addStaticToLambdaDeclSpecifier(*this, StaticLoc, DS); + addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS); + addConstevalToLambdaDeclSpecifier(*this, ConstevalLoc, DS); + } + + Actions.ActOnLambdaClosureParameters(getCurScope(), ParamInfo); + + if (!HasParentheses) + Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc); + + if (HasSpecifiers || HasParentheses) { + // Parse exception-specification[opt]. + ExceptionSpecificationType ESpecType = EST_None; + SourceRange ESpecRange; + SmallVector<ParsedType, 2> DynamicExceptions; + SmallVector<SourceRange, 2> DynamicExceptionRanges; + ExprResult NoexceptExpr; + CachedTokens *ExceptionSpecTokens; + + ESpecType = tryParseExceptionSpecification( + /*Delayed=*/false, ESpecRange, DynamicExceptions, + DynamicExceptionRanges, NoexceptExpr, ExceptionSpecTokens); + + if (ESpecType != EST_None) + DeclEndLoc = ESpecRange.getEnd(); + + // Parse attribute-specifier[opt]. + if (MaybeParseCXX11Attributes(Attributes)) + DeclEndLoc = Attributes.Range.getEnd(); + + // Parse OpenCL addr space attribute. + if (Tok.isOneOf(tok::kw___private, tok::kw___global, tok::kw___local, + tok::kw___constant, tok::kw___generic)) { + ParseOpenCLQualifiers(DS.getAttributes()); + ConsumeToken(); + } + + SourceLocation FunLocalRangeEnd = DeclEndLoc; + + // Parse trailing-return-type[opt]. + if (Tok.is(tok::arrow)) { + FunLocalRangeEnd = Tok.getLocation(); + SourceRange Range; + TrailingReturnType = + ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit=*/false); + TrailingReturnTypeLoc = Range.getBegin(); + if (Range.getEnd().isValid()) + DeclEndLoc = Range.getEnd(); + } SourceLocation NoLoc; - // Parse lambda-specifiers. - std::vector<DeclaratorChunk::ParamInfo> EmptyParamInfo; - ParseLambdaSpecifiers(/*LParenLoc=*/NoLoc, /*RParenLoc=*/NoLoc, - EmptyParamInfo, /*EllipsisLoc=*/NoLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + /*HasProto=*/true, + /*IsAmbiguous=*/false, LParenLoc, ParamInfo.data(), + ParamInfo.size(), EllipsisLoc, RParenLoc, + /*RefQualifierIsLvalueRef=*/true, + /*RefQualifierLoc=*/NoLoc, MutableLoc, ESpecType, + ESpecRange, DynamicExceptions.data(), + DynamicExceptionRanges.data(), DynamicExceptions.size(), + NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + /*ExceptionSpecTokens*/ nullptr, + /*DeclsInPrototype=*/std::nullopt, LParenLoc, + FunLocalRangeEnd, D, TrailingReturnType, + TrailingReturnTypeLoc, &DS), + std::move(Attributes), DeclEndLoc); + + Actions.ActOnLambdaClosureQualifiers(Intro, MutableLoc); + + if (HasParentheses && Tok.is(tok::kw_requires)) + ParseTrailingRequiresClause(D); + } + + // Emit a warning if we see a CUDA host/device/global attribute + // after '(...)'. nvcc doesn't accept this. + if (getLangOpts().CUDA) { + for (const ParsedAttr &A : Attributes) + if (A.getKind() == ParsedAttr::AT_CUDADevice || + A.getKind() == ParsedAttr::AT_CUDAHost || + A.getKind() == ParsedAttr::AT_CUDAGlobal) + Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position) + << A.getAttrName()->getName(); } - WarnIfHasCUDATargetAttr(); + Prototype.Exit(); // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using // it. @@ -1459,7 +1521,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( Scope::CompoundStmtScope; ParseScope BodyScope(this, ScopeFlags); - Actions.ActOnStartOfLambdaDefinition(Intro, D, getCurScope()); + Actions.ActOnStartOfLambdaDefinition(Intro, D, DS); // Parse compound-statement. if (!Tok.is(tok::l_brace)) { @@ -1471,9 +1533,11 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( StmtResult Stmt(ParseCompoundStatementBody()); BodyScope.Exit(); TemplateParamScope.Exit(); + LambdaScope.Exit(); - if (!Stmt.isInvalid() && !TrailingReturnType.isInvalid()) - return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get(), getCurScope()); + if (!Stmt.isInvalid() && !TrailingReturnType.isInvalid() && + !D.isInvalidType()) + return Actions.ActOnLambdaExpr(LambdaBeginLoc, Stmt.get()); Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope()); return ExprError(); @@ -1519,10 +1583,12 @@ 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, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); ParseDeclarator(DeclaratorInfo); SourceLocation RAngleBracketLoc = Tok.getLocation(); @@ -1848,8 +1914,9 @@ ExprResult Parser::ParseCXXThis() { /// In C++1z onwards, the type specifier can also be a template-name. ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { - Declarator DeclaratorInfo(DS, DeclaratorContext::FunctionalCast); - ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::FunctionalCast); + ParsedType TypeRep = Actions.ActOnTypeName(DeclaratorInfo).get(); assert((Tok.is(tok::l_paren) || (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))) @@ -1871,20 +1938,19 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { PreferredType.enterTypeCast(Tok.getLocation(), TypeRep.get()); ExprVector Exprs; - CommaLocsTy CommaLocs; auto RunSignatureHelp = [&]() { QualType PreferredType; if (TypeRep) PreferredType = Actions.ProduceConstructorSignatureHelp( - getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), - DS.getEndLoc(), Exprs, T.getOpenLocation()); + TypeRep.get()->getCanonicalTypeInternal(), DS.getEndLoc(), Exprs, + T.getOpenLocation(), /*Braced=*/false); CalledSignatureHelp = true; return PreferredType; }; if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(Exprs, CommaLocs, [&] { + if (ParseExpressionList(Exprs, [&] { PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); })) { @@ -1902,14 +1968,34 @@ 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); } } +Parser::DeclGroupPtrTy +Parser::ParseAliasDeclarationInInitStatement(DeclaratorContext Context, + ParsedAttributes &Attrs) { + assert(Tok.is(tok::kw_using) && "Expected using"); + assert((Context == DeclaratorContext::ForInit || + Context == DeclaratorContext::SelectionInit) && + "Unexpected Declarator Context"); + DeclGroupPtrTy DG; + SourceLocation DeclStart = ConsumeToken(), DeclEnd; + + DG = ParseUsingDeclaration(Context, {}, DeclStart, DeclEnd, Attrs, AS_none); + if (!DG) + return DG; + + Diag(DeclStart, !getLangOpts().CPlusPlus23 + ? diag::ext_alias_in_init_statement + : diag::warn_cxx20_alias_in_init_statement) + << SourceRange(DeclStart, DeclEnd); + + return DG; +} + /// ParseCXXCondition - if/switch/while condition expression. /// /// condition: @@ -1931,6 +2017,9 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// \param Loc The location of the start of the statement that requires this /// condition, e.g., the "for" in a for loop. /// +/// \param MissingOK Whether an empty condition is acceptable here. Otherwise +/// it is considered an error to be recovered from. +/// /// \param FRI If non-null, a for range declaration is permitted, and if /// present will be parsed and stored here, and a null result will be returned. /// @@ -1938,11 +2027,10 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { /// appropriate moment for a 'for' loop. /// /// \returns The parsed condition. -Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, - SourceLocation Loc, - Sema::ConditionKind CK, - ForRangeInfo *FRI, - bool EnterForConditionScope) { +Sema::ConditionResult +Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, + Sema::ConditionKind CK, bool MissingOK, + ForRangeInfo *FRI, bool EnterForConditionScope) { // Helper to ensure we always enter a continue/break scope if requested. struct ForConditionScopeRAII { Scope *S; @@ -1967,7 +2055,7 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, return Sema::ConditionError(); } - ParsedAttributesWithRange attrs(AttrFactory); + ParsedAttributes attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); const auto WarnOnInit = [this, &CK] { @@ -1997,7 +2085,7 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, } ConsumeToken(); *InitStmt = Actions.ActOnNullStmt(SemiLoc); - return ParseCXXCondition(nullptr, Loc, CK); + return ParseCXXCondition(nullptr, Loc, CK, MissingOK); } // Parse the expression. @@ -2009,19 +2097,27 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, WarnOnInit(); *InitStmt = Actions.ActOnExprStmt(Expr.get()); ConsumeToken(); - return ParseCXXCondition(nullptr, Loc, CK); + return ParseCXXCondition(nullptr, Loc, CK, MissingOK); } - return Actions.ActOnCondition(getCurScope(), Loc, Expr.get(), CK); + return Actions.ActOnCondition(getCurScope(), Loc, Expr.get(), CK, + MissingOK); } case ConditionOrInitStatement::InitStmtDecl: { WarnOnInit(); + DeclGroupPtrTy DG; SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy DG = ParseSimpleDeclaration( - DeclaratorContext::SelectionInit, DeclEnd, attrs, /*RequireSemi=*/true); + if (Tok.is(tok::kw_using)) + DG = ParseAliasDeclarationInInitStatement( + DeclaratorContext::SelectionInit, attrs); + else { + ParsedAttributes DeclSpecAttrs(AttrFactory); + DG = ParseSimpleDeclaration(DeclaratorContext::SelectionInit, DeclEnd, + attrs, DeclSpecAttrs, /*RequireSemi=*/true); + } *InitStmt = Actions.ActOnDeclStmt(DG, DeclStart, DeclEnd); - return ParseCXXCondition(nullptr, Loc, CK); + return ParseCXXCondition(nullptr, Loc, CK, MissingOK); } case ConditionOrInitStatement::ForRangeDecl: { @@ -2030,11 +2126,10 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, // permitted here. assert(FRI && "should not parse a for range declaration here"); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy DG = ParseSimpleDeclaration(DeclaratorContext::ForInit, - DeclEnd, attrs, false, FRI); + ParsedAttributes DeclSpecAttrs(AttrFactory); + DeclGroupPtrTy DG = ParseSimpleDeclaration( + DeclaratorContext::ForInit, DeclEnd, attrs, DeclSpecAttrs, false, FRI); FRI->LoopVar = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); - assert((FRI->ColonLoc.isValid() || !DG) && - "cannot find for range declaration"); return Sema::ConditionResult(); } @@ -2048,11 +2143,10 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, // type-specifier-seq DeclSpec DS(AttrFactory); - DS.takeAttributesFrom(attrs); ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_condition); // declarator - Declarator DeclaratorInfo(DS, DeclaratorContext::Condition); + Declarator DeclaratorInfo(DS, attrs, DeclaratorContext::Condition); ParseDeclarator(DeclaratorInfo); // simple-asm-expr[opt] @@ -2164,12 +2258,14 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { return; } - case tok::kw__ExtInt: { + case tok::kw__ExtInt: + case tok::kw__BitInt: { + DiagnoseBitIntUse(Tok); ExprResult ER = ParseExtIntegerArgument(); if (ER.isInvalid()) DS.SetTypeSpecError(); else - DS.SetExtIntType(Loc, ER.get(), PrevSpec, DiagID, Policy); + DS.SetBitIntType(Loc, ER.get(), PrevSpec, DiagID, Policy); // Do this here because we have already consumed the close paren. DS.SetRangeEnd(PrevTokLocation); @@ -2199,6 +2295,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::kw_void: DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw_auto: + DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID, Policy); + break; case tok::kw_char: DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID, Policy); break; @@ -2226,6 +2325,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::kw___float128: DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw___ibm128: + DS.SetTypeSpecType(DeclSpec::TST_ibm128, Loc, PrevSpec, DiagID, Policy); + break; case tok::kw_wchar_t: DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy); break; @@ -2241,6 +2343,15 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::kw_bool: DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw__Accum: + DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec, DiagID, Policy); + break; + case tok::kw__Fract: + DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec, DiagID, Policy); + break; + case tok::kw__Sat: + DS.SetTypeSpecSat(Loc, PrevSpec, DiagID); + break; #define GENERIC_IMAGE_TYPE(ImgType, Id) \ case tok::kw_##ImgType##_t: \ DS.SetTypeSpecType(DeclSpec::TST_##ImgType##_t, Loc, PrevSpec, DiagID, \ @@ -2275,8 +2386,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; } @@ -2422,8 +2534,8 @@ bool Parser::ParseUnqualifiedIdTemplateId( // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, - RAngleLoc)) + if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, RAngleLoc, + Template)) return true; // If this is a non-template, we already issued a diagnostic. @@ -2692,16 +2804,18 @@ 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 // ptr-operators. - Declarator D(DS, DeclaratorContext::ConversionId); + Declarator D(DS, ParsedAttributesView::none(), + DeclaratorContext::ConversionId); ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr); // Finish up the type. - TypeResult Ty = Actions.ActOnTypeName(getCurScope(), D); + TypeResult Ty = Actions.ActOnTypeName(D); if (Ty.isInvalid()) return true; @@ -2775,6 +2889,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(); @@ -2795,9 +2910,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, if (!Ty) return true; Result.setConstructorName(Ty, IdLoc, IdLoc); - } else if (getLangOpts().CPlusPlus17 && - AllowDeductionGuide && SS.isEmpty() && - Actions.isDeductionGuideName(getCurScope(), *Id, IdLoc, + } else if (getLangOpts().CPlusPlus17 && AllowDeductionGuide && + SS.isEmpty() && + Actions.isDeductionGuideName(getCurScope(), *Id, IdLoc, SS, &TemplateName)) { // We have parsed a template-name naming a deduction guide. Result.setDeductionGuideName(TemplateName, IdLoc); @@ -2998,10 +3113,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, } // Note that this is a destructor name. - ParsedType Ty = Actions.getDestructorName(TildeLoc, *ClassName, - ClassNameLoc, getCurScope(), - SS, ObjectType, - EnteringContext); + ParsedType Ty = + Actions.getDestructorName(*ClassName, ClassNameLoc, getCurScope(), SS, + ObjectType, EnteringContext); if (!Ty) return true; @@ -3009,9 +3123,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 @@ -3055,7 +3180,8 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { SourceRange TypeIdParens; DeclSpec DS(AttrFactory); - Declarator DeclaratorInfo(DS, DeclaratorContext::CXXNew); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::CXXNew); if (Tok.is(tok::l_paren)) { // If it turns out to be a placement, we change the type location. BalancedDelimiterTracker T(*this, tok::l_paren); @@ -3103,7 +3229,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { // A new-type-id is a simplified type-id, where essentially the // direct-declarator is replaced by a direct-new-declarator. MaybeParseGNUAttributes(DeclaratorInfo); - if (ParseCXXTypeSpecifierSeq(DS)) + if (ParseCXXTypeSpecifierSeq(DS, DeclaratorContext::CXXNew)) DeclaratorInfo.setInvalidType(true); else { DeclaratorInfo.SetSourceRange(DS.getSourceRange()); @@ -3125,22 +3251,21 @@ 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(); + ParsedType TypeRep = Actions.ActOnTypeName(DeclaratorInfo).get(); QualType PreferredType; // ActOnTypeName might adjust DeclaratorInfo and return a null type even // the passing DeclaratorInfo is valid, e.g. running SignatureHelp on // `new decltype(invalid) (^)`. if (TypeRep) PreferredType = Actions.ProduceConstructorSignatureHelp( - getCurScope(), TypeRep.get()->getCanonicalTypeInternal(), - DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen); + TypeRep.get()->getCanonicalTypeInternal(), + DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen, + /*Braced=*/false); CalledSignatureHelp = true; return PreferredType; }; - if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] { + if (ParseExpressionList(ConstructorArgs, [&] { PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); })) { @@ -3239,9 +3364,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 @@ -3367,11 +3490,11 @@ ExprResult Parser::ParseRequiresExpression() { SourceLocation RequiresKWLoc = ConsumeToken(); // Consume 'requires' llvm::SmallVector<ParmVarDecl *, 2> LocalParameterDecls; + BalancedDelimiterTracker Parens(*this, tok::l_paren); if (Tok.is(tok::l_paren)) { // requirement parameter list is present. ParseScope LocalParametersScope(this, Scope::FunctionPrototypeScope | Scope::DeclScope); - BalancedDelimiterTracker Parens(*this, tok::l_paren); Parens.consumeOpen(); if (!Tok.is(tok::r_paren)) { ParsedAttributes FirstArgAttrs(getAttrFactory()); @@ -3401,6 +3524,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()); @@ -3496,10 +3623,12 @@ ExprResult Parser::ParseRequiresExpression() { auto Res = TryParseParameterDeclarationClause(); if (Res != TPResult::False) { // Skip to the closing parenthesis - // FIXME: Don't traverse these tokens twice (here and in - // TryParseParameterDeclarationClause). unsigned Depth = 1; while (Depth != 0) { + bool FoundParen = SkipUntil(tok::l_paren, tok::r_paren, + SkipUntilFlags::StopBeforeMatch); + if (!FoundParen) + break; if (Tok.is(tok::l_paren)) Depth++; else if (Tok.is(tok::r_paren)) @@ -3553,7 +3682,7 @@ ExprResult Parser::ParseRequiresExpression() { // We need to consume the typename to allow 'requires { typename a; }' SourceLocation TypenameKWLoc = ConsumeToken(); - if (TryAnnotateCXXScopeToken()) { + if (TryAnnotateOptionalCXXScopeToken()) { TPA.Commit(); SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); break; @@ -3602,7 +3731,7 @@ ExprResult Parser::ParseRequiresExpression() { break; } if (!Expression.isInvalid() && PossibleRequiresExprInSimpleRequirement) - Diag(StartLoc, diag::warn_requires_expr_in_simple_requirement) + Diag(StartLoc, diag::err_requires_expr_in_simple_requirement) << FixItHint::CreateInsertion(StartLoc, "requires"); if (auto *Req = Actions.ActOnSimpleRequirement(Expression.get())) Requirements.push_back(Req); @@ -3638,8 +3767,10 @@ ExprResult Parser::ParseRequiresExpression() { } Braces.consumeClose(); Actions.ActOnFinishRequiresExpr(); - return Actions.ActOnRequiresExpr(RequiresKWLoc, Body, LocalParameterDecls, - Requirements, Braces.getCloseLocation()); + ParsingBodyDecl.complete(Body); + return Actions.ActOnRequiresExpr( + RequiresKWLoc, Body, Parens.getOpenLocation(), LocalParameterDecls, + Parens.getCloseLocation(), Requirements, Braces.getCloseLocation()); } static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) { @@ -3678,14 +3809,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. /// @@ -3699,7 +3822,6 @@ static unsigned TypeTraitArity(tok::TokenKind kind) { /// ExprResult Parser::ParseTypeTrait() { tok::TokenKind Kind = Tok.getKind(); - unsigned Arity = TypeTraitArity(Kind); SourceLocation Loc = ConsumeToken(); @@ -3734,18 +3856,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); } @@ -3905,7 +4015,8 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, if (ParseAs >= CompoundLiteral) { // Parse the type declarator. DeclSpec DS(AttrFactory); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); { ColonProtectionRAIIObject InnerColonProtection(*this); ParseSpecifierQualifierList(DS); @@ -3925,7 +4036,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, if (DeclaratorInfo.isInvalidType()) return ExprError(); - TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); + TypeResult Ty = Actions.ActOnTypeName(DeclaratorInfo); return ParseCompoundLiteralExpression(Ty.get(), Tracker.getOpenLocation(), Tracker.getCloseLocation()); @@ -3983,7 +4094,8 @@ ExprResult Parser::ParseBuiltinBitCast() { ParseSpecifierQualifierList(DS); // Parse the abstract-declarator, if present. - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); ParseDeclarator(DeclaratorInfo); if (ExpectAndConsume(tok::comma)) { |