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/Parser.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'clang/lib/Parse/Parser.cpp')
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 161 |
1 files changed, 106 insertions, 55 deletions
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index fd044660845b..6db3dc3156fd 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -386,7 +386,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { case tok::semi: if (HasFlagsSet(Flags, StopAtSemi)) return false; - LLVM_FALLTHROUGH; + [[fallthrough]]; default: // Skip this token. ConsumeAnyToken(); @@ -707,8 +707,7 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, // Late template parsing can begin. Actions.SetLateTemplateParser(LateTemplateParserCallback, nullptr, this); - if (!PP.isIncrementalProcessingEnabled()) - Actions.ActOnEndOfTranslationUnit(); + Actions.ActOnEndOfTranslationUnit(); //else don't tell Sema that we ended parsing: more input might come. return true; @@ -731,10 +730,17 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, break; } - ParsedAttributes attrs(AttrFactory); - MaybeParseCXX11Attributes(attrs); + ParsedAttributes DeclAttrs(AttrFactory); + ParsedAttributes DeclSpecAttrs(AttrFactory); + // GNU attributes are applied to the declaration specification while the + // standard attributes are applied to the declaration. We parse the two + // attribute sets into different containters so we can apply them during + // the regular parsing process. + while (MaybeParseCXX11Attributes(DeclAttrs) || + MaybeParseGNUAttributes(DeclSpecAttrs)) + ; - Result = ParseExternalDeclaration(attrs); + Result = ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs); // An empty Result might mean a line with ';' or some parsing error, ignore // it. if (Result) { @@ -744,6 +750,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, else if (ImportState == Sema::ModuleImportState::ImportAllowed) // Non-imports disallow further imports. ImportState = Sema::ModuleImportState::ImportFinished; + else if (ImportState == + Sema::ModuleImportState::PrivateFragmentImportAllowed) + // Non-imports disallow further imports. + ImportState = Sema::ModuleImportState::PrivateFragmentImportFinished; } return false; } @@ -777,8 +787,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, /// /// [Modules-TS] module-import-declaration /// -Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, - ParsingDeclSpec *DS) { +Parser::DeclGroupPtrTy +Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, + ParsedAttributes &DeclSpecAttrs, + ParsingDeclSpec *DS) { DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this); ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -866,7 +878,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. ConsumeToken(); - return ParseExternalDeclaration(Attrs); + return ParseExternalDeclaration(Attrs, DeclSpecAttrs); } case tok::kw_asm: { ProhibitAttributes(Attrs); @@ -894,7 +906,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, break; } case tok::at: - return ParseObjCAtDirectives(Attrs); + return ParseObjCAtDirectives(Attrs, DeclSpecAttrs); case tok::minus: case tok::plus: if (!getLangOpts().ObjC) { @@ -909,7 +921,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, if (CurParsedObjCImpl) { // Code-complete Objective-C methods even without leading '-'/'+' prefix. Actions.CodeCompleteObjCMethodDecl(getCurScope(), - /*IsInstanceMethod=*/None, + /*IsInstanceMethod=*/std::nullopt, /*ReturnType=*/nullptr); } Actions.CodeCompleteOrdinaryName( @@ -932,7 +944,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, } // This must be 'export template'. Parse it so we can diagnose our lack // of support. - LLVM_FALLTHROUGH; + [[fallthrough]]; case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: @@ -942,10 +954,18 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, // A function definition cannot start with any of these keywords. { SourceLocation DeclEnd; - ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs, - EmptyDeclSpecAttrs); + DeclSpecAttrs); + } + + case tok::kw_cbuffer: + case tok::kw_tbuffer: + if (getLangOpts().HLSL) { + SourceLocation DeclEnd; + return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs, + DeclSpecAttrs); } + goto dont_know; case tok::kw_static: // Parse (then ignore) 'static' prior to a template instantiation. This is @@ -954,9 +974,8 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 0; SourceLocation DeclEnd; - ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs, - EmptyDeclSpecAttrs); + DeclSpecAttrs); } goto dont_know; @@ -967,9 +986,8 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, // Inline namespaces. Allowed as an extension even in C++03. if (NextKind == tok::kw_namespace) { SourceLocation DeclEnd; - ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs, - EmptyDeclSpecAttrs); + DeclSpecAttrs); } // Parse (then ignore) 'inline' prior to a template instantiation. This is @@ -978,9 +996,8 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 1; SourceLocation DeclEnd; - ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs, - EmptyDeclSpecAttrs); + DeclSpecAttrs); } } goto dont_know; @@ -1015,8 +1032,13 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(ParsedAttributes &Attrs, ConsumeToken(); return nullptr; } + if (PP.isIncrementalProcessingEnabled() && + !isDeclarationStatement(/*DisambiguatingWithExpression=*/true)) + return ParseTopLevelStmtDecl(); + // We can't tell whether this is a function-definition or declaration yet. - return ParseDeclarationOrFunctionDefinition(Attrs, DS); + if (!SingleDecl) + return ParseDeclarationOrFunctionDefinition(Attrs, DeclSpecAttrs, DS); } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -1053,7 +1075,7 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { // Handle K&R C argument lists: int X(f) int f; {} if (!getLangOpts().CPlusPlus && Declarator.getFunctionTypeInfo().isKNRPrototype()) - return isDeclarationSpecifier(); + return isDeclarationSpecifier(ImplicitTypenameContext::No); if (getLangOpts().CPlusPlus && Tok.is(tok::equal)) { const Token &KW = NextToken(); @@ -1081,7 +1103,17 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { /// [OMP] allocate-directive [TODO] /// Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal( - ParsedAttributes &Attrs, ParsingDeclSpec &DS, AccessSpecifier AS) { + ParsedAttributes &Attrs, ParsedAttributes &DeclSpecAttrs, + ParsingDeclSpec &DS, AccessSpecifier AS) { + // Because we assume that the DeclSpec has not yet been initialised, we simply + // overwrite the source range and attribute the provided leading declspec + // attributes. + assert(DS.getSourceRange().isInvalid() && + "expected uninitialised source range"); + DS.SetRangeStart(DeclSpecAttrs.Range.getBegin()); + DS.SetRangeEnd(DeclSpecAttrs.Range.getEnd()); + DS.takeAttributesFrom(DeclSpecAttrs); + MaybeParseMicrosoftAttributes(DS.getAttributes()); // Parse the common declaration-specifiers piece. ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, @@ -1180,9 +1212,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclOrFunctionDefInternal( } Parser::DeclGroupPtrTy Parser::ParseDeclarationOrFunctionDefinition( - ParsedAttributes &Attrs, ParsingDeclSpec *DS, AccessSpecifier AS) { + ParsedAttributes &Attrs, ParsedAttributes &DeclSpecAttrs, + ParsingDeclSpec *DS, AccessSpecifier AS) { if (DS) { - return ParseDeclOrFunctionDefInternal(Attrs, *DS, AS); + return ParseDeclOrFunctionDefInternal(Attrs, DeclSpecAttrs, *DS, AS); } else { ParsingDeclSpec PDS(*this); // Must temporarily exit the objective-c container scope for @@ -1190,7 +1223,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclarationOrFunctionDefinition( // afterwards. ObjCDeclContextSwitch ObjCDC(*this); - return ParseDeclOrFunctionDefInternal(Attrs, PDS, AS); + return ParseDeclOrFunctionDefInternal(Attrs, DeclSpecAttrs, PDS, AS); } } @@ -1462,7 +1495,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { Scope::FunctionDeclarationScope | Scope::DeclScope); // Read all the argument declarations. - while (isDeclarationSpecifier()) { + while (isDeclarationSpecifier(ImplicitTypenameContext::No)) { SourceLocation DSStart = Tok.getLocation(); // Parse the common declaration-specifiers piece. @@ -1675,8 +1708,12 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) { /// /// \param CCC Indicates how to perform typo-correction for this name. If NULL, /// no typo correction will be performed. +/// \param AllowImplicitTypename Whether we are in a context where a dependent +/// nested-name-specifier without typename is treated as a type (e.g. +/// T::type). Parser::AnnotatedNameKind -Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) { +Parser::TryAnnotateName(CorrectionCandidateCallback *CCC, + ImplicitTypenameContext AllowImplicitTypename) { assert(Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope)); const bool EnteringContext = false; @@ -1690,7 +1727,8 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) { return ANK_Error; if (Tok.isNot(tok::identifier) || SS.isInvalid()) { - if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation)) + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation, + AllowImplicitTypename)) return ANK_Error; return ANK_Unresolved; } @@ -1700,10 +1738,11 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) { // FIXME: Move the tentative declaration logic into ClassifyName so we can // typo-correct to tentatively-declared identifiers. - if (isTentativelyDeclared(Name)) { + if (isTentativelyDeclared(Name) && SS.isEmpty()) { // Identifier has been tentatively declared, and thus cannot be resolved as // an expression. Fall back to annotating it as a type. - if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation)) + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation, + AllowImplicitTypename)) return ANK_Error; return Tok.is(tok::annot_typename) ? ANK_Success : ANK_TentativeDecl; } @@ -1830,7 +1869,7 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) { AnnotateScopeToken(SS, !WasScopeAnnotation); return ANK_TemplateName; } - LLVM_FALLTHROUGH; + [[fallthrough]]; case Sema::NC_VarTemplate: case Sema::NC_FunctionTemplate: case Sema::NC_UndeclaredTemplate: { @@ -1899,7 +1938,8 @@ bool Parser::TryKeywordIdentFallback(bool DisableKeyword) { /// /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. -bool Parser::TryAnnotateTypeOrScopeToken() { +bool Parser::TryAnnotateTypeOrScopeToken( + ImplicitTypenameContext AllowImplicitTypename) { assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) || Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) || @@ -1916,7 +1956,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { if (getLangOpts().MSVCCompat && NextToken().is(tok::kw_typedef)) { Token TypedefToken; PP.Lex(TypedefToken); - bool Result = TryAnnotateTypeOrScopeToken(); + bool Result = TryAnnotateTypeOrScopeToken(AllowImplicitTypename); PP.EnterToken(Tok, /*IsReinject=*/true); Tok = TypedefToken; if (!Result) @@ -1942,7 +1982,8 @@ bool Parser::TryAnnotateTypeOrScopeToken() { Tok.is(tok::annot_decltype)) { // Attempt to recover by skipping the invalid 'typename' if (Tok.is(tok::annot_decltype) || - (!TryAnnotateTypeOrScopeToken() && Tok.isAnnotation())) { + (!TryAnnotateTypeOrScopeToken(AllowImplicitTypename) && + Tok.isAnnotation())) { unsigned DiagID = diag::err_expected_qualified_after_typename; // MS compatibility: MSVC permits using known types with typename. // e.g. "typedef typename T* pointer_type" @@ -2008,22 +2049,24 @@ bool Parser::TryAnnotateTypeOrScopeToken() { /*EnteringContext*/ false)) return true; - return TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation); + return TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation, + AllowImplicitTypename); } /// Try to annotate a type or scope token, having already parsed an /// optional scope specifier. \p IsNewScope should be \c true unless the scope /// specifier was extracted from an existing tok::annot_cxxscope annotation. -bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, - bool IsNewScope) { +bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec( + CXXScopeSpec &SS, bool IsNewScope, + ImplicitTypenameContext AllowImplicitTypename) { if (Tok.is(tok::identifier)) { // Determine whether the identifier is a type name. if (ParsedType Ty = Actions.getTypeName( *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS, false, NextToken().is(tok::period), nullptr, /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo*/true, - /*IsClassTemplateDeductionContext*/true)) { + /*NonTrivialTypeSourceInfo=*/true, + /*IsClassTemplateDeductionContext=*/true, AllowImplicitTypename)) { SourceLocation BeginLoc = Tok.getLocation(); if (SS.isNotEmpty()) // it was a C++ qualified type name. BeginLoc = SS.getBeginLoc(); @@ -2060,9 +2103,9 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, } if (!getLangOpts().CPlusPlus) { - // If we're in C, we can't have :: tokens at all (the lexer won't return - // them). If the identifier is not a type, then it can't be scope either, - // just early exit. + // If we're in C, the only place we can have :: tokens is C2x + // attribute which is parsed elsewhere. If the identifier is not a type, + // then it can't be scope either, just early exit. return false; } @@ -2109,7 +2152,7 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, // template-id annotation in a context where we weren't allowed // to produce a type annotation token. Update the template-id // annotation token to a type annotation token now. - AnnotateTemplateIdTokenAsType(SS); + AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename); return false; } } @@ -2167,7 +2210,7 @@ bool Parser::isTokenEqualOrEqualTypo() { Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal) << Kind << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); - LLVM_FALLTHROUGH; + [[fallthrough]]; case tok::equal: return true; } @@ -2322,7 +2365,8 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { ParsedAttributes Attrs(AttrFactory); MaybeParseCXX11Attributes(Attrs); - DeclGroupPtrTy Result = ParseExternalDeclaration(Attrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + DeclGroupPtrTy Result = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs); if (Result && !getCurScope()->getParent()) Actions.getASTConsumer().HandleTopLevelDecl(Result.get()); } @@ -2387,7 +2431,9 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) { SourceLocation PrivateLoc = ConsumeToken(); DiagnoseAndSkipCXX11Attributes(); ExpectAndConsumeSemi(diag::err_private_module_fragment_expected_semi); - ImportState = Sema::ModuleImportState::PrivateFragment; + ImportState = ImportState == Sema::ModuleImportState::ImportAllowed + ? Sema::ModuleImportState::PrivateFragmentImportAllowed + : Sema::ModuleImportState::PrivateFragmentImportFinished; return Actions.ActOnPrivateModuleFragmentDecl(ModuleLoc, PrivateLoc); } @@ -2504,23 +2550,28 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc, SeenError = false; break; case Sema::ModuleImportState::GlobalFragment: - // We can only have pre-processor directives in the global module - // fragment. We cannot import a named modules here, however we have a - // header unit import. - if (!HeaderUnit || HeaderUnit->Kind != Module::ModuleKind::ModuleHeaderUnit) - Diag(ImportLoc, diag::err_import_in_wrong_fragment) << IsPartition << 0; + case Sema::ModuleImportState::PrivateFragmentImportAllowed: + // We can only have pre-processor directives in the global module fragment + // which allows pp-import, but not of a partition (since the global module + // does not have partitions). + // We cannot import a partition into a private module fragment, since + // [module.private.frag]/1 disallows private module fragments in a multi- + // TU module. + if (IsPartition || (HeaderUnit && HeaderUnit->Kind != + Module::ModuleKind::ModuleHeaderUnit)) + Diag(ImportLoc, diag::err_import_in_wrong_fragment) + << IsPartition + << (ImportState == Sema::ModuleImportState::GlobalFragment ? 0 : 1); else SeenError = false; break; case Sema::ModuleImportState::ImportFinished: + case Sema::ModuleImportState::PrivateFragmentImportFinished: if (getLangOpts().CPlusPlusModules) Diag(ImportLoc, diag::err_import_not_allowed_here); else SeenError = false; break; - case Sema::ModuleImportState::PrivateFragment: - Diag(ImportLoc, diag::err_import_in_wrong_fragment) << IsPartition << 1; - break; } if (SeenError) { ExpectAndConsumeSemi(diag::err_module_expected_semi); |