What code generates default constructors?

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

What code generates default constructors?

David Blaikie via cfe-dev
Hello --

I'm trying to understand how ASTs for constructors are generated when they are referenced. In particular, I'm working on a libtooling tool that will dump the AST to another format on a per-file basis so I need to know the code for any constructors even if they are not called in the file.

Very concretely, if I write the following code:

class P {};
int main() {
   P x;
   return 0;
}

the result of -ast-dump will contain the implementation of the default constructor (not very interesting in this case). What code generates this?

Thank you.

--
gregory malecha

_______________________________________________
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: What code generates default constructors?

David Blaikie via cfe-dev
I am not sure I understand the question, but in general one way I found to be
useful to know what piece of code creates which AST node is to grep for
eg: StringLiteral::Create, or StringLiteral and new. In this case what you are
looking for is CXXConstructorDecl::Create, which gives a few matches.

In particular Sema::DeclareImplicitDefaultConstructor seems to be what you want.
The other matches in SemaDeclCXX are for the other implicitely declared constructors.

Bruno

On 22/01/2019 11:48, Gregory Malecha via cfe-dev wrote:

> Hello --
>
> I'm trying to understand how ASTs for constructors are generated when they are referenced. In particular, I'm working on a libtooling tool that will dump the AST to another format on a per-file basis so I need to know the code for any constructors even if they are not called in the file.
>
> Very concretely, if I write the following code:
>
> class P {};
> int main() {
>    P x;
>    return 0;
> }
>
> the result of -ast-dump will contain the implementation of the default constructor (not very interesting in this case). What code generates this?
>
> Thank you.
>
> --
> gregory malecha
> gmalecha.github.io <https://gmalecha.github.io>
>
> _______________________________________________
> 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: What code generates default constructors?

David Blaikie via cfe-dev
I tend to use a debugger to help with these sort of things too - create an example that involves invoking a default ctor, break in CXXConstructorDecl's ctor, and run the program to see where that's invoked from.

On Tue, Jan 22, 2019 at 5:17 AM Bruno Ricci via cfe-dev <[hidden email]> wrote:
I am not sure I understand the question, but in general one way I found to be
useful to know what piece of code creates which AST node is to grep for
eg: StringLiteral::Create, or StringLiteral and new. In this case what you are
looking for is CXXConstructorDecl::Create, which gives a few matches.

In particular Sema::DeclareImplicitDefaultConstructor seems to be what you want.
The other matches in SemaDeclCXX are for the other implicitely declared constructors.

Bruno

On 22/01/2019 11:48, Gregory Malecha via cfe-dev wrote:
> Hello --
>
> I'm trying to understand how ASTs for constructors are generated when they are referenced. In particular, I'm working on a libtooling tool that will dump the AST to another format on a per-file basis so I need to know the code for any constructors even if they are not called in the file.
>
> Very concretely, if I write the following code:
>
> class P {};
> int main() {
>    P x;
>    return 0;
> }
>
> the result of -ast-dump will contain the implementation of the default constructor (not very interesting in this case). What code generates this?
>
> Thank you.
>
> --
> gregory malecha
> gmalecha.github.io <https://gmalecha.github.io>
>
> _______________________________________________
> 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: What code generates default constructors?

David Blaikie via cfe-dev
In reply to this post by David Blaikie via cfe-dev
Hi Gregory,

I am not familiar with libtooling but if you use Clang driver I don't think that the implicit constructors are actually generated in the AST.

As far as I am aware Clang generates all declarations of special members lazily (ctors are added in Sema::LookupConstructors() for example). It seems however the definitions are generated only for the ones that are actually used during the CodeGen phase.  Clang memorizes special members by putting them in DeferredDeclsToEmit of CodeGenModule::GetOrCreateLLVMFunction() when it encounters their uses. At the end of the module generation CodeGenModule::EmitDeferred() will be called to emit definitions of implicit special members in IR.

The AST dump of your example will look like this:

|-CXXRecordDecl 0x20c7c48 <test.cpp:1:1, col:10> col:7 referenced class P definition
| |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| | |-DefaultConstructor exists trivial constexpr defaulted_is_constexpr
| | |-CopyConstructor simple trivial has_const_param implicit_has_const_param
| | |-MoveConstructor exists simple trivial
| | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial needs_implicit
| |-CXXRecordDecl 0x20c7d58 <col:1, col:7> col:7 implicit class P
| |-CXXConstructorDecl 0x20c7fe0 <col:7> col:7 implicit used constexpr P 'void () noexcept' inline default trivial
| | `-CompoundStmt 0x20c8448 <col:7>
| |-CXXConstructorDecl 0x20c8108 <col:7> col:7 implicit constexpr P 'void (const P &)' inline default trivial noexcept-unevaluated 0x20c8108
| | `-ParmVarDecl 0x20c8218 <col:7> col:7 'const P &'
| `-CXXConstructorDecl 0x20c82a8 <col:7> col:7 implicit constexpr P 'void (P &&)' inline default trivial noexcept-unevaluated 0x20c82a8
|   `-ParmVarDecl 0x20c83b8 <col:7> col:7 'P &&'
`-FunctionDecl 0x20c7e50 <line:2:1, line:5:1> line:2:5 main 'int ()'
  `-CompoundStmt 0x20c84c8 <col:12, line:5:1>
    |-DeclStmt 0x20c8480 <line:3:4, col:7>
    | `-VarDecl 0x20c7f68 <col:4, col:6> col:6 x 'P' callinit
    |   `-CXXConstructExpr 0x20c8458 <col:6> 'P' 'void () noexcept'
    `-ReturnStmt 0x20c84b8 <line:4:4, col:11>
      `-IntegerLiteral 0x20c8498 <col:11> 'int'

