LLVM: Clang does not run Pass if CallGraphWrapperPass is a requirement - c++

I wrote the following pass for llvm.
using namespace llvm;
namespace {
struct SkeletonPass : public FunctionPass {
static char ID;
SkeletonPass() : FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<CallGraphWrapperPass>();
AU.setPreservesAll();
}
virtual bool runOnFunction(Function &F) {
errs() << "Function: " << F.getName() << "!\n";
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
return false;
}
};
}
char SkeletonPass::ID = 0;
static RegisterPass<SkeletonPass> X("skeleton", "text");
If I execute this code with
opt -load ./libSkeletonPass.so -skeleton test.bc > /dev/null
I get the correct output. (test.bc can be neglected)
According to this great blog, the next command
clang -Xclang -load -Xclang ./libSkeletonPass.so test.c
should also work, as long as we replace the last line with:
static void registerSkeletonPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) {
PM.add(new SkeletonPass());
}
static RegisterStandardPasses
RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible,
registerSkeletonPass);
The problem is that clang crashes and returns this error:
...
clang-3.8: error: unable to execute command: Segmentation fault (core dumped)
clang-3.8: error: clang frontend command failed due to signal (use -v to see invocation)
...
Without all the CallGraphWrapperPass references clang executes the pass correct.
I'm new to llvm, so is there something I missed?
System: Linux 4.4.0 (64bit)
clang version: 3.8.1

The solution was to change EP_EarlyAsPossible to EP_EnabledOnOptLevel0.

Related

Clang plugin to print function call locations

