diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-02-01 21:36:38 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-02-01 21:36:38 +0000 |
commit | cfe8992bb16dc0421c93760305a12a42af2a5dc8 (patch) | |
tree | 569fdd07ed229289cd2a5af64fdf60b2263b1507 /lib/Parse | |
parent | cafee2d0da44351199ed5bb6cfb076bf2a4ed4c5 (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.cpp | 12 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 11 |
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()); |