diff options
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 253 |
1 files changed, 172 insertions, 81 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index bf73ddfd1031..b26ec00cfedf 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -18,6 +18,7 @@ #include "clang/Basic/CharInfo.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" @@ -26,6 +27,7 @@ #include "clang/Sema/Scope.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/TimeProfiler.h" +#include <optional> using namespace clang; @@ -226,7 +228,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident, - T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl); + T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, false); PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl, NamespaceLoc, "parsing namespace"); @@ -253,9 +255,10 @@ void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs, if (index == InnerNSs.size()) { while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { - ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs); - ParseExternalDeclaration(Attrs); + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs); } // The caller is what called check -- we are simply calling @@ -273,7 +276,7 @@ void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs, Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc, InnerNSs[index].IdentLoc, InnerNSs[index].Ident, - Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl); + Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, true); assert(!ImplicitUsingDirectiveDecl && "nested namespace definition cannot define anonymous namespace"); @@ -357,7 +360,11 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation()); ParsedAttributes DeclAttrs(AttrFactory); - MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes DeclSpecAttrs(AttrFactory); + + while (MaybeParseCXX11Attributes(DeclAttrs) || + MaybeParseGNUAttributes(DeclSpecAttrs)) + ; if (Tok.isNot(tok::l_brace)) { // Reset the source range in DS, as the leading "extern" @@ -366,7 +373,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { DS.SetRangeEnd(SourceLocation()); // ... but anyway remember that such an "extern" was seen. DS.setExternInLinkageSpec(true); - ParseExternalDeclaration(DeclAttrs, &DS); + ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs, &DS); return LinkageSpec ? Actions.ActOnFinishLinkageSpecification( getCurScope(), LinkageSpec, SourceLocation()) : nullptr; @@ -404,11 +411,11 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { case tok::r_brace: if (!NestedModules) break; - LLVM_FALLTHROUGH; + [[fallthrough]]; default: - ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs); - ParseExternalDeclaration(Attrs); + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); + ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs); continue; } @@ -438,9 +445,10 @@ Decl *Parser::ParseExportDeclaration() { if (Tok.isNot(tok::l_brace)) { // FIXME: Factor out a ParseExternalDeclarationWithAttrs. - ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs); - ParseExternalDeclaration(Attrs); + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs); return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl, SourceLocation()); } @@ -457,9 +465,10 @@ Decl *Parser::ParseExportDeclaration() { while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { - ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs); - ParseExternalDeclaration(Attrs); + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs); } T.consumeClose(); @@ -677,6 +686,8 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context, /// /// using-enum-declaration: [C++20, dcl.enum] /// 'using' elaborated-enum-specifier ; +/// The terminal name of the elaborated-enum-specifier undergoes +/// ordinary lookup /// /// elaborated-enum-specifier: /// 'enum' nested-name-specifier[opt] identifier @@ -696,21 +707,47 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration( DiagnoseCXX11AttributeExtension(PrefixAttrs); - DeclSpec DS(AttrFactory); - ParseEnumSpecifier(UELoc, DS, TemplateInfo, AS, - // DSC_trailing has the semantics we desire - DeclSpecContext::DSC_trailing); - if (TemplateInfo.Kind) { SourceRange R = TemplateInfo.getSourceRange(); Diag(UsingLoc, diag::err_templated_using_directive_declaration) << 1 /* declaration */ << R << FixItHint::CreateRemoval(R); + SkipUntil(tok::semi); + return nullptr; + } + CXXScopeSpec SS; + if (ParseOptionalCXXScopeSpecifier(SS, /*ParsedType=*/nullptr, + /*ObectHasErrors=*/false, + /*EnteringConttext=*/false, + /*MayBePseudoDestructor=*/nullptr, + /*IsTypename=*/false, + /*IdentifierInfo=*/nullptr, + /*OnlyNamespace=*/false, + /*InUsingDeclaration=*/true)) { + SkipUntil(tok::semi); + return nullptr; + } + + if (Tok.is(tok::code_completion)) { + cutOffParsing(); + Actions.CodeCompleteUsing(getCurScope()); + return nullptr; + } + if (!Tok.is(tok::identifier)) { + Diag(Tok.getLocation(), diag::err_using_enum_expect_identifier) + << Tok.is(tok::kw_enum); + SkipUntil(tok::semi); + return nullptr; + } + IdentifierInfo *IdentInfo = Tok.getIdentifierInfo(); + SourceLocation IdentLoc = ConsumeToken(); + Decl *UED = Actions.ActOnUsingEnumDeclaration( + getCurScope(), AS, UsingLoc, UELoc, IdentLoc, *IdentInfo, &SS); + if (!UED) { + SkipUntil(tok::semi); return nullptr; } - Decl *UED = Actions.ActOnUsingEnumDeclaration(getCurScope(), AS, UsingLoc, - UELoc, DS); DeclEnd = Tok.getLocation(); if (ExpectAndConsume(tok::semi, diag::err_expected_after, "using-enum declaration")) @@ -934,10 +971,11 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) { if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11) Diag(Tok, diag::ext_c11_feature) << Tok.getName(); if (Tok.is(tok::kw_static_assert)) { - if (!getLangOpts().CPlusPlus) - Diag(Tok, diag::ext_ms_static_assert) - << FixItHint::CreateReplacement(Tok.getLocation(), "_Static_assert"); - else + if (!getLangOpts().CPlusPlus) { + if (!getLangOpts().C2x) + Diag(Tok, diag::ext_ms_static_assert) << FixItHint::CreateReplacement( + Tok.getLocation(), "_Static_assert"); + } else Diag(Tok, diag::warn_cxx98_compat_static_assert); } @@ -1021,7 +1059,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { EndLoc = Tok.getAnnotationEndLoc(); // Unfortunately, we don't know the LParen source location as the annotated // token doesn't have it. - DS.setTypeofParensRange(SourceRange(SourceLocation(), EndLoc)); + DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc)); ConsumeAnnotationToken(); if (Result.isInvalid()) { DS.SetTypeSpecError(); @@ -1085,7 +1123,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // Match the ')' T.consumeClose(); - DS.setTypeofParensRange(T.getRange()); + DS.setTypeArgumentRange(T.getRange()); if (T.getCloseLocation().isInvalid()) { DS.SetTypeSpecError(); // FIXME: this should return the location of the last token @@ -1142,35 +1180,48 @@ void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, PP.AnnotateCachedTokens(Tok); } -void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { - assert(Tok.is(tok::kw___underlying_type) && - "Not an underlying type specifier"); +DeclSpec::TST Parser::TypeTransformTokToDeclSpec() { + switch (Tok.getKind()) { +#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ + case tok::kw___##Trait: \ + return DeclSpec::TST_##Trait; +#include "clang/Basic/TransformTypeTraits.def" + default: + llvm_unreachable("passed in an unhandled type transformation built-in"); + } +} +bool Parser::MaybeParseTypeTransformTypeSpecifier(DeclSpec &DS) { + if (!NextToken().is(tok::l_paren)) { + Tok.setKind(tok::identifier); + return false; + } + DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec(); SourceLocation StartLoc = ConsumeToken(); + BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen_after, "__underlying_type", - tok::r_paren)) { - return; - } + if (T.expectAndConsume(diag::err_expected_lparen_after, Tok.getName(), + tok::r_paren)) + return true; TypeResult Result = ParseTypeName(); if (Result.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); - return; + return true; } - // Match the ')' T.consumeClose(); if (T.getCloseLocation().isInvalid()) - return; + return true; const char *PrevSpec = nullptr; unsigned DiagID; - if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec, - DiagID, Result.get(), + if (DS.SetTypeSpecType(TypeTransformTST, StartLoc, PrevSpec, DiagID, + Result.get(), Actions.getASTContext().getPrintingPolicy())) Diag(StartLoc, DiagID) << PrevSpec; - DS.setTypeofParensRange(T.getRange()); + DS.setTypeArgumentRange(T.getRange()); + return true; } /// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a @@ -1230,7 +1281,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (TemplateId->mightBeType()) { - AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/ true); + AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No, + /*IsClassName=*/true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TypeResult Type = getTypeAnnotation(Tok); @@ -1272,7 +1324,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, return true; if (Tok.is(tok::annot_template_id) && takeTemplateIdAnnotation(Tok)->mightBeType()) - AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/ true); + AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No, + /*IsClassName=*/true); // If we didn't end up with a typename token, there's nothing more we // can do. @@ -1293,7 +1346,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, *Id, IdLoc, getCurScope(), &SS, /*isClassName=*/true, false, nullptr, /*IsCtorOrDtorName=*/false, /*WantNontrivialTypeSourceInfo=*/true, - /*IsClassTemplateDeductionContext*/ false, &CorrectedII); + /*IsClassTemplateDeductionContext=*/false, ImplicitTypenameContext::No, + &CorrectedII); if (!Type) { Diag(IdLoc, diag::err_expected_class_name); return true; @@ -1525,28 +1579,63 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (TagType == DeclSpec::TST_struct && Tok.isNot(tok::identifier) && !Tok.isAnnotation() && Tok.getIdentifierInfo() && Tok.isOneOf( - tok::kw___is_abstract, tok::kw___is_aggregate, - tok::kw___is_arithmetic, tok::kw___is_array, tok::kw___is_assignable, - tok::kw___is_base_of, tok::kw___is_class, tok::kw___is_complete_type, - tok::kw___is_compound, tok::kw___is_const, tok::kw___is_constructible, - tok::kw___is_convertible, tok::kw___is_convertible_to, - tok::kw___is_destructible, tok::kw___is_empty, tok::kw___is_enum, - tok::kw___is_floating_point, tok::kw___is_final, - tok::kw___is_function, tok::kw___is_fundamental, - tok::kw___is_integral, tok::kw___is_interface_class, - tok::kw___is_literal, tok::kw___is_lvalue_expr, - tok::kw___is_lvalue_reference, tok::kw___is_member_function_pointer, - tok::kw___is_member_object_pointer, tok::kw___is_member_pointer, - tok::kw___is_nothrow_assignable, tok::kw___is_nothrow_constructible, - tok::kw___is_nothrow_destructible, tok::kw___is_object, - tok::kw___is_pod, tok::kw___is_pointer, tok::kw___is_polymorphic, - tok::kw___is_reference, tok::kw___is_rvalue_expr, - tok::kw___is_rvalue_reference, tok::kw___is_same, tok::kw___is_scalar, - tok::kw___is_sealed, tok::kw___is_signed, - tok::kw___is_standard_layout, tok::kw___is_trivial, +#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait, +#include "clang/Basic/TransformTypeTraits.def" + tok::kw___is_abstract, + tok::kw___is_aggregate, + tok::kw___is_arithmetic, + tok::kw___is_array, + tok::kw___is_assignable, + tok::kw___is_base_of, + tok::kw___is_bounded_array, + tok::kw___is_class, + tok::kw___is_complete_type, + tok::kw___is_compound, + tok::kw___is_const, + tok::kw___is_constructible, + tok::kw___is_convertible, + tok::kw___is_convertible_to, + tok::kw___is_destructible, + tok::kw___is_empty, + tok::kw___is_enum, + tok::kw___is_floating_point, + tok::kw___is_final, + tok::kw___is_function, + tok::kw___is_fundamental, + tok::kw___is_integral, + tok::kw___is_interface_class, + tok::kw___is_literal, + tok::kw___is_lvalue_expr, + tok::kw___is_lvalue_reference, + tok::kw___is_member_function_pointer, + tok::kw___is_member_object_pointer, + tok::kw___is_member_pointer, + tok::kw___is_nothrow_assignable, + tok::kw___is_nothrow_constructible, + tok::kw___is_nothrow_destructible, + tok::kw___is_nullptr, + tok::kw___is_object, + tok::kw___is_pod, + tok::kw___is_pointer, + tok::kw___is_polymorphic, + tok::kw___is_reference, + tok::kw___is_referenceable, + tok::kw___is_rvalue_expr, + tok::kw___is_rvalue_reference, + tok::kw___is_same, + tok::kw___is_scalar, + tok::kw___is_scoped_enum, + tok::kw___is_sealed, + tok::kw___is_signed, + tok::kw___is_standard_layout, + tok::kw___is_trivial, tok::kw___is_trivially_assignable, - tok::kw___is_trivially_constructible, tok::kw___is_trivially_copyable, - tok::kw___is_union, tok::kw___is_unsigned, tok::kw___is_void, + tok::kw___is_trivially_constructible, + tok::kw___is_trivially_copyable, + tok::kw___is_unbounded_array, + tok::kw___is_union, + tok::kw___is_unsigned, + tok::kw___is_void, tok::kw___is_volatile)) // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the // name of struct templates, but some are keywords in GCC >= 4.3 @@ -1845,6 +1934,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Create the tag portion of the class or class template. DeclResult TagOrTempResult = true; // invalid TypeResult TypeResult = true; // invalid + UsingShadowDecl *FoundUsing = nullptr; bool Owned = false; Sema::SkipBodyInfo SkipBody; @@ -1914,8 +2004,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // "template<>", so that we treat this construct as a class // template specialization. FakedParamLists.push_back(Actions.ActOnTemplateParameterList( - 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None, - LAngleLoc, nullptr)); + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, + std::nullopt, LAngleLoc, nullptr)); TemplateParams = &FakedParamLists; } } @@ -1985,7 +2075,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, DSC == DeclSpecContext::DSC_type_specifier, DSC == DeclSpecContext::DSC_template_param || DSC == DeclSpecContext::DSC_template_type_arg, - &SkipBody); + OffsetOfState, FoundUsing, &SkipBody); // If ActOnTag said the type was dependent, try again with the // less common call. @@ -2044,7 +2134,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } else if (!TagOrTempResult.isInvalid()) { Result = DS.SetTypeSpecType( TagType, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec, - DiagID, TagOrTempResult.get(), Owned, Policy); + DiagID, FoundUsing ? FoundUsing : TagOrTempResult.get(), Owned, Policy); } else { DS.SetTypeSpecError(); return; @@ -3103,7 +3193,11 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, "Data member initializer not starting with '=' or '{'"); EnterExpressionEvaluationContext Context( - Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, D); + Actions, + isa_and_present<FieldDecl>(D) + ? Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed + : Sema::ExpressionEvaluationContext::PotentiallyEvaluated, + D); if (TryConsumeToken(tok::equal, EqualLoc)) { if (Tok.is(tok::kw_delete)) { // In principle, an initializer of '= delete p;' is legal, but it will @@ -3242,7 +3336,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( // yet. if (getLangOpts().OpenCL && !NextToken().is(tok::colon)) return ParseCXXClassMemberDeclaration(AS, AccessAttrs); - LLVM_FALLTHROUGH; + [[fallthrough]]; case tok::kw_public: case tok::kw_protected: { if (getLangOpts().HLSL) @@ -3688,7 +3782,8 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { ? takeTemplateIdAnnotation(Tok) : nullptr; if (TemplateId && TemplateId->mightBeType()) { - AnnotateTemplateIdTokenAsType(SS, /*IsClassName*/ true); + AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No, + /*IsClassName=*/true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); TemplateTypeTy = getTypeAnnotation(Tok); ConsumeAnnotationToken(); @@ -3721,7 +3816,6 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // Parse the optional expression-list. ExprVector ArgExprs; - CommaLocsTy CommaLocs; auto RunSignatureHelp = [&] { if (TemplateTypeTy.isInvalid()) return QualType(); @@ -3731,8 +3825,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { CalledSignatureHelp = true; return PreferredType; }; - if (Tok.isNot(tok::r_paren) && - ParseExpressionList(ArgExprs, CommaLocs, [&] { + if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, [&] { PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); })) { @@ -3980,7 +4073,7 @@ void Parser::ParseTrailingRequiresClause(Declarator &D) { Actions.ActOnStartTrailingRequiresClause(getCurScope(), D); - llvm::Optional<Sema::CXXThisScopeRAII> ThisScope; + std::optional<Sema::CXXThisScopeRAII> ThisScope; InitCXXThisScopeForDeclaratorIfRelevant(D, D.getDeclSpec(), ThisScope); TrailingRequiresClause = @@ -4405,8 +4498,6 @@ void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs, Diag(Tok.getLocation(), diag::err_expected) << tok::colon; } - llvm::SmallDenseMap<IdentifierInfo *, SourceLocation, 4> SeenAttrs; - bool AttrParsed = false; while (!Tok.isOneOf(tok::r_square, tok::semi, tok::eof)) { if (AttrParsed) { @@ -4717,7 +4808,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration( Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. - LLVM_FALLTHROUGH; + [[fallthrough]]; case IEB_Skip: Braces.skipToEnd(); |