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).
Related
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?
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();
}
I have problem when compiling code below on aix machine with gcc compiler (version 4.7.3):
SomeThread.h
#ifndef SomeThread_H
#define SomeThread_H
class SomeThread {
public:
SomeThread(void);
virtual ~SomeThread(void);
void runThread();
}; // SomeThread
#endif // _SomeThread_H_
SomeThread.cpp
#include "SomeThread.h"
#include <thread>
#include <iostream>
using namespace std;
namespace {
void foo_thread_function() {
for (int i = 0; i < 10; ++i) {
cout << "Some threaded text" << endl;
}
}
}
SomeThread::SomeThread() {
} // SomeThread
SomeThread::~SomeThread() {
} // ~SomeThread
void SomeThread::runThread() {
thread foo_thread_01(foo_thread_function);
thread foo_thread_02(foo_thread_function);
thread foo_thread_03(foo_thread_function);
foo_thread_01.join();
foo_thread_02.join();
foo_thread_03.join();
}
The error which I get is following:
SomeThread.cpp: In member function 'void SomeThread::runThread()':
SomeThread.cpp:58:4: error: reference to 'thread' is ambiguous
In file included from /usr/include/sys/ptrace.h:28:0,
from /usr/include/sys/proc.h:42,
from /usr/include/sys/pri.h:43,
from /usr/include/sys/sched.h:38,
from /usr/include/sched.h:51,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include-fixed/pthread.h:76,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/powerpc-ibm-aix7.1.0.0/pthread/ppc64/bits/gthr-posix.h:41,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/powerpc-ibm-aix7.1.0.0/pthread/ppc64/bits/gthr-default.h:30,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/powerpc-ibm-aix7.1.0.0/pthread/ppc64/bits/gthr.h:150,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/ext/atomicity.h:34,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/memory:75,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/thread:40,
from SomeThread.cpp:5:
/usr/include/sys/thread.h:105:8: error: candidates are: struct thread
In file included from SomeThread.cpp:5:0:
/opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/thread:60:9: error: class std::thread
SomeThread.cpp:58:11: error: expected ';' before 'foo_thread_01'
SomeThread.cpp:59:4: error: reference to 'thread' is ambiguous
In file included from /usr/include/sys/ptrace.h:28:0,
from /usr/include/sys/proc.h:42,
from /usr/include/sys/pri.h:43,
from /usr/include/sys/sched.h:38,
from /usr/include/sched.h:51,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include-fixed/pthread.h:76,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/powerpc-ibm-aix7.1.0.0/pthread/ppc64/bits/gthr-posix.h:41,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/powerpc-ibm-aix7.1.0.0/pthread/ppc64/bits/gthr-default.h:30,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/powerpc-ibm-aix7.1.0.0/pthread/ppc64/bits/gthr.h:150,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/ext/atomicity.h:34,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/memory:75,
from /opt/freeware/lib/gcc/powerpc-ibm-aix7.1.0.0/4.7.3/include/c++/thread:40,
from SomeThread.cpp:5:
I compile the above files with following command line:
g++ -maix64 -DTARGET=target_thread -DGENDATE=04_01_2017 -DTT_LIB_DLLSUFFIX=\".so\" -DOSNAME=\"AIX\" -D_GNU_SOURCE -D_REENTRANT -DAIX -Wno-deprecated -I. -std=gnu++11 -maix64 -pthread -mminimal-toc -fpermissive -Wno-write-strings -Winvalid-offsetof -O3 -c -oSomeThread.o SomeThread.cpp
The problem is, that there are multiple implementations of thread with your compiler options and includes. Maybe it would be just enough to correct the code to this.
SomeThread.cpp
#include "SomeThread.h"
#include <thread>
#include <iostream>
//Stop using namespace std, please
namespace SomeNamespace {
void foo_thread_function() {
for (int i = 0; i < 10; ++i) {
cout << "Some threaded text" << endl;
}
}
}
SomeThread::SomeThread() {
} // SomeThread
SomeThread::~SomeThread() {
} // ~SomeThread
void SomeThread::runThread() {
std::thread foo_thread_01(SomeNamespace::foo_thread_function);
std::thread foo_thread_02(SomeNamespace::foo_thread_function);
std::thread foo_thread_03(SomeNamespace::foo_thread_function);
foo_thread_01.join();
foo_thread_02.join();
foo_thread_03.join();
}
Ambiguous means that there are multiple interpretations of the same word.
Example:
namespace Bla{
struct SomeStruct{
}
}
namespace Blub{
struct SomeStruct{
}
}
int main(){
using namespace Bla;
using namespace Blub;
SomeStruct ImAmbiguous; // Problem now, which struct should the compiler choose now?
Bla::SomeStruct structFromBla; //Now the compiler knows which struct should be choosen
return 0;
}
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.
I have the following code:
#include <iostream>
#include <memory>
using namespace std;
class A
{
public:
void foo() const;
};
void A::foo() const {}
std::unique_ptr<A> foo2()
{
std::unique_ptr<A> pa(new A());
return pa;
}
void
foo()
{
const A& ra = *foo2();
ra.foo();
}
int
main()
{
foo();
return 0;
}
I am trying to use clang's scan-build:
scan-build g++ --std=c++11 unique_ptr.cpp
This program compiles and runs fine with g++.
I am using CentOS and clang3.8 and g++4.8.5.
Error Message:
error: no type named 'unique_ptr' in namespace 'std'
std::unique_ptr<A> foo2()
~~~~~^
You should use:
scan-build g++ -std=c++11 unique_ptr.cpp
Instead of:
scan-build g++ --std=c++11 unique_ptr.cpp
-std works (while --std doesn't) because scan-build checks specifically for the -std flag.
In clang/tools/scan-build/libexec/ccc-analyzer:
if ($Arg =~ /^-std=/) {
push #CompileOpts,$Arg;
next;
}