Using the Sema Object to Generate Implicit Definitions

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

Using the Sema Object to Generate Implicit Definitions

Manas via cfe-dev
Hello --

I've been trying to use the Sema object to generate implicit definitions, e.g. default constructors, destructors, etc, in a tool that I have but I'm running into some issues. The code that I have is a DeclVisitor with the following for the CXXRecord case.

void VisitCXXRecordDecl(CXXRecordDecl *decl, bool is_specialization) {
  if (not(decl->isImplicit() or decl->isAnonymousStructOrUnion())) {
    ci_->getSema().ForceDeclarationOfImplicitMembers(decl);
  } 
  // ...
}

This works great, and always works to get me constructor definitions with empty bodies but marked as default.

To generate the bodies, I have (roughly) the following code for constructors, destructors, and methods:

if (not decl->getBody() && decl->isDefaulted()) {
  if (decl->isMoveAssignmentOperator()) {
    ci_->getSema().DefineImplicitMoveAssignment(decl->getLocation(), decl);
  } else if (decl->isCopyAssignmentOperator()) {
    ci_->getSema().DefineImplicitCopyAssignment(decl->getLocation(), decl);
  }
}

In most cases, this seems to do the trick, but when the implementation of the operator uses something like memcpy I get a segfault (stack trace below) due (it seems) to the fact that TUScope is null when my code runs.
#0  0x00007ffff5ff733a in clang::Sema::PushOnScopeChains(clang::NamedDecl*, clang::Scope*, bool) () from /usr/lib/libclang-cpp.so.10
#1  0x00007ffff601dc18 in clang::Sema::LazilyCreateBuiltin(clang::IdentifierInfo*, unsigned int, clang::Scope*, bool, clang::SourceLocation) () from /usr/lib/libclang-cpp.so.10
#2  0x00007ffff63599ac in clang::Sema::LookupBuiltin(clang::LookupResult&) () from /usr/lib/libclang-cpp.so.10
#3  0x00007ffff636e713 in clang::Sema::LookupName(clang::LookupResult&, clang::Scope*, bool) () from /usr/lib/libclang-cpp.so.10
#4  0x00007ffff61512e4 in ?? () from /usr/lib/libclang-cpp.so.10
#5  0x00007ffff6151643 in ?? () from /usr/lib/libclang-cpp.so.10
#6  0x00007ffff6159481 in clang::Sema::DefineImplicitCopyAssignment(clang::SourceLocation, clang::CXXMethodDecl*) () from /usr/lib/libclang-cpp.so.10
I can avoid this problem if I put the preprocessor in "incremental processing mode" using `enableIncrementalProcessing()` from BeginSourceFileAction in my ASTFrontendAction, but doing this causes clang to not generate the bodies of template specializations. I assume that this is because you can't generate specializations until you have the complete module which makes sense.

Is there some way that I can get both of these, i.e. generate all implicit declarations with their bodies and get template specializations? Perhaps by using Sema to generate the bodies and then somehow finishing the file to get clang to generate the specializations? Or maybe I can manually call something in Sema to generate the bodies of the templates?

Thanks in advance.

--
gregory malecha

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

Re: Using the Sema Object to Generate Implicit Definitions

Manas via cfe-dev
On Thu, 15 Oct 2020 at 14:23, Gregory Malecha via cfe-dev <[hidden email]> wrote:
Hello --

I've been trying to use the Sema object to generate implicit definitions, e.g. default constructors, destructors, etc, in a tool that I have but I'm running into some issues. The code that I have is a DeclVisitor with the following for the CXXRecord case.

void VisitCXXRecordDecl(CXXRecordDecl *decl, bool is_specialization) {
  if (not(decl->isImplicit() or decl->isAnonymousStructOrUnion())) {
    ci_->getSema().ForceDeclarationOfImplicitMembers(decl);
  } 
  // ...
}

This works great, and always works to get me constructor definitions with empty bodies but marked as default.

To generate the bodies, I have (roughly) the following code for constructors, destructors, and methods:

if (not decl->getBody() && decl->isDefaulted()) {
  if (decl->isMoveAssignmentOperator()) {
    ci_->getSema().DefineImplicitMoveAssignment(decl->getLocation(), decl);
  } else if (decl->isCopyAssignmentOperator()) {
    ci_->getSema().DefineImplicitCopyAssignment(decl->getLocation(), decl);
  }
}

