3

私は、clang の AST に基づくツールに取り組んでいます。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 の実装の詳細ですか、それとも C++ 標準の一部ですか?

4

1 に答える 1

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

そのため、仮想である可能性がある暗黙的に定義されたメソッドが vtable の適切な場所に配置されるようにするために、これを行います。

于 2015-09-25T00:39:53.687 に答える