CXCursor_CXXBaseSpecifier for template instantiated base class

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

CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
Hi,

When I use clang_visitChildren() to visit a class, I can't get a
CXCursor_CXXBaseSpecifier for its base class if the base class is a
template. For example:

template <typename BaseType>
class RecursiveBase : public BaseType
{
public:
   virtual void SomeFunc()
   {
      // prevent optimizer to remove the function
      global_var++;
   }
};

class Derived : public RecursiveBase<Base>, public Base2, public Base3
{
public:
   Derived() = default;

   void Func() override {}
};

I can get a CXCursor_CXXBaseSpecifier cursor as children of the
"Derived" cursor, but not RecursiveBase. How can I find out references
to all base classes including templates?

Thanks.

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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
You should be getting three times the `CXCursor_CXXBaseSpecifier`, one for each class you're inheriting from. I ran the analysis on my machine (clang 3.8) and that is exactly what I am getting: `RecursiveBase<class Base>`, `Base2``Base3`. Maybe you could use `clang -Xclang -ast-dump -fsyntax-only <this_demo>` to see the output of Clang's built-in AST dumper. It should contain these entries. Otherwise, clang version you're running might be an older one.

On 12 March 2017 at 05:09, Nestal Wan via cfe-dev <[hidden email]> wrote:
Hi,

When I use clang_visitChildren() to visit a class, I can't get a
CXCursor_CXXBaseSpecifier for its base class if the base class is a
template. For example:

template <typename BaseType>
class RecursiveBase : public BaseType
{
public:
   virtual void SomeFunc()
   {
      // prevent optimizer to remove the function
      global_var++;
   }
};

class Derived : public RecursiveBase<Base>, public Base2, public Base3
{
public:
   Derived() = default;

   void Func() override {}
};

I can get a CXCursor_CXXBaseSpecifier cursor as children of the
"Derived" cursor, but not RecursiveBase. How can I find out references
to all base classes including templates?

Thanks.

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


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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
Thanks for the reply.

-CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid class
Derived definition

| |-public 'class Base2'
| |-public 'class Base3'
| |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit referenced

class Derived

| |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
| |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2 Derived 'void

(void)' noexcept-unevaluated 0x55e6db0f5ef0

| `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void (void)'
| `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>


Sometimes I got "invalid class Derived definition", but if I extract the
classes in another source file, the result is different:

|-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class Derived

definition

| |-public 'RecursiveBase<class Base>':'class RecursiveBase<class Base>'
| |-public 'class Base2'
| |-public 'class Base3'
| |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit referenced

class Derived

What does it mean the class definition is invalid? There is no compile error.

Nestal

On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic <[hidden email]> wrote:

> You should be getting three times the `CXCursor_CXXBaseSpecifier`, one for
> each class you're inheriting from. I ran the analysis on my machine (clang
> 3.8) and that is exactly what I am getting: `RecursiveBase<class Base>`,
> `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump -fsyntax-only
> <this_demo>` to see the output of Clang's built-in AST dumper. It should
> contain these entries. Otherwise, clang version you're running might be an
> older one.
>
> On 12 March 2017 at 05:09, Nestal Wan via cfe-dev <[hidden email]>
> wrote:
>>
>> Hi,
>>
>> When I use clang_visitChildren() to visit a class, I can't get a
>> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>> template. For example:
>>
>> template <typename BaseType>
>> class RecursiveBase : public BaseType
>> {
>> public:
>>    virtual void SomeFunc()
>>    {
>>       // prevent optimizer to remove the function
>>       global_var++;
>>    }
>> };
>>
>> class Derived : public RecursiveBase<Base>, public Base2, public Base3
>> {
>> public:
>>    Derived() = default;
>>
>>    void Func() override {}
>> };
>>
>> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>> "Derived" cursor, but not RecursiveBase. How can I find out references
>> to all base classes including templates?
>>
>> Thanks.
>>
>> Nestal
>> _______________________________________________
>> cfe-dev mailing list
>> [hidden email]
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
It is hard to tell without more context why you're getting this error, but my guess is that you're missing some command line args (i.e. include paths, preprocessor flags, etc.) which is specific to the code you're analyzing and which is required in order to get the parsing stage done right. Very often this is the case and which is why you should, whenever you have doubts, always try to come up with a small reproducible example (without dependencies) and have it validated separately.

Additionally, you can try to extract diagnostics for the given translation unit and see if you get any hints there. Normally, you should get hints if clang parser was not able to fully parse the source code because it was missing some information such as failing to find particular headers.

Cheers,
Adi

On 12 March 2017 at 10:13, Nestal Wan <[hidden email]> wrote:
Thanks for the reply.

-CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid class
Derived definition

| |-public 'class Base2'
| |-public 'class Base3'
| |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit referenced

class Derived

| |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
| |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2 Derived 'void

(void)' noexcept-unevaluated 0x55e6db0f5ef0

| `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void (void)'
| `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>


Sometimes I got "invalid class Derived definition", but if I extract the
classes in another source file, the result is different:

|-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class Derived

definition

| |-public 'RecursiveBase<class Base>':'class RecursiveBase<class Base>'
| |-public 'class Base2'
| |-public 'class Base3'
| |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit referenced

class Derived

What does it mean the class definition is invalid? There is no compile error.

Nestal

On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic <[hidden email]> wrote:
> You should be getting three times the `CXCursor_CXXBaseSpecifier`, one for
> each class you're inheriting from. I ran the analysis on my machine (clang
> 3.8) and that is exactly what I am getting: `RecursiveBase<class Base>`,
> `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump -fsyntax-only
> <this_demo>` to see the output of Clang's built-in AST dumper. It should
> contain these entries. Otherwise, clang version you're running might be an
> older one.
>
> On 12 March 2017 at 05:09, Nestal Wan via cfe-dev <[hidden email]>
> wrote:
>>
>> Hi,
>>
>> When I use clang_visitChildren() to visit a class, I can't get a
>> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>> template. For example:
>>
>> template <typename BaseType>
>> class RecursiveBase : public BaseType
>> {
>> public:
>>    virtual void SomeFunc()
>>    {
>>       // prevent optimizer to remove the function
>>       global_var++;
>>    }
>> };
>>
>> class Derived : public RecursiveBase<Base>, public Base2, public Base3
>> {
>> public:
>>    Derived() = default;
>>
>>    void Func() override {}
>> };
>>
>> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>> "Derived" cursor, but not RecursiveBase. How can I find out references
>> to all base classes including templates?
>>
>> Thanks.
>>
>> Nestal
>> _______________________________________________
>> cfe-dev mailing list
>> [hidden email]
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>


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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
Thanks Adi,

Like you said, I solve the problem by fixing the errors that were
indicated by the diagnostic messages.

Now I have another question, if you don't mind I keep using this thread.

I wish know the class hierarchy of "Derived". That means getting the
base class the the instantiated RecursiveBase<Base> template. That
should be "Base".

When I visit "Dervied", I got a cursor to a CXCursor_CXXBaseSpecifier.
I tried to get the type by:

CXType recursive_base =
clang_getCursorType(clang_getCursorDefinition(cxx_base_specifier));

"recursive_base" refers to the RecursiveBase<Base> instantiation. How
can I get the base type of this class? I know I can get the cursor to
the template that instantiate it (i.e. template <typename BaseType>
RecursiveBase), and I can see it inherits "BaseType" by visiting it
and look for CXCursor_CXXBaseSpecifier. But how can I know "BaseType"
will become "Base" when we instantiate it? Will the CXType provides me
this linkage or I need to use LibTooling instead?

Thanks again.

Nestal

On Sun, Mar 12, 2017 at 9:25 PM, Jusufadis Bakamovic <[hidden email]> wrote:

