aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/Parser.cpp')
-rw-r--r--clang/lib/Parse/Parser.cpp137
1 files changed, 83 insertions, 54 deletions
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 4249de361b89..764d4e8e9d52 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
@@ -432,16 +433,7 @@ Parser::~Parser() {
PP.clearCodeCompletionHandler();
- if (getLangOpts().DelayedTemplateParsing &&
- !PP.isIncrementalProcessingEnabled() && !TemplateIds.empty()) {
- // If an ASTConsumer parsed delay-parsed templates in their
- // HandleTranslationUnit() method, TemplateIds created there were not
- // guarded by a DestroyTemplateIdAnnotationsRAIIObj object in
- // ParseTopLevelDecl(). Destroy them here.
- DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
- }
-
- assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?");
+ DestroyTemplateIds();
}
/// Initialize - Warm up the parser.
@@ -537,11 +529,10 @@ void Parser::Initialize() {
ConsumeToken();
}
-void Parser::LateTemplateParserCleanupCallback(void *P) {
- // While this RAII helper doesn't bracket any actual work, the destructor will
- // clean up annotations that were created during ActOnEndOfTranslationUnit
- // when incremental processing is enabled.
- DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(((Parser *)P)->TemplateIds);
+void Parser::DestroyTemplateIds() {
+ for (TemplateIdAnnotation *Id : TemplateIds)
+ Id->Destroy();
+ TemplateIds.clear();
}
/// Parse the first top-level declaration in a translation unit.
@@ -576,7 +567,7 @@ bool Parser::ParseFirstTopLevelDecl(DeclGroupPtrTy &Result) {
/// declaration
/// [C++20] module-import-declaration
bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, bool IsFirstDecl) {
- DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
+ DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);
// Skip over the EOF token, flagging end of previous input for incremental
// processing
@@ -650,12 +641,18 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, bool IsFirstDecl) {
return false;
case tok::eof:
+ // Check whether -fmax-tokens= was reached.
+ if (PP.getMaxTokens() != 0 && PP.getTokenCount() > PP.getMaxTokens()) {
+ PP.Diag(Tok.getLocation(), diag::warn_max_tokens_total)
+ << PP.getTokenCount() << PP.getMaxTokens();
+ SourceLocation OverrideLoc = PP.getMaxTokensOverrideLoc();
+ if (OverrideLoc.isValid()) {
+ PP.Diag(OverrideLoc, diag::note_max_tokens_total_override);
+ }
+ }
+
// Late template parsing can begin.
- if (getLangOpts().DelayedTemplateParsing)
- Actions.SetLateTemplateParser(LateTemplateParserCallback,
- PP.isIncrementalProcessingEnabled() ?
- LateTemplateParserCleanupCallback : nullptr,
- this);
+ Actions.SetLateTemplateParser(LateTemplateParserCallback, nullptr, this);
if (!PP.isIncrementalProcessingEnabled())
Actions.ActOnEndOfTranslationUnit();
//else don't tell Sema that we ended parsing: more input might come.
@@ -716,7 +713,7 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, bool IsFirstDecl) {
Parser::DeclGroupPtrTy
Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
ParsingDeclSpec *DS) {
- DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
+ DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
if (PP.isCodeCompletionReached()) {
@@ -753,6 +750,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
case tok::annot_pragma_fenv_access:
HandlePragmaFEnvAccess();
return nullptr;
+ case tok::annot_pragma_float_control:
+ HandlePragmaFloatControl();
+ return nullptr;
case tok::annot_pragma_fp:
HandlePragmaFP();
break;
@@ -1136,6 +1136,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// Poison SEH identifiers so they are flagged as illegal in function bodies.
PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true);
const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
// If this is C90 and the declspecs were completely missing, fudge in an
// implicit int. We do this here because this is the only place where
@@ -1262,6 +1263,15 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// safe because we're always the sole owner.
D.getMutableDeclSpec().abort();
+ // With abbreviated function templates - we need to explicitly add depth to
+ // account for the implicit template parameter list induced by the template.
+ if (auto *Template = dyn_cast_or_null<FunctionTemplateDecl>(Res))
+ if (Template->isAbbreviated() &&
+ Template->getTemplateParameters()->getParam(0)->isImplicit())
+ // First template parameter is implicit - meaning no explicit template
+ // parameter list was specified.
+ CurTemplateDepthTracker.addDepth(1);
+
if (TryConsumeToken(tok::equal)) {
assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='");
@@ -1508,13 +1518,13 @@ ExprResult Parser::ParseSimpleAsm(bool ForAsmLabel, SourceLocation *EndLoc) {
assert(Tok.is(tok::kw_asm) && "Not an asm!");
SourceLocation Loc = ConsumeToken();
- if (Tok.is(tok::kw_volatile)) {
- // Remove from the end of 'asm' to the end of 'volatile'.
+ if (isGNUAsmQualifier(Tok)) {
+ // Remove from the end of 'asm' to the end of the asm qualifier.
SourceRange RemovalRange(PP.getLocForEndOfToken(Loc),
PP.getLocForEndOfToken(Tok.getLocation()));
-
- Diag(Tok, diag::warn_file_asm_volatile)
- << FixItHint::CreateRemoval(RemovalRange);
+ Diag(Tok, diag::err_global_asm_qualifier_ignored)
+ << GNUAsmQualifiers::getQualifierName(getGNUAsmQualifier(Tok))
+ << FixItHint::CreateRemoval(RemovalRange);
ConsumeToken();
}
@@ -1584,7 +1594,9 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) {
CXXScopeSpec SS;
if (getLangOpts().CPlusPlus &&
- ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext))
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
+ EnteringContext))
return ANK_Error;
if (Tok.isNot(tok::identifier) || SS.isInvalid()) {
@@ -1680,7 +1692,8 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) {
}
case Sema::NC_ContextIndependentExpr:
- Tok.setKind(tok::annot_primary_expr);
+ Tok.setKind(Actions.isUnevaluatedContext() ? tok::annot_uneval_primary_expr
+ : tok::annot_primary_expr);
setExprAnnotation(Tok, Classification.getExpression());
Tok.setAnnotationEndLoc(NameLoc);
if (SS.isNotEmpty())
@@ -1732,6 +1745,20 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) {
return ANK_Error;
return ANK_Success;
}
+ case Sema::NC_Concept: {
+ UnqualifiedId Id;
+ Id.setIdentifier(Name, NameLoc);
+ if (Next.is(tok::less))
+ // We have a concept name followed by '<'. Consume the identifier token so
+ // we reach the '<' and annotate it.
+ ConsumeToken();
+ if (AnnotateTemplateIdToken(
+ TemplateTy::make(Classification.getTemplateName()),
+ Classification.getTemplateNameKind(), SS, SourceLocation(), Id,
+ /*AllowTypeAnnotation=*/false, /*TypeConstraint=*/true))
+ return ANK_Error;
+ return ANK_Success;
+ }
}
// Unable to classify the name, but maybe we can annotate a scope specifier.
@@ -1807,10 +1834,11 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
SourceLocation TypenameLoc = ConsumeToken();
CXXScopeSpec SS;
if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
/*EnteringContext=*/false, nullptr,
/*IsTypename*/ true))
return true;
- if (!SS.isSet()) {
+ if (SS.isEmpty()) {
if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id) ||
Tok.is(tok::annot_decltype)) {
// Attempt to recover by skipping the invalid 'typename'
@@ -1840,9 +1868,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
Tok.getLocation());
} else if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
- if (TemplateId->Kind != TNK_Type_template &&
- TemplateId->Kind != TNK_Dependent_template_name &&
- TemplateId->Kind != TNK_Undeclared_template) {
+ if (!TemplateId->mightBeType()) {
Diag(Tok, diag::err_typename_refers_to_non_type_template)
<< Tok.getAnnotationRange();
return true;
@@ -1851,14 +1877,13 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS,
- TemplateId->TemplateKWLoc,
- TemplateId->Template,
- TemplateId->Name,
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->RAngleLoc);
+ Ty = TemplateId->isInvalid()
+ ? TypeError()
+ : Actions.ActOnTypenameType(
+ getCurScope(), TypenameLoc, SS, TemplateId->TemplateKWLoc,
+ TemplateId->Template, TemplateId->Name,
+ TemplateId->TemplateNameLoc, TemplateId->LAngleLoc,
+ TemplateArgsPtr, TemplateId->RAngleLoc);
} else {
Diag(Tok, diag::err_expected_type_name_after_typename)
<< SS.getRange();
@@ -1867,7 +1892,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
SourceLocation EndLoc = Tok.getLastLoc();
Tok.setKind(tok::annot_typename);
- setTypeAnnotation(Tok, Ty.isInvalid() ? nullptr : Ty.get());
+ setTypeAnnotation(Tok, Ty);
Tok.setAnnotationEndLoc(EndLoc);
Tok.setLocation(TypenameLoc);
PP.AnnotateCachedTokens(Tok);
@@ -1879,7 +1904,9 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
CXXScopeSpec SS;
if (getLangOpts().CPlusPlus)
- if (ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext*/false))
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
+ /*EnteringContext*/ false))
return true;
return TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation);
@@ -1983,7 +2010,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();
+ AnnotateTemplateIdTokenAsType(SS);
return false;
}
}
@@ -2005,13 +2032,12 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS,
bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
assert(getLangOpts().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
- assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) ||
- Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super)) &&
- "Cannot be a type or scope token!");
+ assert(MightBeCXXScopeToken() && "Cannot be a type or scope token!");
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext))
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
+ EnteringContext))
return true;
if (SS.isEmpty())
return false;
@@ -2120,7 +2146,8 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) {
// Parse nested-name-specifier.
if (getLangOpts().CPlusPlus)
- ParseOptionalCXXScopeSpecifier(Result.SS, nullptr,
+ ParseOptionalCXXScopeSpecifier(Result.SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false,
/*EnteringContext=*/false);
// Check nested-name specifier.
@@ -2131,10 +2158,12 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) {
// Parse the unqualified-id.
SourceLocation TemplateKWLoc; // FIXME: parsed, but unused.
- if (ParseUnqualifiedId(
- Result.SS, /*EnteringContext*/false, /*AllowDestructorName*/true,
- /*AllowConstructorName*/true, /*AllowDeductionGuide*/false, nullptr,
- &TemplateKWLoc, Result.Name)) {
+ if (ParseUnqualifiedId(Result.SS, /*ObjectType=*/nullptr,
+ /*ObjectHadErrors=*/false, /*EnteringContext*/ false,
+ /*AllowDestructorName*/ true,
+ /*AllowConstructorName*/ true,
+ /*AllowDeductionGuide*/ false, &TemplateKWLoc,
+ Result.Name)) {
T.skipToEnd();
return true;
}