CodeCompass
CodeCompass copied to clipboard
Ast visitor function for using declarations.
Recursive ast visitor function for using declarations.
Someone please put the WIP label on this, I don't have the right to do that.
What is the status of this PR, @filbeofITK ? Is still work-in-progress, or is ready for review?
It is ready for review I just can't manage flags so I can't remove the WIP.
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.
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.
I have fixed the VisitUsingDirectiveDecl
function to properly handle namespace usings, now it works as expected:
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
Any suggestion @whisperity, @bruntib, how we could get the referenced
Decl
from aUsingDecl
? 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 using
ed namespace...
NamespaceDecl
s 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
.
Superseded by #645, closing this one.