> It is hard to tell without more context why you're getting this error, but
> my guess is that you're missing some command line args (i.e. include paths,
> preprocessor flags, etc.) which is specific to the code you're analyzing and
> which is required in order to get the parsing stage done right. Very often
> this is the case and which is why you should, whenever you have doubts,
> always try to come up with a small reproducible example (without
> dependencies) and have it validated separately.
>
> Additionally, you can try to extract diagnostics for the given translation
> unit and see if you get any hints there. Normally, you should get hints if
> clang parser was not able to fully parse the source code because it was
> missing some information such as failing to find particular headers.
>
> Cheers,
> Adi
>
> On 12 March 2017 at 10:13, Nestal Wan <[hidden email]> wrote:
>>
>> Thanks for the reply.
>>
>> -CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid
>> class
>> Derived definition
>>
>> | |-public 'class Base2'
>> | |-public 'class Base3'
>> | |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit referenced
>>
>> class Derived
>>
>> | |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
>> | |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2 Derived
>> 'void
>>
>> (void)' noexcept-unevaluated 0x55e6db0f5ef0
>>
>> | `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void
>> (void)'
>> | `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>
>>
>>
>> Sometimes I got "invalid class Derived definition", but if I extract the
>> classes in another source file, the result is different:
>>
>> |-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class
>> Derived
>>
>> definition
>>
>> | |-public 'RecursiveBase<class Base>':'class RecursiveBase<class Base>'
>> | |-public 'class Base2'
>> | |-public 'class Base3'
>> | |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit referenced
>>
>> class Derived
>>
>> What does it mean the class definition is invalid? There is no compile
>> error.
>>
>> Nestal
>>
>> On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic <[hidden email]>
>> wrote:
>> > You should be getting three times the `CXCursor_CXXBaseSpecifier`, one
>> > for
>> > each class you're inheriting from. I ran the analysis on my machine
>> > (clang
>> > 3.8) and that is exactly what I am getting: `RecursiveBase<class Base>`,
>> > `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump
>> > -fsyntax-only
>> > <this_demo>` to see the output of Clang's built-in AST dumper. It should
>> > contain these entries. Otherwise, clang version you're running might be
>> > an
>> > older one.
>> >
>> > On 12 March 2017 at 05:09, Nestal Wan via cfe-dev
>> > <[hidden email]>
>> > wrote:
>> >>
>> >> Hi,
>> >>
>> >> When I use clang_visitChildren() to visit a class, I can't get a
>> >> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>> >> template. For example:
>> >>
>> >> template <typename BaseType>
>> >> class RecursiveBase : public BaseType
>> >> {
>> >> public:
>> >>    virtual void SomeFunc()
>> >>    {
>> >>       // prevent optimizer to remove the function
>> >>       global_var++;
>> >>    }
>> >> };
>> >>
>> >> class Derived : public RecursiveBase<Base>, public Base2, public Base3
>> >> {
>> >> public:
>> >>    Derived() = default;
>> >>
>> >>    void Func() override {}
>> >> };
>> >>
>> >> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>> >> "Derived" cursor, but not RecursiveBase. How can I find out references
>> >> to all base classes including templates?
>> >>
>> >> Thanks.
>> >>
>> >> Nestal
>> >> _______________________________________________
>> >> cfe-dev mailing list
>> >> [hidden email]
>> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>> >
>> >
>
>
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
This is an interesting question I was also wondering about the other
day... (sorry, if you were hoping for an answer;)

The best thing I figured out was: get the type of template parameter
RecursiveBase<Base> (via clang_Type_getTemplateArgumentAsType), then go
to the referenced template RecursiveBase and do the parameter mapping
myself. Of course this will get more complicated if that again derives
from a template using that parameter...

Running the example through "clang++ -Xclang -ast-dump -fsyntax-only .."
I see the needed ClassTemplateSpecializationDecls, also for further base
templates, carrying the proper specialized parameter types...

I would have expected clang_getSpecializedCursorTemplate giving me these
specialized versions of the templates, but either I understand it wrong
what is supposed to do or it's implementation is incomplete here? Some
insight on this question would be appreciated.

Thanks

Michael


On 03/14/2017 05:39 PM, Nestal Wan via cfe-dev wrote:

> Thanks Adi,
>
> Like you said, I solve the problem by fixing the errors that were
> indicated by the diagnostic messages.
>
> Now I have another question, if you don't mind I keep using this thread.
>
> I wish know the class hierarchy of "Derived". That means getting the
> base class the the instantiated RecursiveBase<Base> template. That
> should be "Base".
>
> When I visit "Dervied", I got a cursor to a CXCursor_CXXBaseSpecifier.
> I tried to get the type by:
>
> CXType recursive_base =
> clang_getCursorType(clang_getCursorDefinition(cxx_base_specifier));
>
> "recursive_base" refers to the RecursiveBase<Base> instantiation. How
> can I get the base type of this class? I know I can get the cursor to
> the template that instantiate it (i.e. template <typename BaseType>
> RecursiveBase), and I can see it inherits "BaseType" by visiting it
> and look for CXCursor_CXXBaseSpecifier. But how can I know "BaseType"
> will become "Base" when we instantiate it? Will the CXType provides me
> this linkage or I need to use LibTooling instead?
>
> Thanks again.
>
> Nestal
>
> On Sun, Mar 12, 2017 at 9:25 PM, Jusufadis Bakamovic <[hidden email]> wrote:
>> It is hard to tell without more context why you're getting this error, but
>> my guess is that you're missing some command line args (i.e. include paths,
>> preprocessor flags, etc.) which is specific to the code you're analyzing and
>> which is required in order to get the parsing stage done right. Very often
>> this is the case and which is why you should, whenever you have doubts,
>> always try to come up with a small reproducible example (without
>> dependencies) and have it validated separately.
>>
>> Additionally, you can try to extract diagnostics for the given translation
>> unit and see if you get any hints there. Normally, you should get hints if
>> clang parser was not able to fully parse the source code because it was
>> missing some information such as failing to find particular headers.
>>
>> Cheers,
>> Adi
>>
>> On 12 March 2017 at 10:13, Nestal Wan <[hidden email]> wrote:
>>> Thanks for the reply.
>>>
>>> -CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid
>>> class
>>> Derived definition
>>>
>>> | |-public 'class Base2'
>>> | |-public 'class Base3'
>>> | |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit referenced
>>>
>>> class Derived
>>>
>>> | |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
>>> | |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2 Derived
>>> 'void
>>>
>>> (void)' noexcept-unevaluated 0x55e6db0f5ef0
>>>
>>> | `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void
>>> (void)'
>>> | `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>
>>>
>>>
>>> Sometimes I got "invalid class Derived definition", but if I extract the
>>> classes in another source file, the result is different:
>>>
>>> |-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class
>>> Derived
>>>
>>> definition
>>>
>>> | |-public 'RecursiveBase<class Base>':'class RecursiveBase<class Base>'
>>> | |-public 'class Base2'
>>> | |-public 'class Base3'
>>> | |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit referenced
>>>
>>> class Derived
>>>
>>> What does it mean the class definition is invalid? There is no compile
>>> error.
>>>
>>> Nestal
>>>
>>> On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic <[hidden email]>
>>> wrote:
>>>> You should be getting three times the `CXCursor_CXXBaseSpecifier`, one
>>>> for
>>>> each class you're inheriting from. I ran the analysis on my machine
>>>> (clang
>>>> 3.8) and that is exactly what I am getting: `RecursiveBase<class Base>`,
>>>> `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump
>>>> -fsyntax-only
>>>> <this_demo>` to see the output of Clang's built-in AST dumper. It should
>>>> contain these entries. Otherwise, clang version you're running might be
>>>> an
>>>> older one.
>>>>
>>>> On 12 March 2017 at 05:09, Nestal Wan via cfe-dev
>>>> <[hidden email]>
>>>> wrote:
>>>>> Hi,
>>>>>
>>>>> When I use clang_visitChildren() to visit a class, I can't get a
>>>>> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>>>>> template. For example:
>>>>>
>>>>> template <typename BaseType>
>>>>> class RecursiveBase : public BaseType
>>>>> {
>>>>> public:
>>>>>     virtual void SomeFunc()
>>>>>     {
>>>>>        // prevent optimizer to remove the function
>>>>>        global_var++;
>>>>>     }
>>>>> };
>>>>>
>>>>> class Derived : public RecursiveBase<Base>, public Base2, public Base3
>>>>> {
>>>>> public:
>>>>>     Derived() = default;
>>>>>
>>>>>     void Func() override {}
>>>>> };
>>>>>
>>>>> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>>>>> "Derived" cursor, but not RecursiveBase. How can I find out references
>>>>> to all base classes including templates?
>>>>>
>>>>> Thanks.
>>>>>
>>>>> Nestal
>>>>> _______________________________________________
>>>>> cfe-dev mailing list
>>>>> [hidden email]
>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>>
>>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev


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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
In reply to this post by James Y Knight via cfe-dev
Hi Nestal,

I am not sure if I understood you correctly but you want to find out the structure/hierarchy of your "Derived" class, that is all of the base classes that your derived class is inheriting from? If this is what you are asking for, then you can accomplish this by enumerating all of the `CXCursor_TypeRef`'s of corresponding `CXCursor_CXXBaseSpecifier` cursors which are descendants (children) of class declaration (`CXCursor_ClassDecl`) which you're interested in (i.e. "Derived").

When parser is run on your example, `CXCursor_CXXBaseSpecifier` cursors are `RecursiveBase<class Base>``class Base2` and `class Base3`. Corresponding `CXCursor_TypeRef` cursors are `class Base`, `class Base2` and `class Base3`. This is what I believe you're looking for.

For a generic and full-proof solution, you will want to do the same thing recursively for each `CXCursor_CXXBaseSpecifier` found.

Cheers,
Adi

On 14 March 2017 at 17:39, Nestal Wan <[hidden email]> wrote:
Thanks Adi,

Like you said, I solve the problem by fixing the errors that were
indicated by the diagnostic messages.

Now I have another question, if you don't mind I keep using this thread.

