summaryrefslogtreecommitdiffstats
path: root/lib/Parse
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-02-01 21:36:38 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-02-01 21:36:38 +0000
commitcfe8992bb16dc0421c93760305a12a42af2a5dc8 (patch)
tree569fdd07ed229289cd2a5af64fdf60b2263b1507 /lib/Parse
parentcafee2d0da44351199ed5bb6cfb076bf2a4ed4c5 (diff)
Fix hole in our enforcement of rule requiring 'typename' prior to a dependent
name. If the dependent name happened to end in a template-id (X<T>::Y<U>), we would fail to notice that the 'typename' keyword is missing when resolving it to a type. It turns out that GCC has a similar bug. If this shows up in much real code, we can easily downgrade this to an ExtWarn. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@293815 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/ParseDeclCXX.cpp12
-rw-r--r--lib/Parse/ParseTemplate.cpp11
2 files changed, 15 insertions, 8 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 0775de33da..6403caa27b 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1076,7 +1076,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) {
- AnnotateTemplateIdTokenAsType();
+ AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
ParsedType Type = getTypeAnnotation(Tok);
@@ -1124,10 +1124,10 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// Parse the full template-id, then turn it into a type.
if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
- TemplateName, true))
+ TemplateName))
return true;
- if (TNK == TNK_Dependent_template_name)
- AnnotateTemplateIdTokenAsType();
+ if (TNK == TNK_Type_template || TNK == TNK_Dependent_template_name)
+ AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
// If we didn't end up with a typename token, there's nothing more we
// can do.
@@ -1145,7 +1145,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
// We have an identifier; check whether it is actually a type.
IdentifierInfo *CorrectedII = nullptr;
ParsedType Type = Actions.getTypeName(
- *Id, IdLoc, getCurScope(), &SS, true, false, nullptr,
+ *Id, IdLoc, getCurScope(), &SS, /*IsClassName=*/true, false, nullptr,
/*IsCtorOrDtorName=*/false,
/*NonTrivialTypeSourceInfo=*/true,
/*IsClassTemplateDeductionContext*/ false, &CorrectedII);
@@ -3377,7 +3377,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) {
- AnnotateTemplateIdTokenAsType();
+ AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
TemplateTypeTy = getTypeAnnotation(Tok);
}
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 6bc35e3df5..f12e3f55e5 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -1064,7 +1064,12 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
/// If there was a failure when forming the type from the template-id,
/// a type annotation token will still be created, but will have a
/// NULL type pointer to signify an error.
-void Parser::AnnotateTemplateIdTokenAsType() {
+///
+/// \param IsClassName Is this template-id appearing in a context where we
+/// know it names a class, such as in an elaborated-type-specifier or
+/// base-specifier? ('typename' and 'template' are unneeded and disallowed
+/// in those contexts.)
+void Parser::AnnotateTemplateIdTokenAsType(bool IsClassName) {
assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
@@ -1083,7 +1088,9 @@ void Parser::AnnotateTemplateIdTokenAsType() {
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
- TemplateId->RAngleLoc);
+ TemplateId->RAngleLoc,
+ /*IsCtorOrDtorName*/false,
+ IsClassName);
// Create the new "type" annotation token.
Tok.setKind(tok::annot_typename);
setTypeAnnotation(Tok, Type.isInvalid() ? nullptr : Type.get());