Determining if a UsingDecl/UsingShadowDecl was used in the instantiation of a variable.

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

Determining if a UsingDecl/UsingShadowDecl was used in the instantiation of a variable.

Kristof Beyls via cfe-dev

Hi,

I have a plugin I'm working on a clang plugin where we need to determine all the things used in the creation of a piece of code.  Right now we have a situation as follows:

namespace X { class Y { enum Z { A=0, B, C }; }; };
using X::Y;

void MyFunc() {
	Y::Z q;
        ...
}

What we currently do is traverse the whole of MyFunc looking for referenced elements using VisitStmt().  The problem I have is that I can't find any way to determine that "using X::Y;" was used and that it was involved in resolving "Y::Z" to "X::Y::Z" in the creation of "q".   This has not been a problem for all sorts of sugar (like typedefs, type aliases, etc), but I am beside myself to find a way in this case.  Is there any way to do this?  I'm even interested if it's a sort of "long way around" solution.  It's surprising to me that this has been this hard... there have been breadcrumbs for every other piece of syntactic sugar.

Thanks in advance,

    -Eric

PS - I thought I had found some clues, but they only seemed to work for functions in one case (DeclRefExpr), and templates in another (getInstantiatedFromUsingDecl()).


_______________________________________________
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: Determining if a UsingDecl/UsingShadowDecl was used in the instantiation of a variable.

Kristof Beyls via cfe-dev
I don't believe that information is preserved in Clang's AST (if it was, we'd probably want to use it from the DWARF emission (GCC judiciously emits only referenced alias directives, whereas clang just emits them all, unfortunately) - and also to power a -Wunused... hmm, I thought GCC had a warning for unused using directives, but I can't seem to reproduce that now, so maybe I hallucinated).

On Tue, Oct 22, 2019 at 2:02 PM Eric Bayer via cfe-dev <[hidden email]> wrote:

Hi,

I have a plugin I'm working on a clang plugin where we need to determine all the things used in the creation of a piece of code.  Right now we have a situation as follows:

namespace X { class Y { enum Z { A=0, B, C }; }; };
using X::Y;

void MyFunc() {
	Y::Z q;
        ...
}

What we currently do is traverse the whole of MyFunc looking for referenced elements using VisitStmt().  The problem I have is that I can't find any way to determine that "using X::Y;" was used and that it was involved in resolving "Y::Z" to "X::Y::Z" in the creation of "q".   This has not been a problem for all sorts of sugar (like typedefs, type aliases, etc), but I am beside myself to find a way in this case.  Is there any way to do this?  I'm even interested if it's a sort of "long way around" solution.  It's surprising to me that this has been this hard... there have been breadcrumbs for every other piece of syntactic sugar.

Thanks in advance,

    -Eric

PS - I thought I had found some clues, but they only seemed to work for functions in one case (DeclRefExpr), and templates in another (getInstantiatedFromUsingDecl()).

_______________________________________________
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: Determining if a UsingDecl/UsingShadowDecl was used in the instantiation of a variable.

Kristof Beyls via cfe-dev

Thanks for the answer.  Damn.  Yeah, that is the conclusion I was coming to as well.  We had a similar problem capturing pre-processor macros as they really are not part of the AST.  Eventually I figured out a way to do it because I could capture data during the expansions and maintain a data structure on the side.  Unfortunately for name resolution there seems to be no similar callback/hook.

I also had wondered if there was some stage when maybe they'd be unresolved and I could build a data structure for later reference, but I've still not explored that avenue.

   -Eric

On 10/28/2019 1:08 PM, David Blaikie wrote:
I don't believe that information is preserved in Clang's AST (if it was, we'd probably want to use it from the DWARF emission (GCC judiciously emits only referenced alias directives, whereas clang just emits them all, unfortunately) - and also to power a -Wunused... hmm, I thought GCC had a warning for unused using directives, but I can't seem to reproduce that now, so maybe I hallucinated).

On Tue, Oct 22, 2019 at 2:02 PM Eric Bayer via cfe-dev <[hidden email]> wrote:

Hi,

I have a plugin I'm working on a clang plugin where we need to determine all the things used in the creation of a piece of code.  Right now we have a situation as follows:

namespace X { class Y { enum Z { A=0, B, C }; }; };
using X::Y;

void MyFunc() {
	Y::Z q;
        ...
}

What we currently do is traverse the whole of MyFunc looking for referenced elements using VisitStmt().  The problem I have is that I can't find any way to determine that "using X::Y;" was used and that it was involved in resolving "Y::Z" to "X::Y::Z" in the creation of "q".   This has not been a problem for all sorts of sugar (like typedefs, type aliases, etc), but I am beside myself to find a way in this case.  Is there any way to do this?  I'm even interested if it's a sort of "long way around" solution.  It's surprising to me that this has been this hard... there have been breadcrumbs for every other piece of syntactic sugar.

Thanks in advance,

    -Eric

PS - I thought I had found some clues, but they only seemed to work for functions in one case (DeclRefExpr), and templates in another (getInstantiatedFromUsingDecl()).

_______________________________________________
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: Determining if a UsingDecl/UsingShadowDecl was used in the instantiation of a variable.

Kristof Beyls via cfe-dev

Properly tracking which `using` directives actually get used has been on my wishlist for a long time, so that we can suppress the unused ones from DWARF.  But it sounds like you want more than just used-or-not, but actually where it was used.  That would be more ambitious.

--paulr

 

From: cfe-dev <[hidden email]> On Behalf Of Eric Bayer via cfe-dev
Sent: Monday, October 28, 2019 4:52 PM
To: David Blaikie <[hidden email]>
Cc: cfe-dev <[hidden email]>
Subject: Re: [cfe-dev] Determining if a UsingDecl/UsingShadowDecl was used in the instantiation of a variable.

 