I wish know the class hierarchy of "Derived". That means getting the
base class the the instantiated RecursiveBase<Base> template. That
should be "Base".

When I visit "Dervied", I got a cursor to a CXCursor_CXXBaseSpecifier.
I tried to get the type by:

CXType recursive_base =
clang_getCursorType(clang_getCursorDefinition(cxx_base_specifier));

"recursive_base" refers to the RecursiveBase<Base> instantiation. How
can I get the base type of this class? I know I can get the cursor to
the template that instantiate it (i.e. template <typename BaseType>
RecursiveBase), and I can see it inherits "BaseType" by visiting it
and look for CXCursor_CXXBaseSpecifier. But how can I know "BaseType"
will become "Base" when we instantiate it? Will the CXType provides me
this linkage or I need to use LibTooling instead?

Thanks again.

Nestal

On Sun, Mar 12, 2017 at 9:25 PM, Jusufadis Bakamovic <[hidden email]> wrote:
> It is hard to tell without more context why you're getting this error, but
> my guess is that you're missing some command line args (i.e. include paths,
> preprocessor flags, etc.) which is specific to the code you're analyzing and
> which is required in order to get the parsing stage done right. Very often
> this is the case and which is why you should, whenever you have doubts,
> always try to come up with a small reproducible example (without
> dependencies) and have it validated separately.
>
> Additionally, you can try to extract diagnostics for the given translation
> unit and see if you get any hints there. Normally, you should get hints if
> clang parser was not able to fully parse the source code because it was
> missing some information such as failing to find particular headers.
>
> Cheers,
> Adi
>
> On 12 March 2017 at 10:13, Nestal Wan <[hidden email]> wrote:
>>
>> Thanks for the reply.
>>
>> -CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid
>> class
>> Derived definition
>>
>> | |-public 'class Base2'
>> | |-public 'class Base3'
>> | |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit referenced
>>
>> class Derived
>>
>> | |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
>> | |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2 Derived
>> 'void
>>
>> (void)' noexcept-unevaluated 0x55e6db0f5ef0
>>
>> | `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void
>> (void)'
>> | `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>
>>
>>
>> Sometimes I got "invalid class Derived definition", but if I extract the
>> classes in another source file, the result is different:
>>
>> |-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class
>> Derived
>>
>> definition
>>
>> | |-public 'RecursiveBase<class Base>':'class RecursiveBase<class Base>'
>> | |-public 'class Base2'
>> | |-public 'class Base3'
>> | |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit referenced
>>
>> class Derived
>>
>> What does it mean the class definition is invalid? There is no compile
>> error.
>>
>> Nestal
>>
>> On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic <[hidden email]>
>> wrote:
>> > You should be getting three times the `CXCursor_CXXBaseSpecifier`, one
>> > for
>> > each class you're inheriting from. I ran the analysis on my machine
>> > (clang
>> > 3.8) and that is exactly what I am getting: `RecursiveBase<class Base>`,
>> > `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump
>> > -fsyntax-only
>> > <this_demo>` to see the output of Clang's built-in AST dumper. It should
>> > contain these entries. Otherwise, clang version you're running might be
>> > an
>> > older one.
>> >
>> > On 12 March 2017 at 05:09, Nestal Wan via cfe-dev
>> > <[hidden email]>
>> > wrote:
>> >>
>> >> Hi,
>> >>
>> >> When I use clang_visitChildren() to visit a class, I can't get a
>> >> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>> >> template. For example:
>> >>
>> >> template <typename BaseType>
>> >> class RecursiveBase : public BaseType
>> >> {
>> >> public:
>> >>    virtual void SomeFunc()
>> >>    {
>> >>       // prevent optimizer to remove the function
>> >>       global_var++;
>> >>    }
>> >> };
>> >>
>> >> class Derived : public RecursiveBase<Base>, public Base2, public Base3
>> >> {
>> >> public:
>> >>    Derived() = default;
>> >>
>> >>    void Func() override {}
>> >> };
>> >>
>> >> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>> >> "Derived" cursor, but not RecursiveBase. How can I find out references
>> >> to all base classes including templates?
>> >>
>> >> Thanks.
>> >>
>> >> Nestal
>> >> _______________________________________________
>> >> cfe-dev mailing list
>> >> [hidden email]
>> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>> >
>> >
>
>


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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
Thanks, Adi! Do you mean that CXCursor_TypeRef is a child under the
CXCursor_CXXBaseSpecifier?

On Fri, Mar 17, 2017 at 1:10 AM, Jusufadis Bakamovic <[hidden email]> wrote:

> Hi Nestal,
>
> I am not sure if I understood you correctly but you want to find out the
> structure/hierarchy of your "Derived" class, that is all of the base classes
> that your derived class is inheriting from? If this is what you are asking
> for, then you can accomplish this by enumerating all of the
> `CXCursor_TypeRef`'s of corresponding `CXCursor_CXXBaseSpecifier` cursors
> which are descendants (children) of class declaration (`CXCursor_ClassDecl`)
> which you're interested in (i.e. "Derived").
>
> When parser is run on your example, `CXCursor_CXXBaseSpecifier` cursors are
> `RecursiveBase<class Base>`, `class Base2` and `class Base3`. Corresponding
> `CXCursor_TypeRef` cursors are `class Base`, `class Base2` and `class
> Base3`. This is what I believe you're looking for.
>
> For a generic and full-proof solution, you will want to do the same thing
> recursively for each `CXCursor_CXXBaseSpecifier` found.
>
> Cheers,
> Adi
>
> On 14 March 2017 at 17:39, Nestal Wan <[hidden email]> wrote:
>>
>> Thanks Adi,
>>
>> Like you said, I solve the problem by fixing the errors that were
>> indicated by the diagnostic messages.
>>
>> Now I have another question, if you don't mind I keep using this thread.
>>
>> I wish know the class hierarchy of "Derived". That means getting the
>> base class the the instantiated RecursiveBase<Base> template. That
>> should be "Base".
>>
>> When I visit "Dervied", I got a cursor to a CXCursor_CXXBaseSpecifier.
>> I tried to get the type by:
>>
>> CXType recursive_base =
>> clang_getCursorType(clang_getCursorDefinition(cxx_base_specifier));
>>
>> "recursive_base" refers to the RecursiveBase<Base> instantiation. How
>> can I get the base type of this class? I know I can get the cursor to
>> the template that instantiate it (i.e. template <typename BaseType>
>> RecursiveBase), and I can see it inherits "BaseType" by visiting it
>> and look for CXCursor_CXXBaseSpecifier. But how can I know "BaseType"
>> will become "Base" when we instantiate it? Will the CXType provides me
>> this linkage or I need to use LibTooling instead?
>>
>> Thanks again.
>>
>> Nestal
>>
>> On Sun, Mar 12, 2017 at 9:25 PM, Jusufadis Bakamovic <[hidden email]>
>> wrote:
>> > It is hard to tell without more context why you're getting this error,
>> > but
>> > my guess is that you're missing some command line args (i.e. include
>> > paths,
>> > preprocessor flags, etc.) which is specific to the code you're analyzing
>> > and
>> > which is required in order to get the parsing stage done right. Very
>> > often
>> > this is the case and which is why you should, whenever you have doubts,
>> > always try to come up with a small reproducible example (without
>> > dependencies) and have it validated separately.
>> >
>> > Additionally, you can try to extract diagnostics for the given
>> > translation
>> > unit and see if you get any hints there. Normally, you should get hints
>> > if
>> > clang parser was not able to fully parse the source code because it was
>> > missing some information such as failing to find particular headers.
>> >
>> > Cheers,
>> > Adi
>> >
>> > On 12 March 2017 at 10:13, Nestal Wan <[hidden email]> wrote:
>> >>
>> >> Thanks for the reply.
>> >>
>> >> -CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid
>> >> class
>> >> Derived definition
>> >>
>> >> | |-public 'class Base2'
>> >> | |-public 'class Base3'
>> >> | |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit
>> >> referenced
>> >>
>> >> class Derived
>> >>
>> >> | |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
>> >> | |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2 Derived
>> >> 'void
>> >>
>> >> (void)' noexcept-unevaluated 0x55e6db0f5ef0
>> >>
>> >> | `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void
>> >> (void)'
>> >> | `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>
>> >>
>> >>
>> >> Sometimes I got "invalid class Derived definition", but if I extract
>> >> the
>> >> classes in another source file, the result is different:
>> >>
>> >> |-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class
>> >> Derived
>> >>
>> >> definition
>> >>
>> >> | |-public 'RecursiveBase<class Base>':'class RecursiveBase<class
>> >> Base>'
>> >> | |-public 'class Base2'
>> >> | |-public 'class Base3'
>> >> | |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit
>> >> referenced
>> >>
>> >> class Derived
>> >>
>> >> What does it mean the class definition is invalid? There is no compile
>> >> error.
>> >>
>> >> Nestal
>> >>
>> >> On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic <[hidden email]>
>> >> wrote:
>> >> > You should be getting three times the `CXCursor_CXXBaseSpecifier`,
>> >> > one
>> >> > for
>> >> > each class you're inheriting from. I ran the analysis on my machine
>> >> > (clang
>> >> > 3.8) and that is exactly what I am getting: `RecursiveBase<class
>> >> > Base>`,
>> >> > `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump
>> >> > -fsyntax-only
>> >> > <this_demo>` to see the output of Clang's built-in AST dumper. It
>> >> > should
>> >> > contain these entries. Otherwise, clang version you're running might
>> >> > be
>> >> > an
>> >> > older one.
>> >> >
>> >> > On 12 March 2017 at 05:09, Nestal Wan via cfe-dev
>> >> > <[hidden email]>
>> >> > wrote:
>> >> >>
>> >> >> Hi,
>> >> >>
>> >> >> When I use clang_visitChildren() to visit a class, I can't get a
>> >> >> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>> >> >> template. For example:
>> >> >>
>> >> >> template <typename BaseType>
>> >> >> class RecursiveBase : public BaseType
>> >> >> {
>> >> >> public:
>> >> >>    virtual void SomeFunc()
>> >> >>    {
>> >> >>       // prevent optimizer to remove the function
>> >> >>       global_var++;
>> >> >>    }
>> >> >> };
>> >> >>
>> >> >> class Derived : public RecursiveBase<Base>, public Base2, public
>> >> >> Base3
>> >> >> {
>> >> >> public:
>> >> >>    Derived() = default;
>> >> >>
>> >> >>    void Func() override {}
>> >> >> };
>> >> >>
>> >> >> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>> >> >> "Derived" cursor, but not RecursiveBase. How can I find out
>> >> >> references
>> >> >> to all base classes including templates?
>> >> >>
>> >> >> Thanks.
>> >> >>
>> >> >> Nestal
>> >> >> _______________________________________________
>> >> >> cfe-dev mailing list
>> >> >> [hidden email]
>> >> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>> >> >
>> >> >
>> >
>> >
>
>
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
In reply to this post by James Y Knight via cfe-dev
Yes. I think clang_getSpecializedCursorTemplate() will definitely be
useful for me. Thanks for the info.

