summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp3
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp5
-rw-r--r--clang/lib/Parse/ParseExpr.cpp2
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp82
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp6
-rw-r--r--clang/lib/Parse/ParseStmtAsm.cpp2
-rw-r--r--clang/lib/Parse/Parser.cpp2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp7
-rw-r--r--clang/lib/Sema/SemaExprMember.cpp14
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp4
10 files changed, 77 insertions, 50 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;
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 6f2800ea27d..b1ecbfad4c3 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2080,7 +2080,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
(Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam)
? LookupObjCImplicitSelfParam
: LookupOrdinaryName);
- if (TemplateArgs) {
+ if (TemplateKWLoc.isValid() || TemplateArgs) {
// Lookup the template name again to correctly establish the context in
// which it was found. This is really unfortunate as we already did the
// lookup to determine that it was a template name in the first place. If
@@ -2089,7 +2089,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
bool MemberOfUnknownSpecialization;
LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
MemberOfUnknownSpecialization);
-
+
if (MemberOfUnknownSpecialization ||
(R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
@@ -2155,6 +2155,9 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
if (SS.isValid())
CCC->setTypoNNS(SS.getScopeRep());
}
+ // FIXME: DiagnoseEmptyLookup produces bad diagnostics if we're looking for
+ // a template name, but we happen to have always already looked up the name
+ // before we get here if it must be a template name.
if (DiagnoseEmptyLookup(S, SS, R,
CCC ? std::move(CCC) : std::move(DefaultValidator),
nullptr, None, &TE)) {
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 775008ea807..e03f143bcba 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -759,9 +759,9 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
TypoExpr *TE = nullptr;
QualType RecordTy = BaseType;
if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType();
- if (LookupMemberExprInRecord(*this, R, nullptr,
- RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
- SS, TemplateArgs != nullptr, TE))
+ if (LookupMemberExprInRecord(
+ *this, R, nullptr, RecordTy->getAs<RecordType>(), OpLoc, IsArrow,
+ SS, TemplateKWLoc.isValid() || TemplateArgs != nullptr, TE))
return ExprError();
if (TE)
return TE;
@@ -769,10 +769,10 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
// Explicit member accesses.
} else {
ExprResult BaseResult = Base;
- ExprResult Result = LookupMemberExpr(
- *this, R, BaseResult, IsArrow, OpLoc, SS,
- ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
- TemplateArgs != nullptr);
+ ExprResult Result =
+ LookupMemberExpr(*this, R, BaseResult, IsArrow, OpLoc, SS,
+ ExtraArgs ? ExtraArgs->ObjCImpDecl : nullptr,
+ TemplateKWLoc.isValid() || TemplateArgs != nullptr);
if (BaseResult.isInvalid())
return ExprError();
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 788eaca6740..d98176ad2e5 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -158,7 +158,7 @@ bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
TemplateNameKind Sema::isTemplateName(Scope *S,
CXXScopeSpec &SS,
bool hasTemplateKeyword,
- UnqualifiedId &Name,
+ const UnqualifiedId &Name,
ParsedType ObjectTypePtr,
bool EnteringContext,
TemplateTy &TemplateResult,
@@ -4102,7 +4102,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
- UnqualifiedId &Name,
+ const UnqualifiedId &Name,
ParsedType ObjectType,
bool EnteringContext,
TemplateTy &Result,
OpenPOWER on IntegriCloud