In most cases, this seems to do the trick, but when the implementation of the operator uses something like memcpy I get a segfault (stack trace below) due (it seems) to the fact that TUScope is null when my code runs.
#0  0x00007ffff5ff733a in clang::Sema::PushOnScopeChains(clang::NamedDecl*, clang::Scope*, bool) () from /usr/lib/libclang-cpp.so.10
#1  0x00007ffff601dc18 in clang::Sema::LazilyCreateBuiltin(clang::IdentifierInfo*, unsigned int, clang::Scope*, bool, clang::SourceLocation) () from /usr/lib/libclang-cpp.so.10
#2  0x00007ffff63599ac in clang::Sema::LookupBuiltin(clang::LookupResult&) () from /usr/lib/libclang-cpp.so.10
#3  0x00007ffff636e713 in clang::Sema::LookupName(clang::LookupResult&, clang::Scope*, bool) () from /usr/lib/libclang-cpp.so.10
#4  0x00007ffff61512e4 in ?? () from /usr/lib/libclang-cpp.so.10
#5  0x00007ffff6151643 in ?? () from /usr/lib/libclang-cpp.so.10
#6  0x00007ffff6159481 in clang::Sema::DefineImplicitCopyAssignment(clang::SourceLocation, clang::CXXMethodDecl*) () from /usr/lib/libclang-cpp.so.10
I can avoid this problem if I put the preprocessor in "incremental processing mode" using `enableIncrementalProcessing()` from BeginSourceFileAction in my ASTFrontendAction, but doing this causes clang to not generate the bodies of template specializations. I assume that this is because you can't generate specializations until you have the complete module which makes sense.

Is there some way that I can get both of these, i.e. generate all implicit declarations with their bodies and get template specializations? Perhaps by using Sema to generate the bodies and then somehow finishing the file to get clang to generate the specializations? Or maybe I can manually call something in Sema to generate the bodies of the templates?

You can call Sema::ActOnEndOfTranslationUnit() to get it to perform the pending actions that it's been saving up, such as template instantiations.
 
Thanks in advance.

--
gregory malecha
_______________________________________________
cfe-dev mailing list
[hidden email]
https://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
Reply | Threaded
Open this post in threaded view
|

Re: Using the Sema Object to Generate Implicit Definitions

Manas via cfe-dev
Thanks! Worked like a charm.

On Thu, Oct 15, 2020 at 8:17 PM Richard Smith <[hidden email]> wrote:
On Thu, 15 Oct 2020 at 14:23, Gregory Malecha via cfe-dev <[hidden email]> wrote:
Hello --

I've been trying to use the Sema object to generate implicit definitions, e.g. default constructors, destructors, etc, in a tool that I have but I'm running into some issues. The code that I have is a DeclVisitor with the following for the CXXRecord case.

void VisitCXXRecordDecl(CXXRecordDecl *decl, bool is_specialization) {
  if (not(decl->isImplicit() or decl->isAnonymousStructOrUnion())) {
    ci_->getSema().ForceDeclarationOfImplicitMembers(decl);
  } 
  // ...
}

This works great, and always works to get me constructor definitions with empty bodies but marked as default.

To generate the bodies, I have (roughly) the following code for constructors, destructors, and methods:

if (not decl->getBody() && decl->isDefaulted()) {
  if (decl->isMoveAssignmentOperator()) {
    ci_->getSema().DefineImplicitMoveAssignment(decl->getLocation(), decl);
  } else if (decl->isCopyAssignmentOperator()) {
    ci_->getSema().DefineImplicitCopyAssignment(decl->getLocation(), decl);
  }
}

In most cases, this seems to do the trick, but when the implementation of the operator uses something like memcpy I get a segfault (stack trace below) due (it seems) to the fact that TUScope is null when my code runs.
#0  0x00007ffff5ff733a in clang::Sema::PushOnScopeChains(clang::NamedDecl*, clang::Scope*, bool) () from /usr/lib/libclang-cpp.so.10
#1  0x00007ffff601dc18 in clang::Sema::LazilyCreateBuiltin(clang::IdentifierInfo*, unsigned int, clang::Scope*, bool, clang::SourceLocation) () from /usr/lib/libclang-cpp.so.10
#2  0x00007ffff63599ac in clang::Sema::LookupBuiltin(clang::LookupResult&) () from /usr/lib/libclang-cpp.so.10
#3  0x00007ffff636e713 in clang::Sema::LookupName(clang::LookupResult&, clang::Scope*, bool) () from /usr/lib/libclang-cpp.so.10
#4  0x00007ffff61512e4 in ?? () from /usr/lib/libclang-cpp.so.10
#5  0x00007ffff6151643 in ?? () from /usr/lib/libclang-cpp.so.10
#6  0x00007ffff6159481 in clang::Sema::DefineImplicitCopyAssignment(clang::SourceLocation, clang::CXXMethodDecl*) () from /usr/lib/libclang-cpp.so.10
I can avoid this problem if I put the preprocessor in "incremental processing mode" using `enableIncrementalProcessing()` from BeginSourceFileAction in my ASTFrontendAction, but doing this causes clang to not generate the bodies of template specializations. I assume that this is because you can't generate specializations until you have the complete module which makes sense.

Is there some way that I can get both of these, i.e. generate all implicit declarations with their bodies and get template specializations? Perhaps by using Sema to generate the bodies and then somehow finishing the file to get clang to generate the specializations? Or maybe I can manually call something in Sema to generate the bodies of the templates?

You can call Sema::ActOnEndOfTranslationUnit() to get it to perform the pending actions that it's been saving up, such as template instantiations.
 
Thanks in advance.

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


--
gregory malecha

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