On Thu, Mar 16, 2017 at 2:02 AM, Michael via cfe-dev
<[hidden email]> wrote:

> This is an interesting question I was also wondering about the other day...
> (sorry, if you were hoping for an answer;)
>
> The best thing I figured out was: get the type of template parameter
> RecursiveBase<Base> (via clang_Type_getTemplateArgumentAsType), then go to
> the referenced template RecursiveBase and do the parameter mapping myself.
> Of course this will get more complicated if that again derives from a
> template using that parameter...
>
> Running the example through "clang++ -Xclang -ast-dump -fsyntax-only .." I
> see the needed ClassTemplateSpecializationDecls, also for further base
> templates, carrying the proper specialized parameter types...
>
> I would have expected clang_getSpecializedCursorTemplate giving me these
> specialized versions of the templates, but either I understand it wrong what
> is supposed to do or it's implementation is incomplete here? Some insight on
> this question would be appreciated.
>
> Thanks
>
> Michael
>
>
>
> On 03/14/2017 05:39 PM, Nestal Wan via cfe-dev wrote:
>>
>> Thanks Adi,
>>
>> Like you said, I solve the problem by fixing the errors that were
>> indicated by the diagnostic messages.
>>
>> Now I have another question, if you don't mind I keep using this thread.
>>
>> I wish know the class hierarchy of "Derived". That means getting the
>> base class the the instantiated RecursiveBase<Base> template. That
>> should be "Base".
>>
>> When I visit "Dervied", I got a cursor to a CXCursor_CXXBaseSpecifier.
>> I tried to get the type by:
>>
>> CXType recursive_base =
>> clang_getCursorType(clang_getCursorDefinition(cxx_base_specifier));
>>
>> "recursive_base" refers to the RecursiveBase<Base> instantiation. How
>> can I get the base type of this class? I know I can get the cursor to
>> the template that instantiate it (i.e. template <typename BaseType>
>> RecursiveBase), and I can see it inherits "BaseType" by visiting it
>> and look for CXCursor_CXXBaseSpecifier. But how can I know "BaseType"
>> will become "Base" when we instantiate it? Will the CXType provides me
>> this linkage or I need to use LibTooling instead?
>>
>> Thanks again.
>>
>> Nestal
>>
>> On Sun, Mar 12, 2017 at 9:25 PM, Jusufadis Bakamovic <[hidden email]>
>> wrote:
>>>
>>> It is hard to tell without more context why you're getting this error,
>>> but
>>> my guess is that you're missing some command line args (i.e. include
>>> paths,
>>> preprocessor flags, etc.) which is specific to the code you're analyzing
>>> and
>>> which is required in order to get the parsing stage done right. Very
>>> often
>>> this is the case and which is why you should, whenever you have doubts,
>>> always try to come up with a small reproducible example (without
>>> dependencies) and have it validated separately.
>>>
>>> Additionally, you can try to extract diagnostics for the given
>>> translation
>>> unit and see if you get any hints there. Normally, you should get hints
>>> if
>>> clang parser was not able to fully parse the source code because it was
>>> missing some information such as failing to find particular headers.
>>>
>>> Cheers,
>>> Adi
>>>
>>> On 12 March 2017 at 10:13, Nestal Wan <[hidden email]> wrote:
>>>>
>>>> Thanks for the reply.
>>>>
>>>> -CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid
>>>> class
>>>> Derived definition
>>>>
>>>> | |-public 'class Base2'
>>>> | |-public 'class Base3'
>>>> | |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit
>>>> referenced
>>>>
>>>> class Derived
>>>>
>>>> | |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
>>>> | |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2 Derived
>>>> 'void
>>>>
>>>> (void)' noexcept-unevaluated 0x55e6db0f5ef0
>>>>
>>>> | `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void
>>>> (void)'
>>>> | `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>
>>>>
>>>>
>>>> Sometimes I got "invalid class Derived definition", but if I extract the
>>>> classes in another source file, the result is different:
>>>>
>>>> |-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class
>>>> Derived
>>>>
>>>> definition
>>>>
>>>> | |-public 'RecursiveBase<class Base>':'class RecursiveBase<class Base>'
>>>> | |-public 'class Base2'
>>>> | |-public 'class Base3'
>>>> | |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit
>>>> referenced
>>>>
>>>> class Derived
>>>>
>>>> What does it mean the class definition is invalid? There is no compile
>>>> error.
>>>>
>>>> Nestal
>>>>
>>>> On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic <[hidden email]>
>>>> wrote:
>>>>>
>>>>> You should be getting three times the `CXCursor_CXXBaseSpecifier`, one
>>>>> for
>>>>> each class you're inheriting from. I ran the analysis on my machine
>>>>> (clang
>>>>> 3.8) and that is exactly what I am getting: `RecursiveBase<class
>>>>> Base>`,
>>>>> `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump
>>>>> -fsyntax-only
>>>>> <this_demo>` to see the output of Clang's built-in AST dumper. It
>>>>> should
>>>>> contain these entries. Otherwise, clang version you're running might be
>>>>> an
>>>>> older one.
>>>>>
>>>>> On 12 March 2017 at 05:09, Nestal Wan via cfe-dev
>>>>> <[hidden email]>
>>>>> wrote:
>>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> When I use clang_visitChildren() to visit a class, I can't get a
>>>>>> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>>>>>> template. For example:
>>>>>>
>>>>>> template <typename BaseType>
>>>>>> class RecursiveBase : public BaseType
>>>>>> {
>>>>>> public:
>>>>>>     virtual void SomeFunc()
>>>>>>     {
>>>>>>        // prevent optimizer to remove the function
>>>>>>        global_var++;
>>>>>>     }
>>>>>> };
>>>>>>
>>>>>> class Derived : public RecursiveBase<Base>, public Base2, public Base3
>>>>>> {
>>>>>> public:
>>>>>>     Derived() = default;
>>>>>>
>>>>>>     void Func() override {}
>>>>>> };
>>>>>>
>>>>>> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>>>>>> "Derived" cursor, but not RecursiveBase. How can I find out references
>>>>>> to all base classes including templates?
>>>>>>
>>>>>> Thanks.
>>>>>>
>>>>>> Nestal
>>>>>> _______________________________________________
>>>>>> cfe-dev mailing list
>>>>>> [hidden email]
>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>>>
>>>>>
>>>
>> _______________________________________________
>> cfe-dev mailing list
>> [hidden email]
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
>
> _______________________________________________
> cfe-dev mailing list
> [hidden email]
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
In reply to this post by James Y Knight via cfe-dev
Looking at the ast-dump, I think I want to get a cursor to this node:

ClassTemplateSpecializationDecl 0x557ff8ef4e10 <line:16:1, line:25:1>
line:17:7 class RecursiveBase definition

