This repository has been archived by the owner on Jan 19, 2025. It is now read-only.
forked from NN-complr-tech/llvm
-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* lab1 * lab1_1
- Loading branch information
Showing
3 changed files
with
226 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
add_llvm_library(LebedevaRenamePlugin MODULE LebedevaRenameId.cpp PLUGIN_TOOL clang) | ||
|
||
if(WIN32 OR CYGWIN) | ||
set(LLVM_LINK_COMPONENTS | ||
Support | ||
) | ||
clang_target_link_libraries(LebedevaRenamePlugin PRIVATE | ||
clangAST | ||
clangBasic | ||
clangFrontend | ||
) | ||
endif() | ||
|
||
set(CLANG_TEST_DEPS "LebedevaRenamePlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
#include "clang/AST/ASTConsumer.h" | ||
#include "clang/AST/RecursiveASTVisitor.h" | ||
#include "clang/Frontend/CompilerInstance.h" | ||
#include "clang/Frontend/FrontendPluginRegistry.h" | ||
#include "clang/Rewrite/Core/Rewriter.h" | ||
|
||
#include "llvm/ADT/StringRef.h" | ||
#include "llvm/Support/raw_ostream.h" | ||
|
||
class RenameVisitor : public clang::RecursiveASTVisitor<RenameVisitor> { | ||
private: | ||
clang::Rewriter rewriter; | ||
std::string oldName; | ||
std::string newName; | ||
|
||
public: | ||
explicit RenameVisitor(clang::Rewriter rewriter, std::string oldName, | ||
std::string newName) | ||
: rewriter(rewriter), oldName(oldName), newName(newName){}; | ||
|
||
bool VisitFunctionDecl(clang::FunctionDecl *FuncDecl) { | ||
std::string name = FuncDecl->getNameAsString(); | ||
if (name == oldName) { | ||
rewriter.ReplaceText(FuncDecl->getNameInfo().getSourceRange(), newName); | ||
rewriter.overwriteChangedFiles(); | ||
} | ||
return true; | ||
} | ||
|
||
bool VisitDeclRefExpr(clang::DeclRefExpr *DRE) { | ||
std::string name = DRE->getNameInfo().getAsString(); | ||
if (name == oldName) { | ||
rewriter.ReplaceText(DRE->getNameInfo().getSourceRange(), newName); | ||
rewriter.overwriteChangedFiles(); | ||
} | ||
return true; | ||
} | ||
|
||
bool VisitVarDecl(clang::VarDecl *declVar) { | ||
std::string name = declVar->getNameAsString(); | ||
if (name == oldName) { | ||
rewriter.ReplaceText(declVar->getLocation(), name.size(), newName); | ||
rewriter.overwriteChangedFiles(); | ||
} | ||
if (declVar->getType().getAsString() == oldName + " *" || | ||
declVar->getType().getAsString() == oldName) { | ||
rewriter.ReplaceText( | ||
declVar->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), name.size(), | ||
newName); | ||
rewriter.overwriteChangedFiles(); | ||
} | ||
return true; | ||
} | ||
|
||
bool VisitCXXRecordDecl(clang::CXXRecordDecl *CXXRDecl) { | ||
std::string name = CXXRDecl->getNameAsString(); | ||
if (name == oldName) { | ||
rewriter.ReplaceText(CXXRDecl->getLocation(), name.size(), newName); | ||
const clang::CXXDestructorDecl *CXXDD = CXXRDecl->getDestructor(); | ||
if (CXXDD) | ||
rewriter.ReplaceText(CXXDD->getLocation(), name.size() + 1, | ||
"~" + newName); | ||
rewriter.overwriteChangedFiles(); | ||
} | ||
return true; | ||
} | ||
|
||
bool VisitCXXNewExpr(clang::CXXNewExpr *CXXNExpr) { | ||
std::string name = CXXNExpr->getConstructExpr()->getType().getAsString(); | ||
if (name == oldName) { | ||
rewriter.ReplaceText(CXXNExpr->getExprLoc(), name.size() + 4, | ||
"new " + newName); | ||
rewriter.overwriteChangedFiles(); | ||
} | ||
return true; | ||
} | ||
}; | ||
|
||
class RenameIdConsumer : public clang::ASTConsumer { | ||
RenameVisitor visitor; | ||
|
||
public: | ||
explicit RenameIdConsumer(clang::CompilerInstance &compInst, | ||
std::string oldName, std::string newName) | ||
: visitor(clang::Rewriter(compInst.getSourceManager(), | ||
compInst.getLangOpts()), | ||
oldName, newName) {} | ||
void HandleTranslationUnit(clang::ASTContext &Context) override { | ||
visitor.TraverseDecl(Context.getTranslationUnitDecl()); | ||
} | ||
}; | ||
|
||
class RenameIdPlugin : public clang::PluginASTAction { | ||
private: | ||
std::string oldName; | ||
std::string newName; | ||
|
||
protected: | ||
bool ParseArgs(const clang::CompilerInstance &Compiler, | ||
const std::vector<std::string> &args) override { | ||
oldName = args[0]; | ||
newName = args[1]; | ||
if (oldName.find("=") == 0 || oldName.find("=") == std::string::npos) { | ||
llvm::errs() << "Error in the `oldName` parameter.\n"; | ||
} | ||
if (newName.find("=") == 0 || newName.find("=") == std::string::npos) { | ||
llvm::errs() << "Error in the `newName` parameter.\n"; | ||
} | ||
oldName = oldName.substr(oldName.find("=") + 1); | ||
newName = newName.substr(newName.find("=") + 1); | ||
return true; | ||
} | ||
|
||
public: | ||
std::unique_ptr<clang::ASTConsumer> | ||
CreateASTConsumer(clang::CompilerInstance &Compiler, | ||
llvm::StringRef InFile) override { | ||
return std::make_unique<RenameIdConsumer>(Compiler, oldName, newName); | ||
} | ||
}; | ||
|
||
static clang::FrontendPluginRegistry::Add<RenameIdPlugin> | ||
X("lebedeva-rename-plugin", "Renaming an identifier"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// RUN: split-file %s %t | ||
|
||
// RUN: %clang_cc1 -load %llvmshlibdir/LebedevaRenamePlugin%pluginext -add-plugin lebedeva-rename-plugin\ | ||
// RUN: -plugin-arg-lebedeva-rename-plugin OldName="A" -plugin-arg-lebedeva-rename-plugin NewName="B" %t/test1.cpp | ||
// RUN: FileCheck %s < %t/test1.cpp --check-prefix=FIRST-CHECK | ||
|
||
// FIRST-CHECK: class B { | ||
// FIRST-CHECK-NEXT: public: | ||
// FIRST-CHECK-NEXT: B() {}; | ||
// FIRST-CHECK-NEXT: ~B(); | ||
// FIRST-CHECK-NEXT: }; | ||
|
||
//--- test1.cpp | ||
class A { | ||
public: | ||
A() {}; | ||
~A(); | ||
}; | ||
|
||
// RUN: %clang_cc1 -load %llvmshlibdir/LebedevaRenamePlugin%pluginext -add-plugin lebedeva-rename-plugin\ | ||
// RUN: -plugin-arg-lebedeva-rename-plugin OldName="C" -plugin-arg-lebedeva-rename-plugin NewName="D" %t/test2.cpp | ||
// RUN: FileCheck %s < %t/test2.cpp --check-prefix=SECOND-CHECK | ||
|
||
// SECOND-CHECK: class D { | ||
// SECOND-CHECK-NEXT: private: | ||
// SECOND-CHECK-NEXT: int a; | ||
// SECOND-CHECK-NEXT: public: | ||
// SECOND-CHECK-NEXT: D() {} | ||
// SECOND-CHECK-NEXT: D(int a): a(a) {} | ||
// SECOND-CHECK-NEXT: ~D(); | ||
// SECOND-CHECK-NEXT: int getA() { | ||
// SECOND-CHECK-NEXT: return a; | ||
// SECOND-CHECK-NEXT: } | ||
// SECOND-CHECK-NEXT: }; | ||
// SECOND-CHECK-NEXT: void func() { | ||
// SECOND-CHECK-NEXT: D* c = new D(); | ||
// SECOND-CHECK-NEXT: delete c; | ||
// SECOND-CHECK-NEXT: } | ||
|
||
//--- test2.cpp | ||
class C { | ||
private: | ||
int a; | ||
public: | ||
C() {} | ||
C(int a): a(a) {} | ||
~C(); | ||
int getA() { | ||
return a; | ||
} | ||
}; | ||
void func() { | ||
C* c = new C(); | ||
delete c; | ||
} | ||
|
||
// RUN: %clang_cc1 -load %llvmshlibdir/LebedevaRenamePlugin%pluginext -add-plugin lebedeva-rename-plugin\ | ||
// RUN: -plugin-arg-lebedeva-rename-plugin OldName="func1" -plugin-arg-lebedeva-rename-plugin NewName="newFunc" %t/test3.cpp | ||
// RUN: FileCheck %s < %t/test3.cpp --check-prefix=THIRD-CHECK | ||
|
||
// THIRD-CHECK: double newFunc(int a) { | ||
// THIRD-CHECK-NEXT: int c = a + 10; | ||
// THIRD-CHECK-NEXT: double d = c * 6; | ||
// THIRD-CHECK-NEXT: return c + d; | ||
// THIRD-CHECK-NEXT: }; | ||
|
||
//--- test3.cpp | ||
double func1(int a) { | ||
int c = a + 10; | ||
double d = c * 6; | ||
return c + d; | ||
}; | ||
|
||
// RUN: %clang_cc1 -load %llvmshlibdir/LebedevaRenamePlugin%pluginext -add-plugin lebedeva-rename-plugin\ | ||
// RUN: -plugin-arg-lebedeva-rename-plugin OldName="notFunc" -plugin-arg-lebedeva-rename-plugin NewName="newFunc" %t/test4.cpp | ||
// RUN: FileCheck %s < %t/test4.cpp --check-prefix=FOURTH-CHECK | ||
|
||
// FOURTH-CHECK: int func2(int a, int b) { | ||
// FOURTH-CHECK-NEXT: int c = a + 10; | ||
// FOURTH-CHECK-NEXT: int d = c * 10; | ||
// FOURTH-CHECK-NEXT: return c + d; | ||
// FOURTH-CHECK-NEXT: }; | ||
|
||
//--- test4.cpp | ||
int func2(int a, int b) { | ||
int c = a + 10; | ||
int d = c * 10; | ||
return c + d; | ||
}; |