[cfe-commits] r67308 - in /cfe/trunk: include/clang/AST/DeclTemplate.h include/clang/AST/ExprCXX.h include/clang/AST/StmtNodes.def include/clang/Parse/DeclSpec.h lib/AST/DeclTemplate.cpp lib/AST/ExprCXX.cpp lib/AST/StmtPrinter.cpp lib/Sema/Sema.h lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/fibonacci.cpp
Douglas Gregor
dgregor at apple.com
Thu Mar 19 11:30:22 PDT 2009
On Mar 19, 2009, at 11:04 AM, Sebastian Redl wrote:
> Douglas Gregor wrote:
>> Author: dgregor
>> Date: Thu Mar 19 12:26:29 2009
>> New Revision: 67308
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=67308&view=rev
>> Log:
>> Introduce a new expression type, UnresolvedDeclRefExpr, that
>> describes
>> dependent qualified-ids such as
>>
>> Fibonacci<N - 1>::value
>>
>> where N is a template parameter. These references are "unresolved"
>> because the name is dependent and, therefore, cannot be resolved to a
>> declaration node (as we would do for a DeclRefExpr or
>> QualifiedDeclRefExpr). UnresolvedDeclRefExprs instantiate to
>> DeclRefExprs, QualifiedDeclRefExprs, etc.
>>
>> Also, be a bit more careful about keeping only a single set of
>> specializations for a class template, and instantiating from the
>> definition of that template rather than a previous declaration. In
>> general, we need a better solution for this for all TagDecls, because
>> it's too easy to accidentally look at a declaration that isn't the
>> definition.
>>
>> We can now process a simple Fibonacci computation described as a
>> template metaprogram.
>>
>
> Very nice. Is this computation linear or exponential, though?
Linear, assuming that the hash function is good enough.
> The usual
> template instantiation rules are memoizing, so it should be linear,
> but
> that only works if the compiler won't try to instantiation
> FibonacciEval<N> twice (once as FibonacciEval<I-1> where I == N+1, and
> once as FibonacciEval<I-2> where I == N + 2).
Instantiating a class template twice would cause some serious problems
internally, so we certainly don't do that. Compilers often exhibit
exponential behavior when evaluating template metaprograms because
(1) they tend to keep specializations in a list (note: we use a
FoldingSet)
(2) they tend to have slow type-comparison operations (note: the
introduction of canonical types into GCC resulted in a pretty big win
for template metaprograms; our canonical type system should be better
<g>)
I do have one performance concern, which is that we keep around a lot
of information in the instantiations that might prove expensive. For
example, given
template<unsigned I>
struct Fibonacci {
enum { value = FibonacciEval<I-1>::value +
FibonacciEval<I-2>::value };
};
when we instantiate for 'I = 3', we get an AST representation that
looks like:
template<> struct Fibonacci<3u> {
enum { value = FibonacciEval<3u - 1>::value + FibonacciEval<3u -
2>::value };
};
That's totally awesome, but I'm a little concerned that we'll be
putting a lot of pressure on the FoldingSet that stores all of those
FibonacciEval<3u - 1> types.
- Doug
More information about the cfe-commits
mailing list