The dump indicates it to be under:

ClassTemplateDecl 0x557ff8eed798 <line:16:1, line:25:1> line:17:7 RecursiveBase

But I can't see this ClassTemplateSpecializationDecl to be a child of
the CXCursor_ClassTemplate. Am I missing something here?

Does the CXCursor_ClassTemplate cursor corresponds to the
ClassTemplateSpecializationDecl in the AST dump?

Many thanks!

On Fri, Mar 17, 2017 at 2:16 AM, Nestal Wan <[hidden email]> wrote:

> Thanks, Adi! Do you mean that CXCursor_TypeRef is a child under the
> CXCursor_CXXBaseSpecifier?
>
> On Fri, Mar 17, 2017 at 1:10 AM, Jusufadis Bakamovic <[hidden email]> wrote:
>> Hi Nestal,
>>
>> I am not sure if I understood you correctly but you want to find out the
>> structure/hierarchy of your "Derived" class, that is all of the base classes
>> that your derived class is inheriting from? If this is what you are asking
>> for, then you can accomplish this by enumerating all of the
>> `CXCursor_TypeRef`'s of corresponding `CXCursor_CXXBaseSpecifier` cursors
>> which are descendants (children) of class declaration (`CXCursor_ClassDecl`)
>> which you're interested in (i.e. "Derived").
>>
>> When parser is run on your example, `CXCursor_CXXBaseSpecifier` cursors are
>> `RecursiveBase<class Base>`, `class Base2` and `class Base3`. Corresponding
>> `CXCursor_TypeRef` cursors are `class Base`, `class Base2` and `class
>> Base3`. This is what I believe you're looking for.
>>
>> For a generic and full-proof solution, you will want to do the same thing
>> recursively for each `CXCursor_CXXBaseSpecifier` found.
>>
>> Cheers,
>> Adi
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
In reply to this post by James Y Knight via cfe-dev
Well, at least for me it didn't really help, it did not do what I would
have expected it to do... i.e. return the specialized versions of the
template, "RecursiveBase<Base>" and more importantly it's base "Base" in
your example.


On 03/16/2017 07:16 PM, Nestal Wan wrote:

> Yes. I think clang_getSpecializedCursorTemplate() will definitely be
> useful for me. Thanks for the info.
>
> On Thu, Mar 16, 2017 at 2:02 AM, Michael via cfe-dev
> <[hidden email]> wrote:
>> This is an interesting question I was also wondering about the other day...
>> (sorry, if you were hoping for an answer;)
>>
>> The best thing I figured out was: get the type of template parameter
>> RecursiveBase<Base> (via clang_Type_getTemplateArgumentAsType), then go to
>> the referenced template RecursiveBase and do the parameter mapping myself.
>> Of course this will get more complicated if that again derives from a
>> template using that parameter...
>>
>> Running the example through "clang++ -Xclang -ast-dump -fsyntax-only .." I
>> see the needed ClassTemplateSpecializationDecls, also for further base
>> templates, carrying the proper specialized parameter types...
>>
>> I would have expected clang_getSpecializedCursorTemplate giving me these
>> specialized versions of the templates, but either I understand it wrong what
>> is supposed to do or it's implementation is incomplete here? Some insight on
>> this question would be appreciated.
>>
>> Thanks
>>
>> Michael
>>
>>
>>
>> On 03/14/2017 05:39 PM, Nestal Wan via cfe-dev wrote:
>>>
>>> Thanks Adi,
>>>
>>> Like you said, I solve the problem by fixing the errors that were
>>> indicated by the diagnostic messages.
>>>
>>> Now I have another question, if you don't mind I keep using this thread.
>>>
>>> I wish know the class hierarchy of "Derived". That means getting the
>>> base class the the instantiated RecursiveBase<Base> template. That
>>> should be "Base".
>>>
>>> When I visit "Dervied", I got a cursor to a CXCursor_CXXBaseSpecifier.
>>> I tried to get the type by:
>>>
>>> CXType recursive_base =
>>> clang_getCursorType(clang_getCursorDefinition(cxx_base_specifier));
>>>
>>> "recursive_base" refers to the RecursiveBase<Base> instantiation. How
>>> can I get the base type of this class? I know I can get the cursor to
>>> the template that instantiate it (i.e. template <typename BaseType>
>>> RecursiveBase), and I can see it inherits "BaseType" by visiting it
>>> and look for CXCursor_CXXBaseSpecifier. But how can I know "BaseType"
>>> will become "Base" when we instantiate it? Will the CXType provides me
>>> this linkage or I need to use LibTooling instead?
>>>
>>> Thanks again.
>>>
>>> Nestal
>>>
>>> On Sun, Mar 12, 2017 at 9:25 PM, Jusufadis Bakamovic <[hidden email]>
>>> wrote:
>>>>
>>>> It is hard to tell without more context why you're getting this error,
>>>> but
>>>> my guess is that you're missing some command line args (i.e. include
>>>> paths,
>>>> preprocessor flags, etc.) which is specific to the code you're analyzing
>>>> and
>>>> which is required in order to get the parsing stage done right. Very
>>>> often
>>>> this is the case and which is why you should, whenever you have doubts,
>>>> always try to come up with a small reproducible example (without
>>>> dependencies) and have it validated separately.
>>>>
>>>> Additionally, you can try to extract diagnostics for the given
>>>> translation
>>>> unit and see if you get any hints there. Normally, you should get hints
>>>> if
>>>> clang parser was not able to fully parse the source code because it was
>>>> missing some information such as failing to find particular headers.
>>>>
>>>> Cheers,
>>>> Adi
>>>>
>>>> On 12 March 2017 at 10:13, Nestal Wan <[hidden email]> wrote:
>>>>>
>>>>> Thanks for the reply.
>>>>>
>>>>> -CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid
>>>>> class
>>>>> Derived definition
>>>>>
>>>>> | |-public 'class Base2'
>>>>> | |-public 'class Base3'
>>>>> | |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit
>>>>> referenced
>>>>>
>>>>> class Derived
>>>>>
>>>>> | |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
>>>>> | |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2 Derived
>>>>> 'void
>>>>>
>>>>> (void)' noexcept-unevaluated 0x55e6db0f5ef0
>>>>>
>>>>> | `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void
>>>>> (void)'
>>>>> | `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>
>>>>>
>>>>>
>>>>> Sometimes I got "invalid class Derived definition", but if I extract the
>>>>> classes in another source file, the result is different:
>>>>>
>>>>> |-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class
>>>>> Derived
>>>>>
>>>>> definition
>>>>>
>>>>> | |-public 'RecursiveBase<class Base>':'class RecursiveBase<class Base>'
>>>>> | |-public 'class Base2'
>>>>> | |-public 'class Base3'
>>>>> | |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit
>>>>> referenced
>>>>>
>>>>> class Derived
>>>>>
>>>>> What does it mean the class definition is invalid? There is no compile
>>>>> error.
>>>>>
>>>>> Nestal
>>>>>
>>>>> On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic <[hidden email]>
>>>>> wrote:
>>>>>>
>>>>>> You should be getting three times the `CXCursor_CXXBaseSpecifier`, one
>>>>>> for
>>>>>> each class you're inheriting from. I ran the analysis on my machine
>>>>>> (clang
>>>>>> 3.8) and that is exactly what I am getting: `RecursiveBase<class
>>>>>> Base>`,
>>>>>> `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump
>>>>>> -fsyntax-only
>>>>>> <this_demo>` to see the output of Clang's built-in AST dumper. It
>>>>>> should
>>>>>> contain these entries. Otherwise, clang version you're running might be
>>>>>> an
>>>>>> older one.
>>>>>>
>>>>>> On 12 March 2017 at 05:09, Nestal Wan via cfe-dev
>>>>>> <[hidden email]>
>>>>>> wrote:
>>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> When I use clang_visitChildren() to visit a class, I can't get a
>>>>>>> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>>>>>>> template. For example:
>>>>>>>
>>>>>>> template <typename BaseType>
>>>>>>> class RecursiveBase : public BaseType
>>>>>>> {
>>>>>>> public:
>>>>>>>     virtual void SomeFunc()
>>>>>>>     {
>>>>>>>        // prevent optimizer to remove the function
>>>>>>>        global_var++;
>>>>>>>     }
>>>>>>> };
>>>>>>>
>>>>>>> class Derived : public RecursiveBase<Base>, public Base2, public Base3
>>>>>>> {
>>>>>>> public:
>>>>>>>     Derived() = default;
>>>>>>>
>>>>>>>     void Func() override {}
>>>>>>> };
>>>>>>>
>>>>>>> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>>>>>>> "Derived" cursor, but not RecursiveBase. How can I find out references
>>>>>>> to all base classes including templates?
>>>>>>>
>>>>>>> Thanks.
>>>>>>>
>>>>>>> Nestal
>>>>>>> _______________________________________________
>>>>>>> cfe-dev mailing list
>>>>>>> [hidden email]
>>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>>>>
>>>>>>
>>>>
>>> _______________________________________________
>>> cfe-dev mailing list
>>> [hidden email]
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>>
>>
>> _______________________________________________
>> cfe-dev mailing list
>> [hidden email]
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
Do you mean this?

