c'tor 和 d'tour 从抽象基础通过其他抽象 类 继承到具体
Inheritence of c'tor and d'tor from abstract base through other abstract classes into concrete
主要问题
我正尝试按照说明构建 clang 插件 here,但在尝试构建时遇到链接器错误。
这些是错误:
/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'
我的 class 是 TestPlugin
(代码在下面),它从以下链中的三个抽象库 classes 扩展: FrontendAction
> ASTFrontendAction
> PluginASTAction
> TestPlugin
。我本以为,由于库 classes 是抽象的,因此永远不需要它们的构造函数和析构函数,但我对 C++ 还很陌生,如果我错了,请指正。是什么导致了这些链接器错误?
补充信息
对于背景:我遵循的说明适用于 clang 3.7,但我使用的是 clang 3.4 的标准 Ubuntu 发行版,因此这可能是问题的一部分。未经修改的教程代码甚至无法编译,所以我不得不进行一些更改(主要是删除)才能做到这一点,但我在链接过程中仍然遇到上述错误。
这是我的整个插件文件(为简洁起见压缩了一些空格)
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; }
这里是我继承的库代码的相关部分(我认为)
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
我很乐意提供任何其他可能有用的信息。
更新
这是 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()
...
它们出现在 libclangFrontend.a
中,状态为 'T',我理解这意味着该方法的实现就在那里。它们还出现在其他几个状态为 'U'(未定义)的库中。 libclangFrontend.a
还声称持有失踪的 typeinfo for clang::PluginASTAction
。
但是,我已经包含了那个库,即使在将它放在其他 libclangXYZ 库之前,我仍然遇到同样的错误。这是我当前的链接器调用(由 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
更新:已解决!
事实证明,我在链接器调用中遗漏了大量的 LLVM 库(例如 libLLVMSupport.a
)和一些 clang 库。我想我还需要明确添加 libstdc++.so
.
这是对链接器的最终工作调用,由 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
这看起来您没有链接任何工具 clang::FrontendAction::~FrontendAction()
。尝试查看此 Makefile:http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-check/Makefile?view=markup
在 this article 中,它将此放入您的 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.
所有classes如果被实例化,都需要构造函数和析构函数。这包括抽象 classes - 尽管它们不能直接实例化,但它们可以作为具体派生 class 的一部分实例化,为此需要构造函数和析构函数。
What might be causing these linker errors?
您声明了析构函数,但没有定义它。如果它不需要做任何事情(通常是抽象 class 中的情况),您可以只用空主体定义它
virtual ~FrontendAction() {}
或默认
virtual ~FrontendAction() = default;
在 class 定义中。
主要问题
我正尝试按照说明构建 clang 插件 here,但在尝试构建时遇到链接器错误。
这些是错误:
/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'
我的 class 是 TestPlugin
(代码在下面),它从以下链中的三个抽象库 classes 扩展: FrontendAction
> ASTFrontendAction
> PluginASTAction
> TestPlugin
。我本以为,由于库 classes 是抽象的,因此永远不需要它们的构造函数和析构函数,但我对 C++ 还很陌生,如果我错了,请指正。是什么导致了这些链接器错误?
补充信息
对于背景:我遵循的说明适用于 clang 3.7,但我使用的是 clang 3.4 的标准 Ubuntu 发行版,因此这可能是问题的一部分。未经修改的教程代码甚至无法编译,所以我不得不进行一些更改(主要是删除)才能做到这一点,但我在链接过程中仍然遇到上述错误。
这是我的整个插件文件(为简洁起见压缩了一些空格)
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; }
这里是我继承的库代码的相关部分(我认为)
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
我很乐意提供任何其他可能有用的信息。
更新
这是 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()
...
它们出现在 libclangFrontend.a
中,状态为 'T',我理解这意味着该方法的实现就在那里。它们还出现在其他几个状态为 'U'(未定义)的库中。 libclangFrontend.a
还声称持有失踪的 typeinfo for clang::PluginASTAction
。
但是,我已经包含了那个库,即使在将它放在其他 libclangXYZ 库之前,我仍然遇到同样的错误。这是我当前的链接器调用(由 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
更新:已解决!
事实证明,我在链接器调用中遗漏了大量的 LLVM 库(例如 libLLVMSupport.a
)和一些 clang 库。我想我还需要明确添加 libstdc++.so
.
这是对链接器的最终工作调用,由 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
这看起来您没有链接任何工具 clang::FrontendAction::~FrontendAction()
。尝试查看此 Makefile:http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-check/Makefile?view=markup
在 this article 中,它将此放入您的 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.
所有classes如果被实例化,都需要构造函数和析构函数。这包括抽象 classes - 尽管它们不能直接实例化,但它们可以作为具体派生 class 的一部分实例化,为此需要构造函数和析构函数。
What might be causing these linker errors?
您声明了析构函数,但没有定义它。如果它不需要做任何事情(通常是抽象 class 中的情况),您可以只用空主体定义它
virtual ~FrontendAction() {}
或默认
virtual ~FrontendAction() = default;
在 class 定义中。