CodeCompass icon indicating copy to clipboard operation
CodeCompass copied to clipboard

Ast visitor function for using declarations.

Open filbeofITK opened this issue 3 years ago • 5 comments

Recursive ast visitor function for using declarations.

filbeofITK avatar Oct 30 '20 12:10 filbeofITK

Someone please put the WIP label on this, I don't have the right to do that.

filbeofITK avatar Oct 30 '20 12:10 filbeofITK

What is the status of this PR, @filbeofITK ? Is still work-in-progress, or is ready for review?

mcserep avatar May 08 '21 19:05 mcserep

It is ready for review I just can't manage flags so I can't remove the WIP.

filbeofITK avatar May 10 '21 09:05 filbeofITK

The change of this PR does not seem to fix #305 for me. Have you tested it @filbeofITK ?

I have tested it on TinyXML2, there are few using statements in xmltest.cpp, but nothing happens when I click on them.

mcserep avatar May 30 '21 19:05 mcserep

Consider the following code:

namespace MyNamespace
{
  void f() {}
}

using namespace MyNamespace;  // UsingDirectiveDecl
using MyNamespace::f; // UsingDecl

int main()
{
}

Since VisitUsingDecl() has been implemented, only the latter one applies.

bruntib avatar Jun 07 '21 19:06 bruntib

I have fixed the VisitUsingDirectiveDecl function to properly handle namespace usings, now it works as expected: image

The VisitUsingDecl function still has to be done, to handle using statements like this correctly:

using MyNamespace::f;

Any suggestion @whisperity, @bruntib, how we could get the referenced Decl from a UsingDecl? https://clang.llvm.org/doxygen/classclang_1_1UsingDecl.html

mcserep avatar Feb 10 '23 23:02 mcserep

Any suggestion @whisperity, @bruntib, how we could get the referenced Decl from a UsingDecl? https://clang.llvm.org/doxygen/classclang_1_1UsingDecl.html

I have given it some thought and I think I found the solution.

So given

❯ clang++ --version
Ubuntu clang version 13.0.1-++20220120110844+75e33f71c2da-1~exp1~20220120230854.66

and

namespace foo {
  int foo() { return 1; }
}

using foo::foo;

int main() { return foo(); }

the relevant parts of the AST look like this:

|-NamespaceDecl 0x1ab41b0 <test.cpp:1:1, line:3:1> line:1:11 foo
| `-FunctionDecl 0x1ab4270 <line:2:3, col:25> col:7 foo 'int ()'
|   `-CompoundStmt 0x1ab4340 <col:13, col:25>
|     `-ReturnStmt 0x1ab4330 <col:15, col:22>
|       `-IntegerLiteral 0x1ab4310 <col:22> 'int' 1
|-UsingDecl 0x1ab4378 <line:5:1, col:12> col:12 foo::foo
|-UsingShadowDecl 0x1ab43e0 <col:12> col:12 implicit Function 0x1ab4270 'foo' 'int ()'
`-FunctionDecl 0x1ab4468 <line:7:1, line:10:1> line:7:5 main 'int ()'
  `-CompoundStmt 0x1ab4580 <line:8:1, line:10:1>
    `-ReturnStmt 0x56f7c0 <col:14, col:25>
      `-CallExpr 0x56f7a0 <col:21, col:25> 'int'
        `-ImplicitCastExpr 0x56f788 <col:21> 'int (*)()' <FunctionToPointerDecay>
          `-DeclRefExpr 0x56f738 <col:21> 'int ()' lvalue Function 0x1ab4270 'foo' 'int ()' (UsingShadow 0x1ab43e0 'foo')

Importantly, there are two nodes created for the using foo::foo; in line 5. Oddly enough, they are not parent-child of one another (which I expected them to be...). clang::BaseUsingDecl contains an iterable range under shadows() (shadows_begin() and shadows_end()) which iterate UsingShadowDecl*s which

Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration or using-enum-declaration to achieve the desired lookup semantics.