Here is a minimal Clang plugin to print location of function calls.
I have a RecursiveASTVisitor visitor named FuncCallVisitor that is initialized with an ASTContext and tries to print the source location of the CallExpr.
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendPluginRegistry.h>
#include <clang/Frontend/ASTConsumers.h>
#include <iostream>
using std::unique_ptr;
using std::make_unique;
using std::string;
using namespace clang;
class FuncCallVisitor : public RecursiveASTVisitor<FuncCallVisitor> {
public:
explicit FuncCallVisitor(CompilerInstance *CI)
: astContext(&(CI->getASTContext()))
{ }
bool VisitCallExpr(CallExpr * expr) {
auto loc = expr->getDirectCallee()->getLocation();
std::cerr << loc.printToString(astContext->getSourceManager()) << std::endl;
return true;
}
private:
ASTContext *astContext;
};
class FuncCallConsumer : public ASTConsumer {
public:
explicit FuncCallConsumer(CompilerInstance *CI)
: m_visitor(FuncCallVisitor(CI))
{ }
virtual bool HandleTopLevelDecl(DeclGroupRef dg) override {
for (Decl *decl : dg)
m_visitor.TraverseDecl(decl);
return true;
}
private:
FuncCallVisitor m_visitor;
};
class ParameterNameChecker : public PluginASTAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &ci,
llvm::StringRef) override {
return make_unique<FuncCallConsumer>(&ci);
}
bool ParseArgs(const CompilerInstance&, const std::vector<string>&) override {
return true;
}
};
static FrontendPluginRegistry::Add<ParameterNameChecker>
X("-print-calls", "print location of function calls");
This expression from the above code causes a SEGFAULT
loc.printToString(astContext->getSourceManager())
https://i.stack.imgur.com/AQQWU.png
clang invocation:
clang-10 test.c -Xclang -load -Xclang ./Plugin.so -Xclang -plugin -Xclang -print-calls -c
Stack dump:
0. Program arguments: clang-10 ../../ast_test.c -o ast_test -Xclang -load -Xclang ./Plugin.so -Xclang -plugin -Xclang -print-calls -c
1. <eof> parser at end of file
/lib/x86_64-linux-gnu/libLLVM-10.so.1(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x1f)[0x7f17ba3c94ff]
/lib/x86_64-linux-gnu/libLLVM-10.so.1(_ZN4llvm3sys17RunSignalHandlersEv+0x50)[0x7f17ba3c77b0]
/lib/x86_64-linux-gnu/libLLVM-10.so.1(_ZN4llvm3sys15CleanupOnSignalEm+0xdd)[0x7f17ba3c8c4d]
/lib/x86_64-linux-gnu/libLLVM-10.so.1(+0x8d6e60)[0x7f17ba31ee60]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x153c0)[0x7f17c0b993c0]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(+0x797ffe)[0x7f17be873ffe]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(+0x795cb7)[0x7f17be871cb7]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZNK5clang13SourceManager14getPresumedLocENS_14SourceLocationEb+0x25)[0x7f17be874da5]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZNK5clang14SourceLocation5printERN4llvm11raw_ostreamERKNS_13SourceManagerE+0x2d)[0x7f17be86f77d]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZNK5clang14SourceLocation13printToStringB5cxx11ERKNS_13SourceManagerE+0x69)[0x7f17be86fa09]
./Plugin.so(_ZN15FuncCallVisitor13VisitCallExprEPN5clang8CallExprE+0x48)[0x7f17b803a378]
./Plugin.so(_ZN5clang19RecursiveASTVisitorI15FuncCallVisitorE18WalkUpFromCallExprEPNS_8CallExprE+0x60)[0x7f17b8035e90]
./Plugin.so(_ZN5clang19RecursiveASTVisitorI15FuncCallVisitorE16TraverseCallExprEPNS_8CallExprEPN4llvm15SmallVectorImplINS5_14PointerIntPairIPNS_4StmtELj1EbNS5_21PointerLikeTypeTraitsIS9_EENS5_18PointerIntPairInfoIS9_Lj1ESB_EEEEEE+0x5f)[0x7f17b80511ef]
./Plugin.so(_ZN5clang19RecursiveASTVisitorI15FuncCallVisitorE16dataTraverseNodeEPNS_4StmtEPN4llvm15SmallVectorImplINS5_14PointerIntPairIS4_Lj1EbNS5_21PointerLikeTypeTraitsIS4_EENS5_18PointerIntPairInfoIS4_Lj1ES9_EEEEEE+0x16ab)[0x7f17b80309bb]
./Plugin.so(_ZN5clang19RecursiveASTVisitorI15FuncCallVisitorE12TraverseStmtEPNS_4StmtEPN4llvm15SmallVectorImplINS5_14PointerIntPairIS4_Lj1EbNS5_21PointerLikeTypeTraitsIS4_EENS5_18PointerIntPairInfoIS4_Lj1ES9_EEEEEE+0x233)[0x7f17b802c143]
./Plugin.so(_ZN5clang19RecursiveASTVisitorI15FuncCallVisitorE22TraverseFunctionHelperEPNS_12FunctionDeclE+0x55f)[0x7f17b80bf92f]
./Plugin.so(_ZN5clang19RecursiveASTVisitorI15FuncCallVisitorE20TraverseFunctionDeclEPNS_12FunctionDeclE+0x7e)[0x7f17b800fa5e]
./Plugin.so(_ZN5clang19RecursiveASTVisitorI15FuncCallVisitorE12TraverseDeclEPNS_4DeclE+0x9a6)[0x7f17b8007a56]
./Plugin.so(_ZN16FuncCallConsumer18HandleTopLevelDeclEN5clang12DeclGroupRefE+0x69)[0x7f17b8006d89]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZN5clang17MultiplexConsumer18HandleTopLevelDeclENS_12DeclGroupRefE+0x2c)[0x7f17bfddc8bc]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZN5clang8ParseASTERNS_4SemaEbb+0x214)[0x7f17be931ba4]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZN5clang14FrontendAction7ExecuteEv+0x48)[0x7f17bfda7e58]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZN5clang16CompilerInstance13ExecuteActionERNS_14FrontendActionE+0x621)[0x7f17bfd608a1]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZN5clang25ExecuteCompilerInvocationEPNS_16CompilerInstanceE+0x66f)[0x7f17bfe0bdaf]
clang-10(_Z8cc1_mainN4llvm8ArrayRefIPKcEES2_Pv+0x98d)[0x41229d]
clang-10[0x4105b1]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(+0x19d58f2)[0x7f17bfab18f2]
/lib/x86_64-linux-gnu/libLLVM-10.so.1(_ZN4llvm20CrashRecoveryContext9RunSafelyENS_12function_refIFvvEEE+0xd7)[0x7f17ba31ec67]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZNK5clang6driver10CC1Command7ExecuteEN4llvm8ArrayRefINS2_8OptionalINS2_9StringRefEEEEEPNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPb+0x13f)[0x7f17bfab0e2f]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZNK5clang6driver11Compilation14ExecuteCommandERKNS0_7CommandERPS3_+0x2df)[0x7f17bfa8952f]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZNK5clang6driver11Compilation11ExecuteJobsERKNS0_7JobListERN4llvm15SmallVectorImplISt4pairIiPKNS0_7CommandEEEE+0x7a)[0x7f17bfa896da]
/lib/x86_64-linux-gnu/libclang-cpp.so.10(_ZN5clang6driver6Driver18ExecuteCompilationERNS0_11CompilationERN4llvm15SmallVectorImplISt4pairIiPKNS0_7CommandEEEE+0xdc)[0x7f17bfa9c93c]
clang-10(main+0x259f)[0x41002f]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x7f17b95300b3]
clang-10(_start+0x2e)[0x40d7ce]
clang: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
clang: note: diagnostic msg: PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, and associated run script.
clang: error: unable to execute command: Segmentation fault (core dumped)
clang: note: diagnostic msg: Error generating preprocessed source(s).

gcc 4.8 failed to check type conversion in c++ template