| `-ClassTemplateSpecializationDecl 0x557ff8ef4e10 <line:16:1,
line:25:1> line:17:7 class RecursiveBase definition
|   |-public 'class Base':'class Base'
|   |-TemplateArgument type 'class Base'
|   |-CXXRecordDecl 0x557ff8ef5098 prev 0x557ff8ef4e10 <col:1, col:7>
col:7 implicit class RecursiveBase
|   |-AccessSpecDecl 0x557ff8ef5130 <line:19:1, col:7> col:1 public

I can see it from the AST dump, but not know how to get a cursor to it.


On Fri, Mar 17, 2017 at 3:01 AM, Michael <[hidden email]> wrote:

> Well, at least for me it didn't really help, it did not do what I would have
> expected it to do... i.e. return the specialized versions of the template,
> "RecursiveBase<Base>" and more importantly it's base "Base" in your example.
>
>
>
> On 03/16/2017 07:16 PM, Nestal Wan wrote:
>>
>> Yes. I think clang_getSpecializedCursorTemplate() will definitely be
>> useful for me. Thanks for the info.
>>
>> On Thu, Mar 16, 2017 at 2:02 AM, Michael via cfe-dev
>> <[hidden email]> wrote:
>>>
>>> This is an interesting question I was also wondering about the other
>>> day...
>>> (sorry, if you were hoping for an answer;)
>>>
>>> The best thing I figured out was: get the type of template parameter
>>> RecursiveBase<Base> (via clang_Type_getTemplateArgumentAsType), then go
>>> to
>>> the referenced template RecursiveBase and do the parameter mapping
>>> myself.
>>> Of course this will get more complicated if that again derives from a
>>> template using that parameter...
>>>
>>> Running the example through "clang++ -Xclang -ast-dump -fsyntax-only .."
>>> I
>>> see the needed ClassTemplateSpecializationDecls, also for further base
>>> templates, carrying the proper specialized parameter types...
>>>
>>> I would have expected clang_getSpecializedCursorTemplate giving me these
>>> specialized versions of the templates, but either I understand it wrong
>>> what
>>> is supposed to do or it's implementation is incomplete here? Some insight
>>> on
>>> this question would be appreciated.
>>>
>>> Thanks
>>>
>>> Michael
>>>
>>>
>>>
>>> On 03/14/2017 05:39 PM, Nestal Wan via cfe-dev wrote:
>>>>
>>>>
>>>> Thanks Adi,
>>>>
>>>> Like you said, I solve the problem by fixing the errors that were
>>>> indicated by the diagnostic messages.
>>>>
>>>> Now I have another question, if you don't mind I keep using this thread.
>>>>
>>>> I wish know the class hierarchy of "Derived". That means getting the
>>>> base class the the instantiated RecursiveBase<Base> template. That
>>>> should be "Base".
>>>>
>>>> When I visit "Dervied", I got a cursor to a CXCursor_CXXBaseSpecifier.
>>>> I tried to get the type by:
>>>>
>>>> CXType recursive_base =
>>>> clang_getCursorType(clang_getCursorDefinition(cxx_base_specifier));
>>>>
>>>> "recursive_base" refers to the RecursiveBase<Base> instantiation. How
>>>> can I get the base type of this class? I know I can get the cursor to
>>>> the template that instantiate it (i.e. template <typename BaseType>
>>>> RecursiveBase), and I can see it inherits "BaseType" by visiting it
>>>> and look for CXCursor_CXXBaseSpecifier. But how can I know "BaseType"
>>>> will become "Base" when we instantiate it? Will the CXType provides me
>>>> this linkage or I need to use LibTooling instead?
>>>>
>>>> Thanks again.
>>>>
>>>> Nestal
>>>>
>>>> On Sun, Mar 12, 2017 at 9:25 PM, Jusufadis Bakamovic <[hidden email]>
>>>> wrote:
>>>>>
>>>>>
>>>>> It is hard to tell without more context why you're getting this error,
>>>>> but
>>>>> my guess is that you're missing some command line args (i.e. include
>>>>> paths,
>>>>> preprocessor flags, etc.) which is specific to the code you're
>>>>> analyzing
>>>>> and
>>>>> which is required in order to get the parsing stage done right. Very
>>>>> often
>>>>> this is the case and which is why you should, whenever you have doubts,
>>>>> always try to come up with a small reproducible example (without
>>>>> dependencies) and have it validated separately.
>>>>>
>>>>> Additionally, you can try to extract diagnostics for the given
>>>>> translation
>>>>> unit and see if you get any hints there. Normally, you should get hints
>>>>> if
>>>>> clang parser was not able to fully parse the source code because it was
>>>>> missing some information such as failing to find particular headers.
>>>>>
>>>>> Cheers,
>>>>> Adi
>>>>>
>>>>> On 12 March 2017 at 10:13, Nestal Wan <[hidden email]> wrote:
>>>>>>
>>>>>>
>>>>>> Thanks for the reply.
>>>>>>
>>>>>> -CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid
>>>>>> class
>>>>>> Derived definition
>>>>>>
>>>>>> | |-public 'class Base2'
>>>>>> | |-public 'class Base3'
>>>>>> | |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit
>>>>>> referenced
>>>>>>
>>>>>> class Derived
>>>>>>
>>>>>> | |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
>>>>>> | |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2
>>>>>> Derived
>>>>>> 'void
>>>>>>
>>>>>> (void)' noexcept-unevaluated 0x55e6db0f5ef0
>>>>>>
>>>>>> | `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void
>>>>>> (void)'
>>>>>> | `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>
>>>>>>
>>>>>>
>>>>>> Sometimes I got "invalid class Derived definition", but if I extract
>>>>>> the
>>>>>> classes in another source file, the result is different:
>>>>>>
>>>>>> |-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class
>>>>>> Derived
>>>>>>
>>>>>> definition
>>>>>>
>>>>>> | |-public 'RecursiveBase<class Base>':'class RecursiveBase<class
>>>>>> Base>'
>>>>>> | |-public 'class Base2'
>>>>>> | |-public 'class Base3'
>>>>>> | |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit
>>>>>> referenced
>>>>>>
>>>>>> class Derived
>>>>>>
>>>>>> What does it mean the class definition is invalid? There is no compile
>>>>>> error.
>>>>>>
>>>>>> Nestal
>>>>>>
>>>>>> On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic
>>>>>> <[hidden email]>
>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>> You should be getting three times the `CXCursor_CXXBaseSpecifier`,
>>>>>>> one
>>>>>>> for
>>>>>>> each class you're inheriting from. I ran the analysis on my machine
>>>>>>> (clang
>>>>>>> 3.8) and that is exactly what I am getting: `RecursiveBase<class
>>>>>>> Base>`,
>>>>>>> `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump
>>>>>>> -fsyntax-only
>>>>>>> <this_demo>` to see the output of Clang's built-in AST dumper. It
>>>>>>> should
>>>>>>> contain these entries. Otherwise, clang version you're running might
>>>>>>> be
>>>>>>> an
>>>>>>> older one.
>>>>>>>
>>>>>>> On 12 March 2017 at 05:09, Nestal Wan via cfe-dev
>>>>>>> <[hidden email]>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> When I use clang_visitChildren() to visit a class, I can't get a
>>>>>>>> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>>>>>>>> template. For example:
>>>>>>>>
>>>>>>>> template <typename BaseType>
>>>>>>>> class RecursiveBase : public BaseType
>>>>>>>> {
>>>>>>>> public:
>>>>>>>>     virtual void SomeFunc()
>>>>>>>>     {
>>>>>>>>        // prevent optimizer to remove the function
>>>>>>>>        global_var++;
>>>>>>>>     }
>>>>>>>> };
>>>>>>>>
>>>>>>>> class Derived : public RecursiveBase<Base>, public Base2, public
>>>>>>>> Base3
>>>>>>>> {
>>>>>>>> public:
>>>>>>>>     Derived() = default;
>>>>>>>>
>>>>>>>>     void Func() override {}
>>>>>>>> };
>>>>>>>>
>>>>>>>> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>>>>>>>> "Derived" cursor, but not RecursiveBase. How can I find out
>>>>>>>> references
>>>>>>>> to all base classes including templates?
>>>>>>>>
>>>>>>>> Thanks.
>>>>>>>>
>>>>>>>> Nestal
>>>>>>>> _______________________________________________
>>>>>>>> cfe-dev mailing list
>>>>>>>> [hidden email]
>>>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>> _______________________________________________
>>>> cfe-dev mailing list
>>>> [hidden email]
>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> cfe-dev mailing list
>>> [hidden email]
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
On Fri, Mar 17, 2017 at 2:16 AM, Nestal Wan <[hidden email]> wrote:
> Thanks, Adi! Do you mean that CXCursor_TypeRef is a child under the
> CXCursor_CXXBaseSpecifier?

Yes, that's right. `CXCursor_TypeRef` is going to be a child of `CXCursor_CXXBaseSpecifier` cursor.

But I would advise you to make yourself a big favor and write a simple AST traversal function which dumps _all_ the information you can extract from cursors. Clang built-in AST dump is a good one but does not contain every bit of information which might be quite important while you're debugging or developing a new specific use-case which, for example, is not covered by libclang API. Given you have such debugging tool you would immediately see that `CXCursor_TypeRef`s are descendants of `CXCursor_CXXBaseSpecifier` cursors as well as many other similar details for other use-cases.

I've developed such debugging tool for myself and you can have a look at it to get some inspiration:

On Fri, Mar 17, 2017 at 3:01 AM, Michael <[hidden email]> wrote:
> Well, at least for me it didn't really help, it did not do what I would have
> expected it to do... i.e. return the specialized versions of the template,
> "RecursiveBase<Base>" and more importantly it's base "Base" in your example.

How come? This is the AST representation of that piece of code (reads as CursorKind : CursorSpelling):

|-`CXCursor_ClassDecl`: 'Derived'
|    |-`CXCursor_CXXBaseSpecifier`: 'RecursiveBase<class Base>'
|        |-`CXCursor_TemplateRef`: 'RecursiveBase'
|        |-`CXCursor_TypeRef`: 'class Base'
|    |-`CXCursor_CXXBaseSpecifier`: 'class Base2'
|       |-`CXCursor_TypeRef`: 'class Base2'
|    |-`CXCursor_CXXBaseSpecifier`: 'class Base3'
|        |-`CXCursor_TypeRef`: 'class Base3'

Cheers,
Adi

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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev

On 16 Mar 2017, at 21:05, Jusufadis Bakamovic <[hidden email]> wrote:

How come? This is the AST representation of that piece of code (reads as CursorKind : CursorSpelling)

Well, yes, and no. In this particular case you can do the mapping. One could also use clang_Type_getTemplateArgumentAsType. But you loose this relation if you go a bit further, like: 

template <typename BaseType>
class BaseTemplate : public BaseType
{
 void bar(BaseType arg1);
}

template <typename BaseType>
class RecursiveBase : public BaseTemplate<BaseType>
{
 void foo(BaseType arg2);
}

You also want to know that the specialised parameter of “BaseTemplate" is “Base”
And you also want to know that arg1 and arg2 of the specialised “RecursiveBase” are of type “Base”
The methods are only accessible through the referenced raw template (ClassTemplate?), where you only have the raw template parameters.
It’s still possible to figure out the types in this case, yes, but it gets more and more cumbersome in the more general cases.

With a cursor directly at the specialised version of the template everything would already be resolved, readily usable. As you can see when dumping the tree with commandline clang. It seems just that libclang does not expose that information.

I was able to get this information with clang_getSpecializedCursorTemplate for partially specialised templates. But not for any other kind of specialisation. In those cases the function returns just a null cursor.

I might be missing something, though...

Michael


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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
In reply to this post by James Y Knight via cfe-dev
Hmm, I don’t have my code atm. to compare, but yes, I think this is what I mean.


> On 16 Mar 2017, at 20:07, Nestal Wan <[hidden email]> wrote:
>
> Do you mean this?
>
> | `-ClassTemplateSpecializationDecl 0x557ff8ef4e10 <line:16:1,
> line:25:1> line:17:7 class RecursiveBase definition
> |   |-public 'class Base':'class Base'
> |   |-TemplateArgument type 'class Base'
> |   |-CXXRecordDecl 0x557ff8ef5098 prev 0x557ff8ef4e10 <col:1, col:7>
> col:7 implicit class RecursiveBase
> |   |-AccessSpecDecl 0x557ff8ef5130 <line:19:1, col:7> col:1 public
>
> I can see it from the AST dump, but not know how to get a cursor to it.
>
>
> On Fri, Mar 17, 2017 at 3:01 AM, Michael <[hidden email]> wrote:
>> Well, at least for me it didn't really help, it did not do what I would have
>> expected it to do... i.e. return the specialized versions of the template,
>> "RecursiveBase<Base>" and more importantly it's base "Base" in your example.
>>
>>
>>
>> On 03/16/2017 07:16 PM, Nestal Wan wrote:
>>>
>>> Yes. I think clang_getSpecializedCursorTemplate() will definitely be
>>> useful for me. Thanks for the info.
>>>
>>> On Thu, Mar 16, 2017 at 2:02 AM, Michael via cfe-dev
>>> <[hidden email]> wrote:
>>>>
>>>> This is an interesting question I was also wondering about the other
>>>> day...
>>>> (sorry, if you were hoping for an answer;)
>>>>
>>>> The best thing I figured out was: get the type of template parameter
>>>> RecursiveBase<Base> (via clang_Type_getTemplateArgumentAsType), then go
>>>> to
>>>> the referenced template RecursiveBase and do the parameter mapping
>>>> myself.
>>>> Of course this will get more complicated if that again derives from a
>>>> template using that parameter...
>>>>
>>>> Running the example through "clang++ -Xclang -ast-dump -fsyntax-only .."
>>>> I
>>>> see the needed ClassTemplateSpecializationDecls, also for further base
>>>> templates, carrying the proper specialized parameter types...
>>>>
>>>> I would have expected clang_getSpecializedCursorTemplate giving me these
>>>> specialized versions of the templates, but either I understand it wrong
>>>> what
>>>> is supposed to do or it's implementation is incomplete here? Some insight
>>>> on
>>>> this question would be appreciated.
>>>>
>>>> Thanks
>>>>
>>>> Michael
>>>>
>>>>
>>>>
>>>> On 03/14/2017 05:39 PM, Nestal Wan via cfe-dev wrote:
>>>>>
>>>>>
>>>>> Thanks Adi,
>>>>>
>>>>> Like you said, I solve the problem by fixing the errors that were
>>>>> indicated by the diagnostic messages.
>>>>>
>>>>> Now I have another question, if you don't mind I keep using this thread.
>>>>>
>>>>> I wish know the class hierarchy of "Derived". That means getting the
>>>>> base class the the instantiated RecursiveBase<Base> template. That
>>>>> should be "Base".
>>>>>
>>>>> When I visit "Dervied", I got a cursor to a CXCursor_CXXBaseSpecifier.
>>>>> I tried to get the type by:
>>>>>
>>>>> CXType recursive_base =
>>>>> clang_getCursorType(clang_getCursorDefinition(cxx_base_specifier));
>>>>>
>>>>> "recursive_base" refers to the RecursiveBase<Base> instantiation. How
>>>>> can I get the base type of this class? I know I can get the cursor to
>>>>> the template that instantiate it (i.e. template <typename BaseType>
>>>>> RecursiveBase), and I can see it inherits "BaseType" by visiting it
>>>>> and look for CXCursor_CXXBaseSpecifier. But how can I know "BaseType"
>>>>> will become "Base" when we instantiate it? Will the CXType provides me
>>>>> this linkage or I need to use LibTooling instead?
>>>>>
>>>>> Thanks again.
>>>>>
>>>>> Nestal
>>>>>
>>>>> On Sun, Mar 12, 2017 at 9:25 PM, Jusufadis Bakamovic <[hidden email]>
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>> It is hard to tell without more context why you're getting this error,
>>>>>> but
>>>>>> my guess is that you're missing some command line args (i.e. include
>>>>>> paths,
>>>>>> preprocessor flags, etc.) which is specific to the code you're
>>>>>> analyzing
>>>>>> and
>>>>>> which is required in order to get the parsing stage done right. Very
>>>>>> often
>>>>>> this is the case and which is why you should, whenever you have doubts,
>>>>>> always try to come up with a small reproducible example (without
>>>>>> dependencies) and have it validated separately.
>>>>>>
>>>>>> Additionally, you can try to extract diagnostics for the given
>>>>>> translation
>>>>>> unit and see if you get any hints there. Normally, you should get hints
>>>>>> if
>>>>>> clang parser was not able to fully parse the source code because it was
>>>>>> missing some information such as failing to find particular headers.
>>>>>>
>>>>>> Cheers,
>>>>>> Adi
>>>>>>
>>>>>> On 12 March 2017 at 10:13, Nestal Wan <[hidden email]> wrote:
>>>>>>>
>>>>>>>
>>>>>>> Thanks for the reply.
>>>>>>>
>>>>>>> -CXXRecordDecl 0x55e6db0f5ad8 <line:53:1, line:59:1> line:53:7 invalid
>>>>>>> class
>>>>>>> Derived definition
>>>>>>>
>>>>>>> | |-public 'class Base2'
>>>>>>> | |-public 'class Base3'
>>>>>>> | |-CXXRecordDecl 0x55e6db0f5df8 <col:1, col:7> col:7 implicit
>>>>>>> referenced
>>>>>>>
>>>>>>> class Derived
>>>>>>>
>>>>>>> | |-AccessSpecDecl 0x55e6db0f5e88 <line:55:1, col:7> col:1 public
>>>>>>> | |-CXXConstructorDecl 0x55e6db0f5ef0 <line:56:2, col:20> col:2
>>>>>>> Derived
>>>>>>> 'void
>>>>>>>
>>>>>>> (void)' noexcept-unevaluated 0x55e6db0f5ef0
>>>>>>>
>>>>>>> | `-CXXMethodDecl 0x55e6db0f5fd0 <line:58:2, col:24> col:7 Func 'void
>>>>>>> (void)'
>>>>>>> | `-CompoundStmt 0x55e6db0f6118 <col:23, col:24>
>>>>>>>
>>>>>>>
>>>>>>> Sometimes I got "invalid class Derived definition", but if I extract
>>>>>>> the
>>>>>>> classes in another source file, the result is different:
>>>>>>>
>>>>>>> |-CXXRecordDecl 0x55ccfcb583b0 <line:33:1, line:39:1> line:33:7 class
>>>>>>> Derived
>>>>>>>
>>>>>>> definition
>>>>>>>
>>>>>>> | |-public 'RecursiveBase<class Base>':'class RecursiveBase<class
>>>>>>> Base>'
>>>>>>> | |-public 'class Base2'
>>>>>>> | |-public 'class Base3'
>>>>>>> | |-CXXRecordDecl 0x55ccfcb58c70 <col:1, col:7> col:7 implicit
>>>>>>> referenced
>>>>>>>
>>>>>>> class Derived
>>>>>>>
>>>>>>> What does it mean the class definition is invalid? There is no compile
>>>>>>> error.
>>>>>>>
>>>>>>> Nestal
>>>>>>>
>>>>>>> On Sun, Mar 12, 2017 at 4:46 PM, Jusufadis Bakamovic
>>>>>>> <[hidden email]>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> You should be getting three times the `CXCursor_CXXBaseSpecifier`,
>>>>>>>> one
>>>>>>>> for
>>>>>>>> each class you're inheriting from. I ran the analysis on my machine
>>>>>>>> (clang
>>>>>>>> 3.8) and that is exactly what I am getting: `RecursiveBase<class
>>>>>>>> Base>`,
>>>>>>>> `Base2`, `Base3`. Maybe you could use `clang -Xclang -ast-dump
>>>>>>>> -fsyntax-only
>>>>>>>> <this_demo>` to see the output of Clang's built-in AST dumper. It
>>>>>>>> should
>>>>>>>> contain these entries. Otherwise, clang version you're running might
>>>>>>>> be
>>>>>>>> an
>>>>>>>> older one.
>>>>>>>>
>>>>>>>> On 12 March 2017 at 05:09, Nestal Wan via cfe-dev
>>>>>>>> <[hidden email]>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> When I use clang_visitChildren() to visit a class, I can't get a
>>>>>>>>> CXCursor_CXXBaseSpecifier for its base class if the base class is a
>>>>>>>>> template. For example:
>>>>>>>>>
>>>>>>>>> template <typename BaseType>
>>>>>>>>> class RecursiveBase : public BaseType
>>>>>>>>> {
>>>>>>>>> public:
>>>>>>>>>    virtual void SomeFunc()
>>>>>>>>>    {
>>>>>>>>>       // prevent optimizer to remove the function
>>>>>>>>>       global_var++;
>>>>>>>>>    }
>>>>>>>>> };
>>>>>>>>>
>>>>>>>>> class Derived : public RecursiveBase<Base>, public Base2, public
>>>>>>>>> Base3
>>>>>>>>> {
>>>>>>>>> public:
>>>>>>>>>    Derived() = default;
>>>>>>>>>
>>>>>>>>>    void Func() override {}
>>>>>>>>> };
>>>>>>>>>
>>>>>>>>> I can get a CXCursor_CXXBaseSpecifier cursor as children of the
>>>>>>>>> "Derived" cursor, but not RecursiveBase. How can I find out
>>>>>>>>> references
>>>>>>>>> to all base classes including templates?
>>>>>>>>>
>>>>>>>>> Thanks.
>>>>>>>>>
>>>>>>>>> Nestal
>>>>>>>>> _______________________________________________
>>>>>>>>> cfe-dev mailing list
>>>>>>>>> [hidden email]
>>>>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>> _______________________________________________
>>>>> cfe-dev mailing list
>>>>> [hidden email]
>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>>
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> cfe-dev mailing list
>>>> [hidden email]
>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>>

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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
In reply to this post by James Y Knight via cfe-dev

