diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/Parser.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/Parse/Parser.cpp | 100 |
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)) |
