Skip to content

Conversation

@filbeofITK
Copy link
Contributor

Recursive ast visitor function for using declarations.

@filbeofITK
Copy link
Contributor Author

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

@intjftw intjftw added the Status: WIP 👷 Issue or PR under development - feel free to review, though! label Oct 30, 2020
@filbeofITK filbeofITK force-pushed the using_ast branch 2 times, most recently from e6efc89 to a69a2db Compare December 26, 2020 19:09
@filbeofITK filbeofITK force-pushed the using_ast branch 2 times, most recently from 5a45324 to 73e1297 Compare February 5, 2021 10:18
@mcserep
Copy link
Collaborator

mcserep commented May 8, 2021

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

@mcserep mcserep linked an issue May 8, 2021 that may be closed by this pull request
@filbeofITK
Copy link
Contributor Author

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

@mcserep mcserep added Kind: Enhancement 🌟 Plugin: C++ Issues related to the parsing and presentation of C++ projects. and removed Status: WIP 👷 Issue or PR under development - feel free to review, though! labels May 10, 2021
@mcserep mcserep requested a review from intjftw May 10, 2021 09:12
Copy link
Collaborator

@mcserep mcserep left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good based on the code, some minor changes required. Also, please apply the coding convention of the existing codebase, e.g. Allman indentation style instead of K&R.

I will check the functionality meanwhile.

@filbeofITK filbeofITK force-pushed the using_ast branch 2 times, most recently from 67e2195 to 4529cd0 Compare May 13, 2021 16:44
@mcserep
Copy link
Collaborator

mcserep commented May 30, 2021

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.

@bruntib
Copy link
Collaborator

bruntib commented Jun 7, 2021

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.

Copy link
Collaborator

@mcserep mcserep left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is still some issue with this functionality. E.g. if I clicked on the using namespace N; on line 4, the other, unrelated namespace using statement was also selected in the code and displayed in the Info Tree for some reason.

Screenshot from 2021-10-20 10-33-22

Test code:
https://github.com/mcserep/cc-tests/blob/master/namespaces/main.cpp

@mcserep mcserep added this to the Release Gershwin milestone Jan 23, 2022
@mcserep mcserep force-pushed the master branch 2 times, most recently from bcca4c9 to 52327cd Compare January 25, 2022 09:18
@mcserep mcserep added the Status: At risk 🚨 Issue or PR which got stuck and progress in work is at risk. label Oct 22, 2022
@mcserep mcserep self-assigned this Feb 10, 2023
@mcserep
Copy link
Collaborator

mcserep commented Feb 10, 2023

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

@whisperity
Copy link
Contributor

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.

@mcserep mcserep removed the Status: At risk 🚨 Issue or PR which got stuck and progress in work is at risk. label Oct 1, 2023
@mcserep
Copy link
Collaborator

mcserep commented Oct 18, 2023

Superseded by #645, closing this one.

@mcserep mcserep closed this Oct 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Kind: Enhancement 🌟 Plugin: C++ Issues related to the parsing and presentation of C++ projects.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"using" declarative is not handled

6 participants