On 16 March 2017 at 22:14, Michael <[hidden email]> wrote:
template <typename BaseType>
class BaseTemplate : public BaseType
{
 void bar(BaseType arg1);
}

template <typename BaseType>
class RecursiveBase : public BaseTemplate<BaseType>
{
 void foo(BaseType arg2);
}

I am not sure if I understood you correctly but:
 
You also want to know that the specialised parameter of “BaseTemplate" is “Base”

Sure, you can get this information once you _instantiate_ a class from your class template. I.e.
    class Base {};
    class Derived : public RecursiveBase<Base> {};

Traversing the AST and getting to the 'CXCursor_TypeRef's of 'Derived' will get you this information.
 
And you also want to know that arg1 and arg2 of the specialised “RecursiveBase” are of type “Base”

If you have the information that 'Derived' is built with 'Base', which you do have, then you should be able to match this information against 'foo()'/'bar()' and corresponding arguments. I.e. if we have the following:

    void fun() {
        Derived d;
        d.foo(Base());
    }

Then AST dump for 'd.foo(Base())' line would look something like this:

|-`CXCursor_UnexposedExpr`: ''
|    |-`CXCursor_CallExpr`: 'foo'
|        |-`CXCursor_MemberRefExpr`: 'foo'
|            |-`CXCursor_UnexposedExpr`: 'd'
|                |-`CXCursor_DeclRefExpr`: 'd'
|        |-`CXCursor_CallExpr`: ''
|            |-`CXCursor_UnexposedExpr`: ''
|                |-`CXCursor_CallExpr`: 'Base'

