Help with integral template argument suffix and cast printing

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Help with integral template argument suffix and cast printing

Keane, Erich via cfe-dev
Hi, 

I am a little stuck with 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Help with integral template argument suffix and cast printing

Keane, Erich via cfe-dev

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 <[hidden email]> wrote:

Hi, 

I am a little stuck with 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Help with integral template argument suffix and cast printing

Keane, Erich via cfe-dev
That change does not work :( 

Thanks though! 

On Tue, 21 Jul 2020 at 23:30, David Rector <[hidden email]> 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 <[hidden email]> wrote:

Hi, 

I am a little stuck with 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



--
Pratyush Das(Reik)

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Help with integral template argument suffix and cast printing

Keane, Erich via cfe-dev
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 <[hidden email]> wrote:

That change does not work :( 

Thanks though! 

On Tue, 21 Jul 2020 at 23:30, David Rector <[hidden email]> 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 <[hidden email]> wrote:

Hi, 

I am a little stuck with 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



--
Pratyush Das(Reik)


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Help with integral template argument suffix and cast printing

Keane, Erich via cfe-dev
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

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 <[hidden email]> 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 <[hidden email]> wrote:

That change does not work :( 

Thanks though! 

On Tue, 21 Jul 2020 at 23:30, David Rector <[hidden email]> 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 <[hidden email]> wrote:

Hi, 

I am a little stuck with 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



--
Pratyush Das(Reik)



--
Pratyush Das(Reik)

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Help with integral template argument suffix and cast printing

Keane, Erich via cfe-dev
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 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 <[hidden email]> 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

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 <[hidden email]> 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 <[hidden email]> wrote:

That change does not work :( 

Thanks though! 

On Tue, 21 Jul 2020 at 23:30, David Rector <[hidden email]> 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 <[hidden email]> wrote:

Hi, 

I am a little stuck with 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



--
Pratyush Das(Reik)



--
Pratyush Das(Reik)


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Help with integral template argument suffix and cast printing

Keane, Erich via cfe-dev
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 <[hidden email]> 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 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 <[hidden email]> 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

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 <[hidden email]> 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 <[hidden email]> wrote:

That change does not work :( 

Thanks though! 

On Tue, 21 Jul 2020 at 23:30, David Rector <[hidden email]> 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 <[hidden email]> wrote:

Hi, 

I am a little stuck with 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



--
Pratyush Das(Reik)



--
Pratyush Das(Reik)



_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Help with integral template argument suffix and cast printing

Keane, Erich via cfe-dev
That worked! Thanks. I have updated the diff in  https://reviews.llvm.org/D77598
(I tried to add you as a reviewer, but I was unable to find your phabricator id)

On Fri, 7 Aug 2020 at 23:53, David Rector <[hidden email]> wrote:
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 <[hidden email]> 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 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 <[hidden email]> 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

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 <[hidden email]> 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 <[hidden email]> wrote:

That change does not work :( 

Thanks though! 

On Tue, 21 Jul 2020 at 23:30, David Rector <[hidden email]> 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 <[hidden email]> wrote:

Hi, 

I am a little stuck with 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
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



--
Pratyush Das(Reik)



--
Pratyush Das(Reik)





_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev