diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-06-10 23:29:48 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-06-10 23:29:48 +0000 |
commit | 4ed0870592c05a5c6f80268bdaf62a081c47477f (patch) | |
tree | ac488872253455f43e3c99dcd76e809a7c141304 /lib/Sema/SemaTemplate.cpp | |
parent | a438edc06abbe6f78fc5cc692b6aaecf0730eb08 (diff) |
Recover from missing typenames on template args for MSVC compatibility
While matching a non-type template argument against a known template
type parameter we now modify the AST's TemplateArgumentLoc to assume the
user wrote typename. Under -fms-compatibility, we downgrade our
diagnostic from an error to an extwarn.
Reviewed by: rsmith
Differential Revision: http://reviews.llvm.org/D4049
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210607 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d6ea3d0e2e..68c1c7430a 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2999,9 +2999,11 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, } bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, - const TemplateArgumentLoc &AL, + TemplateArgumentLoc &AL, SmallVectorImpl<TemplateArgument> &Converted) { const TemplateArgument &Arg = AL.getArgument(); + QualType ArgType; + TypeSourceInfo *TSI = nullptr; // Check template type parameter. switch(Arg.getKind()) { @@ -3009,6 +3011,8 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, // C++ [temp.arg.type]p1: // A template-argument for a template-parameter which is a // type shall be a type-id. + ArgType = Arg.getAsType(); + TSI = AL.getTypeSourceInfo(); break; case TemplateArgument::Template: { // We have a template type parameter but the template argument @@ -3043,18 +3047,38 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, } } - if (NameInfo.getName().isIdentifier()) { + if (auto *II = NameInfo.getName().getAsIdentifierInfo()) { LookupResult Result(*this, NameInfo, LookupOrdinaryName); LookupParsedName(Result, CurScope, &SS); if (Result.getAsSingle<TypeDecl>() || Result.getResultKind() == - LookupResult::NotFoundInCurrentInstantiation) { - // FIXME: Add a FixIt and fix up the template argument for recovery. + LookupResult::NotFoundInCurrentInstantiation) { + // Suggest that the user add 'typename' before the NNS. SourceLocation Loc = AL.getSourceRange().getBegin(); - Diag(Loc, diag::err_template_arg_must_be_type_suggest); + Diag(Loc, getLangOpts().MSVCCompat + ? diag::ext_ms_template_type_arg_missing_typename + : diag::err_template_arg_must_be_type_suggest) + << FixItHint::CreateInsertion(Loc, "typename "); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + + // Recover by synthesizing a type using the location information that we + // already have. + ArgType = + Context.getDependentNameType(ETK_Typename, SS.getScopeRep(), II); + TypeLocBuilder TLB; + DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(ArgType); + TL.setElaboratedKeywordLoc(SourceLocation(/*synthesized*/)); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(NameInfo.getLoc()); + TSI = TLB.getTypeSourceInfo(Context, ArgType); + + // Overwrite our input TemplateArgumentLoc so that we can recover + // properly. + AL = TemplateArgumentLoc(TemplateArgument(ArgType), + TemplateArgumentLocInfo(TSI)); + + break; } } // fallthrough @@ -3070,11 +3094,11 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, } } - if (CheckTemplateArgument(Param, AL.getTypeSourceInfo())) + if (CheckTemplateArgument(Param, TSI)) return true; // Add the converted template type argument. - QualType ArgType = Context.getCanonicalType(Arg.getAsType()); + ArgType = Context.getCanonicalType(ArgType); // Objective-C ARC: // If an explicitly-specified template argument type is a lifetime type @@ -3356,7 +3380,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, /// /// \returns true on error, false otherwise. bool Sema::CheckTemplateArgument(NamedDecl *Param, - const TemplateArgumentLoc &Arg, + TemplateArgumentLoc &Arg, NamedDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, @@ -5078,7 +5102,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, /// This routine implements the semantics of C++ [temp.arg.template]. /// It returns true if an error occurred, and false otherwise. bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, - const TemplateArgumentLoc &Arg, + TemplateArgumentLoc &Arg, unsigned ArgumentPackIndex) { TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern(); TemplateDecl *Template = Name.getAsTemplateDecl(); |