diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-04-27 02:00:13 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-04-27 02:00:13 +0000 |
| commit | c08b693e309baa80f0a3dd7794af130c3393c777 (patch) | |
| tree | 30986154bf0d7997794a5746ca6270df4d53f40c /clang/lib/Parse | |
| parent | 93979f67f8cc49f596ae34c45699371bd3cda785 (diff) | |
| download | bcm5719-llvm-c08b693e309baa80f0a3dd7794af130c3393c777.tar.gz bcm5719-llvm-c08b693e309baa80f0a3dd7794af130c3393c777.zip | |
Parse A::template B as an identifier rather than as a template-id with no
template arguments.
This fixes some cases where we'd incorrectly accept "A::template B" when B is a
kind of template that requires template arguments (in particular, a variable
template or a concept).
llvm-svn: 331013
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 82 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseStmtAsm.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/Parser.cpp | 2 |
7 files changed, 63 insertions, 39 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 3d3abe32ab8..fc0ca613c73 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5600,12 +5600,11 @@ void Parser::ParseDirectDeclarator(Declarator &D) { D.getContext() == DeclaratorContext::MemberContext); } - SourceLocation TemplateKWLoc; bool HadScope = D.getCXXScopeSpec().isValid(); if (ParseUnqualifiedId(D.getCXXScopeSpec(), /*EnteringContext=*/true, /*AllowDestructorName=*/true, AllowConstructorName, - AllowDeductionGuide, nullptr, TemplateKWLoc, + AllowDeductionGuide, nullptr, nullptr, D.getName()) || // Once we're past the identifier, if the scope was bad, mark the // whole declarator bad. diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 0c789c9b1c4..ec1177aece2 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -602,7 +602,7 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context, /*AllowConstructorName=*/!(Tok.is(tok::identifier) && NextToken().is(tok::equal)), /*AllowDeductionGuide=*/false, - nullptr, D.TemplateKWLoc, D.Name)) + nullptr, nullptr, D.Name)) return true; } @@ -2476,7 +2476,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SourceLocation TemplateKWLoc; UnqualifiedId Name; if (ParseUnqualifiedId(SS, false, true, true, false, nullptr, - TemplateKWLoc, Name)) { + &TemplateKWLoc, Name)) { SkipUntil(tok::semi); return nullptr; } @@ -2488,6 +2488,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return nullptr; } + // FIXME: We should do something with the 'template' keyword here. return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( getCurScope(), AS, /*UsingLoc*/ SourceLocation(), /*TypenameLoc*/ SourceLocation(), SS, Name, diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 1b8865edb79..ca5d3bce9cf 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1755,7 +1755,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /*AllowConstructorName=*/ getLangOpts().MicrosoftExt, /*AllowDeductionGuide=*/false, - ObjectType, TemplateKWLoc, Name)) { + ObjectType, &TemplateKWLoc, Name)) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 7ebd90ef239..8e39adf8a5d 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -553,7 +553,7 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe /*AllowDestructorName=*/false, /*AllowConstructorName=*/false, /*AllowDeductionGuide=*/false, - /*ObjectType=*/nullptr, TemplateKWLoc, Name)) + /*ObjectType=*/nullptr, &TemplateKWLoc, Name)) return ExprError(); // This is only the direct operand of an & operator if it is not @@ -2044,9 +2044,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, ParsedType ObjectType, UnqualifiedId &Id, bool AssumeTemplateId) { - assert((AssumeTemplateId || Tok.is(tok::less)) && - "Expected '<' to finish parsing a template-id"); - + assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id"); + TemplateTy Template; TemplateNameKind TNK = TNK_Non_template; switch (Id.getKind()) { @@ -2142,10 +2141,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - if (Tok.is(tok::less) && ParseTemplateIdAfterTemplateName( - true, LAngleLoc, TemplateArgs, RAngleLoc)) + if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc)) return true; - + if (Id.getKind() == UnqualifiedIdKind::IK_Identifier || Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId || Id.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) { @@ -2465,16 +2464,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowConstructorName, bool AllowDeductionGuide, ParsedType ObjectType, - SourceLocation& TemplateKWLoc, + SourceLocation *TemplateKWLoc, UnqualifiedId &Result) { + if (TemplateKWLoc) + *TemplateKWLoc = SourceLocation(); // Handle 'A::template B'. This is for template-ids which have not // already been annotated by ParseOptionalCXXScopeSpecifier(). bool TemplateSpecified = false; - if (getLangOpts().CPlusPlus && Tok.is(tok::kw_template) && - (ObjectType || SS.isSet())) { - TemplateSpecified = true; - TemplateKWLoc = ConsumeToken(); + if (Tok.is(tok::kw_template)) { + if (TemplateKWLoc && (ObjectType || SS.isSet())) { + TemplateSpecified = true; + *TemplateKWLoc = ConsumeToken(); + } else { + SourceLocation TemplateLoc = ConsumeToken(); + Diag(TemplateLoc, diag::err_unexpected_template_in_unqualified_id) + << FixItHint::CreateRemoval(TemplateLoc); + } } // unqualified-id: @@ -2513,11 +2519,18 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, } // If the next token is a '<', we may have a template. - if (TemplateSpecified || Tok.is(tok::less)) - return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, Id, IdLoc, - EnteringContext, ObjectType, - Result, TemplateSpecified); - + TemplateTy Template; + if (Tok.is(tok::less)) + return ParseUnqualifiedIdTemplateId( + SS, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, + EnteringContext, ObjectType, Result, TemplateSpecified); + else if (TemplateSpecified && + Actions.ActOnDependentTemplateName( + getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, + EnteringContext, Template, + /*AllowInjectedClassName*/ true) == TNK_Non_template) + return true; + return false; } @@ -2558,7 +2571,14 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // We have already parsed a template-id; consume the annotation token as // our unqualified-id. Result.setTemplateId(TemplateId); - TemplateKWLoc = TemplateId->TemplateKWLoc; + SourceLocation TemplateLoc = TemplateId->TemplateKWLoc; + if (TemplateLoc.isValid()) { + if (TemplateKWLoc && (ObjectType || SS.isSet())) + *TemplateKWLoc = TemplateLoc; + else + Diag(TemplateLoc, diag::err_unexpected_template_in_unqualified_id) + << FixItHint::CreateRemoval(TemplateLoc); + } ConsumeAnnotationToken(); return false; } @@ -2575,13 +2595,20 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // // template-id: // operator-function-id < template-argument-list[opt] > + TemplateTy Template; if ((Result.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId || Result.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) && - (TemplateSpecified || Tok.is(tok::less))) - return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, - nullptr, SourceLocation(), - EnteringContext, ObjectType, - Result, TemplateSpecified); + Tok.is(tok::less)) + return ParseUnqualifiedIdTemplateId( + SS, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), nullptr, + SourceLocation(), EnteringContext, ObjectType, Result, + TemplateSpecified); + else if (TemplateSpecified && + Actions.ActOnDependentTemplateName( + getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, + EnteringContext, Template, + /*AllowInjectedClassName*/ true) == TNK_Non_template) + return true; return false; } @@ -2649,12 +2676,11 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, IdentifierInfo *ClassName = Tok.getIdentifierInfo(); SourceLocation ClassNameLoc = ConsumeToken(); - if (TemplateSpecified || Tok.is(tok::less)) { + if (Tok.is(tok::less)) { Result.setDestructorName(TildeLoc, nullptr, ClassNameLoc); - return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, - ClassName, ClassNameLoc, - EnteringContext, ObjectType, - Result, TemplateSpecified); + return ParseUnqualifiedIdTemplateId( + SS, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), ClassName, + ClassNameLoc, EnteringContext, ObjectType, Result, TemplateSpecified); } // Note that this is a destructor name. diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index e00bfb845fc..bfd708fe86e 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -1154,7 +1154,6 @@ bool Parser::ParseOpenMPSimpleVarList( // Read tokens while ')' or annot_pragma_openmp_end is not found. while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { CXXScopeSpec SS; - SourceLocation TemplateKWLoc; UnqualifiedId Name; // Read var name. Token PrevTok = Tok; @@ -1166,7 +1165,7 @@ bool Parser::ParseOpenMPSimpleVarList( SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr, - TemplateKWLoc, Name)) { + nullptr, Name)) { IsCorrect = false; SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); @@ -1648,7 +1647,6 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId) { - SourceLocation TemplateKWLoc; if (ReductionIdScopeSpec.isEmpty()) { auto OOK = OO_None; switch (P.getCurToken().getKind()) { @@ -1690,7 +1688,7 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, /*AllowDestructorName*/ false, /*AllowConstructorName*/ false, /*AllowDeductionGuide*/ false, - nullptr, TemplateKWLoc, ReductionId); + nullptr, nullptr, ReductionId); } /// Parses clauses with list. diff --git a/clang/lib/Parse/ParseStmtAsm.cpp b/clang/lib/Parse/ParseStmtAsm.cpp index d81029e2797..290723c2953 100644 --- a/clang/lib/Parse/ParseStmtAsm.cpp +++ b/clang/lib/Parse/ParseStmtAsm.cpp @@ -239,7 +239,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, /*AllowDestructorName=*/false, /*AllowConstructorName=*/false, /*AllowDeductionGuide=*/false, - /*ObjectType=*/nullptr, TemplateKWLoc, Id); + /*ObjectType=*/nullptr, &TemplateKWLoc, Id); // Perform the lookup. Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, IsUnevaluatedContext); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index d8f9f7a3902..036688cf8f9 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -2002,7 +2002,7 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { if (ParseUnqualifiedId( Result.SS, /*EnteringContext*/false, /*AllowDestructorName*/true, /*AllowConstructorName*/true, /*AllowDeductionGuide*/false, nullptr, - TemplateKWLoc, Result.Name)) { + &TemplateKWLoc, Result.Name)) { T.skipToEnd(); return true; } |

