diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-06-26 23:20:26 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-06-26 23:20:26 +0000 |
commit | bf5bcf2c15c50381ad84d1ac9bbb171c91188b56 (patch) | |
tree | e101c340b1b367af47e9570d0eefdf5407830ac4 /clang/lib/Sema/SemaTemplate.cpp | |
parent | 69b859c2d8d9a0500cf8164c332b378c927f059e (diff) | |
download | bcm5719-llvm-bf5bcf2c15c50381ad84d1ac9bbb171c91188b56.tar.gz bcm5719-llvm-bf5bcf2c15c50381ad84d1ac9bbb171c91188b56.zip |
Diagnose missing 'template' keywords in more cases.
We track when we see a name-shaped expression followed by a '<' token
and parse the '<' as a comparison. Then:
* if we see a token sequence that cannot possibly be an expression but
can be a template argument (in particular, a type-id) that follows
either a ',' or the '<', diagnose that the '<' was supposed to start
a template argument list, and
* if we see '>()', diagnose that the '<' was supposed to start a
template argument list.
This only changes the diagnostic for error cases, and in practice
appears to catch the most common cases where a missing 'template'
keyword leads to parse errors within a template.
Differential Revision: https://reviews.llvm.org/D48571
llvm-svn: 335687
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 8f316024cc6..68a5196f6b8 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -508,20 +508,41 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, DeclContext *LookupCtx = nullptr; NamedDecl *Found = nullptr; + bool MissingTemplateKeyword = false; // Figure out what name we looked up. - if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) { + if (auto *DRE = dyn_cast<DeclRefExpr>(TemplateName.get())) { + NameInfo = DRE->getNameInfo(); + SS.Adopt(DRE->getQualifierLoc()); + LookupKind = LookupOrdinaryName; + Found = DRE->getFoundDecl(); + } else if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) { NameInfo = ME->getMemberNameInfo(); SS.Adopt(ME->getQualifierLoc()); LookupKind = LookupMemberName; LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl(); Found = ME->getMemberDecl(); + } else if (auto *DSDRE = + dyn_cast<DependentScopeDeclRefExpr>(TemplateName.get())) { + NameInfo = DSDRE->getNameInfo(); + SS.Adopt(DSDRE->getQualifierLoc()); + MissingTemplateKeyword = true; + } else if (auto *DSME = + dyn_cast<CXXDependentScopeMemberExpr>(TemplateName.get())) { + NameInfo = DSME->getMemberNameInfo(); + SS.Adopt(DSME->getQualifierLoc()); + MissingTemplateKeyword = true; } else { - auto *DRE = cast<DeclRefExpr>(TemplateName.get()); - NameInfo = DRE->getNameInfo(); - SS.Adopt(DRE->getQualifierLoc()); - LookupKind = LookupOrdinaryName; - Found = DRE->getFoundDecl(); + llvm_unreachable("unexpected kind of potential template name"); + } + + // If this is a dependent-scope lookup, diagnose that the 'template' keyword + // was missing. + if (MissingTemplateKeyword) { + Diag(NameInfo.getLocStart(), diag::err_template_kw_missing) + << "" << NameInfo.getName().getAsString() + << SourceRange(Less, Greater); + return; } // Try to correct the name by looking for templates and C++ named casts. |