diff options
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index e3c784c..95706fb 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3162,9 +3162,19 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // We are looking for a qualified typename. Token Next = NextToken(); - if (Next.is(tok::annot_template_id) && - static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue()) - ->Kind == TNK_Type_template) { + + TemplateIdAnnotation *TemplateId = Next.is(tok::annot_template_id) + ? takeTemplateIdAnnotation(Next) + : nullptr; + if (TemplateId && TemplateId->hasInvalidName()) { + // We found something like 'T::U<Args> x', but U is not a template. + // Assume it was supposed to be a type. + DS.SetTypeSpecError(); + ConsumeAnnotationToken(); + break; + } + + if (TemplateId && TemplateId->Kind == TNK_Type_template) { // We have a qualified template-id, e.g., N::A<int> // If this would be a valid constructor declaration with template @@ -3174,7 +3184,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // // 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 == DeclSpecContext::DSC_top_level || DSContext == DeclSpecContext::DSC_class) && TemplateId->Name && @@ -3195,9 +3204,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; } - if (Next.is(tok::annot_template_id) && - static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue()) - ->Kind == TNK_Concept_template && + if (TemplateId && TemplateId->Kind == TNK_Concept_template && GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype)) { DS.getTypeSpecScope() = SS; // This is a qualified placeholder-specifier, e.g., ::C<int> auto ... @@ -3459,7 +3466,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // type-name or placeholder-specifier case tok::annot_template_id: { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); + + if (TemplateId->hasInvalidName()) { + DS.SetTypeSpecError(); + break; + } + if (TemplateId->Kind == TNK_Concept_template) { + // If we've already diagnosed that this type-constraint has invalid + // arguemnts, drop it and just form 'auto' or 'decltype(auto)'. + if (TemplateId->hasInvalidArgs()) + TemplateId = nullptr; + if (NextToken().is(tok::identifier)) { Diag(Loc, diag::err_placeholder_expected_auto_or_decltype_auto) << FixItHint::CreateInsertion(NextToken().getLocation(), "auto"); @@ -5197,14 +5215,30 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { // placeholder-type-specifier case tok::annot_template_id: { + TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); + if (TemplateId->hasInvalidName()) + return true; + // FIXME: What about type templates that have only been annotated as + // annot_template_id, not as annot_typename? return isTypeConstraintAnnotation() && - (NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype)); + (NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype)); } - case tok::annot_cxxscope: + + case tok::annot_cxxscope: { + TemplateIdAnnotation *TemplateId = + NextToken().is(tok::annot_template_id) + ? takeTemplateIdAnnotation(NextToken()) + : nullptr; + if (TemplateId && TemplateId->hasInvalidName()) + return true; + // FIXME: What about type templates that have only been annotated as + // annot_template_id, not as annot_typename? if (NextToken().is(tok::identifier) && TryAnnotateTypeConstraint()) return true; return isTypeConstraintAnnotation() && GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype); + } + case tok::kw___declspec: case tok::kw___cdecl: case tok::kw___stdcall: |