Skip to content
This repository was archived by the owner on Jan 19, 2025. It is now read-only.

Commit 8f9a2ad

Browse files
Korablev Nikita. Lab №1. Option №4. (#8)
1 parent e47fbee commit 8f9a2ad

File tree

3 files changed

+238
-0
lines changed

3 files changed

+238
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
add_llvm_library(RenamedIdPlugin MODULE RenameIdentificator.cpp PLUGIN_TOOL clang)
2+
3+
if(WIN32 OR CYGWIN)
4+
set(LLVM_LINK_COMPONENTS
5+
Support
6+
)
7+
clang_target_link_libraries(DeprecatedWarningPlugin PRIVATE
8+
clangAST
9+
clangBasic
10+
clangFrontend
11+
)
12+
endif()
13+
14+
set(CLANG_TEST_DEPS "RenamedIdPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE)
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#include "clang/AST/ASTConsumer.h"
2+
#include "clang/AST/RecursiveASTVisitor.h"
3+
#include "clang/Frontend/CompilerInstance.h"
4+
#include "clang/Frontend/FrontendPluginRegistry.h"
5+
#include "clang/Rewrite/Core/Rewriter.h"
6+
7+
#include "llvm/ADT/StringRef.h"
8+
#include "llvm/Support/raw_ostream.h"
9+
10+
class RenameVisitor : public clang::RecursiveASTVisitor<RenameVisitor> {
11+
private:
12+
clang::Rewriter Rewriter;
13+
std::string OldName;
14+
std::string NewName;
15+
16+
public:
17+
explicit RenameVisitor(clang::Rewriter Rewriter, std::string OldName,
18+
std::string NewName)
19+
: Rewriter(Rewriter), OldName(OldName), NewName(NewName){};
20+
21+
bool VisitFunctionDecl(clang::FunctionDecl *FD) {
22+
std::string Name = FD->getNameAsString();
23+
24+
if (Name == OldName) {
25+
Rewriter.ReplaceText(FD->getNameInfo().getSourceRange(), NewName);
26+
Rewriter.overwriteChangedFiles();
27+
}
28+
29+
return true;
30+
}
31+
32+
bool VisitDeclRefExpr(clang::DeclRefExpr *DRE) {
33+
std::string Name = DRE->getNameInfo().getAsString();
34+
35+
if (Name == OldName) {
36+
Rewriter.ReplaceText(DRE->getNameInfo().getSourceRange(), NewName);
37+
Rewriter.overwriteChangedFiles();
38+
}
39+
40+
return true;
41+
}
42+
43+
bool VisitVarDecl(clang::VarDecl *VD) {
44+
std::string Name = VD->getNameAsString();
45+
46+
if (Name == OldName) {
47+
Rewriter.ReplaceText(VD->getLocation(), Name.size(), NewName);
48+
Rewriter.overwriteChangedFiles();
49+
}
50+
51+
if (VD->getType().getAsString() == OldName + " *" ||
52+
VD->getType().getAsString() == OldName) {
53+
Rewriter.ReplaceText(VD->getTypeSourceInfo()->getTypeLoc().getBeginLoc(),
54+
Name.size(), NewName);
55+
Rewriter.overwriteChangedFiles();
56+
}
57+
58+
return true;
59+
}
60+
61+
bool VisitCXXRecordDecl(clang::CXXRecordDecl *CXXRD) {
62+
std::string Name = CXXRD->getNameAsString();
63+
64+
if (Name == OldName) {
65+
Rewriter.ReplaceText(CXXRD->getLocation(), Name.size(), NewName);
66+
67+
const clang::CXXDestructorDecl *CXXDD = CXXRD->getDestructor();
68+
if (CXXDD)
69+
Rewriter.ReplaceText(CXXDD->getLocation(), Name.size() + 1,
70+
"~" + NewName);
71+
72+
Rewriter.overwriteChangedFiles();
73+
}
74+
75+
return true;
76+
}
77+
78+
bool VisitCXXNewExpr(clang::CXXNewExpr *CXXNE) {
79+
std::string Name = CXXNE->getConstructExpr()->getType().getAsString();
80+
81+
if (Name == OldName) {
82+
Rewriter.ReplaceText(CXXNE->getExprLoc(), Name.size() + 4,
83+
"new " + NewName);
84+
Rewriter.overwriteChangedFiles();
85+
}
86+
87+
return true;
88+
}
89+
};
90+
91+
class RenameIdConsumer : public clang::ASTConsumer {
92+
RenameVisitor visitor;
93+
94+
public:
95+
explicit RenameIdConsumer(clang::CompilerInstance &CI, std::string OldName,
96+
std::string NewName)
97+
: visitor(clang::Rewriter(CI.getSourceManager(), CI.getLangOpts()),
98+
OldName, NewName) {}
99+
100+
void HandleTranslationUnit(clang::ASTContext &Context) override {
101+
visitor.TraverseDecl(Context.getTranslationUnitDecl());
102+
}
103+
};
104+
105+
class RenameIdPlugin : public clang::PluginASTAction {
106+
private:
107+
std::string OldName;
108+
std::string NewName;
109+
110+
protected:
111+
bool ParseArgs(const clang::CompilerInstance &Compiler,
112+
const std::vector<std::string> &args) override {
113+
OldName = args[0];
114+
NewName = args[1];
115+
116+
if (OldName.find("=") == 0 || OldName.find("=") == std::string::npos) {
117+
llvm::errs() << "Error entering the `OldName` parameter."
118+
<< "\n";
119+
}
120+
if (NewName.find("=") == 0 || NewName.find("=") == std::string::npos) {
121+
llvm::errs() << "Error entering the `NewName` parameter."
122+
<< "\n";
123+
}
124+
125+
OldName = OldName.substr(OldName.find("=") + 1);
126+
NewName = NewName.substr(NewName.find("=") + 1);
127+
128+
return true;
129+
}
130+
131+
public:
132+
std::unique_ptr<clang::ASTConsumer>
133+
CreateASTConsumer(clang::CompilerInstance &Compiler,
134+
llvm::StringRef InFile) override {
135+
return std::make_unique<RenameIdConsumer>(Compiler, OldName, NewName);
136+
}
137+
};
138+
139+
static clang::FrontendPluginRegistry::Add<RenameIdPlugin>
140+
X("renamed-id", "Idetificator was renamed.");
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// RUN: split-file %s %t
2+
// RUN: %clang_cc1 -load %llvmshlibdir/RenamedIdPlugin%pluginext -add-plugin renamed-id\
3+
// RUN: -plugin-arg-renamed-id OldName="A"\
4+
// RUN: -plugin-arg-renamed-id NewName="B" %t/test_1.cpp
5+
// RUN: FileCheck %s < %t/test_1.cpp --check-prefix=CLASS-CHECK
6+
7+
// CLASS-CHECK: class B {
8+
// CLASS-CHECK-NEXT: public:
9+
// CLASS-CHECK-NEXT: B() {};
10+
// CLASS-CHECK-NEXT: ~B();
11+
// CLASS-CHECK-NEXT: };
12+
// CLASS-CHECK-NEXT: void func() {
13+
// CLASS-CHECK-NEXT: B* a = new B;
14+
// CLASS-CHECK-NEXT: B b;
15+
// CLASS-CHECK-NEXT: delete a;
16+
// CLASS-CHECK-NEXT: };
17+
18+
//--- test_1.cpp
19+
class A {
20+
public:
21+
A() {};
22+
~A();
23+
};
24+
void func() {
25+
A* a = new A;
26+
A b;
27+
delete a;
28+
};
29+
30+
// RUN: %clang_cc1 -load %llvmshlibdir/RenamedIdPlugin%pluginext -add-plugin renamed-id\
31+
// RUN: -plugin-arg-renamed-id OldName="A"\
32+
// RUN: -plugin-arg-renamed-id NewName="B" %t/test_2.cpp
33+
// RUN: FileCheck %s < %t/test_2.cpp --check-prefix=SUM-CHECK
34+
35+
// SUM-CHECK: int sum(int a, int b) {
36+
// SUM-CHECK-NEXT: int c = sum(1, 2);
37+
// SUM-CHECK-NEXT: c++;
38+
// SUM-CHECK-NEXT: a += b;
39+
// SUM-CHECK-NEXT: return a+b;
40+
// SUM-CHECK-NEXT: };
41+
42+
//--- test_2.cpp
43+
int sum(int a, int b) {
44+
int c = sum(1, 2);
45+
c++;
46+
a += b;
47+
return a+b;
48+
};
49+
50+
// RUN: %clang_cc1 -load %llvmshlibdir/RenamedIdPlugin%pluginext -add-plugin renamed-id\
51+
// RUN: -plugin-arg-renamed-id OldName="C"\
52+
// RUN: -plugin-arg-renamed-id NewName="Renamed_C" %t/test_3.cpp
53+
// RUN: FileCheck %s < %t/test_3.cpp --check-prefix=CLASS2-CHECK
54+
55+
// CLASS2-CHECK: class Renamed_C {
56+
// CLASS2-CHECK-NEXT: private:
57+
// CLASS2-CHECK-NEXT: int a;
58+
// CLASS2-CHECK-NEXT: int b;
59+
// CLASS2-CHECK-NEXT: public:
60+
// CLASS2-CHECK-NEXT: Renamed_C() {}
61+
// CLASS2-CHECK-NEXT: Renamed_C(int a, int b): a(a), b(b) {}
62+
// CLASS2-CHECK-NEXT: ~Renamed_C();
63+
// CLASS2-CHECK-NEXT: };
64+
// CLASS2-CHECK-NEXT: void func() {
65+
// CLASS2-CHECK-NEXT: Renamed_C a;
66+
// CLASS2-CHECK-NEXT: Renamed_C* b = new Renamed_C(1, 2);
67+
// CLASS2-CHECK-NEXT: delete b;
68+
// CLASS2-CHECK-NEXT: }
69+
70+
//--- test_3.cpp
71+
class C {
72+
private:
73+
int a;
74+
int b;
75+
public:
76+
C() {}
77+
C(int a, int b): a(a), b(b) {}
78+
~C();
79+
};
80+
void func() {
81+
C a;
82+
C* b = new C(1, 2);
83+
delete b;
84+
};

0 commit comments

Comments
 (0)