If we wanted to find out more information about 'foo' we would do the follow-up on 'CXCursor_MemberRefExpr' : 'foo' node by using a 'clang_getCursorReferenced()' and dumping the information we get from resulting node. You will find out that type spelling of referenced (resulting) node will be set to 'void (Base)', and not to 'void (BaseType)' as it was for a 'RecursiveBase' template class. I am not sure but there might be a libclang API from this point on wards to get the number of arguments and their types.

The methods are only accessible through the referenced raw template (ClassTemplate?), where you only have the raw template parameters.
It’s still possible to figure out the types in this case, yes, but it gets more and more cumbersome in the more general cases.

With a cursor directly at the specialised version of the template everything would already be resolved, readily usable. As you can see when dumping the tree with commandline clang. It seems just that libclang does not expose that information.

Not every use-case is covered and exposed via libclang API. There are situations where you will have to handle your specific use-cases manually with your code (as shown above). If shown that these use-cases might be relevant for general purpose then you might go ahead and issue a patch to libclang API.

Cheers,
Adi

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

Re: CXCursor_CXXBaseSpecifier for template instantiated base class

James Y Knight via cfe-dev
On 03/17/2017 10:55 AM, Jusufadis Bakamovic wrote:

>
> I am not sure if I understood you correctly but:
>
>
>     You also want to know that the specialised parameter of
>     “BaseTemplate" is “Base”
>
>
> Sure, you can get this information once you _instantiate_ a class from
> your class template. I.e.
>     class Base {};
>     class Derived : public RecursiveBase<Base> {};
>
> Traversing the AST and getting to the 'CXCursor_TypeRef's of 'Derived'
> will get you this information.
>
>
>     And you also want to know that arg1 and arg2 of the specialised
>     “RecursiveBase” are of type “Base”
>
>
> If you have the information that 'Derived' is built with 'Base', which
> you do have, then you should be able to match this information against
> 'foo()'/'bar()' and corresponding arguments.

Plus you have to take the detour via the ClassTemplates to find out
which and where template parameters are used and passed on to possible
base templates... So yes, this is basically what I said. It's possible
to match things manually. But it gets cumbersome in the general case, if
you have deeper hierarchies, more parameters.
(While the needed information is actually already available in clang as
ClassTemplateSpecializationDecl, just not exposed by libclang.)

> Not every use-case is covered and exposed via libclang API. There are
> situations where you will have to handle your specific use-cases
> manually with your code (as shown above). If shown that these use-cases
> might be relevant for general purpose then you might go ahead and issue
> a patch to libclang API.

Right, I might actually do that. I just wanted to figure out first
whether I'm maybe just missing something.


Thanks

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