[cfe-commits] r89874 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateDeduction.cpp test/Parser/cxx-template-decl.cpp test/SemaTemplate/default-arguments-cxx0x.cpp
Douglas Gregor
dgregor at apple.com
Wed Nov 25 10:55:14 PST 2009
Author: dgregor
Date: Wed Nov 25 12:55:14 2009
New Revision: 89874
URL: http://llvm.org/viewvc/llvm-project?rev=89874&view=rev
Log:
Implement support for default template arguments of function templates.
Added:
cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp (with props)
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/test/Parser/cxx-template-decl.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=89874&r1=89873&r2=89874&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Nov 25 12:55:14 2009
@@ -882,7 +882,7 @@
def err_template_param_shadow : Error<
"declaration of %0 shadows template parameter">;
def note_template_param_here : Note<"template parameter is declared here">;
-def note_template_export_unsupported : Note<
+def warn_template_export_unsupported : Warning<
"exported templates are unsupported">;
def err_template_outside_namespace_or_class_scope : Error<
"templates can only be declared in namespace or class scope">;
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=89874&r1=89873&r2=89874&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 25 12:55:14 2009
@@ -2384,6 +2384,13 @@
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,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=89874&r1=89873&r2=89874&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Nov 25 12:55:14 2009
@@ -764,7 +764,7 @@
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 @@
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,
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=89874&r1=89873&r2=89874&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Nov 25 12:55:14 2009
@@ -1272,18 +1272,56 @@
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 @@
= 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>(
Modified: cfe/trunk/test/Parser/cxx-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=89874&r1=89873&r2=89874&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Wed Nov 25 12:55:14 2009
@@ -5,7 +5,7 @@
template x; // expected-error {{C++ requires a type specifier for all declarations}} \
// expected-error {{does not refer}}
export template x; // expected-error {{expected '<' after 'template'}}
-export template<class T> class x0; // expected-note {{exported templates are unsupported}}
+export template<class T> class x0; // expected-warning {{exported templates are unsupported}}
template < ; // expected-error {{parse error}} expected-error {{declaration does not declare anything}}
template <template X> struct Err1; // expected-error {{expected '<' after 'template'}} \
// expected-error{{extraneous}}
Added: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp?rev=89874&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp (added)
+++ cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp Wed Nov 25 12:55:14 2009
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s
+
+// Test default template arguments for function templates.
+template<typename T = int>
+void f0();
+
+template<typename T>
+void f0();
+
+void g0() {
+ f0(); // okay!
+}
+
+template<typename T, int N = T::value>
+int &f1(T);
+
+float &f1(...);
+
+struct HasValue {
+ static const int value = 17;
+};
+
+void g1() {
+ float &fr = f1(15);
+ int &ir = f1(HasValue());
+}
Propchange: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list