[cfe-dev] Help with integral template argument suffix and cast printing

David Rector via cfe-dev cfe-dev at lists.llvm.org
Fri Aug 7 11:23:33 PDT 2020


Actually ParamType may already be constructed with the proper AutoType sugar, so just try changing that line to 
> 
> QualType CanonParamType = ParamType;

If that works and doesn’t break any tests, then get rid of CanonParamType and replace it with ParamType in that function.

- Dave


> On Aug 7, 2020, at 2:03 PM, David Rector <davrecthreads at gmail.com> wrote:
> 
> You’re not making a mistake, the template argument was not constructed with the proper type sugar, which means there’s nothing you can do to distinguish deduced from non-deduced template arguments as is.
> 
> I think the following will solve it; change line https://github.com/llvm/llvm-project/blob/master/clang/lib/Sema/SemaTemplate.cpp#L6823 <https://github.com/llvm/llvm-project/blob/master/clang/lib/Sema/SemaTemplate.cpp#L6823> to the following:
> 
> QualType CanonParamType = Context.getCanonicalType(ParamType);
> 
> // FIXME: this renders CanonParamType non-canonical, but…why do we need 
> // a canonical type in the first place to construct template args?  
> // Seems to just lose type sugar info prematurely.
> if (Param->getType()->getAs<AutoType>())
>   CanonParamType = Context.getAutoType(CanonParamType, AutoTypeKeyword::Auto,
>                                        false, false);
> 
> See if that gets your thing to work (both T->getAs<AutoType>() and T->getAs<BuiltinType>() should return non-null for deduced builtins, allowing you to T->getAs<AutoType>() use distinguish deduced from non-deduced), then see if it breaks any others tests (it shouldn’t, because nothing should depend on template arguments being constructed with a canonical type at that point — I think we should be able to get rid of CanonParamType and use ParamType in its place in that function).
> 
> Good luck,
> 
> Dave
> 
> 
>> On Aug 7, 2020, at 8:30 AM, Pratyush Das <reikdas at gmail.com <mailto:reikdas at gmail.com>> wrote:
>> 
>> This is where we get the Integral type from the TemplateArgument - https://github.com/llvm/llvm-project/blob/master/clang/lib/AST/TemplateBase.cpp#L55 <https://github.com/llvm/llvm-project/blob/master/clang/lib/AST/TemplateBase.cpp#L55>. 
>> 
>> I tried - 
>> bool flag = false;
>> if (auto *autoT = T->getAs<AutoType>()) {
>>  flag = true;
>> }
>> 
>> But flag is not true for the example - 
>> template<auto N> struct S {};
>> template<> struct S<1> { using type = int };
>> S<1L>::type t;
>> 
>> Am I making a mistake in getting the AutoType?
>> 
>> On Wed, 22 Jul 2020 at 20:23, David Rector <davrecthreads at gmail.com <mailto:davrecthreads at gmail.com>> wrote:
>> The issue may be that the proper sugar isn’t being stored in the integral type when the TemplateArgument is created, so that there is no way to distinguish a non-deduced BuiltInType from a deduced one.
>> 
>> The type of the NonTypeTemplateParmDecl N in 
>> 
>> template<auto N> struct S {}` is an AutoType — so far so good.
>> 
>> But the type of the integral TemplateArgument '1' in S<1>, though, seems to be a BuiltInType — no sugar atop it, nothing to distinguish it from the situation where N had a BuiltInType instead of an AutoType.  
>> 
>> If I understand DeducedTypes correctly, when they are substituted, they should remain as sugar atop the substitution (someone correct me if I’m wrong), and that does not seem to happen here.
>> 
>> If others agree this is the issue, I would imagine you will have to dig around to figure out where the template argument is being created, and wrap the integral’s type in an AutoType.  Then testing if getAs<DeducedType>() before testing getAs<BuiltInType>() should tell you when your BuiltInType was deduced.  
>> 
>> That’s my last best guess anyway.  Good luck,
>> 
>> Dave
>> 
>>> On Jul 22, 2020, at 3:53 AM, Pratyush Das <reikdas at gmail.com <mailto:reikdas at gmail.com>> wrote:
>>> 
>>> That change does not work :( 
>>> 
>>> Thanks though! 
>>> 
>>> On Tue, 21 Jul 2020 at 23:30, David Rector <davrecthreads at gmail.com <mailto:davrecthreads at gmail.com>> wrote:
>>> 
>>> I would try replacing
>>> 
>>>  else if (auto *DT = T->getContainedDeducedType())
>>> 
>>> with
>>> 
>>>   else if (auto *DT = T->getAs<DeducedType>())
>>> 
>>> I think that is what you want anyway, since getContainedDeducedType seems to look not only through type sugar but through pointee types, array element types, etc.
>>> 
>>> To be sure, your example still should have worked using getContainedDeducedType but I think GetContainedDeducedTypeVisitor may have a problem in its implementation: it doesn’t handle all the possible sugar types.   In this case, you probably have a SubstTemplateTypeParmType, and I don’t see a VisitSubstTemplateTypeParmType implementation in there anywhere, so it is probably returning nullptr instead of desugaring and continuing to search.  That’s my best guess anyway from my perusal.
>>> 
>>> If this change works, it is probably another reason to replace stuff like GetContainedDeducedTypeVisitor with a more advanced getAs<T>(), with an extra template param that would allow you to look through e.g. pointee types, element types, function return types etc. when desired.
>>> 
>>> If that doesn’t work though, disregard.  Good luck,
>>> 
>>> Dave
>>> 
>>>> On Jul 21, 2020, at 9:06 AM, Pratyush Das via cfe-dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
>>>> 
>>>> Hi, 
>>>> 
>>>> I am a little stuck with https://reviews.llvm.org/D77598 <https://reviews.llvm.org/D77598> and would really appreciate any help.
>>>> 
>>>> I am trying to get the proper suffixes in the error messages for the following two examples - 
>>>> 
>>>> template<auto N> struct S {};
>>>> template<> struct S<1> { using type = int };
>>>> S<1L>::type t;
>>>> 
>>>> which should give the error message with a suffix - 
>>>> error: no type named 'type' in 'S<1L>'; did you mean 'S<1>::type'?
>>>> 
>>>> and
>>>> 
>>>> template <unsigned long long N> struct enable_if_unsigned_long_long {};
>>>> template <> struct enable_if_unsigned_long_long<1> { typedef int type; }; 
>>>> void test_unsigned_long_long() { enable_if_unsigned_long_long<2>::type i; } 
>>>> 
>>>> which should give no suffix in the error message - 
>>>> error: no type named 'type' in 'enable_if_unsigned_int<2>'; did you mean 'enable_if_unsigned_int<1>::type'?
>>>> 
>>>> I am trying to find the correct combination that would enable suffix in the first case, but not in the second case. I have been tinkering with checks for DeducedType and DependentType, but always either the suffixes are disabled for both the cases, or enabled for both the cases. 
>>>> 
>>>> Can anyone please provide any insight on how to proceed?
>>>> 
>>>> Thanks!
>>>> 
>>>> -- 
>>>> Pratyush Das(Reik)
>>>> _______________________________________________
>>>> cfe-dev mailing list
>>>> cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
>>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev <https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev>
>>> 
>>> 
>>> 
>>> -- 
>>> Pratyush Das(Reik)
>> 
>> 
>> 
>> -- 
>> Pratyush Das(Reik)
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200807/66551b11/attachment.html>


More information about the cfe-dev mailing list