summaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Parse/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/Parser.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Parse/Parser.cpp100
1 files changed, 74 insertions, 26 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/Parser.cpp b/contrib/llvm-project/clang/lib/Parse/Parser.cpp
index 9124f1558664..0b778bd24277 100644
--- a/contrib/llvm-project/clang/lib/Parse/Parser.cpp
+++ b/contrib/llvm-project/clang/lib/Parse/Parser.cpp
@@ -174,7 +174,7 @@ bool Parser::ExpectAndConsumeSemi(unsigned DiagID) {
return ExpectAndConsume(tok::semi, DiagID);
}
-void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) {
+void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, DeclSpec::TST TST) {
if (!Tok.is(tok::semi)) return;
bool HadMultipleSemis = false;
@@ -202,7 +202,7 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) {
if (Kind != AfterMemberFunctionDefinition || HadMultipleSemis)
Diag(StartLoc, diag::ext_extra_semi)
- << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST,
+ << Kind << DeclSpec::getSpecifierName(TST,
Actions.getASTContext().getPrintingPolicy())
<< FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));
else
@@ -278,6 +278,10 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
case tok::annot_pragma_openmp:
case tok::annot_pragma_openmp_end:
// Stop before an OpenMP pragma boundary.
+ if (OpenMPDirectiveParsing)
+ return false;
+ ConsumeAnnotationToken();
+ break;
case tok::annot_module_begin:
case tok::annot_module_end:
case tok::annot_module_include:
@@ -799,7 +803,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
SourceLocation StartLoc = Tok.getLocation();
SourceLocation EndLoc;
- ExprResult Result(ParseSimpleAsm(&EndLoc));
+ ExprResult Result(ParseSimpleAsm(/*ForAsmLabel*/ false, &EndLoc));
// Check if GNU-style InlineAsm is disabled.
// Empty asm string is allowed because it will not introduce
@@ -1132,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
@@ -1174,8 +1179,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
if (Tok.isNot(tok::equal)) {
for (const ParsedAttr &AL : D.getAttributes())
if (AL.isKnownToGCC() && !AL.isCXX11Attribute())
- Diag(AL.getLoc(), diag::warn_attribute_on_function_definition)
- << AL.getName();
+ Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) << AL;
}
// In delayed template parsing mode, for function template we consume the
@@ -1259,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 '='");
@@ -1464,11 +1477,14 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
/// ParseAsmStringLiteral - This is just a normal string-literal, but is not
/// allowed to be a wide string, and is not subject to character translation.
+/// Unlike GCC, we also diagnose an empty string literal when parsing for an
+/// asm label as opposed to an asm statement, because such a construct does not
+/// behave well.
///
/// [GNU] asm-string-literal:
/// string-literal
///
-ExprResult Parser::ParseAsmStringLiteral() {
+ExprResult Parser::ParseAsmStringLiteral(bool ForAsmLabel) {
if (!isTokenStringLiteral()) {
Diag(Tok, diag::err_expected_string_literal)
<< /*Source='in...'*/0 << "'asm'";
@@ -1484,6 +1500,11 @@ ExprResult Parser::ParseAsmStringLiteral() {
<< SL->getSourceRange();
return ExprError();
}
+ if (ForAsmLabel && SL->getString().empty()) {
+ Diag(Tok, diag::err_asm_operand_wide_string_literal)
+ << 2 /* an empty */ << SL->getSourceRange();
+ return ExprError();
+ }
}
return AsmString;
}
@@ -1493,7 +1514,7 @@ ExprResult Parser::ParseAsmStringLiteral() {
/// [GNU] simple-asm-expr:
/// 'asm' '(' asm-string-literal ')'
///
-ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
+ExprResult Parser::ParseSimpleAsm(bool ForAsmLabel, SourceLocation *EndLoc) {
assert(Tok.is(tok::kw_asm) && "Not an asm!");
SourceLocation Loc = ConsumeToken();
@@ -1513,7 +1534,7 @@ ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
return ExprError();
}
- ExprResult Result(ParseAsmStringLiteral());
+ ExprResult Result(ParseAsmStringLiteral(ForAsmLabel));
if (!Result.isInvalid()) {
// Close the paren and get the location of the end bracket
@@ -1562,13 +1583,10 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) {
/// with a typo-corrected keyword. This is only appropriate when the current
/// name must refer to an entity which has already been declared.
///
-/// \param IsAddressOfOperand Must be \c true if the name is preceded by an '&'
-/// and might possibly have a dependent nested name specifier.
/// \param CCC Indicates how to perform typo-correction for this name. If NULL,
/// no typo correction will be performed.
Parser::AnnotatedNameKind
-Parser::TryAnnotateName(bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC) {
+Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) {
assert(Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope));
const bool EnteringContext = false;
@@ -1604,9 +1622,8 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
// after a scope specifier, because in general we can't recover from typos
// there (eg, after correcting 'A::template B<X>::C' [sic], we would need to
// jump back into scope specifier parsing).
- Sema::NameClassification Classification =
- Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next,
- IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr);
+ Sema::NameClassification Classification = Actions.ClassifyName(
+ getCurScope(), SS, Name, NameLoc, Next, SS.isEmpty() ? CCC : nullptr);
// If name lookup found nothing and we guessed that this was a template name,
// double-check before committing to that interpretation. C++20 requires that
@@ -1619,7 +1636,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
FakeNext.setKind(tok::unknown);
Classification =
Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, FakeNext,
- IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr);
+ SS.isEmpty() ? CCC : nullptr);
}
switch (Classification.getKind()) {
@@ -1672,7 +1689,7 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
return ANK_Success;
}
- case Sema::NC_Expression:
+ case Sema::NC_ContextIndependentExpr:
Tok.setKind(tok::annot_primary_expr);
setExprAnnotation(Tok, Classification.getExpression());
Tok.setAnnotationEndLoc(NameLoc);
@@ -1681,6 +1698,29 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
PP.AnnotateCachedTokens(Tok);
return ANK_Success;
+ case Sema::NC_NonType:
+ Tok.setKind(tok::annot_non_type);
+ setNonTypeAnnotation(Tok, Classification.getNonTypeDecl());
+ Tok.setLocation(NameLoc);
+ Tok.setAnnotationEndLoc(NameLoc);
+ PP.AnnotateCachedTokens(Tok);
+ if (SS.isNotEmpty())
+ AnnotateScopeToken(SS, !WasScopeAnnotation);
+ return ANK_Success;
+
+ case Sema::NC_UndeclaredNonType:
+ case Sema::NC_DependentNonType:
+ Tok.setKind(Classification.getKind() == Sema::NC_UndeclaredNonType
+ ? tok::annot_non_type_undeclared
+ : tok::annot_non_type_dependent);
+ setIdentifierAnnotation(Tok, Name);
+ Tok.setLocation(NameLoc);
+ Tok.setAnnotationEndLoc(NameLoc);
+ PP.AnnotateCachedTokens(Tok);
+ if (SS.isNotEmpty())
+ AnnotateScopeToken(SS, !WasScopeAnnotation);
+ return ANK_Success;
+
case Sema::NC_TypeTemplate:
if (Next.isNot(tok::less)) {
// This may be a type template being used as a template template argument.
@@ -1702,9 +1742,20 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
return ANK_Error;
return ANK_Success;
}
-
- case Sema::NC_NestedNameSpecifier:
- llvm_unreachable("already parsed nested name specifier");
+ 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.
@@ -1783,7 +1834,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
/*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'
@@ -1956,7 +2007,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;
}
}
@@ -1978,10 +2029,7 @@ 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))