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

Commit

Permalink
Lebedeva Ksenia Lab1 Var4 (#164)
Browse files Browse the repository at this point in the history
* lab1

* lab1_1
  • Loading branch information
ks2k23 authored May 20, 2024
1 parent f36d729 commit e08e388
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 0 deletions.
14 changes: 14 additions & 0 deletions clang/labs/lab1/lebedeva_ksenia/CMakeLists.txt
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)
123 changes: 123 additions & 0 deletions clang/labs/lab1/lebedeva_ksenia/LebedevaRenameId.cpp
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");
89 changes: 89 additions & 0 deletions clang/test/lab1/lebedeva_ksenia/test.cpp
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;
};

0 comments on commit e08e388

Please sign in to comment.