简体   繁体   English

c'tor和d'tor从抽象基础到其他抽象类的继承到具体

[英]Inheritence of c'tor and d'tor from abstract base through other abstract classes into concrete

Main Question 主要问题

I am trying to build a clang plugin as per the instructions here , but I am encountering linker errors when I try to build. 我正在尝试按照此处的说明构建clang插件,但是在尝试构建时遇到链接器错误。

These are the errors: 这些是错误:

/tmp/Test-1ea47e.o: In function `ASTFrontendAction':
/usr/lib/llvm-3.4/include/clang/Frontend/FrontendAction.h:216: undefined reference to `clang::FrontendAction::FrontendAction()'

/tmp/Test-1ea47e.o: In function `~TestPlugin':
/home/path/to/plugin/Test.cpp:12: undefined reference to `clang::FrontendAction::~FrontendAction()'

/tmp/Test-1ea47e.o:(.data.rel.ro+0x20): undefined reference to `clang::FrontendAction::~FrontendAction()'

/tmp/Test-1ea47e.o:(.data.rel.ro+0x50): undefined reference to `typeinfo for clang::PluginASTAction'

My class is TestPlugin (code is below), and it extends from three abstract library classes in the following chain: FrontendAction > ASTFrontendAction > PluginASTAction > TestPlugin . 我的类是TestPlugin (下面的代码),它从以下链中的三个抽象库类扩展而来: FrontendAction > ASTFrontendAction > PluginASTAction > TestPlugin I would have expected that since the library classes are abstract, their constructors and destructors would never be needed, but I am fairly new to C++, so kindly correct me, if I'm wrong. 我本来希望,因为库类是抽象的,所以将不再需要它们的构造函数和析构函数,但是我对C ++还是很陌生,所以如果我错了,请纠正我。 What might be causing these linker errors? 是什么导致这些链接器错误?

Supplementary Info 补充资料

For background: the instructions I'm following are meant for clang 3.7, but I am on the standard Ubuntu distribution of clang 3.4, so that could be part of the problem. 对于背景:我遵循的说明适用于clang 3.7,但是我使用的是clang 3.4的标准Ubuntu发行版,因此这可能是问题的一部分。 The unmodified tutorial code wouldn't even compile, so I had to make a number of changes (mostly deletions) to get this far, but I am still getting the aforementioned errors during linking. 未经修改的教程代码甚至都不会编译,因此我不得不进行很多更改(主要是删除操作)才能达到目的,但是在链接过程中我仍然遇到上述错误。

Here is my entire plugin file (some whitespace condensed for brevity) 这是我的整个插件文件(为简洁起见,压缩了一些空格)

Test.cpp : Test.cpp

#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;

namespace {
    class TestPlugin: public PluginASTAction {
        private:
            void anchor(){}

        protected:
            ASTConsumer* CreateASTConsumer(CompilerInstance &CI, llvm::StringRef){ return NULL; }
            void ExecuteAction(){ return; }
            bool shouldEraseOutputFiles(){ return false; }

        public:
            bool ParseArgs(const CompilerInstance &CI, const std::vector<std::string>& args){ return true; }
    };
}

static FrontendPluginRegistry::Add<TestPlugin>
    X("test-stuff", "Does some test stuff");

int main(){ return 0; }

And here are the relevant parts (I think) of the library code from which mine inherits 这是我继承的库代码的相关部分(我认为)

FrontendAction.h : FrontendAction.h

//////// snip ////////
namespace clang {

    class FrontendAction {
    //////// snip ////////
        public:
            FrontendAction();
            virtual ~FrontendAction();
            virtual bool usesPreprocessorOnly() const = 0;
            //////// snip ////////
    }; // class FrontendAction


    class ASTFrontendAction : public FrontendAction {
        protected:
            virtual void ExecuteAction();

        public:
            virtual bool usesPreprocessorOnly() const { return false; }
    }; // class ASTFrontendAction


    class PluginASTAction : public ASTFrontendAction {
            virtual void anchor();

        protected:
            virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile) = 0;

        public:
            virtual bool ParseArgs(const CompilerInstance &CI, const std::vector<std::string> &arg) = 0;
    }; // class PluginASTAction

    //////// snip ////////
} // namespace clang

I'm Happy to provide any other information that might be useful. 我很乐意提供其他可能有用的信息。

Update 更新资料

Here is the output that nm gives for the whereabouts of the c'tor and d'tor: 这是nm给出c'tor和d'tor下落的输出:

/usr/lib/llvm-3.4/lib$ nm -AC *.a | grep 'FrontendAction::~\?FrontendAction'
...
libclangFrontend.a:FrontendAction.o:00000960 T clang::FrontendAction::FrontendAction()
libclangFrontend.a:FrontendAction.o:000004a0 T clang::FrontendAction::~FrontendAction()
...

