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.

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.


Hi Gregory,

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

Hope this helps!