summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-11-25 18:55:14 +0000
committerDouglas Gregor <dgregor@apple.com>2009-11-25 18:55:14 +0000
commit5c80a27ba26431c9f88d80edbbe61c562c5f9950 (patch)
treece2ca684e8296e670efbce658f337fb7513372d4 /clang/lib
parent4cd30817d3739207cca1ef07e4048b122280081a (diff)
downloadbcm5719-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.h7
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp61
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp56
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>(
OpenPOWER on IntegriCloud