[cfe-dev] Using clang-tool to Exact type names in template specification arguments

Oliver Zhang via cfe-dev cfe-dev at lists.llvm.org
Wed Aug 19 00:37:03 PDT 2020


Thanks for your thoughtful reply, Dave! It's really helpful!

Best,
Oliver

On Mon, Aug 17, 2020 at 11:50 PM David Rector <davrecthreads at gmail.com>
wrote:

> There will not be any template arguments in the DeclRefExpr in that
> example, as nothing was specifically written in brackets.
>
> If instead of func(vecPtr) you wrote func<vector32_t>(vecPtr), there
> *would* be a template argument in the DeclRefExpr with the proper sugared
> type (i.e. vector32_t, not unsigned int[32]).
>
> But the DeclRefExpr does not implicitly generate this template argument,
> and probably should not, because that would muddy its purpose of
> representing the particular syntax used in referring to some declaration.
>
> So, I think your best bet if you really want to refer to vector32_t
> instead of unsigned int[32] is to either a) explicitly specify the template
> arguments in your func calls or b) define vector32_t as a wrapper class
> instead of a typedef (such that when passed as a template argument it would
> be instantiated separately from an unsigned int[32] argument).
>
> Hope that helps,
>
> Dave
>
> On Aug 17, 2020, at 12:41 AM, Oliver Zhang <oliverthekitten2017 at gmail.com>
> wrote:
>
> Thanks David and Dave for your nice suggestions and thoughts!
>
> Unfortunately the case I need to handle is a little more complex than I
> thought, as implicit template specification is involved. Now the full
> example looks like this (differences from the previous example is
> highlighted):
>
> typedef unsigned int vectors32_t[32];
> template <typename T>
> func(T *const vec) {
>     ...
> }
> int main() {
>     ...
>
>     *vector32_t *vecPtr = ...;*
>
>     *func(vecPtr);*
>     ...
> }
>
>
> I didn't find a way to get the type alias name ("vector32_t") from
> an implicit template argument by using CallExpr or DeclRefExpr. Actually it
> seems information about "vector32_t" can only be retrieved from the typedef
> and the declaration of "vecPtr".
>
> Best,
> Oliver
>
> On Fri, Aug 14, 2020 at 12:20 AM David Rector <davrecthreads at gmail.com>
> wrote:
>
>> Yes you’re right, good point.  In the FunctionDecl level the template
>> argument types must be canonical.
>>
>> Oliver definitely take David’s advice to get the template arguments from
>> the DeclRefExpr referenced in the CallExpr — hopefully that should contain
>> the proper type sugar.
>>
>> Pratyush, this unfortunately may have the implications for the solution
>> you employed in https://reviews.llvm.org/D77598 at my suggestion, in
>> order to distinguish between deduced and non-deduced non-type template
>> arguments.
>>
>> I think you should go with the first suggestion I gave you: simply change
>> line
>> https://github.com/llvm/llvm-project/blob/master/clang/lib/Sema/SemaTemplate.cpp#L6823 to
>> this:
>>
>> QualType CanonParamType = Context.getCanonicalType(ParamType);
>>
>> // Note: this renders CanonParamType non-canonical, but since every
>> instantiation
>> // of this argument will be wrapped in an AutoType (since
>> Param->getType() will always
>> // be an AutoType for this template), there should be no difference in
>> how arguments
>> // are distinguished.
>> if (Param->getType()->getAs<AutoType>())
>>   CanonParamType = Context.getAutoType(CanonParamType,
>> AutoTypeKeyword::Auto,
>>                                        false, false);
>>
>> Good catch, David.
>>
>> Dave
>>
>>
>> On Aug 13, 2020, at 11:58 AM, David Blaikie <dblaikie at gmail.com> wrote:
>>
>> On Thu, Aug 13, 2020 at 7:45 AM David Rector <davrecthreads at gmail.com>
>> wrote:
>>
>>
>> Correction: I did not notice that was a typename parameter, not a
>> non-type template parameter as Pratyush addressed — so the issue is
>> broader.  Perhaps CheckTemplateArgument(TemplateTypeParmDecl *, …) needs to
>> be addressed too, e.g. perhaps in this line the original type should be
>> used instead of the canonical type:
>>
>>
>> https://github.com/llvm/llvm-project/blob/master/clang/lib/Sema/SemaTemplate.cpp#L6126
>>
>> That fix, or one like it, would probably solve Oliver’s issue.
>>
>> More generally there is no reason to be replacing types with their
>> canonical types anywhere in the AST, I believe.
>>
>>
>> I believe there is - ultimately there's only one implicit
>> specialization of 'f1' (f1<int>, specifically) in code like this:
>>
>> template<typename T> void f1() { }
>> int main() {
>>  using x = int;
>>  using y = int;
>>  f1<x>();
>>  f1<y>();
>> }
>>
>> So the FunctionDecl for 'f1' can't refer to x or y, it has to refer to
>> 'int', right?
>>
>>
>> - Dave
>>
>> On Aug 13, 2020, at 10:13 AM, David Rector <davrecthreads at gmail.com>
>> wrote:
>>
>> Ha, deja vu - Pratyush (cc’d) was just dealing with this exact issue in
>> another context the other day, and Oliver we were kind of dealing with this
>> same general issue the other week re: attributes.
>>
>> You definitely *should* be able to get the full type sugar without fuss.
>> The obstacle to that is in
>>
>> Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType
>> ParamType, …)
>>
>> linked to here:
>> https://github.com/llvm/llvm-project/blob/master/clang/lib/Sema/SemaTemplate.cpp#L6688
>> .
>>
>> For some reason within that function the Converted template argument is
>> always constructed with Context.getCanonicalType(ParamType), instead of
>> ParamType, which erases the type sugar needlessly.
>>
>> Pratyush has solved this for the C++17 branch of that function in
>> https://reviews.llvm.org/D77598, but Pratyush it is probably a good idea
>> to replace all other instances of Context.getCanonicalType(XYZ) in that
>> function with XYZ, e.g. this line (among others):
>>
>> https://github.com/llvm/llvm-project/blob/master/clang/lib/Sema/SemaTemplate.cpp#L6955
>>
>> I suspect no tests will be broken with such a change, and the result will
>> be that template arguments will always have the proper sugar available.
>>
>> - Dave
>>
>> On Aug 13, 2020, at 12:30 AM, David Blaikie via cfe-dev <
>> cfe-dev at lists.llvm.org> wrote:
>>
>> Once you have the FunctionDecl you've gone too far and any type sugar
>> is lost, I believe. (because func<vectors32_t> is the same function as
>> func<unsigned int[32]> or any other typedef/alias/etc of that type
>> parameter, etc)
>>
>> I think you'd have to be able to see the call to the function, and go
>> from there to find the type as written.
>>
>> On Wed, Aug 12, 2020 at 8:14 PM Oliver Zhang via cfe-dev
>> <cfe-dev at lists.llvm.org> wrote:
>>
>>
>> Hi,
>>
>> I'm using clang-tool to extract type names in template arguments. For
>> example,
>>
>> typedef unsigned int vectors32_t[32];
>> template <typename T>
>> func(T *const vec) {
>>   ...
>> }
>> int main() {
>>   ...
>>   func<vector32_t>(...);
>>   ...
>> }
>>
>>
>>
>> I'd like to get the type name "vector32_t" from func's template argument.
>> So I use clang::FunctionDecl::getTemplateSpecializationArgs() to get func's
>> template argument list, extract the argument from the list, and then try to
>> get the type name for the argument by using
>> clang::TemplateArgument::getAsType().getAsString(). However, "unsigned int
>> [32]" is returned rather than "vector32_t".
>>
>> Any thoughts on how I can extract the type alias name "vector32_t" in my
>> above example?
>>
>> Thanks,
>> Oliver
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>>
>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200819/1fe7ee90/attachment.html>


More information about the cfe-dev mailing list