diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp | 108 |
1 files changed, 93 insertions, 15 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp index 9c61c4da447a..09e5c7996fcd 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp @@ -600,7 +600,10 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context, if (ParseOptionalCXXScopeSpecifier(D.SS, nullptr, /*EnteringContext=*/false, /*MayBePseudoDtor=*/nullptr, /*IsTypename=*/false, - /*LastII=*/&LastII)) + /*LastII=*/&LastII, + /*OnlyNamespace=*/false, + /*InUsingDeclaration=*/true)) + return true; if (D.SS.isInvalid()) return true; @@ -862,7 +865,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ "Not a static_assert declaration"); if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11) - Diag(Tok, diag::ext_c11_static_assert); + Diag(Tok, diag::ext_c11_feature) << Tok.getName(); if (Tok.is(tok::kw_static_assert)) Diag(Tok, diag::warn_cxx98_compat_static_assert); @@ -1139,7 +1142,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (TemplateId->Kind == TNK_Type_template || TemplateId->Kind == TNK_Dependent_template_name || TemplateId->Kind == TNK_Undeclared_template) { - AnnotateTemplateIdTokenAsType(/*IsClassName*/true); + AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); ParsedType Type = getTypeAnnotation(Tok); @@ -1190,7 +1193,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, TemplateName)) return true; if (TNK == TNK_Type_template || TNK == TNK_Dependent_template_name) - AnnotateTemplateIdTokenAsType(/*IsClassName*/true); + AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); // If we didn't end up with a typename token, there's nothing more we // can do. @@ -1313,6 +1316,8 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { case tok::kw_mutable: // struct foo {...} mutable x; case tok::kw_thread_local: // struct foo {...} thread_local x; case tok::kw_constexpr: // struct foo {...} constexpr x; + case tok::kw_consteval: // struct foo {...} consteval x; + case tok::kw_constinit: // struct foo {...} constinit x; // As shown above, type qualifiers and storage class specifiers absolutely // can occur after class specifiers according to the grammar. However, // almost no one actually writes code like this. If we see one of these, @@ -1821,7 +1826,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { ProhibitAttributes(attrs); TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc, - TemplateId->SS, + SS, TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->TemplateNameLoc, @@ -1871,7 +1876,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Build the class template specialization. TagOrTempResult = Actions.ActOnClassTemplateSpecialization( getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), - *TemplateId, attrs, + SS, *TemplateId, attrs, MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, TemplateParams ? TemplateParams->size() : 0), @@ -2296,6 +2301,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( LateParsedAttrList &LateParsedAttrs) { // member-declarator: // declarator pure-specifier[opt] + // declarator requires-clause // declarator brace-or-equal-initializer[opt] // identifier[opt] ':' constant-expression if (Tok.isNot(tok::colon)) @@ -2309,6 +2315,8 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( BitfieldSize = ParseConstantExpression(); if (BitfieldSize.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); + } else if (Tok.is(tok::kw_requires)) { + ParseTrailingRequiresClause(DeclaratorInfo); } else { ParseOptionalCXX11VirtSpecifierSeq( VS, getCurrentClass().IsInterface, @@ -2320,7 +2328,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { SourceLocation Loc; - ExprResult AsmLabel(ParseSimpleAsm(&Loc)); + ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc)); if (AsmLabel.isInvalid()) SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch); @@ -2431,6 +2439,7 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( /// /// member-declarator: /// declarator virt-specifier-seq[opt] pure-specifier[opt] +/// [C++2a] declarator requires-clause /// declarator constant-initializer[opt] /// [C++11] declarator brace-or-equal-initializer[opt] /// identifier[opt] ':' constant-expression @@ -2633,6 +2642,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::MemberContext); + if (TemplateInfo.TemplateParams) + DeclaratorInfo.setTemplateParameterLists(TemplateParams); VirtSpecifiers VS; // Hold late-parsed attributes so we can attach a Decl to them later. @@ -2664,6 +2675,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SmallVector<Decl *, 8> DeclsInGroup; ExprResult BitfieldSize; + ExprResult TrailingRequiresClause; bool ExpectSemi = true; // Parse the first declarator. @@ -2704,7 +2716,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains // to a friend declaration, that declaration shall be a definition. if (DeclaratorInfo.isFunctionDeclarator() && - DefinitionKind != FDK_Definition && DS.isFriendSpecified()) { + DefinitionKind == FDK_Declaration && DS.isFriendSpecified()) { // Diagnose attributes that appear before decl specifier: // [[]] friend int foo(); ProhibitAttributes(FnAttrs); @@ -2976,7 +2988,8 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, Diag(Tok, diag::err_default_delete_in_multiple_declaration) << 0 /* default */; else - Diag(ConsumeToken(), diag::err_default_special_members); + Diag(ConsumeToken(), diag::err_default_special_members) + << getLangOpts().CPlusPlus2a; return ExprError(); } } @@ -3130,10 +3143,17 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( } case tok::annot_pragma_openmp: - return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, AccessAttrs, TagType, - TagDecl); + return ParseOpenMPDeclarativeDirectiveWithExtDecl( + AS, AccessAttrs, /*Delayed=*/true, TagType, TagDecl); default: + if (tok::isPragmaAnnotation(Tok.getKind())) { + Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl) + << DeclSpec::getSpecifierName(TagType, + Actions.getASTContext().getPrintingPolicy()); + ConsumeAnnotationToken(); + return nullptr; + } return ParseCXXClassMemberDeclaration(AS, AccessAttrs); } } @@ -3342,6 +3362,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // declarations and the lexed inline method definitions, along with any // delayed attributes. SourceLocation SavedPrevTokLocation = PrevTokLocation; + ParseLexedPragmas(getCurrentClass()); ParseLexedAttributes(getCurrentClass()); ParseLexedMethodDeclarations(getCurrentClass()); @@ -3354,7 +3375,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // We've finished parsing everything, including default argument // initializers. - Actions.ActOnFinishCXXNonNestedClass(TagDecl); + Actions.ActOnFinishCXXNonNestedClass(); } if (TagDecl) @@ -3501,7 +3522,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { if (TemplateId && (TemplateId->Kind == TNK_Type_template || TemplateId->Kind == TNK_Dependent_template_name || TemplateId->Kind == TNK_Undeclared_template)) { - AnnotateTemplateIdTokenAsType(/*IsClassName*/true); + AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TemplateTypeTy = getTypeAnnotation(Tok); ConsumeAnnotationToken(); @@ -3779,6 +3800,62 @@ TypeResult Parser::ParseTrailingReturnType(SourceRange &Range, : DeclaratorContext::TrailingReturnContext); } +/// Parse a requires-clause as part of a function declaration. +void Parser::ParseTrailingRequiresClause(Declarator &D) { + assert(Tok.is(tok::kw_requires) && "expected requires"); + + SourceLocation RequiresKWLoc = ConsumeToken(); + + ExprResult TrailingRequiresClause; + ParseScope ParamScope(this, + Scope::DeclScope | + Scope::FunctionDeclarationScope | + Scope::FunctionPrototypeScope); + + Actions.ActOnStartTrailingRequiresClause(getCurScope(), D); + + llvm::Optional<Sema::CXXThisScopeRAII> ThisScope; + InitCXXThisScopeForDeclaratorIfRelevant(D, D.getDeclSpec(), ThisScope); + + TrailingRequiresClause = + ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true); + + TrailingRequiresClause = + Actions.ActOnFinishTrailingRequiresClause(TrailingRequiresClause); + + if (!D.isDeclarationOfFunction()) { + Diag(RequiresKWLoc, + diag::err_requires_clause_on_declarator_not_declaring_a_function); + return; + } + + if (TrailingRequiresClause.isInvalid()) + SkipUntil({tok::l_brace, tok::arrow, tok::kw_try, tok::comma, tok::colon}, + StopAtSemi | StopBeforeMatch); + else + D.setTrailingRequiresClause(TrailingRequiresClause.get()); + + // Did the user swap the trailing return type and requires clause? + if (D.isFunctionDeclarator() && Tok.is(tok::arrow) && + D.getDeclSpec().getTypeSpecType() == TST_auto) { + SourceLocation ArrowLoc = Tok.getLocation(); + SourceRange Range; + TypeResult TrailingReturnType = + ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit=*/false); + + if (!TrailingReturnType.isInvalid()) { + Diag(ArrowLoc, + diag::err_requires_clause_must_appear_after_trailing_return) + << Range; + auto &FunctionChunk = D.getFunctionTypeInfo(); + FunctionChunk.HasTrailingReturnType = TrailingReturnType.isUsable(); + FunctionChunk.TrailingReturnType = TrailingReturnType.get(); + } else + SkipUntil({tok::equal, tok::l_brace, tok::arrow, tok::kw_try, tok::comma}, + StopAtSemi | StopBeforeMatch); + } +} + /// We have just started parsing the definition of a new class, /// so push that class onto our stack of classes that is currently /// being parsed. @@ -3907,7 +3984,8 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, IdentifierInfo *ScopeName) { - switch (ParsedAttr::getKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) { + switch ( + ParsedAttr::getParsedKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) { case ParsedAttr::AT_CarriesDependency: case ParsedAttr::AT_Deprecated: case ParsedAttr::AT_FallThrough: @@ -4337,7 +4415,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration( while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // __if_exists, __if_not_exists can nest. if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { - ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, + ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, CurAS); continue; } |
