diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-25 18:55:14 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-25 18:55:14 +0000 |
commit | 5c80a27ba26431c9f88d80edbbe61c562c5f9950 (patch) | |
tree | ce2ca684e8296e670efbce658f337fb7513372d4 /clang/lib | |
parent | 4cd30817d3739207cca1ef07e4048b122280081a (diff) | |
download | bcm5719-llvm-5c80a27ba26431c9f88d80edbbe61c562c5f9950.tar.gz bcm5719-llvm-5c80a27ba26431c9f88d80edbbe61c562c5f9950.zip |
Implement support for default template arguments of function templates.
llvm-svn: 89874
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/Sema.h | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 61 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 56 |
3 files changed, 108 insertions, 16 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 8528560555c..084f720d4dd 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2384,6 +2384,13 @@ public: SourceLocation TemplateLoc, Declarator &D); + TemplateArgumentLoc + SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + Decl *Param, + TemplateArgumentListBuilder &Converted); + bool CheckTemplateArgument(NamedDecl *Param, const TemplateArgumentLoc &Arg, TemplateDecl *Template, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 621362d2efb..4efecea9351 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -764,7 +764,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth, DeclPtrTy *Params, unsigned NumParams, SourceLocation RAngleLoc) { if (ExportLoc.isValid()) - Diag(ExportLoc, diag::note_template_export_unsupported); + Diag(ExportLoc, diag::warn_template_export_unsupported); return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, (NamedDecl**)Params, NumParams, @@ -1869,6 +1869,65 @@ SubstDefaultTemplateArgument(Sema &SemaRef, AllTemplateArgs); } +/// \brief If the given template parameter has a default template +/// argument, substitute into that default template argument and +/// return the corresponding template argument. +TemplateArgumentLoc +Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + Decl *Param, + TemplateArgumentListBuilder &Converted) { + if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (!TypeParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + DeclaratorInfo *DI = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TypeParm, + Converted); + if (DI) + return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI); + + return TemplateArgumentLoc(); + } + + if (NonTypeTemplateParmDecl *NonTypeParm + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (!NonTypeParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + OwningExprResult Arg = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + NonTypeParm, + Converted); + if (Arg.isInvalid()) + return TemplateArgumentLoc(); + + Expr *ArgE = Arg.takeAs<Expr>(); + return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE); + } + + TemplateTemplateParmDecl *TempTempParm + = cast<TemplateTemplateParmDecl>(Param); + if (!TempTempParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + TemplateName TName = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TempTempParm, + Converted); + if (TName.isNull()) + return TemplateArgumentLoc(); + + return TemplateArgumentLoc(TemplateArgument(TName), + TempTempParm->getDefaultArgument().getTemplateQualifierRange(), + TempTempParm->getDefaultArgument().getTemplateNameLoc()); +} + /// \brief Check that the given template argument corresponds to the given /// template parameter. bool Sema::CheckTemplateArgument(NamedDecl *Param, diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index c5571d16436..06b2dec590b 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1272,18 +1272,56 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); + // Template argument deduction for function templates in a SFINAE context. + // Trap any errors that might occur. + SFINAETrap Trap(*this); + + // Enter a new template instantiation context while we instantiate the + // actual function declaration. + InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), + FunctionTemplate, Deduced.data(), Deduced.size(), + ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution); + if (Inst) + return TDK_InstantiationDepth; + // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size()); for (unsigned I = 0, N = Deduced.size(); I != N; ++I) { - if (Deduced[I].isNull()) { + if (!Deduced[I].isNull()) { + Builder.Append(Deduced[I]); + continue; + } + + // Substitute into the default template argument, if available. + NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I); + TemplateArgumentLoc DefArg + = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate, + FunctionTemplate->getLocation(), + FunctionTemplate->getSourceRange().getEnd(), + Param, + Builder); + + // If there was no default argument, deduction is incomplete. + if (DefArg.getArgument().isNull()) { Info.Param = makeTemplateParameter( - const_cast<NamedDecl *>(TemplateParams->getParam(I))); + const_cast<NamedDecl *>(TemplateParams->getParam(I))); return TDK_Incomplete; } + + // Check whether we can actually use the default argument. + if (CheckTemplateArgument(Param, DefArg, + FunctionTemplate, + FunctionTemplate->getLocation(), + FunctionTemplate->getSourceRange().getEnd(), + Builder)) { + Info.Param = makeTemplateParameter( + const_cast<NamedDecl *>(TemplateParams->getParam(I))); + return TDK_SubstitutionFailure; + } - Builder.Append(Deduced[I]); + // If we get here, we successfully used the default template argument. } // Form the template argument list from the deduced template arguments. @@ -1291,18 +1329,6 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true); Info.reset(DeducedArgumentList); - // Template argument deduction for function templates in a SFINAE context. - // Trap any errors that might occur. - SFINAETrap Trap(*this); - - // Enter a new template instantiation context while we instantiate the - // actual function declaration. - InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), - FunctionTemplate, Deduced.data(), Deduced.size(), - ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution); - if (Inst) - return TDK_InstantiationDepth; - // Substitute the deduced template arguments into the function template // declaration to produce the function template specialization. Specialization = cast_or_null<FunctionDecl>( |