diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 51 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 24 |
3 files changed, 77 insertions, 6 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 61a494193c7..90040c54bfb 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -490,18 +490,57 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation, return true; } + IdentifierInfo *Id = Tok.getIdentifierInfo(); + SourceLocation IdLoc = ConsumeToken(); + + if (Tok.is(tok::less)) { + // It looks the user intended to write a template-id here, but the + // template-name was wrong. Try to fix that. + TemplateNameKind TNK = TNK_Type_template; + TemplateTy Template; + if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, CurScope, + SS, Template, TNK)) { + Diag(IdLoc, diag::err_unknown_template_name) + << Id; + } + + if (!Template) + return true; + + // Form the template name + UnqualifiedId TemplateName; + TemplateName.setIdentifier(Id, IdLoc); + + // Parse the full template-id, then turn it into a type. + if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName, + SourceLocation(), true)) + return true; + if (TNK == TNK_Dependent_template_name) + AnnotateTemplateIdTokenAsType(SS); + + // If we didn't end up with a typename token, there's nothing more we + // can do. + if (Tok.isNot(tok::annot_typename)) + return true; + + // Retrieve the type from the annotation token, consume that token, and + // return. + EndLocation = Tok.getAnnotationEndLoc(); + TypeTy *Type = Tok.getAnnotationValue(); + ConsumeToken(); + return Type; + } + // We have an identifier; check whether it is actually a type. - TypeTy *Type = Actions.getTypeName(*Tok.getIdentifierInfo(), - Tok.getLocation(), CurScope, SS, - true); - if (!Type) { - Diag(Tok, DestrExpected ? diag::err_destructor_class_name + TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true); + if (!Type) { + Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name : diag::err_expected_class_name); return true; } // Consume the identifier. - EndLocation = ConsumeToken(); + EndLocation = IdLoc; return Type; } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index d46bfc6cffd..d06cecc4678 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2367,6 +2367,14 @@ public: TypeTy *ObjectType, bool EnteringContext, TemplateTy &Template); + + virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + const CXXScopeSpec *SS, + TemplateTy &SuggestedTemplate, + TemplateNameKind &SuggestedKind); + bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); TemplateDecl *AdjustDeclIfTemplate(DeclPtrTy &Decl); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d11bf3c0645..e75277e823e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -143,6 +143,30 @@ TemplateNameKind Sema::isTemplateName(Scope *S, return TemplateKind; } +bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + const CXXScopeSpec *SS, + TemplateTy &SuggestedTemplate, + TemplateNameKind &SuggestedKind) { + // We can't recover unless there's a dependent scope specifier preceding the + // template name. + if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) || + computeDeclContext(*SS)) + return false; + + // The code is missing a 'template' keyword prior to the dependent template + // name. + NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep(); + Diag(IILoc, diag::err_template_kw_missing) + << Qualifier << II.getName() + << CodeModificationHint::CreateInsertion(IILoc, "template "); + SuggestedTemplate + = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II)); + SuggestedKind = TNK_Dependent_template_name; + return true; +} + void Sema::LookupTemplateName(LookupResult &Found, Scope *S, const CXXScopeSpec &SS, QualType ObjectType, |