llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29k stars 11.95k forks source link

Created CallExpr has its DeclRefExpr replaced using Visitor pattern #71890

Open SaltyPhoti opened 1 year ago

SaltyPhoti commented 1 year ago

Crash trace:

Stack dump:
0.  Program arguments: ./clang -rewrite-pflow -fopenmp /home/litianying/test.c -o test-rw.c
 #0 0x00005567acf6e444 PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
 #1 0x00005567acf6c26c llvm::sys::CleanupOnSignal(unsigned long) (./clang+0x384b26c)
 #2 0x00005567acea9fd8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007fdd6ebc6420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #4 0x00005567b026e3d9 clang::Stmt::getEndLoc() const (./clang+0x6b4d3d9)
 #5 0x00005567b026eb6d clang::Stmt::getSourceRange() const (./clang+0x6b4db6d)
 #6 0x00005567b02d3fd3 clang::TextNodeDumper::Visit(clang::Stmt const*) (./clang+0x6bb2fd3)
 #7 0x00005567aff087b2 clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()::operator()() const (./clang+0x67e77b2)
 #8 0x00005567aff091c5 std::_Function_handler<void (bool), void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'())::'lambda'(bool)>::_M_invoke(std::_Any_data const&, bool&&) (./clang+0x67e81c5)
 #9 0x00005567aff091fe std::_Function_handler<void (bool), void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'())::'lambda'(bool)>::_M_invoke(std::_Any_data const&, bool&&) (./clang+0x67e81fe)
#10 0x00005567aff08ac8 void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()) (./clang+0x67e7ac8)
#11 0x00005567aff088d1 clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()::operator()() const (./clang+0x67e78d1)
#12 0x00005567aff091c5 std::_Function_handler<void (bool), void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'())::'lambda'(bool)>::_M_invoke(std::_Any_data const&, bool&&) (./clang+0x67e81c5)
#13 0x00005567aff0e1b6 std::_Function_handler<void (bool), void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Decl const*)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Decl const*)::'lambda'())::'lambda'(bool)>::_M_invoke(std::_Any_data const&, bool&&) (./clang+0x67ed1b6)
#14 0x00005567aff21ec6 clang::Decl::dump(llvm::raw_ostream&, bool, clang::ASTDumpOutputFormat) const (./clang+0x6800ec6)
#15 0x00005567aeff50eb clang::SourceTransformAction::ExecuteAction() (./clang+0x58d40eb)
#16 0x00005567ada97b11 clang::FrontendAction::Execute() (./clang+0x4376b11)
#17 0x00005567ada1ece3 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (./clang+0x42fdce3)
#18 0x00005567adb7af7b clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (./clang+0x4459f7b)
#19 0x00005567aa8c77b4 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (./clang+0x11a67b4)
#20 0x00005567aa8c0d5b ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) driver.cpp:0:0
#21 0x00005567ad888559 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#22 0x00005567aceaa0d7 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (./clang+0x37890d7)
#23 0x00005567ad888b4c clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#24 0x00005567ad85293e clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (./clang+0x413193e)
#25 0x00005567ad85335d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (./clang+0x413235d)
#26 0x00005567ad85e1ac clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (./clang+0x413d1ac)
#27 0x00005567aa8c5539 clang_main(int, char**) (./clang+0x11a4539)
#28 0x00007fdd6e644083 __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:342:3
#29 0x00005567aa8c096e _start (./clang+0x119f96e)

Relavant code: (Create CallExpr)

CallExpr *MyNodeCreater::CreateCall() {
    std::string FuncName = "Func";
    QualType T = getContext().getFunctionType(getContext().UnsignedIntTy, {getContext().VoidTy}, {});
    DeclarationName N =
        DeclarationName(&(getContext().Idents).get(PtoolsStartFuncName));
    FunctionDecl *FD= FunctionDecl::Create(
        getContext(), getContext().getTranslationUnitDecl(), SourceLocation(),
        SourceLocation(), N, T, nullptr, SC_Extern);
    // add extern func
    FD->setDeclContext(getContext().getTranslationUnitDecl());
    Expr *funcExpr= DeclRefExpr::Create(getContext(), NestedNameSpecifierLoc(), SourceLocation(), FD,
                                            false, SourceLocation(), FD->getType(), VK_LValue);
    CallExpr *callExpr= CallExpr::Create(
        getContext(), funcExpr, None, getContext().VoidTy, VK_LValue, SourceLocation(), FPOptionsOverride());
    return callExpr;
}

