aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/Parse/Parser.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'clang/lib/Parse/Parser.cpp')
-rw-r--r--clang/lib/Parse/Parser.cpp161
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);