[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