(Visit function)

    DeclNode VisitFunctionDecl(FunctionDecl *D) override {
      FunctionDecl *NewFD = nullptr;
      DeclarationName N = D->getNameInfo().getName();
      QualType T = D->getType();
      ASTContext &Ctx = getContext();
      NewFD = FunctionDecl::Create(Ctx, Ctx.getTranslationUnitDecl(), 
                                    SourceLocation(), SourceLocation(), N, T, nullptr, SC_None);
      NewFD->setDeclContext(Ctx.getTranslationUnitDecl());
      PToolsAstNodeCreator astNodeCreator(getContext());

      // std::cout << "N name getAsString: " << N.getAsString() << " ------------------\n";

      CallExpr *func= myNodeCreater.CreateCall();
      CallExpr *anotherFunc = myNodeCreater.CreateAnotherCall(); // identical function to CreateCall, with only function name change
      std::vector<Stmt *> NewStmts;
      NewStmts.push_back(func);
      StmtNode NewBody = Visit(D->getBody());
      for (auto SubToBody : NewBody) {
        NewStmts.push_back(SubToBody);
      }
      NewStmts.push_back(anotherFunc );

      CompoundStmt *CS = CompoundStmt::Create(getContext(), NewStmts, FPOptionsOverride(), SourceLocation(), SourceLocation());
      NewFD->setBody(CS);
      Ctx.getTranslationUnitDecl()->addDecl(NewFD);
      return NewFD;
    }

(runPass function)

void SourceTransformAction::runPass(ASTTransformer *Pass) {
  std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
  Clang->createDiagnostics();
  CompilerInstance &CI = *Clang.get();
  auto Invocation = std::make_shared<CompilerInvocation>(getCompilerInstance().getInvocation());
  CI.setInvocation(std::move(Invocation));
  CI.createTarget();
  CI.LoadRequestedPlugins();
  CI.createFileManager();
  CI.createSourceManager(CI.getFileManager());
  CI.createPreprocessor(getTranslationUnitKind());
  CI.createASTContext();
  ASTContext &NewContext = CI.getASTContext();
  NewContext.addTranslationUnitDecl();
  Pass->setContext(NewContext);
  auto &SrcManager = CI.getSourceManager();
  std::cout << "Old TU: ---------------------------------\n";
  getContext().getTranslationUnitDecl()->dump();
  for (Decl *D : getContext().getTranslationUnitDecl()->decls()) {
    SourceLocation Loc = D->getLocation();
    Loc = SrcManager.getExpansionLoc(Loc);
    // If this is for a builtin, ignore it.
    if (Loc.isInvalid())
      continue;
    Pass->Visit(D);
  }
  setContext(NewContext);
  std::cout << "New TU: ---------------------------------\n";
  getContext().getTranslationUnitDecl()->dump();
}

(Transform())

  virtual void Transform() override {
    runPass(new MyTransformer());
    std::cout << "after runpass --------------\n";
    getContext().getTranslationUnitDecl()->dump();
  };

The printing shows that, the transformation is OK after "NEW TU" printing, but changed after "after runpass" printing. Really need some help on this. Thanks a lot in advance!

llvmbot commented 4 months ago

@llvm/issue-subscribers-clang-frontend

Author: None (SaltyPhoti)