They show up in libclangFrontend.a with status 'T', which I understand to mean that the implementation of the method is there. 它们显示在libclangFrontend.a ,状态为“ T”,据我了解,这意味着该方法的实现已存在。 They also show up in several other libraries with status 'U' (undefined). 它们还显示在其他几个状态为“ U”(未定义)的库中。 libclangFrontend.a also claims to hold the missing typeinfo for clang::PluginASTAction . libclangFrontend.a还声称保留typeinfo for clang::PluginASTAction缺少的typeinfo for clang::PluginASTAction

However, I was already including that library, and even after positioning it before the other libclangXYZ libs I still get the same error. 但是,我已经包含了该库,即使将其放置在其他libclangXYZ库之前,我仍然会遇到相同的错误。 Here is my current linker invocation (generated by make , linebreaks added for readability): 这是我当前的链接器调用(由make生成,添加了换行符以提高可读性):

"/usr/bin/ld"
    -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_i386
    -dynamic-linker /lib/ld-linux.so.2

    -o Test

    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crt1.o
    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crti.o
    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/crtbegin.o

    -L/usr/lib/llvm-3.4/lib/
    -L/usr/bin/../lib/gcc/i686-linux-gnu/4.8
    -L/usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu
    -L/lib/i386-linux-gnu
    -L/usr/lib/i386-linux-gnu
    -L/usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../..
    -L/lib
    -L/usr/lib

    -lpthread -lffi -ltinfo -ldl -lm

    -lclangFrontend
    -lclang
    -lclangBasic
    -lclangAST
    -lclangFrontendTool
    -lclangRewriteFrontend
    -lclangStaticAnalyzerFrontend
    -lclangCodeGen
    -lclangTooling
    -lclangARCMigrate
    -lclangTidy

    /tmp/Test-fd7749.o

    -lc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc

    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/crtend.o
    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crtn.o

Update: Solved! 更新:解决!

It turns out that I was missing a ton of LLVM libraries (eg libLLVMSupport.a ) and some clang ones too from the linker invocation. 事实证明,链接器调用中缺少大量的LLVM库(例如libLLVMSupport.a )和一些clang库。 I think I also needed to explicitly add libstdc++.so . 我认为我还需要显式添加libstdc++.so

Here is the final working call to the linker, generated by make (note: I'm not sure this is a minimal set, but at least it links...): 这是由make生成的对链接器的最终工作调用(请注意:我不确定这是否是最小集,但至少它会链接...):

"/usr/bin/ld"
    -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_i386
    -dynamic-linker /lib/ld-linux.so.2

    -o Test

    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crt1.o
    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crti.o
    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/crtbegin.o

    -L/usr/lib/llvm-3.4/lib
    -L/usr/bin/../lib/gcc/i686-linux-gnu/4.8
    -L/usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu
    -L/lib/i386-linux-gnu
    -L/usr/lib/i386-linux-gnu
    -L/usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../..
    -L/lib
    -L/usr/lib

    /tmp/Test-6c811b.o

    /usr/lib/gcc/i686-linux-gnu/4.8/libstdc++.so

    -lpthread -lffi -ltinfo -ldl -lm -lc++

    -lclangFrontend
    -lclangSerialization
    -lclangDriver
    -lclangTooling
    -lclangParse
    -lclangSema
    -lclangStaticAnalyzerFrontend
    -lclangStaticAnalyzerCheckers
    -lclangStaticAnalyzerCore
    -lclangAnalysis
    -lclangRewriteFrontend
    -lclangEdit
    -lclangAST
    -lclangLex
    -lclangBasic

    -lLLVMTransformUtils
    -lLLVMCore
    -lLLVMSupport
    -lLLVMOption
    -lLLVMMCParser
    -lLLVMMC
    -lLLVMBitReader

    -lc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc

    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/crtend.o
    /usr/bin/../lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/crtn.o

This looks like you are not linking with whatever implements clang::FrontendAction::~FrontendAction() . 看起来您没有与任何实现clang::FrontendAction::~FrontendAction() Try looking at this Makefile: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-check/Makefile?view=markup 尝试查看此Makefile: http : //llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-check/Makefile? view= markup

In this article , it put this in your cmake file: 本文中 ,将其放入您的cmake文件中:

set(LLVM_USED_LIBS clangTooling clangBasic clangAST)

I would have expected that since the library classes are abstract, their constructors and destructors would never be needed. 我本来希望,由于库类是抽象的,因此将不再需要它们的构造函数和析构函数。

All classes need constructors and destructors if they are instantiated. 如果实例化了所有类,则它们需要构造函数和析构函数。 That includes abstract classes - even though they can't be directly instantiated, they can be instantiated as part of the concrete derived class, and the constructor and destructor are needed for that. 其中包括抽象类-即使不能直接实例化它们,也可以将它们实例化为具体派生类的一部分,并且为此需要构造函数和析构函数。

What might be causing these linker errors? 是什么导致这些链接器错误?

You declare the destructor, but don't define it. 您声明了析构函数,但未定义它。 If it doesn't need to do anything (as is usually the case in an abstract class), you can just define it with an empty body 如果不需要执行任何操作(通常在抽象类中就是这种情况),则可以使用空主体定义它

virtual ~FrontendAction() {}

or as defaulted 或默认

virtual ~FrontendAction() = default;

in the class definition. 在类定义中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM