Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does clang create these implicit methods when a class contains a virtual method?

I'm working on a tool based on clang's AST, and I'm curious to know why clang works this way.

Here's my input. I have a very simple class that is defined like this:

class Foo {
    int foo();
};

Then in my RecursiveASTVisitor, I have code that looks like this:

bool MyASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl *D) {
    for (auto const & method : D->methods()) {
        llvm::outs() << method->getQualifiedNameAsString() << "(";
        for (auto const & param : method->params())
            llvm::outs() << param->getType().getAsString() << ", ";
        llvm::outs() << ")";
        if (method->isImplicit())
            llvm::outs() << " [implicit]";
        llvm::outs() << "\n";
    }
    return true;
}

All this does is spit out the list of methods defined in all the classes that are visited. The output for this is as we'd expect:

Foo::foo()

Now, let's make a small change to our Foo class. Let's make the foo() method virtual:

class Foo {
    virtual int foo();
};

Now my output changes:

Foo::foo()
Foo::operator=(const class Foo &, ) [implicit]
Foo::~Foo() [implicit]

My question is, why does adding a virtual method to a class cause clang to create an implicit assignment operator and destructor? If I add --std=c++11, it creates an implicit move-assignment operator as well. Is this an implementation detail of clang, or is it part of the C++ standard?

like image 809
Chris Avatar asked Nov 23 '25 18:11

Chris


1 Answers

Turns out that I should just read the clang source code. SemaDeclCXX.cpp has a method called Sema::AddImplicitlyDeclaredMembersToClass. There's a comment about why it declares the implicit copy assignment:

if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
  ++ASTContext::NumImplicitCopyAssignmentOperators;

  // If we have a dynamic class, then the copy assignment operator may be
  // virtual, so we have to declare it immediately. This ensures that, e.g.,
  // it shows up in the right place in the vtable and that we diagnose
  // problems with the implicit exception specification.
  if (ClassDecl->isDynamicClass() ||
      ClassDecl->needsOverloadResolutionForCopyAssignment())
    DeclareImplicitCopyAssignment(ClassDecl);
}

So it does this in order to ensure that the implicitly defined methods, that may be virtual, end up in the right place in the vtable.

like image 66
Chris Avatar answered Nov 26 '25 10:11

Chris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!