As you can see that only declarations of the implicit special members appear in AST.

Cheers,
Anastasia


From: cfe-dev <[hidden email]> on behalf of Gregory Malecha via cfe-dev <[hidden email]>
Sent: 22 January 2019 11:48
To: [hidden email]
Subject: [cfe-dev] What code generates default constructors?
 
Hello --

I'm trying to understand how ASTs for constructors are generated when they are referenced. In particular, I'm working on a libtooling tool that will dump the AST to another format on a per-file basis so I need to know the code for any constructors even if they are not called in the file.

Very concretely, if I write the following code:

class P {};
int main() {
   P x;
   return 0;
}

the result of -ast-dump will contain the implementation of the default constructor (not very interesting in this case). What code generates this?

Thank you.

--
gregory malecha

_______________________________________________
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: What code generates default constructors?

David Blaikie via cfe-dev
Hi Gregory,

These Sema methods might also be of interest:
Sema::DeclareImplicitDefaultConstructor
Sema::DeclareImplicitCopyAssignment
Sema::DeclareImplicitCopyConstructor
(+ Move versions)

Hope this helps!

Jan

On Jan 23, 2019, at 6:30 AM, Anastasia Stulova via cfe-dev <[hidden email]> wrote:

Hi Gregory,

I am not familiar with libtooling but if you use Clang driver I don't think that the implicit constructors are actually generated in the AST.

As far as I am aware Clang generates all declarations of special members lazily (ctors are added in Sema::LookupConstructors() for example). It seems however the definitions are generated only for the ones that are actually used during the CodeGen phase.  Clang memorizes special members by putting them inDeferredDeclsToEmit of CodeGenModule::GetOrCreateLLVMFunction() when it encounters their uses. At the end of the module generation CodeGenModule::EmitDeferred() will be called to emit definitions of implicit special members in IR.

The AST dump of your example will look like this:

|-CXXRecordDecl 0x20c7c48 <test.cpp:1:1, col:10> col:7 referenced class P definition
| |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| | |-DefaultConstructor exists trivial constexpr defaulted_is_constexpr
| | |-CopyConstructor simple trivial has_const_param implicit_has_const_param
| | |-MoveConstructor exists simple trivial
| | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
| | |-MoveAssignment exists simple trivial needs_implicit
| | `-Destructor simple irrelevant trivial needs_implicit
| |-CXXRecordDecl 0x20c7d58 <col:1, col:7> col:7 implicit class P
| |-CXXConstructorDecl 0x20c7fe0 <col:7> col:7 implicit used constexpr P 'void () noexcept' inline default trivial
| | `-CompoundStmt 0x20c8448 <col:7>
| |-CXXConstructorDecl 0x20c8108 <col:7> col:7 implicit constexpr P 'void (const P &)' inline default trivial noexcept-unevaluated 0x20c8108
| | `-ParmVarDecl 0x20c8218 <col:7> col:7 'const P &'
| `-CXXConstructorDecl 0x20c82a8 <col:7> col:7 implicit constexpr P 'void (P &&)' inline default trivial noexcept-unevaluated 0x20c82a8
|   `-ParmVarDecl 0x20c83b8 <col:7> col:7 'P &&'
`-FunctionDecl 0x20c7e50 <line:2:1, line:5:1> line:2:5 main 'int ()'
  `-CompoundStmt 0x20c84c8 <col:12, line:5:1>
    |-DeclStmt 0x20c8480 <line:3:4, col:7>
    | `-VarDecl 0x20c7f68 <col:4, col:6> col:6 x 'P' callinit
    |   `-CXXConstructExpr 0x20c8458 <col:6> 'P' 'void () noexcept'
    `-ReturnStmt 0x20c84b8 <line:4:4, col:11>
      `-IntegerLiteral 0x20c8498 <col:11> 'int' 

As you can see that only declarations of the implicit special members appear in AST.

Cheers,
Anastasia


From: cfe-dev <[hidden email]> on behalf of Gregory Malecha via cfe-dev <[hidden email]>
Sent: 22 January 2019 11:48
To: [hidden email]
Subject: [cfe-dev] What code generates default constructors?
 
Hello --

I'm trying to understand how ASTs for constructors are generated when they are referenced. In particular, I'm working on a libtooling tool that will dump the AST to another format on a per-file basis so I need to know the code for any constructors even if they are not called in the file.

Very concretely, if I write the following code:

class P {};
int main() {
   P x;
   return 0;
}

the result of -ast-dump will contain the implementation of the default constructor (not very interesting in this case). What code generates this?

Thank you.

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


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