diff options
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 69 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/Parse/Parser.cpp | 1 |
4 files changed, 28 insertions, 57 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 2d320878014..255f27dbfb2 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2824,44 +2824,23 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ->Kind == TNK_Type_template) { // We have a qualified template-id, e.g., N::A<int> - // C++ [class.qual]p2: - // In a lookup in which the constructor is an acceptable lookup - // result and the nested-name-specifier nominates a class C: + // If this would be a valid constructor declaration with template + // arguments, we will reject the attempt to form an invalid type-id + // referring to the injected-class-name when we annotate the token, + // per C++ [class.qual]p2. // - // - if the name specified after the - // nested-name-specifier, when looked up in C, is the - // injected-class-name of C (Clause 9), or - // - // - if the name specified after the nested-name-specifier - // is the same as the identifier or the - // simple-template-id's template-name in the last - // component of the nested-name-specifier, - // - // the name is instead considered to name the constructor of - // class C. - // - // Thus, if the template-name is actually the constructor - // name, then the code is ill-formed; this interpretation is - // reinforced by the NAD status of core issue 635. + // To improve diagnostics for this case, parse the declaration as a + // constructor (and reject the extra template arguments later). TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next); if ((DSContext == DSC_top_level || DSContext == DSC_class) && TemplateId->Name && - Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) { - if (isConstructorDeclarator(/*Unqualified*/false)) { - // The user meant this to be an out-of-line constructor - // definition, but template arguments are not allowed - // there. Just allow this as a constructor; we'll - // complain about it later. - goto DoneWithDeclSpec; - } - - // The user meant this to name a type, but it actually names - // a constructor with some extraneous template - // arguments. Complain, then parse it as a type as the user - // intended. - Diag(TemplateId->TemplateNameLoc, - diag::err_out_of_line_template_id_type_names_constructor) - << TemplateId->Name << 0 /* template name */; + Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) && + isConstructorDeclarator(/*Unqualified*/false)) { + // The user meant this to be an out-of-line constructor + // definition, but template arguments are not allowed + // there. Just allow this as a constructor; we'll + // complain about it later. + goto DoneWithDeclSpec; } DS.getTypeSpecScope() = SS; @@ -2892,24 +2871,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (Next.isNot(tok::identifier)) goto DoneWithDeclSpec; - // If we're in a context where the identifier could be a class name, - // check whether this is a constructor declaration. + // Check whether this is a constructor declaration. If we're in a + // context where the identifier could be a class name, and it has the + // shape of a constructor declaration, process it as one. if ((DSContext == DSC_top_level || DSContext == DSC_class) && Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(), - &SS)) { - if (isConstructorDeclarator(/*Unqualified*/false)) - goto DoneWithDeclSpec; - - // As noted in C++ [class.qual]p2 (cited above), when the name - // of the class is qualified in a context where it could name - // a constructor, its a constructor name. However, we've - // looked at the declarator, and the user probably meant this - // to be a type. Complain that it isn't supposed to be treated - // as a type, then proceed to parse it as a type. - Diag(Next.getLocation(), - diag::err_out_of_line_template_id_type_names_constructor) - << Next.getIdentifierInfo() << 1 /* type */; - } + &SS) && + isConstructorDeclarator(/*Unqualified*/ false)) + goto DoneWithDeclSpec; ParsedType TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(), Next.getLocation(), diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 124266a42bd..ac0c4fd65b2 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -2155,7 +2155,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Constructor and destructor names. TypeResult Type = Actions.ActOnTemplateIdType(SS, TemplateKWLoc, - Template, NameLoc, + Template, Name, NameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc, /*IsCtorOrDtorName=*/true); if (Type.isInvalid()) diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 6a09ea7abca..6bc35e3df50 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -1000,13 +1000,13 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // Build the annotation token. if (TNK == TNK_Type_template && AllowTypeAnnotation) { - TypeResult Type - = Actions.ActOnTemplateIdType(SS, TemplateKWLoc, - Template, TemplateNameLoc, - LAngleLoc, TemplateArgsPtr, RAngleLoc); + TypeResult Type = Actions.ActOnTemplateIdType( + SS, TemplateKWLoc, Template, TemplateName.Identifier, + TemplateNameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc); if (Type.isInvalid()) { - // If we failed to parse the template ID but skipped ahead to a >, we're not - // going to be able to form a token annotation. Eat the '>' if present. + // If we failed to parse the template ID but skipped ahead to a >, we're + // not going to be able to form a token annotation. Eat the '>' if + // present. TryConsumeToken(tok::greater); return true; } @@ -1079,6 +1079,7 @@ void Parser::AnnotateTemplateIdTokenAsType() { = Actions.ActOnTemplateIdType(TemplateId->SS, TemplateId->TemplateKWLoc, TemplateId->Template, + TemplateId->Name, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 52e5194e623..2f8ee0c068d 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1701,6 +1701,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, TemplateId->TemplateKWLoc, TemplateId->Template, + TemplateId->Name, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, |