I'm trying to update a c++ project's compiler from 4.8.4 to 7.5.0.
The codes can be well compiled with g++4.8.4. However, when I try to compile it with newer g++ 7.5.0. Lots of Werror=conversion errors are triggered.
Here is the demo code abstracted from my project:
// main.cc
template <typename T>
int Hello(T obj) {
float arg = 1.0;
// return obj.func(arg); // good, error detected for both g++ 4.8.4 and 7.5.0
return obj.func(arg) * 2; // failed to detect conversion error for 4.8.4, success for 7.5.0
}
class A {
public:
int func(int a) {
return a;
}
};
int main() {
A a;
Hello(a);
return 0;
}
build:
g++ main.cc -Werror=conversion
As commented above, in a c++ template function, g++4.8 failed to detect the type conversion error when it's in a expression. But it will sucess if it is alone.
I'm very curious about this.
My Question:
Is this a bug of g++4.8? Why does expression matter?

G++ command throws "expected '(' for function-style cast or type construction"

Function foo takes a vector of strings. It's defined as
bool foo(vector<string>& input);
When I call foo with:
foo(vector<string>{"abc"});
my compiler gives the following error:
error: expected '(' for function-style cast or type construction
and points to { as the start of the error. This compiles fine in Xcode but I get the error when running the following via command line with:
g++ -o -std=c++17 main.cpp
What is wrong with my g++ syntax?
G++ Version Information:
g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.3 (clang-1103.0.32.59)
Target: x86_64-apple-darwin19.4.0
Thread model: posix
Your command line specifies that the output file ("-o") should be called "-std=c++17" – it does not say anything about the language version, so you're compiling as C++03.
Remove the "-o" or add an actual file name.
Also, note that your "g++" is an alias for clang.
I took your code and tried to compile it. For me there was rather problem with trying to pass non const value to function. I changed function argument to const and it compiled and printed without any problem.
#include <iostream>
#include <vector>
bool foo(const std::vector<std::string>& v) {
for (auto& a : v) { std::cout << a << std::endl; }
return true;
}
int main()
{
bool result = foo(std::vector<std::string> {"1", "2", "3" });
// do something with result
return 0;
}
Compiled on: https://www.onlinegdb.com/online_c++_compiler
Function foo expects for an l-value.
You are generating an instance and passing it to the function. But lifetime of the object is not enough for the pass-by-reference call.
Here is an example below; instance of class A is immediately destructed.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class A {
public:
A(int m): m(m) {
cerr << __func__ << endl;
}
~A() {
cerr << __func__ << endl;
}
int m;
};
int main() {
cerr << __func__ << endl;
A(5);
cerr << __func__ << endl;
return 0;
}
Outputs:
main
A
~A
main

Symbol not found in debugger only, when having templated template argument

Given the following code as test.cpp,
Building using clang++ -c test.cpp -o test.o -g; clang++ test.o -g -all_load, setting breakpoint at return a.getValue(); and attempting to p a.getValue() from lldb:
Running llvm 3.8.0 on unix - works perfectly
Running xcode or llvm 8.1.0 on OSX - I get the following error:
error: Couldn't lookup symbols:
__ZNK4Test7MyClassILi2ELi3EE8getValueEv
Two interesting facts:
If I remove the last template argument - all works well
If I build directly without going through the .o file (clang++ test.cpp) = all goes well
Anyone has a clue what is going on, and how can it be fixed?
namespace Test{
template<class T>
class BLA{
public:
T getBlaValue() const{return 3;}
};
template <int N1, int N2, template<class T>class Impl = BLA>
class MyClass {
private:
public:
__attribute__((used))
int getValue() const
{
return 3;
}
};
}
int main()
{
Test::MyClass<2, 3> a;
return a.getValue();
}

undefined reference to variable template of pointer to function in clang but not gcc

#include <iostream>
static constexpr bool isSSE2 = true;
template<typename T>
static void (*fp)();
template<typename T>
static void foo_c() {
std::cout << "foo_c get called." << std::endl;
}
template<typename T>
static void foo_sse2() {
std::cout << "foo_sse2 get called." << std::endl;
}
int main() {
if (isSSE2)
fp<int> = foo_sse2<int>;
else
fp<int> = foo_c<int>;
fp<int>();
return 0;
}
I have a project that uses variable template which itself is a pointer to function. The example code above compiles and executes fine in GCC 6.3, but gives warning and error in clang 3.9.1.
$ clang++ "Source.cpp" -o "foo.exe" -std=c++14 -O2
Source.cpp:6:15: warning: variable 'fp<int>' has internal linkage but is not defined [-Wundefined-internal]
static void (*fp)();
^
Source.cpp:20:9: note: used here
fp<int> = foo_sse2<int>;
^
1 warning generated.
C:\msys64\tmp\Source-6600e8.o:(.text+0x2a): undefined reference to `fp<int>'
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)
Any help is appreciated.
You have to initialize your fp<>() first:
template<typename T>
static void (*fp)() = nullptr;
It compiles and runs fine in Clang 4.0: sample code.
And try to always initialize your variables — it may save you from all sorts of headaches. :)