[cfe-commits] r73136 - in /cfe/trunk: lib/Sema/SemaTemplateDeduction.cpp test/SemaTemplate/example-typelist.cpp
Douglas Gregor
dgregor at apple.com
Tue Jun 9 09:35:59 PDT 2009
Author: dgregor
Date: Tue Jun 9 11:35:58 2009
New Revision: 73136
URL: http://llvm.org/viewvc/llvm-project?rev=73136&view=rev
Log:
Implement template argument deduction for class template
specialization types. As the example shows, we can now compute the
length of a type-list using a template metaprogram and class template
partial specialization.
Added:
cfe/trunk/test/SemaTemplate/example-typelist.cpp (with props)
Modified:
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=73136&r1=73135&r2=73136&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Jun 9 11:35:58 2009
@@ -20,6 +20,11 @@
#include "llvm/Support/Compiler.h"
using namespace clang;
+static bool
+DeduceTemplateArguments(ASTContext &Context, const TemplateArgument &Param,
+ const TemplateArgument &Arg,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced);
+
/// \brief If the given expression is of a form that permits the deduction
/// of a non-type template parameter, return the declaration of that
/// non-type template parameter.
@@ -100,6 +105,24 @@
return true;
}
+static bool DeduceTemplateArguments(ASTContext &Context,
+ TemplateName Param,
+ TemplateName Arg,
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+ // FIXME: Implement template argument deduction for template
+ // template parameters.
+
+ TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
+ TemplateDecl *ArgDecl = Arg.getAsTemplateDecl();
+
+ if (!ParamDecl || !ArgDecl)
+ return false;
+
+ ParamDecl = cast<TemplateDecl>(Context.getCanonicalDecl(ParamDecl));
+ ArgDecl = cast<TemplateDecl>(Context.getCanonicalDecl(ArgDecl));
+ return ParamDecl == ArgDecl;
+}
+
static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
QualType Arg,
llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
@@ -305,7 +328,86 @@
return true;
}
+
+ // template-name<T> (wheretemplate-name refers to a class template)
+ // template-name<i>
+ // TT<T> (TODO)
+ // TT<i> (TODO)
+ // TT<> (TODO)
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *SpecParam
+ = cast<TemplateSpecializationType>(Param);
+
+ // Check whether the template argument is a dependent template-id.
+ // FIXME: This is untested code; it can be tested when we implement
+ // partial ordering of class template partial specializations.
+ if (const TemplateSpecializationType *SpecArg
+ = dyn_cast<TemplateSpecializationType>(Arg)) {
+ // Perform template argument deduction for the template name.
+ if (!DeduceTemplateArguments(Context,
+ SpecParam->getTemplateName(),
+ SpecArg->getTemplateName(),
+ Deduced))
+ return false;
+
+ unsigned NumArgs = SpecParam->getNumArgs();
+
+ // FIXME: When one of the template-names refers to a
+ // declaration with default template arguments, do we need to
+ // fill in those default template arguments here? Most likely,
+ // the answer is "yes", but I don't see any references. This
+ // issue may be resolved elsewhere, because we may want to
+ // instantiate default template arguments when
+ if (SpecArg->getNumArgs() != NumArgs)
+ return false;
+
+ // Perform template argument deduction on each template
+ // argument.
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (!DeduceTemplateArguments(Context,
+ SpecParam->getArg(I),
+ SpecArg->getArg(I),
+ Deduced))
+ return false;
+
+ return true;
+ }
+
+ // If the argument type is a class template specialization, we
+ // perform template argument deduction using its template
+ // arguments.
+ const RecordType *RecordArg = dyn_cast<RecordType>(Arg);
+ if (!RecordArg)
+ return false;
+
+ ClassTemplateSpecializationDecl *SpecArg
+ = dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl());
+ if (!SpecArg)
+ return false;
+
+ // Perform template argument deduction for the template name.
+ if (!DeduceTemplateArguments(Context,
+ SpecParam->getTemplateName(),
+ TemplateName(SpecArg->getSpecializedTemplate()),
+ Deduced))
+ return false;
+
+ // FIXME: Can the # of arguments in the parameter and the argument differ?
+ unsigned NumArgs = SpecParam->getNumArgs();
+ const TemplateArgumentList &ArgArgs = SpecArg->getTemplateArgs();
+ if (NumArgs != ArgArgs.size())
+ return false;
+
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (!DeduceTemplateArguments(Context,
+ SpecParam->getArg(I),
+ ArgArgs.get(I),
+ Deduced))
+ return false;
+ return true;
+ }
+
default:
break;
}
Added: cfe/trunk/test/SemaTemplate/example-typelist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/example-typelist.cpp?rev=73136&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/example-typelist.cpp (added)
+++ cfe/trunk/test/SemaTemplate/example-typelist.cpp Tue Jun 9 11:35:58 2009
@@ -0,0 +1,28 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct nil { };
+
+template<typename Head, typename Tail = nil>
+struct cons {
+ typedef Head head;
+ typedef Tail tail;
+};
+
+// metaprogram that computes the length of a list
+template<typename T> struct length;
+
+template<typename Head, typename Tail>
+struct length<cons<Head, Tail> > {
+ static const unsigned value = length<Tail>::value + 1;
+};
+
+template<>
+struct length<nil> {
+ static const unsigned value = 0;
+};
+
+typedef cons<unsigned char,
+ cons<unsigned short,
+ cons<unsigned int,
+ cons<unsigned long> > > > unsigned_inttypes;
+int length0[length<unsigned_inttypes>::value == 4? 1 : -1];
Propchange: cfe/trunk/test/SemaTemplate/example-typelist.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/SemaTemplate/example-typelist.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/SemaTemplate/example-typelist.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list