Crash trace: ``` Stack dump: 0. Program arguments: ./clang -rewrite-pflow -fopenmp /home/litianying/test.c -o test-rw.c #0 0x00005567acf6e444 PrintStackTraceSignalHandler(void*) Signals.cpp:0:0 #1 0x00005567acf6c26c llvm::sys::CleanupOnSignal(unsigned long) (./clang+0x384b26c) #2 0x00005567acea9fd8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0 #3 0x00007fdd6ebc6420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420) #4 0x00005567b026e3d9 clang::Stmt::getEndLoc() const (./clang+0x6b4d3d9) #5 0x00005567b026eb6d clang::Stmt::getSourceRange() const (./clang+0x6b4db6d) #6 0x00005567b02d3fd3 clang::TextNodeDumper::Visit(clang::Stmt const*) (./clang+0x6bb2fd3) #7 0x00005567aff087b2 clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()::operator()() const (./clang+0x67e77b2) #8 0x00005567aff091c5 std::_Function_handler<void (bool), void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'())::'lambda'(bool)>::_M_invoke(std::_Any_data const&, bool&&) (./clang+0x67e81c5) #9 0x00005567aff091fe std::_Function_handler<void (bool), void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'())::'lambda'(bool)>::_M_invoke(std::_Any_data const&, bool&&) (./clang+0x67e81fe) #10 0x00005567aff08ac8 void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()) (./clang+0x67e7ac8) #11 0x00005567aff088d1 clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()::operator()() const (./clang+0x67e78d1) #12 0x00005567aff091c5 std::_Function_handler<void (bool), void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Stmt const*, llvm::StringRef)::'lambda'())::'lambda'(bool)>::_M_invoke(std::_Any_data const&, bool&&) (./clang+0x67e81c5) #13 0x00005567aff0e1b6 std::_Function_handler<void (bool), void clang::TextTreeStructure::AddChild<clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Decl const*)::'lambda'()>(llvm::StringRef, clang::ASTNodeTraverser<clang::ASTDumper, clang::TextNodeDumper>::Visit(clang::Decl const*)::'lambda'())::'lambda'(bool)>::_M_invoke(std::_Any_data const&, bool&&) (./clang+0x67ed1b6) #14 0x00005567aff21ec6 clang::Decl::dump(llvm::raw_ostream&, bool, clang::ASTDumpOutputFormat) const (./clang+0x6800ec6) #15 0x00005567aeff50eb clang::SourceTransformAction::ExecuteAction() (./clang+0x58d40eb) #16 0x00005567ada97b11 clang::FrontendAction::Execute() (./clang+0x4376b11) #17 0x00005567ada1ece3 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (./clang+0x42fdce3) #18 0x00005567adb7af7b clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (./clang+0x4459f7b) #19 0x00005567aa8c77b4 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (./clang+0x11a67b4) #20 0x00005567aa8c0d5b ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) driver.cpp:0:0 #21 0x00005567ad888559 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0 #22 0x00005567aceaa0d7 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (./clang+0x37890d7) #23 0x00005567ad888b4c clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0 #24 0x00005567ad85293e clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (./clang+0x413193e) #25 0x00005567ad85335d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (./clang+0x413235d) #26 0x00005567ad85e1ac clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (./clang+0x413d1ac) #27 0x00005567aa8c5539 clang_main(int, char**) (./clang+0x11a4539) #28 0x00007fdd6e644083 __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:342:3 #29 0x00005567aa8c096e _start (./clang+0x119f96e) ``` Relavant code: (Create CallExpr) ``` CallExpr *MyNodeCreater::CreateCall() { std::string FuncName = "Func"; QualType T = getContext().getFunctionType(getContext().UnsignedIntTy, {getContext().VoidTy}, {}); DeclarationName N = DeclarationName(&(getContext().Idents).get(PtoolsStartFuncName)); FunctionDecl *FD= FunctionDecl::Create( getContext(), getContext().getTranslationUnitDecl(), SourceLocation(), SourceLocation(), N, T, nullptr, SC_Extern); // add extern func FD->setDeclContext(getContext().getTranslationUnitDecl()); Expr *funcExpr= DeclRefExpr::Create(getContext(), NestedNameSpecifierLoc(), SourceLocation(), FD, false, SourceLocation(), FD->getType(), VK_LValue); CallExpr *callExpr= CallExpr::Create( getContext(), funcExpr, None, getContext().VoidTy, VK_LValue, SourceLocation(), FPOptionsOverride()); return callExpr; } ``` (Visit function) ``` DeclNode VisitFunctionDecl(FunctionDecl *D) override { FunctionDecl *NewFD = nullptr; DeclarationName N = D->getNameInfo().getName(); QualType T = D->getType(); ASTContext &Ctx = getContext(); NewFD = FunctionDecl::Create(Ctx, Ctx.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), N, T, nullptr, SC_None); NewFD->setDeclContext(Ctx.getTranslationUnitDecl()); PToolsAstNodeCreator astNodeCreator(getContext()); // std::cout << "N name getAsString: " << N.getAsString() << " ------------------\n"; CallExpr *func= myNodeCreater.CreateCall(); CallExpr *anotherFunc = myNodeCreater.CreateAnotherCall(); // identical function to CreateCall, with only function name change std::vector<Stmt *> NewStmts; NewStmts.push_back(func); StmtNode NewBody = Visit(D->getBody()); for (auto SubToBody : NewBody) { NewStmts.push_back(SubToBody); } NewStmts.push_back(anotherFunc ); CompoundStmt *CS = CompoundStmt::Create(getContext(), NewStmts, FPOptionsOverride(), SourceLocation(), SourceLocation()); NewFD->setBody(CS); Ctx.getTranslationUnitDecl()->addDecl(NewFD); return NewFD; } ``` (runPass function) ``` void SourceTransformAction::runPass(ASTTransformer *Pass) { std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); Clang->createDiagnostics(); CompilerInstance &CI = *Clang.get(); auto Invocation = std::make_shared<CompilerInvocation>(getCompilerInstance().getInvocation()); CI.setInvocation(std::move(Invocation)); CI.createTarget(); CI.LoadRequestedPlugins(); CI.createFileManager(); CI.createSourceManager(CI.getFileManager()); CI.createPreprocessor(getTranslationUnitKind()); CI.createASTContext(); ASTContext &NewContext = CI.getASTContext(); NewContext.addTranslationUnitDecl(); Pass->setContext(NewContext); auto &SrcManager = CI.getSourceManager(); std::cout << "Old TU: ---------------------------------\n"; getContext().getTranslationUnitDecl()->dump(); for (Decl *D : getContext().getTranslationUnitDecl()->decls()) { SourceLocation Loc = D->getLocation(); Loc = SrcManager.getExpansionLoc(Loc); // If this is for a builtin, ignore it. if (Loc.isInvalid()) continue; Pass->Visit(D); } setContext(NewContext); std::cout << "New TU: ---------------------------------\n"; getContext().getTranslationUnitDecl()->dump(); } ``` (Transform()) ``` virtual void Transform() override { runPass(new MyTransformer()); std::cout << "after runpass --------------\n"; getContext().getTranslationUnitDecl()->dump(); }; ``` The printing shows that, the transformation is OK after "NEW TU" printing, but changed after "after runpass" printing. Really need some help on this. Thanks a lot in advance!