Note that the help of this class shows that, as using (<scope>::...)<declaration>; may introduce multiple names in an overload set(!), there is not always a 1:1 mapping from the using to a specific declaration.

From here, UsingShadowDecl::getTargetDecl() should yield some kind of an appropriate result, however!


Given

namespace foo {
  int bar() { return 1; }
}

using namespace foo;

int main() { return bar(); }

however, this becomes a UsingDirectiveDecl

|-NamespaceDecl 0x18591b0 <test.cpp:1:1, line:3:1> line:1:11 foo
| `-FunctionDecl 0x1859270 <line:2:3, col:25> col:7 used bar 'int ()'
|   `-CompoundStmt 0x1859340 <col:13, col:25>
|     `-ReturnStmt 0x1859330 <col:15, col:22>
|       `-IntegerLiteral 0x1859310 <col:22> 'int' 1
|-UsingDirectiveDecl 0x1859358 <line:5:1, col:17> col:17 Namespace 0x18591b0 'foo'
`-FunctionDecl 0x18593d8 <line:7:1, line:10:1> line:7:5 main 'int ()'
  `-CompoundStmt 0x18595d0 <line:8:1, line:10:1>
    `-ReturnStmt 0x18595c0 <line:9:3, col:14>
      `-CallExpr 0x18595a0 <col:10, col:14> 'int'
        `-ImplicitCastExpr 0x1859588 <col:10> 'int (*)()' <FunctionToPointerDecay>
          `-DeclRefExpr 0x1859538 <col:10> 'int ()' lvalue Function 0x1859270 'bar' 'int ()'

from which UsingDirectiveDecl::getNominatedNamespace() should lead you to ONE of the namespace decls that introduce the usinged namespace...

NamespaceDecls are Redeclareable<NamespaceDecl>s as well, so they can be chained. Given

namespace foo {
  int bar() { return 1; }
}

namespace foo {
  int baz() { return 2; }
}

using namespace foo;

int main() { return baz(); }
|-NamespaceDecl 0x1c721b0 <test.cpp:1:1, line:3:1> line:1:11 foo
| `-FunctionDecl 0x1c72270 <line:2:3, col:25> col:7 bar 'int ()'
|   `-CompoundStmt 0x1c72340 <col:13, col:25>
|     `-ReturnStmt 0x1c72330 <col:15, col:22>
|       `-IntegerLiteral 0x1c72310 <col:22> 'int' 1
|-NamespaceDecl 0x1c72358 prev 0x1c721b0 <line:5:1, line:7:1> line:5:11 foo
| |-original Namespace 0x1c721b0 'foo'
| `-FunctionDecl 0x1c723f0 <line:6:3, col:25> col:7 used baz 'int ()'
|   `-CompoundStmt 0x1c724c0 <col:13, col:25>
|     `-ReturnStmt 0x1c724b0 <col:15, col:22>
|       `-IntegerLiteral 0x1c72490 <col:22> 'int' 2
|-UsingDirectiveDecl 0x1c724d8 <line:9:1, col:17> col:17 Namespace 0x1c721b0 'foo'
`-FunctionDecl 0x1c72558 <line:11:1, col:28> col:5 main 'int ()'
  `-CompoundStmt 0x1c72750 <col:12, col:28>
    `-ReturnStmt 0x1c72740 <col:14, col:25>
      `-CallExpr 0x1c72720 <col:21, col:25> 'int'
        `-ImplicitCastExpr 0x1c72708 <col:21> 'int (*)()' <FunctionToPointerDecay>
          `-DeclRefExpr 0x1c726b8 <col:21> 'int ()' lvalue Function 0x1c723f0 'baz' 'int ()'

observe that the "target" of the directive points to the "first" occurrence of namespace foo.

whisperity avatar Sep 29 '23 08:09 whisperity

Superseded by #645, closing this one.

mcserep avatar Oct 18 '23 15:10 mcserep