Почему clang создает эти неявные методы, когда класс содержит виртуальный метод?

Я работаю над инструментом, основанным на AST clang, и мне любопытно узнать, почему clang работает таким образом.

Вот мой вклад. У меня есть очень простой класс, который определяется следующим образом:

class Foo {
    int foo();
};

Затем в моем RecursiveASTVisitor у меня есть код, который выглядит так:

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;
}

Все, что он делает, это выдает список методов, определенных во всех посещаемых классах. Результат для этого, как мы и ожидали:

Foo::foo()

Теперь давайте внесем небольшое изменение в наш класс Foo. Сделаем метод foo() виртуальным:

class Foo {
    virtual int foo();
};

Теперь мой вывод меняется:

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

Мой вопрос: почему добавление виртуального метода в класс приводит к тому, что clang создает неявный оператор присваивания и деструктор? Если я добавлю --std=c++11, он также создаст неявный оператор присваивания перемещения. Является ли это деталью реализации clang или частью стандарта С++?


person Chris    schedule 24.09.2015    source источник
comment
Способ скопировать vtable и уничтожить его?   -  person Jarod42    schedule 25.09.2015
comment
Кстати, стандарт не устанавливает правил для результирующего AST.   -  person Jarod42    schedule 25.09.2015
comment
Обратите внимание, что у каждого класса есть деструктор. C++ как язык напрямую не связан с AST компилятора.   -  person Kerrek SB    schedule 25.09.2015


Ответы (1)


Оказывается, мне нужно просто прочитать исходный код clang. SemaDeclCXX.cpp имеет метод Sema::AddImplicitlyDeclaredMembersToClass. Есть комментарий о том, почему он объявляет неявное присваивание копии:

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);
}

Это делается для того, чтобы неявно определенные методы, которые могут быть виртуальными, оказались в нужном месте в виртуальной таблице.

person Chris    schedule 25.09.2015