Thanks for the answer.  Damn.  Yeah, that is the conclusion I was coming to as well.  We had a similar problem capturing pre-processor macros as they really are not part of the AST.  Eventually I figured out a way to do it because I could capture data during the expansions and maintain a data structure on the side.  Unfortunately for name resolution there seems to be no similar callback/hook.

I also had wondered if there was some stage when maybe they'd be unresolved and I could build a data structure for later reference, but I've still not explored that avenue.

   -Eric

 

On 10/28/2019 1:08 PM, David Blaikie wrote:

I don't believe that information is preserved in Clang's AST (if it was, we'd probably want to use it from the DWARF emission (GCC judiciously emits only referenced alias directives, whereas clang just emits them all, unfortunately) - and also to power a -Wunused... hmm, I thought GCC had a warning for unused using directives, but I can't seem to reproduce that now, so maybe I hallucinated).

 

On Tue, Oct 22, 2019 at 2:02 PM Eric Bayer via cfe-dev <[hidden email]> wrote:

Hi,

I have a plugin I'm working on a clang plugin where we need to determine all the things used in the creation of a piece of code.  Right now we have a situation as follows:

namespace X { class Y { enum Z { A=0, B, C }; }; };
using X::Y;
 
void MyFunc() {
       Y::Z q;
        ...
}

What we currently do is traverse the whole of MyFunc looking for referenced elements using VisitStmt().  The problem I have is that I can't find any way to determine that "using X::Y;" was used and that it was involved in resolving "Y::Z" to "X::Y::Z" in the creation of "q".   This has not been a problem for all sorts of sugar (like typedefs, type aliases, etc), but I am beside myself to find a way in this case.  Is there any way to do this?  I'm even interested if it's a sort of "long way around" solution.  It's surprising to me that this has been this hard... there have been breadcrumbs for every other piece of syntactic sugar.

Thanks in advance,

    -Eric

PS - I thought I had found some clues, but they only seemed to work for functions in one case (DeclRefExpr), and templates in another (getInstantiatedFromUsingDecl()).

_______________________________________________
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: Determining if a UsingDecl/UsingShadowDecl was used in the instantiation of a variable.

Kristof Beyls via cfe-dev
Yes, the purpose of this plugin is to cut apart C++ code for testing.  What it does is clip out the requested functions, find all the referenced types/templates/classes/macros/functions/etc, and generates a web of stubs and google mocks for the code to exist in.  The desired outcome is that you can select one or more functions in a compile unit and can easily perform isolated testing on them.

This represented a place where the end user had to add extra code (the "using X::Y;") to make the extracted code (and stubs/mocks) functional.  Not a huge gap, so I think we can live with it for now... but in the long run I always try to remove the need for the user to reimplement/redefine anything.

Worst case we can emit all of them that exist or can be seen by the context of the function, and that reference types we're already emitting.  That said this would be the only exception to a general rule of only emitting what was actually used, so I'm not entirely keen on that.

   -Eric


On 10/28/2019 1:57 PM, Robinson, Paul wrote:

Properly tracking which `using` directives actually get used has been on my wishlist for a long time, so that we can suppress the unused ones from DWARF.  But it sounds like you want more than just used-or-not, but actually where it was used.  That would be more ambitious.

--paulr

 

From: cfe-dev [hidden email] On Behalf Of Eric Bayer via cfe-dev
Sent: Monday, October 28, 2019 4:52 PM
To: David Blaikie [hidden email]
Cc: cfe-dev [hidden email]
Subject: Re: [cfe-dev] Determining if a UsingDecl/UsingShadowDecl was used in the instantiation of a variable.

 

Thanks for the answer.  Damn.  Yeah, that is the conclusion I was coming to as well.  We had a similar problem capturing pre-processor macros as they really are not part of the AST.  Eventually I figured out a way to do it because I could capture data during the expansions and maintain a data structure on the side.  Unfortunately for name resolution there seems to be no similar callback/hook.

I also had wondered if there was some stage when maybe they'd be unresolved and I could build a data structure for later reference, but I've still not explored that avenue.

   -Eric

 

On 10/28/2019 1:08 PM, David Blaikie wrote:

I don't believe that information is preserved in Clang's AST (if it was, we'd probably want to use it from the DWARF emission (GCC judiciously emits only referenced alias directives, whereas clang just emits them all, unfortunately) - and also to power a -Wunused... hmm, I thought GCC had a warning for unused using directives, but I can't seem to reproduce that now, so maybe I hallucinated).

 

On Tue, Oct 22, 2019 at 2:02 PM Eric Bayer via cfe-dev <[hidden email]> wrote:

Hi,

I have a plugin I'm working on a clang plugin where we need to determine all the things used in the creation of a piece of code.  Right now we have a situation as follows:

namespace X { class Y { enum Z { A=0, B, C }; }; };
using X::Y;
 
void MyFunc() {
       Y::Z q;
        ...
}

What we currently do is traverse the whole of MyFunc looking for referenced elements using VisitStmt().  The problem I have is that I can't find any way to determine that "using X::Y;" was used and that it was involved in resolving "Y::Z" to "X::Y::Z" in the creation of "q".   This has not been a problem for all sorts of sugar (like typedefs, type aliases, etc), but I am beside myself to find a way in this case.  Is there any way to do this?  I'm even interested if it's a sort of "long way around" solution.  It's surprising to me that this has been this hard... there have been breadcrumbs for every other piece of syntactic sugar.

Thanks in advance,

    -Eric

PS - I thought I had found some clues, but they only seemed to work for functions in one case (DeclRefExpr), and templates in another (getInstantiatedFromUsingDecl()).

_______________________________________________
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