Adding template default parameter with as typed explicit parameter

Hi,

With the class template:

    template <typename T> class Coord;
    template <typename T, typename U = Coord<T> > class Point;

If the user code contains:

    typedef long size_t;
    Point<size_t> p;

when traversing the AST, reaching 'p', I have access to a clang::Type
named 'Point<size_t>' which directs the CXXRecordDecl named
'Point<long, Coord<long> >.

Is there a way to create (from Point<size_t>) a type which would be
named 'Point<size_t, Coord<size_t> >'. I.e. which preserves the
typedef when expanding/adding the template default parameters?

If there is not, what would you recommend to start from to
implement support for this?

Thanks,
Philippe.

PS.
             clang::TemplateArgumentLoc ArgType = S.SubstDefaultTemplateArgumentIfAvailable(
Template,
TemplateLoc,
RAngleLoc,
                                                              TTP,
Converted);

with Converted containing the argument passed by the user as is (i.e. non-canonical)
**seems** to work as I need it .... but only if a few asserts (requiring the canonicality
of the element of Converted) are removed and if I avoid the call to:

   } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
     return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;

in Sema::CheckTemplateArgument which only works properly with canonical types.

Hi,

With the class template:

   template <typename T> class Coord;
   template <typename T, typename U = Coord<T> > class Point;

If the user code contains:

   typedef long size_t;
   Point<size_t> p;

when traversing the AST, reaching 'p', I have access to a clang::Type
named 'Point<size_t>' which directs the CXXRecordDecl named
'Point<long, Coord<long> >.

The CXXRecordDecl has to use the canonical types so we don't try to
instantiate Point twice if the user writes e.g. "Point<size_t> x;
Point<unsigned long> y;". I suppose it could store non-canonical
arguments corresponding to the first instantiation as well... but we
haven't had any use for that in the past.

Is there a way to create (from Point<size_t>) a type which would be
named 'Point<size_t, Coord<size_t> >'. I.e. which preserves the
typedef when expanding/adding the template default parameters?

AFAIK no... I'm pretty sure Sema never computes it, and you can't
compute it yourself without the code to perform template type
substitution which isn't exposed outside Sema.

-Eli

Hi,

The CXXRecordDecl has to use the canonical types so we don't try to
instantiate Point twice if the user writes e.g. "Point<size_t> x;
Point<unsigned long> y;".

Yes, indeed. I do not want to change that.

I suppose it could store non-canonical
arguments corresponding to the first instantiation as well... but we
haven't had any use for that in the past.

In our use case there wouldn't be anything magic about the first
instantiation.

AFAIK no... I'm pretty sure Sema never computes it

Yes. However, in the case of auto describing data persistency, one
would want to preserve not only the type as written by the user
(Point<size_t> in my example) but also the default value of the template.
This would help in schema evolution (i.e. being able to read the old
data with a newer schema/library where the default value of the template
may have changed).

From a QualType instanceType (gotten from the variable declaration for example)
which represent Point<size_t>

    const clang::TemplateSpecializationType* TST
       = llvm::dyn_cast<const clang::TemplateSpecializationType>(instanceType.getTypePtr());

I can get the arguments of the template as types (size_t).

I think we need to keep that. What I would also like to have (and am
offering to implement but would need directions on where best to do it
in the code), is something akin to

   TST->getTypeWithDefaultExpanded();

which would return a QualType/TemplateSpecializationType (but not a
CXXRecordDecl) representing
     Point<size_t, Coord<size_t> >'

which would still point to the CXXRecordDecl for Point<long, Coord<long> >.

Thanks,
Philippe.

Hmm... yes, that's possible, but I'm not sure we'd want to pay the
price in memory usage/compile-time for normal compiles (IIRC, the
relevant code is in semantic analysis, so we would have to pre-compute
it then).

-Eli

Could we enable this feature only when explicitly requested, for
example via a language option? (Especially since - as you pointed out -
the correct values can only be calculated in-flight during the semantic
analysis).

If the language option ("SugaredDefaultTemplateArgs"?) makes sense
I'll propose a patch.

Thanks,
Philippe.

We strongly prefer not to use language options to make such behavior optional. We instead try to either make it so cheap to compute that we always have it, or make it easy to lazily compute it.

  - Doug