From 84e732df8fc8c499eb4a0575a8df16fcbd7a9a15 Mon Sep 17 00:00:00 2001 From: AveZorgen <78862872+AveZorgen@users.noreply.github.com> Date: Mon, 4 Mar 2024 17:18:35 +0300 Subject: [PATCH 01/18] kulikov lab1 (#1) * first commit * remove redundant foreach * getting funcname shorter --- clang/CMakeLists.txt | 1 + clang/labs/CMakeLists.txt | 9 ++++ clang/labs/lab1/CMakeLists.txt | 10 ++++ clang/labs/lab1/kulikov_artem/CMakeLists.txt | 14 +++++ .../lab1/kulikov_artem/DeprecatedWarning.cpp | 54 +++++++++++++++++++ clang/test/lab1/kulikov_artem/_demo.cpp | 27 ++++++++++ 6 files changed, 115 insertions(+) create mode 100644 clang/labs/CMakeLists.txt create mode 100644 clang/labs/lab1/CMakeLists.txt create mode 100644 clang/labs/lab1/kulikov_artem/CMakeLists.txt create mode 100644 clang/labs/lab1/kulikov_artem/DeprecatedWarning.cpp create mode 100644 clang/test/lab1/kulikov_artem/_demo.cpp diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index f7936d72e0882..dbae05d01c71e 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -472,6 +472,7 @@ add_subdirectory(runtime) option(CLANG_BUILD_EXAMPLES "Build CLANG example programs by default." OFF) add_subdirectory(examples) +add_subdirectory(labs) if(APPLE) # this line is needed as a cleanup to ensure that any CMakeCaches with the old diff --git a/clang/labs/CMakeLists.txt b/clang/labs/CMakeLists.txt new file mode 100644 index 0000000000000..89e39d86277c9 --- /dev/null +++ b/clang/labs/CMakeLists.txt @@ -0,0 +1,9 @@ +FILE(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) +FOREACH(child ${children}) + IF(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${child}) + add_subdirectory(${child}) + ENDIF() +ENDFOREACH() + +set(CLANG_TEST_DEPS ${CLANG_TEST_DEPS} PARENT_SCOPE) +message("CLANG_TEST_DEPS ${CLANG_TEST_DEPS}") \ No newline at end of file diff --git a/clang/labs/lab1/CMakeLists.txt b/clang/labs/lab1/CMakeLists.txt new file mode 100644 index 0000000000000..a038b07706e81 --- /dev/null +++ b/clang/labs/lab1/CMakeLists.txt @@ -0,0 +1,10 @@ +if(CLANG_PLUGIN_SUPPORT) + FILE(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) + FOREACH(child ${children}) + IF(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${child}) + add_subdirectory(${child}) + ENDIF() + ENDFOREACH() + + set(CLANG_TEST_DEPS ${CLANG_TEST_DEPS} PARENT_SCOPE) +endif() \ No newline at end of file diff --git a/clang/labs/lab1/kulikov_artem/CMakeLists.txt b/clang/labs/lab1/kulikov_artem/CMakeLists.txt new file mode 100644 index 0000000000000..6139bbc52348a --- /dev/null +++ b/clang/labs/lab1/kulikov_artem/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(DeprecatedWarningPlugin MODULE DeprecatedWarning.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(DeprecatedWarningPlugin PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "DeprecatedWarningPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) \ No newline at end of file diff --git a/clang/labs/lab1/kulikov_artem/DeprecatedWarning.cpp b/clang/labs/lab1/kulikov_artem/DeprecatedWarning.cpp new file mode 100644 index 0000000000000..e23fa69beda2f --- /dev/null +++ b/clang/labs/lab1/kulikov_artem/DeprecatedWarning.cpp @@ -0,0 +1,54 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" + +using namespace clang; + +class WarnVisitor : public RecursiveASTVisitor { +public: + explicit WarnVisitor(ASTContext *Context) : Context(Context) {} + + bool VisitFunctionDecl(FunctionDecl *Func) { + const char *name_data = Func->getName().data(); + if (std::string(name_data).find("deprecated") != std::string::npos) { + DiagnosticsEngine &Diags = Context->getDiagnostics(); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning, + "Function '%0' contains 'deprecated' in its name"); + Diags.Report(Func->getLocation(), DiagID) << name_data; + } + return true; + } + +private: + ASTContext *Context; +}; + +class WarnConsumer : public ASTConsumer { +public: + explicit WarnConsumer(CompilerInstance &CI) : Visitor(&CI.getASTContext()) {} + + void HandleTranslationUnit(ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + } + +private: + WarnVisitor Visitor; +}; + +class WarnPlugin : public clang::PluginASTAction { +public: + std::unique_ptr CreateASTConsumer ( + clang::CompilerInstance &Compiler, llvm::StringRef InFile) override { + return std::unique_ptr(new WarnConsumer(Compiler)); + } + +protected: + bool ParseArgs(const clang::CompilerInstance &Compiler, + const std::vector &args) override { + return true; + } +}; + +static FrontendPluginRegistry::Add +X("warn-deprecated", "Prints a warning if a function name contains 'deprecated'"); \ No newline at end of file diff --git a/clang/test/lab1/kulikov_artem/_demo.cpp b/clang/test/lab1/kulikov_artem/_demo.cpp new file mode 100644 index 0000000000000..87bbc23299126 --- /dev/null +++ b/clang/test/lab1/kulikov_artem/_demo.cpp @@ -0,0 +1,27 @@ +// RUN: split-file %s %t +// RUN: %clang_cc1 -load %llvmshlibdir/DeprecatedWarningPlugin%pluginext -add-plugin warn-deprecated -verify %t/bad_one.cpp +// RUN: %clang_cc1 -load %llvmshlibdir/DeprecatedWarningPlugin%pluginext -add-plugin warn-deprecated -verify %t/good_one.cpp + +//--- good_one.cpp +// expected-no-diagnostics +int sum(int a, int b) { + return a + b; +} + +void deprecate_sum(int a, int b) { + ; +} + + +//--- bad_one.cpp +int _deprecated_sum(int a, int b) { // expected-warning {{Function '_deprecated_sum' contains 'deprecated' in its name}} + return a + b; +} + +void _sumdeprecated_(int a, int b) { // expected-warning {{Function '_sumdeprecated_' contains 'deprecated' in its name}} + ; +} + +void _sum_deprecated(int a, int b) { // expected-warning {{Function '_sum_deprecated' contains 'deprecated' in its name}} + ; +} \ No newline at end of file From 5a86d17312f590a45744126443212537e7bfbd07 Mon Sep 17 00:00:00 2001 From: Nikita Ivanov <87970276+Atikin-NT@users.noreply.github.com> Date: Sun, 10 Mar 2024 21:53:06 +0300 Subject: [PATCH 02/18] =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=A4=D0=983.=20=D0=9B?= =?UTF-8?q?=D0=B0=D0=B1=D0=BE=D1=80=D0=B0=D1=82=D0=BE=D1=80=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=E2=84=96=201.?= =?UTF-8?q?=20(#2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deprecated functions warning plugin. --- clang/labs/lab1/ivanov_nikita/CMakeLists.txt | 14 +++++ .../lab1/ivanov_nikita/deprecatedMatcher.cpp | 59 +++++++++++++++++++ clang/test/lab1/ivanov_nikita/dep_matcher.cpp | 16 +++++ 3 files changed, 89 insertions(+) create mode 100644 clang/labs/lab1/ivanov_nikita/CMakeLists.txt create mode 100644 clang/labs/lab1/ivanov_nikita/deprecatedMatcher.cpp create mode 100644 clang/test/lab1/ivanov_nikita/dep_matcher.cpp diff --git a/clang/labs/lab1/ivanov_nikita/CMakeLists.txt b/clang/labs/lab1/ivanov_nikita/CMakeLists.txt new file mode 100644 index 0000000000000..8a0944765253c --- /dev/null +++ b/clang/labs/lab1/ivanov_nikita/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(clangDepMatcher MODULE deprecatedMatcher.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(clangDepMatcher PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "clangDepMatcher" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/labs/lab1/ivanov_nikita/deprecatedMatcher.cpp b/clang/labs/lab1/ivanov_nikita/deprecatedMatcher.cpp new file mode 100644 index 0000000000000..c64bb61e983e1 --- /dev/null +++ b/clang/labs/lab1/ivanov_nikita/deprecatedMatcher.cpp @@ -0,0 +1,59 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" + +using namespace clang; + +class DepConsumer : public ASTConsumer { + CompilerInstance &Instance; + +public: + explicit DepConsumer(CompilerInstance &CI) : Instance(CI) {} + + void HandleTranslationUnit(ASTContext &Context) override { + struct Visitor : public RecursiveASTVisitor { + ASTContext *Context; + + Visitor(ASTContext *Context) : Context(Context) {} + + bool VisitFunctionDecl(FunctionDecl *Func) { + if (Func->getNameInfo().getAsString().find("deprecated") != + std::string::npos) { + DiagnosticsEngine &Diags = Context->getDiagnostics(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Warning, "Deprecated in function name"); + Diags.Report(Func->getLocation(), DiagID) + << Func->getNameInfo().getAsString(); + } + return true; + } + } v(&Instance.getASTContext()); + + v.TraverseDecl(Context.getTranslationUnitDecl()); + } +}; + +class DeprecatedPlugin : public PluginASTAction { +protected: + std::unique_ptr + CreateASTConsumer(CompilerInstance &Compiler, + llvm::StringRef InFile) override { + return std::make_unique(Compiler); + } + + bool ParseArgs(const CompilerInstance &Compiler, + const std::vector &args) override { + if (!args.empty() && args[0] == "help") + PrintHelp(llvm::errs()); + + return true; + } + + void PrintHelp(llvm::raw_ostream &ros) { + ros << "Deprecated Plugin version 1.0\n"; + } +}; + +static FrontendPluginRegistry::Add X("deprecated-match", + "deprecated match"); diff --git a/clang/test/lab1/ivanov_nikita/dep_matcher.cpp b/clang/test/lab1/ivanov_nikita/dep_matcher.cpp new file mode 100644 index 0000000000000..f8bfffd39840e --- /dev/null +++ b/clang/test/lab1/ivanov_nikita/dep_matcher.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/clangDepMatcher%pluginext -plugin deprecated-match %s 2>&1 | FileCheck %s --check-prefix=DEPRECATED +// REQUIRES: plugins + +// DEPRECATED: warning: Deprecated in function name +void foo_deprecated(int a, int b); + +// DEPRECATED: warning: Deprecated in function name +void deprecated(int c); + +// DEPRECATED-NOT: warning: Deprecated in function name +void abc(); + +// RUN: %clang_cc1 -load %llvmshlibdir/clangDepMatcher%pluginext -plugin deprecated-match %s -plugin-arg-deprecated-match help 2>&1 | FileCheck %s --check-prefix=HELP +// REQUIRES: plugins + +// HELP: Deprecated Plugin version 1.0 From d6f98a1f7df8769c03fabf2e80722c9094d7c049 Mon Sep 17 00:00:00 2001 From: Zakharov Artem <108222700+un1i@users.noreply.github.com> Date: Thu, 14 Mar 2024 23:47:46 +0300 Subject: [PATCH 03/18] Zakharov Artem. Lab 1. Option 4. (#4) * Create rename plugin --- clang/labs/lab1/zakharov_artem/CMakeLists.txt | 14 ++ clang/labs/lab1/zakharov_artem/RenameIds.cpp | 197 ++++++++++++++++ clang/test/lab1/zakharov_artem/test.cpp | 212 ++++++++++++++++++ 3 files changed, 423 insertions(+) create mode 100644 clang/labs/lab1/zakharov_artem/CMakeLists.txt create mode 100644 clang/labs/lab1/zakharov_artem/RenameIds.cpp create mode 100644 clang/test/lab1/zakharov_artem/test.cpp diff --git a/clang/labs/lab1/zakharov_artem/CMakeLists.txt b/clang/labs/lab1/zakharov_artem/CMakeLists.txt new file mode 100644 index 0000000000000..72bda7ecd1f97 --- /dev/null +++ b/clang/labs/lab1/zakharov_artem/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(RenamePlugin MODULE RenameIds.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(RenamePlugin PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "RenamePlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/labs/lab1/zakharov_artem/RenameIds.cpp b/clang/labs/lab1/zakharov_artem/RenameIds.cpp new file mode 100644 index 0000000000000..ee465535aed45 --- /dev/null +++ b/clang/labs/lab1/zakharov_artem/RenameIds.cpp @@ -0,0 +1,197 @@ +#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" + +enum class IdType { Var, Func, Class }; + +class RenameVisitor : public clang::RecursiveASTVisitor { +public: + explicit RenameVisitor(clang::Rewriter rewriter, IdType type, + clang::StringRef cur_name, clang::StringRef new_name) + : rewriter(rewriter), type(type), cur_name(cur_name), new_name(new_name) { + } + + bool VisitFunctionDecl(clang::FunctionDecl *func) { + if (type == IdType::Func && func->getName() == cur_name) { + rewriter.ReplaceText(func->getNameInfo().getSourceRange(), new_name); + } + return true; + } + + bool VisitCallExpr(clang::CallExpr *call) { + if (type == IdType::Func) { + clang::FunctionDecl *callee = call->getDirectCallee(); + if (callee && callee->getName() == cur_name) { + rewriter.ReplaceText(call->getCallee()->getSourceRange(), new_name); + } + } + return true; + } + + bool VisitVarDecl(clang::VarDecl *var) { + if (type == IdType::Var && var->getName() == cur_name) { + rewriter.ReplaceText(var->getLocation(), cur_name.size(), new_name); + } + if (type == IdType::Class && + var->getType().getAsString() == cur_name + " *") { + rewriter.ReplaceText(var->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), + cur_name.size(), new_name); + } + if (type == IdType::Class && var->getType().getAsString() == cur_name) { + rewriter.ReplaceText( + var->getTypeSourceInfo()->getTypeLoc().getSourceRange(), new_name); + } + return true; + } + + bool VisitDeclRefExpr(clang::DeclRefExpr *expr) { + clang::VarDecl *var = clang::dyn_cast(expr->getDecl()); + if (type == IdType::Var && var && var->getName() == cur_name) { + rewriter.ReplaceText(expr->getSourceRange(), new_name); + } + return true; + } + + bool VisitCXXRecordDecl(clang::CXXRecordDecl *record) { + if (type == IdType::Class && record->getName() == cur_name) { + rewriter.ReplaceText(record->getLocation(), new_name); + const auto *destructor = record->getDestructor(); + if (destructor) { + rewriter.ReplaceText(destructor->getLocation(), cur_name.size() + 1, + '~' + new_name); + } + } + return true; + } + + bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *constructor) { + if (type == IdType::Class) { + if (constructor->getNameAsString() == cur_name) { + rewriter.ReplaceText(constructor->getLocation(), cur_name.size(), + new_name); + } + } + return true; + } + + bool VisitCXXNewExpr(clang::CXXNewExpr *newExpr) { + if (type == IdType::Class) { + if (newExpr->getConstructExpr()->getType().getAsString() == cur_name) { + rewriter.ReplaceText(newExpr->getExprLoc(), cur_name.size() + 4, + "new " + new_name); + } + } + return true; + } + + bool save_changes() { return rewriter.overwriteChangedFiles(); } + +private: + clang::Rewriter rewriter; + IdType type; + std::string cur_name; + std::string new_name; +}; + +class RenameASTConsumer : public clang::ASTConsumer { +public: + explicit RenameASTConsumer(clang::CompilerInstance &CI, IdType type, + clang::StringRef cur_name, + clang::StringRef new_name) + : Visitor(clang::Rewriter(CI.getSourceManager(), CI.getLangOpts()), type, + cur_name, new_name) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + Visitor.TraverseDecl(context.getTranslationUnitDecl()); + if (Visitor.save_changes()) { + llvm::errs() << "An error occurred while saving changes to a file!\n"; + } + } + +private: + RenameVisitor Visitor; +}; + +class RenamePlugin : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &CI, + clang::StringRef InFile) override { + return std::make_unique(CI, type, cur_name, new_name); + } + +protected: + bool ParseArgs(const clang::CompilerInstance &CI, + const std::vector &args) override { + std::vector> params = { + {"type=", ""}, {"cur-name=", ""}, {"new-name=", ""}}; + + if (!args.empty() && args[0] == "help") { + PrintHelp(llvm::errs()); + return true; + } + + if (args.size() < 3) { + PrintParamsError(CI); + return false; + } + + for (const auto &arg : args) { + bool is_found = false; + for (auto ¶m : params) { + if (arg.find(param.first) == 0 && param.second.empty()) { + param.second = arg.substr(param.first.size()); + is_found = true; + break; + } + } + if (!is_found) { + PrintParamsError(CI); + return false; + } + } + + std::vector> id_type = { + {"var", IdType::Var}, {"func", IdType::Func}, {"class", IdType::Class}}; + size_t i; + for (i = 0; i < id_type.size(); i++) { + if (params[0].second == id_type[i].first) { + type = id_type[i].second; + break; + } + } + if (i == id_type.size()) { + PrintParamsError(CI); + return false; + } + cur_name = params[1].second; + new_name = params[2].second; + return true; + } + + void PrintHelp(llvm::raw_ostream &ros) { + ros << "Specify three required arguments:\n" + "-plugin-arg-rename type=[\"var\", \"func\", \"class\"]\n" + "-plugin-arg-rename cur-name=\"Current identifier name\"\n" + "-plugin-arg-rename new-name=\"New identifier name\"\n"; + } + + void PrintParamsError(const clang::CompilerInstance &CI) { + clang::DiagnosticsEngine &D = CI.getDiagnostics(); + + D.Report( + D.getCustomDiagID(clang::DiagnosticsEngine::Error, + "Invalid arguments\n" + "Specify \"-plugin-arg-rename help\" for usage\n")); + } + +private: + IdType type; + std::string cur_name; + std::string new_name; +}; + +static clang::FrontendPluginRegistry::Add + X("rename", "Rename variable, function or class"); diff --git a/clang/test/lab1/zakharov_artem/test.cpp b/clang/test/lab1/zakharov_artem/test.cpp new file mode 100644 index 0000000000000..544ab72cecf9d --- /dev/null +++ b/clang/test/lab1/zakharov_artem/test.cpp @@ -0,0 +1,212 @@ +// RUN: split-file %s %t + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=var\ +// RUN: -plugin-arg-rename cur-name=a\ +// RUN: -plugin-arg-rename new-name=new_var %t/rename_var.cpp +// RUN: FileCheck %s < %t/rename_var.cpp --check-prefix=VAR + +// VAR: int func() { +// VAR-NEXT: int new_var = 2, b = 2; +// VAR-NEXT: new_var = b + new_var; +// VAR-NEXT: new_var++; +// VAR-NEXT: return new_var; +// VAR-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=var\ +// RUN: -plugin-arg-rename cur-name=c\ +// RUN: -plugin-arg-rename new-name=new_var %t/rename_non_existent_var.cpp +// RUN: FileCheck %s < %t/rename_non_existent_var.cpp --check-prefix=NON_EXIST_VAR + +// NON_EXIST_VAR: int func() { +// NON_EXIST_VAR-NEXT: int a = 2; +// NON_EXIST_VAR-NEXT: int b = 3; +// NON_EXIST_VAR-NEXT: b += a; +// NON_EXIST_VAR-NEXT: a++; +// NON_EXIST_VAR-NEXT: return b - a; +// NON_EXIST_VAR-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=func\ +// RUN: -plugin-arg-rename cur-name=function\ +// RUN: -plugin-arg-rename new-name=new_func %t/rename_func.cpp +// RUN: FileCheck %s < %t/rename_func.cpp --check-prefix=FUNC + +// FUNC: int new_func(int param) { +// FUNC-NEXT: int a; +// FUNC-NEXT: a = 2; +// FUNC-NEXT: return param + a; +// FUNC-NEXT: } +// FUNC-NEXT: int other_func(){ +// FUNC-NEXT: new_func(3); +// FUNC-NEXT: int a = new_func(2) + 3; +// FUNC-NEXT: return a; +// FUNC-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=func\ +// RUN: -plugin-arg-rename cur-name=function\ +// RUN: -plugin-arg-rename new-name=f %t/rename_non_existent_func.cpp +// RUN: FileCheck %s < %t/rename_non_existent_func.cpp --check-prefix=NON_EXIST_FUNC + +// NON_EXIST_FUNC: int func(int a) { +// NON_EXIST_FUNC-NEXT: int b = 2; +// NON_EXIST_FUNC-NEXT: return a + b; +// NON_EXIST_FUNC-NEXT: } +// NON_EXIST_FUNC: void func2() { +// NON_EXIST_FUNC-NEXT: int c = func(2); +// NON_EXIST_FUNC-NEXT: int b = func(c) + func(3); +// NON_EXIST_FUNC-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=class\ +// RUN: -plugin-arg-rename cur-name=Base\ +// RUN: -plugin-arg-rename new-name=SimpleClass %t/rename_class.cpp +// RUN: FileCheck %s < %t/rename_class.cpp --check-prefix=CLASS + +// CLASS: class SimpleClass{ +// CLASS-NEXT: private: +// CLASS-NEXT: int a; +// CLASS-NEXT: int b; +// CLASS-NEXT: public: +// CLASS-NEXT: SimpleClass() {} +// CLASS-NEXT: SimpleClass(int a, int b): a(a), b(b) {} +// CLASS-NEXT: ~SimpleClass(); +// CLASS-NEXT: }; +// CLASS: void func() { +// CLASS-NEXT: SimpleClass a; +// CLASS-NEXT: SimpleClass* var = new SimpleClass(1, 2); +// CLASS-NEXT: delete var; +// CLASS-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=class\ +// RUN: -plugin-arg-rename cur-name=B\ +// RUN: -plugin-arg-rename new-name=C %t/rename_non_existent_class.cpp +// RUN: FileCheck %s < %t/rename_non_existent_class.cpp --check-prefix=NON_EXIST_CLASS + +// NON_EXIST_CLASS: class A{ +// NON_EXIST_CLASS-NEXT: private: +// NON_EXIST_CLASS-NEXT: int var1; +// NON_EXIST_CLASS-NEXT: double var2; +// NON_EXIST_CLASS-NEXT: public: +// NON_EXIST_CLASS-NEXT: A() {}; +// NON_EXIST_CLASS-NEXT: ~A() {}; +// NON_EXIST_CLASS-NEXT: }; +// NON_EXIST_CLASS: void func() { +// NON_EXIST_CLASS-NEXT: A var1; +// NON_EXIST_CLASS-NEXT: A* var2 = new A; +// NON_EXIST_CLASS-NEXT: delete var2; +// NON_EXIST_CLASS-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename help\ +// RUN: 2>&1 | FileCheck %s --check-prefix=HELP + +// HELP: Specify three required arguments: +// HELP-NEXT: -plugin-arg-rename type=["var", "func", "class"] +// HELP-NEXT: -plugin-arg-rename cur-name="Current identifier name" +// HELP-NEXT: -plugin-arg-rename new-name="New identifier name" + +// RUN: not %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename cur-name=B\ +// RUN: -plugin-arg-rename new-name=C\ +// RUN: 2>&1 | FileCheck %s --check-prefix=ERROR + +// RUN: not %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename cur-name=B\ +// RUN: -plugin-arg-rename new-name=C\ +// RUN: -plugin-arg-rename param=val\ +// RUN: 2>&1 | FileCheck %s --check-prefix=ERROR + +// RUN: not %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=undefined\ +// RUN: -plugin-arg-rename cur-name=B\ +// RUN: -plugin-arg-rename new-name=C\ +// RUN: 2>&1 | FileCheck %s --check-prefix=ERROR + +// RUN: not %clang_cc1 -load %llvmshlibdir/RenamePlugin%pluginext\ +// RUN: -add-plugin rename\ +// RUN: 2>&1 | FileCheck %s --check-prefix=ERROR + +//ERROR: Invalid arguments +//ERROR-NEXT: Specify "-plugin-arg-rename help" for usage + +//--- rename_var.cpp +int func() { + int a = 2, b = 2; + a = b + a; + a++; + return a; +} +//--- rename_non_existent_var.cpp +int func() { + int a = 2; + int b = 3; + b += a; + a++; + return b - a; +} +//--- rename_func.cpp +int function(int param) { + int a; + a = 2; + return param + a; +} +int other_func(){ + function(3); + int a = function(2) + 3; + return a; +} +//--- rename_non_existent_func.cpp +int func(int a) { + int b = 2; + return a + b; +} + +void func2() { + int c = func(2); + int b = func(c) + func(3); +} +//--- rename_class.cpp +class Base{ + private: + int a; + int b; + public: + Base() {} + Base(int a, int b): a(a), b(b) {} + ~Base(); +}; + +void func() { + Base a; + Base* var = new Base(1, 2); + delete var; +} +//--- rename_non_existent_class.cpp +class A{ + private: + int var1; + double var2; + public: + A() {}; + ~A() {}; +}; + +void func() { + A var1; + A* var2 = new A; + delete var2; +} From dc4b1b7925c3171958bac30f58b61e38dfa80618 Mon Sep 17 00:00:00 2001 From: nol0n Date: Fri, 15 Mar 2024 03:34:23 +0300 Subject: [PATCH 04/18] Sharapov Georgiy. First Lab. (#3) --- .../labs/lab1/sharapov_georgiy/CMakeLists.txt | 14 ++ .../sharapov_georgiy/DepWarningPlugin.cpp | 108 +++++++++++++++ clang/test/lab1/sharapov_georgiy/test.cpp | 127 ++++++++++++++++++ 3 files changed, 249 insertions(+) create mode 100644 clang/labs/lab1/sharapov_georgiy/CMakeLists.txt create mode 100644 clang/labs/lab1/sharapov_georgiy/DepWarningPlugin.cpp create mode 100644 clang/test/lab1/sharapov_georgiy/test.cpp diff --git a/clang/labs/lab1/sharapov_georgiy/CMakeLists.txt b/clang/labs/lab1/sharapov_georgiy/CMakeLists.txt new file mode 100644 index 0000000000000..ac5bfa022a417 --- /dev/null +++ b/clang/labs/lab1/sharapov_georgiy/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(DepWarningPlugin MODULE DepWarningPlugin.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(DepWarningPlugin PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "DepWarningPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/labs/lab1/sharapov_georgiy/DepWarningPlugin.cpp b/clang/labs/lab1/sharapov_georgiy/DepWarningPlugin.cpp new file mode 100644 index 0000000000000..bc95cb0890266 --- /dev/null +++ b/clang/labs/lab1/sharapov_georgiy/DepWarningPlugin.cpp @@ -0,0 +1,108 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Lex/Lexer.h" + +class DepWarningVisitor : public clang::RecursiveASTVisitor { +public: + explicit DepWarningVisitor(std::string style, bool help) + : attrStyle(style), helpFlag(help) {} + + bool VisitFunctionDecl(clang::FunctionDecl *F) { + if (F->hasAttr() && !helpFlag) { + clang::DiagnosticsEngine &Diag = F->getASTContext().getDiagnostics(); + unsigned DiagID = 0; + + if (decl2str(F).find("__attribute__((deprecated") != std::string::npos) { + if (attrStyle == "c++14") { + return true; + } + DiagID = Diag.getCustomDiagID(clang::DiagnosticsEngine::Warning, + "function '%0' is deprecated (gcc)"); + } else { + if (attrStyle == "gcc") { + return true; + } + DiagID = Diag.getCustomDiagID(clang::DiagnosticsEngine::Warning, + "function '%0' is deprecated (c++14)"); + } + + Diag.Report(F->getLocation(), DiagID) << F->getNameAsString(); + } + return true; + } + +private: + std::string attrStyle; + bool helpFlag; + + std::string decl2str(clang::FunctionDecl *F) { + clang::SourceRange srcRange = F->getSourceRange(); + return clang::Lexer::getSourceText( + clang::CharSourceRange::getTokenRange(srcRange), + F->getASTContext().getSourceManager(), + F->getASTContext().getLangOpts(), 0) + .str(); + } +}; + +class DepWarningConsumer : public clang::ASTConsumer { +public: + explicit DepWarningConsumer(std::string style, bool help) + : Visitor(style, help) {} + + void HandleTranslationUnit(clang::ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + } + +private: + DepWarningVisitor Visitor; +}; + +class DepWarningAction : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &Compiler, + llvm::StringRef InFile) override { + return std::make_unique(attrStyle, help); + } + +protected: + bool ParseArgs(const clang::CompilerInstance &Compiler, + const std::vector &args) override { + for (const auto &Arg : args) { + if (Arg == "-help") { + help = true; + llvm::outs() << "" + "\n --attr-style= - Select which style of " + "attributes will be displayed," + "" + "" + "\n options: gcc, c++14, " + "both. Default value 'both'.\n\n" + ""; + } else if (Arg.find("--attr-style=") == 0) { + attrStyle = Arg.substr(std::string("--attr-style=").length()); + if (attrStyle != "c++14" && attrStyle != "gcc" && attrStyle != "both") { + clang::DiagnosticsEngine &Diag = Compiler.getDiagnostics(); + unsigned DiagID = Diag.getCustomDiagID( + clang::DiagnosticsEngine::Warning, + "Invalid value for attr-style. Using default value 'both'."); + Diag.Report(DiagID); + attrStyle = "both"; + } + } + } + return true; + } + +private: + std::string attrStyle = "both"; + bool help = false; +}; + +static clang::FrontendPluginRegistry::Add + X("DepEmitWarning", "Emit warning for each deprecated function"); diff --git a/clang/test/lab1/sharapov_georgiy/test.cpp b/clang/test/lab1/sharapov_georgiy/test.cpp new file mode 100644 index 0000000000000..3a3fb64a1decc --- /dev/null +++ b/clang/test/lab1/sharapov_georgiy/test.cpp @@ -0,0 +1,127 @@ +// RUN: split-file %s %t +// RUN: %clang++ -cc1 -load %llvmshlibdir/DepWarningPlugin%pluginext -plugin DepEmitWarning %t/no_args.cpp 2>&1 | FileCheck %t/no_args.cpp +// RUN: %clang++ -cc1 -load %llvmshlibdir/DepWarningPlugin%pluginext -plugin DepEmitWarning -plugin-arg-DepEmitWarning --attr-style=gcc %t/gcc.cpp 2>&1 | FileCheck %t/gcc.cpp +// RUN: %clang++ -cc1 -load %llvmshlibdir/DepWarningPlugin%pluginext -plugin DepEmitWarning -plugin-arg-DepEmitWarning --attr-style=c++14 %t/c++14.cpp 2>&1 | FileCheck %t/c++14.cpp +// RUN: %clang++ -cc1 -load %llvmshlibdir/DepWarningPlugin%pluginext -plugin DepEmitWarning -plugin-arg-DepEmitWarning --attr-style=both %t/both.cpp 2>&1 | FileCheck %t/both.cpp +// RUN: %clang++ -cc1 -load %llvmshlibdir/DepWarningPlugin%pluginext -plugin DepEmitWarning -plugin-arg-DepEmitWarning --attr-style=aaaaa %t/wrong_style.cpp 2>&1 | FileCheck %t/wrong_style.cpp + + +//--- no_args.cpp + +// CHECK-NOT: warning: Invalid value for attr-style. Using default value 'both'. + +// CHECK: no_args.cpp:5:20: warning: function 'oldSum' is deprecated (c++14) +[[deprecated]] int oldSum(int a, int b); + +// CHECK: no_args.cpp:8:6: warning: function 'oldFunc1' is deprecated (gcc) +void oldFunc1(int a, int b) __attribute__((deprecated)); + +// CHECK: no_args.cpp:11:34: warning: function 'oldFunc2' is deprecated (gcc) +__attribute__((deprecated)) void oldFunc2(int a, int b); + +// CHECK: no_args.cpp:15:6: warning: function 'oldFunc3' is deprecated (gcc) +__attribute__((deprecated)) +void oldFunc3(int a, int b); + +// CHECK: no_args.cpp:19:6: warning: function 'oldFunc4' is deprecated (c++14) +[[deprecated]] +void oldFunc4(int a, int b); + +// CHECK-NOT: warning: +void Func(int a, int b); + +//--- gcc.cpp + +// CHECK-NOT: warning: Invalid value for attr-style. Using default value 'both'. + +// CHECK-NOT: warning: +[[deprecated]] int oldSum(int a, int b); + +// CHECK: gcc.cpp:8:6: warning: function 'oldFunc1' is deprecated (gcc) +void oldFunc1(int a, int b) __attribute__((deprecated)); + +// CHECK: gcc.cpp:11:34: warning: function 'oldFunc2' is deprecated (gcc) +__attribute__((deprecated)) void oldFunc2(int a, int b); + +// CHECK: gcc.cpp:15:6: warning: function 'oldFunc3' is deprecated (gcc) +__attribute__((deprecated)) +void oldFunc3(int a, int b); + +// CHECK-NOT: warning: +[[deprecated]] +void oldFunc4(int a, int b); + +// CHECK-NOT: warning: +void Func(int a, int b); + +//--- c++14.cpp + +// CHECK-NOT: warning: Invalid value for attr-style. Using default value 'both'. + +// CHECK: c++14.cpp:5:20: warning: function 'oldSum' is deprecated (c++14) +[[deprecated]] int oldSum(int a, int b); + +// CHECK-NOT: warning: +void oldFunc1(int a, int b) __attribute__((deprecated)); + +// CHECK-NOT: warning: +__attribute__((deprecated)) void oldFunc2(int a, int b); + +// CHECK-NOT: warning: +__attribute__((deprecated)) +void oldFunc3(int a, int b); + +// CHECK: c++14.cpp:19:6: warning: function 'oldFunc4' is deprecated (c++14) +[[deprecated]] +void oldFunc4(int a, int b); + +// CHECK-NOT: warning: +void Func(int a, int b); + +//--- both.cpp + +// CHECK-NOT: warning: Invalid value for attr-style. Using default value 'both'. + +// CHECK: both.cpp:5:20: warning: function 'oldSum' is deprecated (c++14) +[[deprecated]] int oldSum(int a, int b); + +// CHECK: both.cpp:8:6: warning: function 'oldFunc1' is deprecated (gcc) +void oldFunc1(int a, int b) __attribute__((deprecated)); + +// CHECK: both.cpp:11:34: warning: function 'oldFunc2' is deprecated (gcc) +__attribute__((deprecated)) void oldFunc2(int a, int b); + +// CHECK: both.cpp:15:6: warning: function 'oldFunc3' is deprecated (gcc) +__attribute__((deprecated)) +void oldFunc3(int a, int b); + +// CHECK: both.cpp:19:6: warning: function 'oldFunc4' is deprecated (c++14) +[[deprecated]] +void oldFunc4(int a, int b); + +// CHECK-NOT: warning: +void Func(int a, int b); + +//--- wrong_style.cpp + +// CHECK: warning: Invalid value for attr-style. Using default value 'both'. + +// CHECK: wrong_style.cpp:5:20: warning: function 'oldSum' is deprecated (c++14) +[[deprecated]] int oldSum(int a, int b); + +// CHECK: wrong_style.cpp:8:6: warning: function 'oldFunc1' is deprecated (gcc) +void oldFunc1(int a, int b) __attribute__((deprecated)); + +// CHECK: wrong_style.cpp:11:34: warning: function 'oldFunc2' is deprecated (gcc) +__attribute__((deprecated)) void oldFunc2(int a, int b); + +// CHECK: wrong_style.cpp:15:6: warning: function 'oldFunc3' is deprecated (gcc) +__attribute__((deprecated)) +void oldFunc3(int a, int b); + +// CHECK: wrong_style.cpp:19:6: warning: function 'oldFunc4' is deprecated (c++14) +[[deprecated]] +void oldFunc4(int a, int b); + +// CHECK-NOT: warning: +void Func(int a, int b); From 84d74da1d4cb171d2a73e5f664fe689a4459510e Mon Sep 17 00:00:00 2001 From: Kuznetsov-Artyom <110616662+Kuznetsov-Artyom@users.noreply.github.com> Date: Fri, 15 Mar 2024 07:47:38 +0300 Subject: [PATCH 05/18] =?UTF-8?q?Kuznetsov=20Artyom=20(Laboratory=20work?= =?UTF-8?q?=20=E2=84=961=20option=20=E2=84=961)=20(#5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../labs/lab1/kuznetsov_artyom/CMakeLists.txt | 14 +++ .../kuznetsov_artyom/PrintClassMembers.cpp | 93 +++++++++++++++++++ clang/test/lab1/kuznetsov_artyom/test.cpp | 88 ++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 clang/labs/lab1/kuznetsov_artyom/CMakeLists.txt create mode 100644 clang/labs/lab1/kuznetsov_artyom/PrintClassMembers.cpp create mode 100644 clang/test/lab1/kuznetsov_artyom/test.cpp diff --git a/clang/labs/lab1/kuznetsov_artyom/CMakeLists.txt b/clang/labs/lab1/kuznetsov_artyom/CMakeLists.txt new file mode 100644 index 0000000000000..33c6caff8f5ec --- /dev/null +++ b/clang/labs/lab1/kuznetsov_artyom/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(PrintClassMembersPlugin MODULE PrintClassMembers.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(PrintClassMembersPlugin PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "PrintClassMembersPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) \ No newline at end of file diff --git a/clang/labs/lab1/kuznetsov_artyom/PrintClassMembers.cpp b/clang/labs/lab1/kuznetsov_artyom/PrintClassMembers.cpp new file mode 100644 index 0000000000000..7f61b97f962e3 --- /dev/null +++ b/clang/labs/lab1/kuznetsov_artyom/PrintClassMembers.cpp @@ -0,0 +1,93 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" + +namespace { +class PrintClassMembersVisitor final + : public clang::RecursiveASTVisitor { +public: + explicit PrintClassMembersVisitor(clang::ASTContext *context) + : m_context(context) {} + bool VisitCXXRecordDecl(clang::CXXRecordDecl *declaration) { + if (declaration->isStruct() || declaration->isClass()) { + outInfoUserType(declaration); + + for (const auto &decl : declaration->decls()) { + if (auto notStaticMember = llvm::dyn_cast(decl)) { + llvm::outs() << "|_ " << notStaticMember->getNameAsString() << ' '; + llvm::outs() << '(' << getTypeAsString(notStaticMember) << '|'; + llvm::outs() << getAccessSpecifierAsString(notStaticMember) << ")\n"; + } else if (auto staticMember = llvm::dyn_cast(decl)) { + if (staticMember->isStaticDataMember()) { + llvm::outs() << "|_ " << staticMember->getNameAsString() << ' '; + llvm::outs() << '(' << getTypeAsString(staticMember) << '|'; + llvm::outs() << getAccessSpecifierAsString(staticMember) + << "|static)\n"; + } + } + } + llvm::outs() << '\n'; + } + return true; + } + +private: + void outInfoUserType(clang::CXXRecordDecl *userType) { + llvm::outs() << userType->getNameAsString() << ' '; + llvm::outs() << (userType->isStruct() ? "(struct" : "(class"); + llvm::outs() << (userType->isTemplated() ? "|template)" : ")") << '\n'; + } + + std::string getTypeAsString(const clang::ValueDecl *member) { + clang::QualType type = member->getType(); + return type.getAsString(); + } + + std::string getAccessSpecifierAsString(const clang::ValueDecl *member) { + switch (member->getAccess()) { + case clang::AS_public: + return "public"; + case clang::AS_protected: + return "protected"; + case clang::AS_private: + return "private"; + default: + return "unknown"; + } + } + +private: + clang::ASTContext *m_context; +}; + +class PrintClassMembersConsumer final : public clang::ASTConsumer { +public: + explicit PrintClassMembersConsumer(clang::ASTContext *сontext) + : m_visitor(сontext) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + m_visitor.TraverseDecl(context.getTranslationUnitDecl()); + } + +private: + PrintClassMembersVisitor m_visitor; +}; + +class PrintClassMembersAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef) override { + return std::make_unique(&ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; +} // namespace + +static clang::FrontendPluginRegistry::Add + X("pcm_plugin", "Prints all members of the class"); \ No newline at end of file diff --git a/clang/test/lab1/kuznetsov_artyom/test.cpp b/clang/test/lab1/kuznetsov_artyom/test.cpp new file mode 100644 index 0000000000000..69b11a71e9d9d --- /dev/null +++ b/clang/test/lab1/kuznetsov_artyom/test.cpp @@ -0,0 +1,88 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/PrintClassMembersPlugin%pluginext -plugin pcm_plugin %s 1>&1 | FileCheck %s + +namespace { +// CHECK: Point3D (struct) +struct Point3D { + // CHECK-NEXT: |_ m_x (double|public) + double m_x{}; + // CHECK-NEXT: |_ m_y (double|public) + double m_y{}; + // CHECK-NEXT: |_ m_z (double|public) + double m_z{}; +}; + +// CHECK: Pair (struct|template) +template struct Pair { + // CHECK-NEXT: |_ first (T1|public) + T1 first{}; + // CHECK-NEXT: |_ second (T2|public) + T2 second{}; +}; + +// CHECK: EmptyClass (class) +class EmptyClass {}; + +// CHECK: NodeList (struct|template) +template struct NodeList { + // CHECK-NEXT: |_ data (T|public) + T data{}; + // CHECK-NEXT: |_ next (NodeList *|public) + NodeList *next{}; +}; + +// CHECK: CheckSpecifiers (class) +class CheckSpecifiers { +public: + // CHECK-NEXT: |_ publicMember (Point3D|public) + Point3D publicMember{}; + +protected: + // CHECK-NEXT: |_ protectedMember (Pair > + // >|protected) + Pair>> protectedMember{}; + +private: + // CHECK-NEXT: |_ privateMember (EmptyClass|private) + EmptyClass privateMember{}; +}; + +// CHECK: User (struct) +// CHECK-NEXT: |_ m_id (int|public) +// CHECK-NEXT: |_ m_human (Human|public) + +// CHECK: Human (struct) +// CHECK-NEXT: |_ m_age (int|public) +// CHECK-NEXT: |_ m_cash (int|public) + +struct User { + struct Human { + int m_age{}; + int m_cash{}; + }; + int m_id{}; + Human m_human{}; +}; + +// CHECK: CheckStatic (class) +class CheckStatic { + // CHECK-NEXT: |_ m_staticMember (float|private|static) + static float m_staticMember; +}; + +float CheckStatic::m_staticMember = 0.0f; + +// CHECK: CheckConst (class) +class CheckConst { + // CHECK-NEXT: |_ m_constMember (const char|private) + const char m_constMember{}; +}; + +// CHECK: CheckStaticConstTemplate (class|template) +template class CheckStaticConstTemplate { + // CHECK-NEXT: |_ m_member (const T|private|static) + static const T m_member; +}; + +template const T CheckStaticConstTemplate::m_member{}; + +} // namespace \ No newline at end of file From d54cd5d1b4655dc913d1d2708bcba7c6037d4bb3 Mon Sep 17 00:00:00 2001 From: Andrey Soloninko <96086452+Manymoera@users.noreply.github.com> Date: Fri, 15 Mar 2024 20:39:37 +0300 Subject: [PATCH 06/18] =?UTF-8?q?Soloninko=20Andrey.=20Lab=20=E2=84=961,?= =?UTF-8?q?=20var=201=20(#7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * first commit * make action * made tests more diversed and got rid of using namespace --- .../labs/lab1/soloninko_andrey/CMakeLists.txt | 14 ++++++ .../labs/lab1/soloninko_andrey/classList.cpp | 43 +++++++++++++++++++ .../lab1/soloninko_andrey/ClassListTests.cpp | 29 +++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 clang/labs/lab1/soloninko_andrey/CMakeLists.txt create mode 100644 clang/labs/lab1/soloninko_andrey/classList.cpp create mode 100644 clang/test/lab1/soloninko_andrey/ClassListTests.cpp diff --git a/clang/labs/lab1/soloninko_andrey/CMakeLists.txt b/clang/labs/lab1/soloninko_andrey/CMakeLists.txt new file mode 100644 index 0000000000000..1c50a930fd5b5 --- /dev/null +++ b/clang/labs/lab1/soloninko_andrey/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(ClassListPlugin MODULE classList.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(ClassListPlugin PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "ClassListPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) \ No newline at end of file diff --git a/clang/labs/lab1/soloninko_andrey/classList.cpp b/clang/labs/lab1/soloninko_andrey/classList.cpp new file mode 100644 index 0000000000000..5f61449d19b87 --- /dev/null +++ b/clang/labs/lab1/soloninko_andrey/classList.cpp @@ -0,0 +1,43 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" + +class PrintClass : public clang::RecursiveASTVisitor { +public: + bool VisitCXXRecordDecl(clang::CXXRecordDecl *declaration) { + if (declaration->isClass() || declaration->isStruct()) { + llvm::outs() << declaration->getNameAsString() << "\n"; + for (auto field_member : declaration->fields()) { + llvm::outs() << "|_" << field_member->getNameAsString() << "\n"; + } + llvm::outs() << "\n"; + } + return true; + } +}; + +class MyASTConsumer : public clang::ASTConsumer { +public: + PrintClass Visitor; + void HandleTranslationUnit(clang::ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + } +}; + +class PrintClassAction : public clang::PluginASTAction { +public: + std::unique_ptr CreateASTConsumer(clang::CompilerInstance &ci, + llvm::StringRef) override { + return std::make_unique(); + } + + bool ParseArgs(const clang::CompilerInstance &ci, + const std::vector &args) override { + return true; + } +}; + +static clang::FrontendPluginRegistry::Add + X("class_list_plugin", "Prints all members of the class"); \ No newline at end of file diff --git a/clang/test/lab1/soloninko_andrey/ClassListTests.cpp b/clang/test/lab1/soloninko_andrey/ClassListTests.cpp new file mode 100644 index 0000000000000..720acaaa91ae8 --- /dev/null +++ b/clang/test/lab1/soloninko_andrey/ClassListTests.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ClassListPlugin%pluginext -plugin class_list_plugin %s 1>&1 | FileCheck %s + +// CHECK: Empty +class Empty {}; + +// CHECK: MyClass +struct MyClass { + // CHECK-NEXT: |_variable + int variable; +}; + +// CHECK: MyClass1 +class MyClass1 { + // CHECK-NEXT: |_var + float var; + // CHECK-NEXT: |_var1 + double var1; + // CHECK: InClass + class InClass { + //CHECK-NEXT: |_InVar + int InVar; + }; +}; + +// CHECK: TClass +template class TClass { + // CHECK-NEXT: TVar + T TVar; +}; \ No newline at end of file From 847c794ad6286c89f2a0066a9cc0cb4c7a9feb0f Mon Sep 17 00:00:00 2001 From: Arseniy Obolenskiy Date: Sat, 16 Mar 2024 02:08:33 +0800 Subject: [PATCH 07/18] Fix clang-format check (#11) --- .github/workflows/nn-cmplr-tidy.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nn-cmplr-tidy.yml b/.github/workflows/nn-cmplr-tidy.yml index ff1432a3b68cb..475a07b77f049 100644 --- a/.github/workflows/nn-cmplr-tidy.yml +++ b/.github/workflows/nn-cmplr-tidy.yml @@ -7,12 +7,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Install clang-format run: | sudo apt-get install -y clang-format - name: Run clang-format run: | - git-clang-format --diff `git merge-base ${GITHUB_SHA} ${GITHUB_BASE_REF}` + git-clang-format --diff `git merge-base ${GITHUB_SHA} origin/${GITHUB_BASE_REF}` ${GITHUB_SHA} clang-tidy: runs-on: ubuntu-latest steps: From a2de4eec217c7c55ca6d588d2b3a33fab22c93b2 Mon Sep 17 00:00:00 2001 From: evldn <91959868+evldn@users.noreply.github.com> Date: Fri, 15 Mar 2024 21:16:54 +0300 Subject: [PATCH 08/18] =?UTF-8?q?Volodin=20Evgeniy.=20Lab=20=E2=84=961.=20?= =?UTF-8?q?Option=20=E2=84=961.=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Task is ready! * Update! * Update for workflow * Update code * Update code * 1. The ASTContext *Context field was removed from the PrintClassVisitor class as unnecessary. 2. The CreateASTConsumer method of the PrintClassLASTAction class now returns make_unique, not new. 3. The help option for the plugin has been added and tested. * Update code for reload actions (windows-build failed). --- .../labs/lab1/volodin_evgeniy/CMakeLists.txt | 14 ++++ .../lab1/volodin_evgeniy/PrintClassPlugin.cpp | 68 +++++++++++++++++++ clang/test/lab1/volodin_evgeniy/test.cpp | 62 +++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 clang/labs/lab1/volodin_evgeniy/CMakeLists.txt create mode 100644 clang/labs/lab1/volodin_evgeniy/PrintClassPlugin.cpp create mode 100644 clang/test/lab1/volodin_evgeniy/test.cpp diff --git a/clang/labs/lab1/volodin_evgeniy/CMakeLists.txt b/clang/labs/lab1/volodin_evgeniy/CMakeLists.txt new file mode 100644 index 0000000000000..1470a493b00f7 --- /dev/null +++ b/clang/labs/lab1/volodin_evgeniy/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(PrintClassPlugin MODULE PrintClassPlugin.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(PrintClassPlugin PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "PrintClassPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) \ No newline at end of file diff --git a/clang/labs/lab1/volodin_evgeniy/PrintClassPlugin.cpp b/clang/labs/lab1/volodin_evgeniy/PrintClassPlugin.cpp new file mode 100644 index 0000000000000..2b13a2865cca5 --- /dev/null +++ b/clang/labs/lab1/volodin_evgeniy/PrintClassPlugin.cpp @@ -0,0 +1,68 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" + +using namespace clang; + +class PrintClassVisitor : public RecursiveASTVisitor { +public: + bool VisitCXXRecordDecl(CXXRecordDecl *declaration) { + llvm::outs() << declaration->getNameAsString().c_str() << "\n"; + for (const auto &field : declaration->fields()) { + llvm::outs() << " |_" << field->getNameAsString().c_str() << "\n"; + } + return true; + } +}; + +class PrintClassConsumer : public ASTConsumer { +public: + explicit PrintClassConsumer(CompilerInstance &CI) : Visitor() {} + + void HandleTranslationUnit(ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + } + +private: + PrintClassVisitor Visitor; +}; + +class PrintClassASTAction : public PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &Compiler, + llvm::StringRef InFile) override { + return std::make_unique(Compiler); + } + + bool ParseArgs(const CompilerInstance &CI, + const std::vector &args) override { + if (!args.empty() && args[0] == "help") { + PrintHelp(llvm::errs()); + return true; + } + } + void PrintHelp(llvm::raw_ostream &ros) { + ros << "#Help for the Clang \"PrintClassPlugin\" plugin\n\n" + << "##Description\n" + << "This clang plugin outputs the names of all classes(structures) and " + "their fields in the C/C++ source file.\n\n" + << "##Usage\n" + << "To use the plugin, upload it to Clang using the following command " + ":\n" + << "clang -cc1 -load /path/to/plugin.so(.dll) -plugin -plugin " + "print-class-plugin /path/to/source.cpp\n\n" + << "##Output format\n" + << "The plugin outputs the names of classes(structures) and fields in " + "the following format :\n" + << "NameClass\n" + << "|_nameField\n\n" + << "##Version\n" + << "Version 1.1\n\n"; + } +}; + +static clang::FrontendPluginRegistry::Add + X("print-class-plugin", + "A plugin that prints the names of classes (structures)."); \ No newline at end of file diff --git a/clang/test/lab1/volodin_evgeniy/test.cpp b/clang/test/lab1/volodin_evgeniy/test.cpp new file mode 100644 index 0000000000000..c0129aeee5c84 --- /dev/null +++ b/clang/test/lab1/volodin_evgeniy/test.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/PrintClassPlugin%pluginext -plugin print-class-plugin %s | FileCheck %s +class SimpleClass { + int a; + float b; +}; +// CHECK: SimpleClass +// CHECK-NEXT: |_a +// CHECK-NEXT: |_b + +class EmptyClass {}; +// CHECK: EmptyClass + +class Empire { + int world; +}; +// CHECK: Empire +// CHECK-NEXT: |_world + +template class One { + T two; +}; +// CHECK: One +// CHECK-NEXT: |_two + +class MyClass { + One t; +}; +// CHECK: MyClass +// CHECK-NEXT: |_t + +struct B { + int e; + float b; + double c; + long long d; +}; +// CHECK: B +// CHECK-NEXT: |_e +// CHECK-NEXT: |_b +// CHECK-NEXT: |_c +// CHECK-NEXT: |_d + +struct Computer { + struct Processor { + int clock_frequency; + }; + struct Memory{ + int size; + }; + struct Motherboard{}; + struct GPU{}; +}; +// CHECK: Computer +// CHECK: Processor +// CHECK-NEXT: |_clock_frequency +// CHECK: Memory +// CHECK-NEXT: |_size +// CHECK: Motherboard +// CHECK: GPU + +// RUN: %clang_cc1 -load %llvmshlibdir/PrintClassPlugin%pluginext -plugin print-class-plugin %s -plugin-arg-print-class-plugin help 2>&1 | FileCheck %s --check-prefix=HELP +// HELP: #Help for the Clang \ No newline at end of file From 8ac9ea39521d46cf2eaab9437cdd95d99f3fd992 Mon Sep 17 00:00:00 2001 From: Damir Sadikov <90563259+Damlrca@users.noreply.github.com> Date: Sun, 17 Mar 2024 10:54:02 +0300 Subject: [PATCH 09/18] =?UTF-8?q?Sadikov=20Damir.=20Lab=20=E2=84=961.=20Va?= =?UTF-8?q?r=203=20(#12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deprecated plugin --- clang/labs/lab1/sadikov_damir/CMakeLists.txt | 14 ++++++ .../DeprecatedPlugin_SadikovD.cpp | 50 +++++++++++++++++++ .../DeprecatedPluginTests_SadikovD.cpp | 23 +++++++++ 3 files changed, 87 insertions(+) create mode 100644 clang/labs/lab1/sadikov_damir/CMakeLists.txt create mode 100644 clang/labs/lab1/sadikov_damir/DeprecatedPlugin_SadikovD.cpp create mode 100644 clang/test/lab1/sadikov_damir/DeprecatedPluginTests_SadikovD.cpp diff --git a/clang/labs/lab1/sadikov_damir/CMakeLists.txt b/clang/labs/lab1/sadikov_damir/CMakeLists.txt new file mode 100644 index 0000000000000..cfc10fda866ce --- /dev/null +++ b/clang/labs/lab1/sadikov_damir/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(DeprecatedPlugin_SadikovD MODULE DeprecatedPlugin_SadikovD.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(DeprecatedPlugin_SadikovD PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "DeprecatedPlugin_SadikovD" ${CLANG_TEST_DEPS} PARENT_SCOPE) \ No newline at end of file diff --git a/clang/labs/lab1/sadikov_damir/DeprecatedPlugin_SadikovD.cpp b/clang/labs/lab1/sadikov_damir/DeprecatedPlugin_SadikovD.cpp new file mode 100644 index 0000000000000..151b2314be847 --- /dev/null +++ b/clang/labs/lab1/sadikov_damir/DeprecatedPlugin_SadikovD.cpp @@ -0,0 +1,50 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" + +class DeprecatedPluginVisitor + : public clang::RecursiveASTVisitor { +public: + bool VisitFunctionDecl(clang::FunctionDecl *FunDec) { + std::string FunctionName = FunDec->getNameInfo().getAsString(); + if (FunctionName.find("deprecated") != std::string::npos) { + clang::DiagnosticsEngine &Diags = + FunDec->getASTContext().getDiagnostics(); + unsigned DiagID = + Diags.getCustomDiagID(clang::DiagnosticsEngine::Warning, + "Name of function '%0' contains 'deprecated'"); + Diags.Report(FunDec->getLocation(), DiagID) << FunctionName; + } + return true; + } +}; + +class DeprecatedPluginConsumer : public clang::ASTConsumer { +private: + DeprecatedPluginVisitor Visitor; + +public: + void HandleTranslationUnit(clang::ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + } +}; + +class DeprecatedPluginAction : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &Compiler, + llvm::StringRef InFile) override { + return std::make_unique(); + } + +protected: + bool ParseArgs(const clang::CompilerInstance &Compiler, + const std::vector &args) override { + return true; + } +}; + +static clang::FrontendPluginRegistry::Add + X("DeprecatedPlugin_SadikovD", + "Warning if function name contains 'deprecated'"); diff --git a/clang/test/lab1/sadikov_damir/DeprecatedPluginTests_SadikovD.cpp b/clang/test/lab1/sadikov_damir/DeprecatedPluginTests_SadikovD.cpp new file mode 100644 index 0000000000000..11c40f1285704 --- /dev/null +++ b/clang/test/lab1/sadikov_damir/DeprecatedPluginTests_SadikovD.cpp @@ -0,0 +1,23 @@ +// RUN: %clang -cc1 -load %llvmshlibdir/DeprecatedPlugin_SadikovD%pluginext -plugin DeprecatedPlugin_SadikovD %s 2>&1 | FileCheck %s + +// CHECK-NOT: warning: Name of function 'just_regular_sum_function' contains 'deprecated' +int just_regular_sum_function(int a, int b) { + return a + b; +} + +// CHECK: warning: Name of function 'strange_deprecated_sum_function' contains 'deprecated' +int strange_deprecated_sum_function(int a, int b) { + return a + b; +} + +// CHECK-NOT: warning: Name of function 'IsItAlsoDeprecated' contains 'deprecated' +int IsItAlsoDeprecated(int a, int b, int c) { + return a + b + c; +} + +struct foo { +// CHECK-NOT: warning: Name of function 'bar' contains 'deprecated' + void bar() {} +// CHECK: warning: Name of function 'bar_deprecated' contains 'deprecated' + void bar_deprecated() {} +}; From 9631799f9d03ae46261e5260c9b1fa804f3698f6 Mon Sep 17 00:00:00 2001 From: evldn <91959868+evldn@users.noreply.github.com> Date: Sun, 17 Mar 2024 10:57:43 +0300 Subject: [PATCH 10/18] =?UTF-8?q?Fix=20for=20Volodin=20Evgeniy.=20Lab=20?= =?UTF-8?q?=E2=84=961.=20Option=20=E2=84=961.=20=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix return statement position --- clang/labs/lab1/volodin_evgeniy/PrintClassPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/labs/lab1/volodin_evgeniy/PrintClassPlugin.cpp b/clang/labs/lab1/volodin_evgeniy/PrintClassPlugin.cpp index 2b13a2865cca5..6b2d1b426468c 100644 --- a/clang/labs/lab1/volodin_evgeniy/PrintClassPlugin.cpp +++ b/clang/labs/lab1/volodin_evgeniy/PrintClassPlugin.cpp @@ -40,8 +40,8 @@ class PrintClassASTAction : public PluginASTAction { const std::vector &args) override { if (!args.empty() && args[0] == "help") { PrintHelp(llvm::errs()); - return true; } + return true; } void PrintHelp(llvm::raw_ostream &ros) { ros << "#Help for the Clang \"PrintClassPlugin\" plugin\n\n" From 74dd97f1cf3992453d196f086d19c55eb8e9b33e Mon Sep 17 00:00:00 2001 From: Arseniy Obolenskiy Date: Sun, 17 Mar 2024 19:07:28 +0800 Subject: [PATCH 11/18] Fix clang-format error code (#23) --- .github/workflows/nn-cmplr-tidy.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nn-cmplr-tidy.yml b/.github/workflows/nn-cmplr-tidy.yml index 475a07b77f049..46e069fea1a2e 100644 --- a/.github/workflows/nn-cmplr-tidy.yml +++ b/.github/workflows/nn-cmplr-tidy.yml @@ -14,7 +14,8 @@ jobs: sudo apt-get install -y clang-format - name: Run clang-format run: | - git-clang-format --diff `git merge-base ${GITHUB_SHA} origin/${GITHUB_BASE_REF}` ${GITHUB_SHA} + git-clang-format --diff `git merge-base ${GITHUB_SHA} origin/${GITHUB_BASE_REF}` ${GITHUB_SHA} 2>&1 | grep diff | tee log.txt + exit `wc -l log.txt | awk '{print $1}'` clang-tidy: runs-on: ubuntu-latest steps: From e47fbee39db0118cba4dca0ce3b18bc16d5728f4 Mon Sep 17 00:00:00 2001 From: m-ly4 Date: Mon, 18 Mar 2024 08:29:10 +0300 Subject: [PATCH 12/18] Turn back clang-format's output in check log (#25) --- .github/workflows/nn-cmplr-tidy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nn-cmplr-tidy.yml b/.github/workflows/nn-cmplr-tidy.yml index 46e069fea1a2e..5d0cf93c7e3ed 100644 --- a/.github/workflows/nn-cmplr-tidy.yml +++ b/.github/workflows/nn-cmplr-tidy.yml @@ -14,8 +14,8 @@ jobs: sudo apt-get install -y clang-format - name: Run clang-format run: | - git-clang-format --diff `git merge-base ${GITHUB_SHA} origin/${GITHUB_BASE_REF}` ${GITHUB_SHA} 2>&1 | grep diff | tee log.txt - exit `wc -l log.txt | awk '{print $1}'` + git-clang-format --diff `git merge-base ${GITHUB_SHA} origin/${GITHUB_BASE_REF}` ${GITHUB_SHA} 2>&1 | tee log.txt + exit `grep -c diff log.txt` clang-tidy: runs-on: ubuntu-latest steps: From 8f9a2ad52565ad89399078b5053b9588b2ec38bf Mon Sep 17 00:00:00 2001 From: CrispiToken <55401919+NikitaKorablev@users.noreply.github.com> Date: Mon, 18 Mar 2024 08:31:31 +0300 Subject: [PATCH 13/18] =?UTF-8?q?Korablev=20Nikita.=20Lab=20=E2=84=961.=20?= =?UTF-8?q?Option=20=E2=84=964.=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../labs/lab1/korablev_nikita/CMakeLists.txt | 14 ++ .../korablev_nikita/RenameIdentificator.cpp | 140 ++++++++++++++++++ clang/test/lab1/korablev_nikita/example.cpp | 84 +++++++++++ 3 files changed, 238 insertions(+) create mode 100644 clang/labs/lab1/korablev_nikita/CMakeLists.txt create mode 100644 clang/labs/lab1/korablev_nikita/RenameIdentificator.cpp create mode 100644 clang/test/lab1/korablev_nikita/example.cpp diff --git a/clang/labs/lab1/korablev_nikita/CMakeLists.txt b/clang/labs/lab1/korablev_nikita/CMakeLists.txt new file mode 100644 index 0000000000000..0fd043f3dd239 --- /dev/null +++ b/clang/labs/lab1/korablev_nikita/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(RenamedIdPlugin MODULE RenameIdentificator.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(DeprecatedWarningPlugin PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "RenamedIdPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) \ No newline at end of file diff --git a/clang/labs/lab1/korablev_nikita/RenameIdentificator.cpp b/clang/labs/lab1/korablev_nikita/RenameIdentificator.cpp new file mode 100644 index 0000000000000..28fceba7818f0 --- /dev/null +++ b/clang/labs/lab1/korablev_nikita/RenameIdentificator.cpp @@ -0,0 +1,140 @@ +#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 { +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 *FD) { + std::string Name = FD->getNameAsString(); + + if (Name == OldName) { + Rewriter.ReplaceText(FD->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 *VD) { + std::string Name = VD->getNameAsString(); + + if (Name == OldName) { + Rewriter.ReplaceText(VD->getLocation(), Name.size(), NewName); + Rewriter.overwriteChangedFiles(); + } + + if (VD->getType().getAsString() == OldName + " *" || + VD->getType().getAsString() == OldName) { + Rewriter.ReplaceText(VD->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), + Name.size(), NewName); + Rewriter.overwriteChangedFiles(); + } + + return true; + } + + bool VisitCXXRecordDecl(clang::CXXRecordDecl *CXXRD) { + std::string Name = CXXRD->getNameAsString(); + + if (Name == OldName) { + Rewriter.ReplaceText(CXXRD->getLocation(), Name.size(), NewName); + + const clang::CXXDestructorDecl *CXXDD = CXXRD->getDestructor(); + if (CXXDD) + Rewriter.ReplaceText(CXXDD->getLocation(), Name.size() + 1, + "~" + NewName); + + Rewriter.overwriteChangedFiles(); + } + + return true; + } + + bool VisitCXXNewExpr(clang::CXXNewExpr *CXXNE) { + std::string Name = CXXNE->getConstructExpr()->getType().getAsString(); + + if (Name == OldName) { + Rewriter.ReplaceText(CXXNE->getExprLoc(), Name.size() + 4, + "new " + NewName); + Rewriter.overwriteChangedFiles(); + } + + return true; + } +}; + +class RenameIdConsumer : public clang::ASTConsumer { + RenameVisitor visitor; + +public: + explicit RenameIdConsumer(clang::CompilerInstance &CI, std::string OldName, + std::string NewName) + : visitor(clang::Rewriter(CI.getSourceManager(), CI.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 &args) override { + OldName = args[0]; + NewName = args[1]; + + if (OldName.find("=") == 0 || OldName.find("=") == std::string::npos) { + llvm::errs() << "Error entering the `OldName` parameter." + << "\n"; + } + if (NewName.find("=") == 0 || NewName.find("=") == std::string::npos) { + llvm::errs() << "Error entering the `NewName` parameter." + << "\n"; + } + + OldName = OldName.substr(OldName.find("=") + 1); + NewName = NewName.substr(NewName.find("=") + 1); + + return true; + } + +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &Compiler, + llvm::StringRef InFile) override { + return std::make_unique(Compiler, OldName, NewName); + } +}; + +static clang::FrontendPluginRegistry::Add + X("renamed-id", "Idetificator was renamed."); \ No newline at end of file diff --git a/clang/test/lab1/korablev_nikita/example.cpp b/clang/test/lab1/korablev_nikita/example.cpp new file mode 100644 index 0000000000000..02e05ae528c2f --- /dev/null +++ b/clang/test/lab1/korablev_nikita/example.cpp @@ -0,0 +1,84 @@ +// RUN: split-file %s %t +// RUN: %clang_cc1 -load %llvmshlibdir/RenamedIdPlugin%pluginext -add-plugin renamed-id\ +// RUN: -plugin-arg-renamed-id OldName="A"\ +// RUN: -plugin-arg-renamed-id NewName="B" %t/test_1.cpp +// RUN: FileCheck %s < %t/test_1.cpp --check-prefix=CLASS-CHECK + +// CLASS-CHECK: class B { +// CLASS-CHECK-NEXT: public: +// CLASS-CHECK-NEXT: B() {}; +// CLASS-CHECK-NEXT: ~B(); +// CLASS-CHECK-NEXT: }; +// CLASS-CHECK-NEXT: void func() { +// CLASS-CHECK-NEXT: B* a = new B; +// CLASS-CHECK-NEXT: B b; +// CLASS-CHECK-NEXT: delete a; +// CLASS-CHECK-NEXT: }; + +//--- test_1.cpp +class A { +public: + A() {}; + ~A(); +}; +void func() { + A* a = new A; + A b; + delete a; +}; + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamedIdPlugin%pluginext -add-plugin renamed-id\ +// RUN: -plugin-arg-renamed-id OldName="A"\ +// RUN: -plugin-arg-renamed-id NewName="B" %t/test_2.cpp +// RUN: FileCheck %s < %t/test_2.cpp --check-prefix=SUM-CHECK + +// SUM-CHECK: int sum(int a, int b) { +// SUM-CHECK-NEXT: int c = sum(1, 2); +// SUM-CHECK-NEXT: c++; +// SUM-CHECK-NEXT: a += b; +// SUM-CHECK-NEXT: return a+b; +// SUM-CHECK-NEXT: }; + +//--- test_2.cpp +int sum(int a, int b) { + int c = sum(1, 2); + c++; + a += b; + return a+b; +}; + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamedIdPlugin%pluginext -add-plugin renamed-id\ +// RUN: -plugin-arg-renamed-id OldName="C"\ +// RUN: -plugin-arg-renamed-id NewName="Renamed_C" %t/test_3.cpp +// RUN: FileCheck %s < %t/test_3.cpp --check-prefix=CLASS2-CHECK + +// CLASS2-CHECK: class Renamed_C { +// CLASS2-CHECK-NEXT: private: +// CLASS2-CHECK-NEXT: int a; +// CLASS2-CHECK-NEXT: int b; +// CLASS2-CHECK-NEXT: public: +// CLASS2-CHECK-NEXT: Renamed_C() {} +// CLASS2-CHECK-NEXT: Renamed_C(int a, int b): a(a), b(b) {} +// CLASS2-CHECK-NEXT: ~Renamed_C(); +// CLASS2-CHECK-NEXT: }; +// CLASS2-CHECK-NEXT: void func() { +// CLASS2-CHECK-NEXT: Renamed_C a; +// CLASS2-CHECK-NEXT: Renamed_C* b = new Renamed_C(1, 2); +// CLASS2-CHECK-NEXT: delete b; +// CLASS2-CHECK-NEXT: } + +//--- test_3.cpp +class C { +private: + int a; + int b; +public: + C() {} + C(int a, int b): a(a), b(b) {} + ~C(); +}; +void func() { + C a; + C* b = new C(1, 2); + delete b; +}; \ No newline at end of file From 579a90c3f348a56902e09c614049b204a877c4bc Mon Sep 17 00:00:00 2001 From: overinvest <49341977+overinvest@users.noreply.github.com> Date: Mon, 18 Mar 2024 08:32:24 +0300 Subject: [PATCH 14/18] Bodrov Daniil. Lab 1. Task 1 (#21) This code represents a plugin for Clang that allows outputting information about class members in C++. The program relies on using the Clang tooling and its Abstract Syntax Tree (AST) to analyze and output information about structures and classes in the source code. The program consists of several components: - **MemberInfoPrinter:** This class is responsible for printing information about class members, such as fields, methods, and static members. It accesses the Clang AST to retrieve information about each member and prints its name, type, and access specifier. - **UserTypePrinter:** This class is responsible for printing information about user-defined types, such as structures and classes. It determines the type of each user-defined type and prints the corresponding information. - **ClassMembersPrinter:** This class is a subclass of `clang::RecursiveASTVisitor` and traverses the AST to find and print information about class members. It uses `MemberInfoPrinter` and `UserTypePrinter` to print information about members and types. - **ClassMembersConsumer:** This class is an `ASTConsumer` that processes the AST and runs `ClassMembersPrinter` for each detected class or structure. - **ClassFieldPrinterAction:** This class represents the action of the Clang plugin. It creates an instance of `ClassMembersConsumer` to process the AST and output information about class members. The program allows analyzing C++ source code and outputting information about class members, their types, and access specifiers. Example: ``` // CHECK: TestClass (class) class TestClass { public: int publicInt; // CHECK-NEXT: |_ publicInt (int|public) static int publicStaticInt; // CHECK-NEXT: |_ publicStaticInt (int|public|static) void publicFunc() {} // CHECK-NEXT: |_ publicFunc (void (void)|public|method) private: int privateInt; // CHECK-NEXT: |_ privateInt (int|private) static int privateStaticInt; // CHECK-NEXT: |_ privateStaticInt (int|private|static) void privateFunc() {} // CHECK-NEXT: |_ privateFunc (void (void)|private|method) }; ``` In the provided example, a class `TestClass` is shown with various members, including public, private, static variables, and methods. The `CHECK` comments represent the expected output of the program in the format defined in the main code. --- clang/labs/lab1/bodrov_daniil/CMakeLists.txt | 14 +++ .../labs/lab1/bodrov_daniil/ClassPrinter.cpp | 104 ++++++++++++++++++ clang/test/lab1/bodrov_daniil/test.cpp | 69 ++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 clang/labs/lab1/bodrov_daniil/CMakeLists.txt create mode 100644 clang/labs/lab1/bodrov_daniil/ClassPrinter.cpp create mode 100644 clang/test/lab1/bodrov_daniil/test.cpp diff --git a/clang/labs/lab1/bodrov_daniil/CMakeLists.txt b/clang/labs/lab1/bodrov_daniil/CMakeLists.txt new file mode 100644 index 0000000000000..878b8e66adad5 --- /dev/null +++ b/clang/labs/lab1/bodrov_daniil/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(ClassFieldPrinter MODULE ClassPrinter.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(ClassFieldPrinter PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "ClassFieldPrinter" ${CLANG_TEST_DEPS} PARENT_SCOPE) \ No newline at end of file diff --git a/clang/labs/lab1/bodrov_daniil/ClassPrinter.cpp b/clang/labs/lab1/bodrov_daniil/ClassPrinter.cpp new file mode 100644 index 0000000000000..00d799abac28e --- /dev/null +++ b/clang/labs/lab1/bodrov_daniil/ClassPrinter.cpp @@ -0,0 +1,104 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +class MemberInfoPrinter { +public: + void print(const clang::ValueDecl *Member, const std::string &MemberType) { + llvm::outs() << "|_ " << Member->getNameAsString() << ' '; + llvm::outs() << '(' << Member->getType().getAsString() << '|'; + llvm::outs() << getAccessSpecifierAsString(Member) + << (MemberType == "field" ? ")" : ("|" + MemberType + ")")) + << "\n"; + } + +private: + std::string getAccessSpecifierAsString(const clang::ValueDecl *Member) { + switch (Member->getAccess()) { + case clang::AS_public: + return "public"; + case clang::AS_protected: + return "protected"; + case clang::AS_private: + return "private"; + default: + return "unknown"; + } + } +}; + +class UserTypePrinter { +public: + void print(clang::CXXRecordDecl *UserType) { + llvm::outs() << UserType->getNameAsString() << ' '; + llvm::outs() << (UserType->isStruct() ? "(struct" : "(class"); + llvm::outs() << (UserType->isTemplated() ? "|template)" : ")") << '\n'; + } +}; + +class ClassMembersPrinter final + : public clang::RecursiveASTVisitor { +public: + explicit ClassMembersPrinter(clang::ASTContext *Context) + : ClassContext(Context) {} + + bool VisitCXXRecordDecl(clang::CXXRecordDecl *Declaration) { + if (Declaration->isStruct() || Declaration->isClass()) { + UserPrinter.print(Declaration); + + for (const auto &Decl : Declaration->decls()) { + if (auto Field = llvm::dyn_cast(Decl)) { + MemberPrinter.print(Field, "field"); + } else if (auto Var = llvm::dyn_cast(Decl)) { + if (Var->isStaticDataMember()) { + MemberPrinter.print(Var, "static"); + } + } else if (auto Method = llvm::dyn_cast(Decl)) { + MemberPrinter.print(Method, "method"); + } + } + llvm::outs() << '\n'; + } + return true; + } + +private: + clang::ASTContext *ClassContext; + MemberInfoPrinter MemberPrinter; + UserTypePrinter UserPrinter; +}; + +class ClassMembersConsumer final : public clang::ASTConsumer { +public: + explicit ClassMembersConsumer(clang::ASTContext *Context) + : Visitor(Context) {} + + void HandleTranslationUnit(clang::ASTContext &Context) override { + Visitor.TraverseDecl(Context.getTranslationUnitDecl()); + } + +private: + ClassMembersPrinter Visitor; +}; + +class ClassFieldPrinterAction final : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &Ci, llvm::StringRef) override { + return std::make_unique(&Ci.getASTContext()); + } + + bool ParseArgs(const clang::CompilerInstance &Ci, + const std::vector &Args) override { + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("class-field-printer", "Prints all members of the class"); \ No newline at end of file diff --git a/clang/test/lab1/bodrov_daniil/test.cpp b/clang/test/lab1/bodrov_daniil/test.cpp new file mode 100644 index 0000000000000..a94954d2326d8 --- /dev/null +++ b/clang/test/lab1/bodrov_daniil/test.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -load %llvmshlibdir/ClassFieldPrinter%pluginext -plugin class-field-printer %s 1>&1 | FileCheck %s + +// CHECK: Empty (class) +class Empty {}; + +// CHECK: Data (class) +class Data { +public: + int A; // CHECK-NEXT: |_ A (int|public) + static int B; // CHECK-NEXT: |_ B (int|public|static) + void func() {} // CHECK-NEXT: |_ func (void (void)|public|method) +}; + +// CHECK: Template (class|template) +template +class Template { +public: + T Value; // CHECK-NEXT: |_ Value (T|public) +}; + +// CHECK: TestClass (class) +class TestClass { +public: + int PublicInt; // CHECK-NEXT: |_ PublicInt (int|public) + static int PublicStaticInt; // CHECK-NEXT: |_ PublicStaticInt (int|public|static) + void publicFunc() {} // CHECK-NEXT: |_ publicFunc (void (void)|public|method) + +private: + int PrivateInt; // CHECK-NEXT: |_ PrivateInt (int|private) + static int PrivateStaticInt; // CHECK-NEXT: |_ PrivateStaticInt (int|private|static) + void privateFunc() {} // CHECK-NEXT: |_ privateFunc (void (void)|private|method) +}; + +// CHECK: AnotherTestClass (class) +class AnotherTestClass { +public: + double PublicDouble; // CHECK-NEXT: |_ PublicDouble (double|public) + static double PublicStaticDouble; // CHECK-NEXT: |_ PublicStaticDouble (double|public|static) + double publicFunc(); // CHECK-NEXT: |_ publicFunc (double (void)|public|method) + + Template TTestClass; // CHECK-NEXT: |_ TTestClass (Template|public) + +private: + double PrivateDouble; // CHECK-NEXT: |_ PrivateDouble (double|private) + static double PrivateStaticDouble; // CHECK-NEXT: |_ PrivateStaticDouble (double|private|static) + float privateFunc(const char* Str); // CHECK-NEXT: privateFunc (float (const char *)|private|method) +}; + +// CHECK: DerivedClass (class) +class DerivedClass : public TestClass { +public: + int DerivedPublicInt; // CHECK-NEXT: |_ DerivedPublicInt (int|public) + static int DerivedPublicStaticInt; // CHECK-NEXT: |_ DerivedPublicStaticInt (int|public|static) + TestClass derivedPublicFunc(Template Data, Template DataStr); // CHECK-NEXT: |_ derivedPublicFunc (TestClass (Template, Template)|public|method) + + AnotherTestClass ClassField; // CHECK-NEXT: |_ ClassField (AnotherTestClass|public) + +private: + int DerivedPrivateInt; // CHECK-NEXT: |_ DerivedPrivateInt (int|private) + static int DerivedPrivateStaticInt; // CHECK-NEXT: |_ DerivedPrivateStaticInt (int|private|static) + void derivedPrivateFunc(); // CHECK-NEXT: |_ derivedPrivateFunc (void (void)|private|method) + Template> TTestClass; // CHECK-NEXT: |_ TTestClass (Template >|private) +}; + +// CHECK: MyStruct (struct) +struct MyStruct { + int X; // CHECK-NEXT: |_ X (int|public) + double Y; // CHECK-NEXT: |_ Y (double|public) +}; \ No newline at end of file From c4295cb05cd6eaaf49069a6f3573a254a614b69a Mon Sep 17 00:00:00 2001 From: mahbhlddnhakkh <99867842+mahbhlddnhakkh@users.noreply.github.com> Date: Mon, 18 Mar 2024 08:52:24 +0300 Subject: [PATCH 15/18] Kulagin Aleksandr / lab1 / var 2 (#24) --- .../lab1/kulagin_aleksandr/CMakeLists.txt | 14 ++++ .../lab1/kulagin_aleksandr/alwaysInline.cpp | 71 ++++++++++++++++ clang/test/lab1/kulagin_aleksandr/test.cpp | 80 +++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 clang/labs/lab1/kulagin_aleksandr/CMakeLists.txt create mode 100644 clang/labs/lab1/kulagin_aleksandr/alwaysInline.cpp create mode 100644 clang/test/lab1/kulagin_aleksandr/test.cpp diff --git a/clang/labs/lab1/kulagin_aleksandr/CMakeLists.txt b/clang/labs/lab1/kulagin_aleksandr/CMakeLists.txt new file mode 100644 index 0000000000000..b6ff19980b5fe --- /dev/null +++ b/clang/labs/lab1/kulagin_aleksandr/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(kulaginAlwaysInline MODULE alwaysInline.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(kulaginAlwaysInline PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "kulaginAlwaysInline" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/labs/lab1/kulagin_aleksandr/alwaysInline.cpp b/clang/labs/lab1/kulagin_aleksandr/alwaysInline.cpp new file mode 100644 index 0000000000000..4d8c587137598 --- /dev/null +++ b/clang/labs/lab1/kulagin_aleksandr/alwaysInline.cpp @@ -0,0 +1,71 @@ +#include "clang/AST/AST.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/Stmt.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "llvm/ADT/StringRef.h" + +namespace { + +class AlwaysInlineConsumer : public clang::ASTConsumer { +public: + bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) override { + for (clang::Decl *Decl : DeclGroup) { + if (clang::isa(Decl)) { + if (Decl->getAttr()) { + continue; + } + clang::Stmt *Body = Decl->getBody(); + if (Body != nullptr) { + bool CondFound = false; + for (clang::Stmt *St : Body->children()) { + if (clang::isa(St) || + clang::isa(St) || + clang::isa(St) || + clang::isa(St) || + clang::isa(St)) { + CondFound = true; + break; + } + } + if (!CondFound) { + // TODO: how to put correct location?? + clang::SourceLocation Location(Decl->getSourceRange().getBegin()); + clang::SourceRange Range(Location); + Decl->addAttr( + clang::AlwaysInlineAttr::Create(Decl->getASTContext(), Range)); + } + } + } + } + return true; + } +}; + +class AlwaysInlinePlugin : public clang::PluginASTAction { +protected: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &Compiler, + llvm::StringRef InFile) override { + return std::make_unique(); + } + bool ParseArgs(const clang::CompilerInstance &Compiler, + const std::vector &Args) override { + for (const std::string &Arg : Args) { + if (Arg == "--help") { + llvm::outs() << "adds always_inline if no conditions inside body\n"; + return false; + } + } + return true; + } +}; + +} // namespace + +static clang::FrontendPluginRegistry::Add + X("always-inline", "adds always_inline if no conditions inside body"); diff --git a/clang/test/lab1/kulagin_aleksandr/test.cpp b/clang/test/lab1/kulagin_aleksandr/test.cpp new file mode 100644 index 0000000000000..ab465b407b6f1 --- /dev/null +++ b/clang/test/lab1/kulagin_aleksandr/test.cpp @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -ast-dump -ast-dump-filter foo -load %llvmshlibdir/kulaginAlwaysInline%pluginext -add-plugin always-inline %s | FileCheck %s +// COM: %clang_cc1 -load %llvmshlibdir/kulaginAlwaysInline%pluginext -add-plugin always-inline %s -emit-llvm -o - | FileCheck %s + +// CHECK: FunctionDecl {{0[xX][0-9a-fA-F]+ <.+test\.cpp:([0-9]+:[0-9]|[0-9]+), (line|col):([0-9]+:[0-9]|[0-9]+)> (line|col):([0-9]+:[0-9]|[0-9]+) foo1 'int \(\)'}} +int __attribute__((always_inline)) foo1() { return 0; } +// CHECK: `-AlwaysInlineAttr {{0[xX][0-9a-fA-F]+ <(line|col):([0-9]+:[0-9]|[0-9]+)> always_inline}} + +// CHECK: FunctionDecl {{0[xX][0-9a-fA-F]+ <.+test\.cpp:([0-9]+:[0-9]|[0-9]+), (line|col):([0-9]+:[0-9]|[0-9]+)> (line|col):([0-9]+:[0-9]|[0-9]+) foo2 'int \(\)'}} +int foo2() { return 0; } +// CHECK: `-AlwaysInlineAttr {{0[xX][0-9a-fA-F]+ <(line|col):([0-9]+:[0-9]|[0-9]+)> always_inline}} + +// CHECK: FunctionDecl {{0[xX][0-9a-fA-F]+ <.+test\.cpp:([0-9]+:[0-9]|[0-9]+), (line|col):([0-9]+:[0-9]|[0-9]+)> (line|col):([0-9]+:[0-9]|[0-9]+) foo3 'int \(\)'}} +int foo3() { + bool f = true; + if (f) { + f = false; + } + return 0; +} +// CHECK-NOT: `-AlwaysInlineAttr {{0[xX][0-9a-fA-F]+ <(line|col):([0-9]+:[0-9]|[0-9]+)> always_inline}} + +// CHECK: FunctionDecl {{0[xX][0-9a-fA-F]+ <.+test\.cpp:([0-9]+:[0-9]|[0-9]+), (line|col):([0-9]+:[0-9]|[0-9]+)> (line|col):([0-9]+:[0-9]|[0-9]+) foo4 'int \(\)'}} +int foo4() { + while (true) { + } + return 0; +} +// CHECK-NOT: `-AlwaysInlineAttr {{0[xX][0-9a-fA-F]+ <(line|col):([0-9]+:[0-9]|[0-9]+)> always_inline}} + +// CHECK: FunctionDecl {{0[xX][0-9a-fA-F]+ <.+test\.cpp:([0-9]+:[0-9]|[0-9]+), (line|col):([0-9]+:[0-9]|[0-9]+)> (line|col):([0-9]+:[0-9]|[0-9]+) foo5 'int \(\)'}} +int foo5() { + for (int i = 0; i < 5; i++) { + } + return 0; +} +// CHECK-NOT: `-AlwaysInlineAttr {{0[xX][0-9a-fA-F]+ <(line|col):([0-9]+:[0-9]|[0-9]+)> always_inline}} + +// CHECK: FunctionDecl {{0[xX][0-9a-fA-F]+ <.+test\.cpp:([0-9]+:[0-9]|[0-9]+), (line|col):([0-9]+:[0-9]|[0-9]+)> (line|col):([0-9]+:[0-9]|[0-9]+) foo6 'int \(\)'}} +int foo6() { + while (true) { + if (false) { + int d = -1; + if (d) { + return d; + } + } + } + return 0; +} +// CHECK-NOT: `-AlwaysInlineAttr {{0[xX][0-9a-fA-F]+ <(line|col):([0-9]+:[0-9]|[0-9]+)> always_inline}} + +// CHECK: FunctionDecl {{0[xX][0-9a-fA-F]+ <.+test\.cpp:([0-9]+:[0-9]|[0-9]+), (line|col):([0-9]+:[0-9]|[0-9]+)> (line|col):([0-9]+:[0-9]|[0-9]+) foo7 'int \(\)'}} +int foo7() { + do { + + } while (true); + return 0; +} +// CHECK-NOT: `-AlwaysInlineAttr {{0[xX][0-9a-fA-F]+ <(line|col):([0-9]+:[0-9]|[0-9]+)> always_inline}} + +// CHECK: FunctionDecl {{0[xX][0-9a-fA-F]+ <.+test\.cpp:([0-9]+:[0-9]|[0-9]+), (line|col):([0-9]+:[0-9]|[0-9]+)> (line|col):([0-9]+:[0-9]|[0-9]+) foo8 'int \(\)'}} +int foo8() { + int a = 1; + switch (a) { + case 1: + break; + default: + break; + } + return a; +} +// CHECK-NOT: `-AlwaysInlineAttr {{0[xX][0-9a-fA-F]+ <(line|col):([0-9]+:[0-9]|[0-9]+)> always_inline}} + +// CHECK: FunctionDecl {{0[xX][0-9a-fA-F]+ <.+test\.cpp:([0-9]+:[0-9]|[0-9]+), (line|col):([0-9]+:[0-9]|[0-9]+)> (line|col):([0-9]+:[0-9]|[0-9]+) foo9 'int \(int, int\)'}} +int foo9(int a, int b) { + int c; + c = a + b; + return c; +} +// CHECK: `-AlwaysInlineAttr {{0[xX][0-9a-fA-F]+ <(line|col):([0-9]+:[0-9]|[0-9]+)> always_inline}} From a9aa53552c0e2734b7c2f023d6485a2eed1bd770 Mon Sep 17 00:00:00 2001 From: aartyomm <91633547+aartyomm@users.noreply.github.com> Date: Mon, 18 Mar 2024 19:25:12 +0300 Subject: [PATCH 16/18] Kostin Artem. Lab #1. Var 3. (#15) * warning plugin * fixed * add -i option * fix clang-tidy * fix CMakeLists * fix clang-tidy 2 --------- Co-authored-by: m-ly4 --- clang/labs/lab1/kostin_artem/CMakeLists.txt | 14 ++++ clang/labs/lab1/kostin_artem/depr_plugin.cpp | 64 +++++++++++++++++++ .../lab1/kostin_artem/depr_plugin_test.cpp | 40 ++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 clang/labs/lab1/kostin_artem/CMakeLists.txt create mode 100644 clang/labs/lab1/kostin_artem/depr_plugin.cpp create mode 100644 clang/test/lab1/kostin_artem/depr_plugin_test.cpp diff --git a/clang/labs/lab1/kostin_artem/CMakeLists.txt b/clang/labs/lab1/kostin_artem/CMakeLists.txt new file mode 100644 index 0000000000000..232909d91022e --- /dev/null +++ b/clang/labs/lab1/kostin_artem/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(deprWarnPlugin MODULE depr_plugin.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(deprWarnPlugin PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "deprWarnPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) \ No newline at end of file diff --git a/clang/labs/lab1/kostin_artem/depr_plugin.cpp b/clang/labs/lab1/kostin_artem/depr_plugin.cpp new file mode 100644 index 0000000000000..a486981aae0e8 --- /dev/null +++ b/clang/labs/lab1/kostin_artem/depr_plugin.cpp @@ -0,0 +1,64 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendPluginRegistry.h" + +using namespace clang; + +class CustomNodeVisitor : public RecursiveASTVisitor { + bool CaseInsensitive; + +public: + CustomNodeVisitor(bool CaseInsensitive) : CaseInsensitive(CaseInsensitive) {} + bool VisitFunctionDecl(FunctionDecl *Pfunction) { // NOLINT + std::string NameOfFunction = Pfunction->getNameInfo().getAsString(); + if (CaseInsensitive) { + std::transform(NameOfFunction.begin(), NameOfFunction.end(), + NameOfFunction.begin(), ::tolower); + } + if (NameOfFunction.find("deprecated") != std::string::npos) { + DiagnosticsEngine &Diagnostics = + Pfunction->getASTContext().getDiagnostics(); + unsigned int DiagnosticsId = Diagnostics.getCustomDiagID( + DiagnosticsEngine::Warning, + "The function name contains \"deprecated\""); + SourceLocation PositionOfFunction = Pfunction->getLocation(); + Diagnostics.Report(PositionOfFunction, DiagnosticsId) << NameOfFunction; + } + return true; + } +}; + +class CustomConsumer : public ASTConsumer { + bool CaseInsensitive; + +public: + explicit CustomConsumer(bool CaseInsensitive) + : CaseInsensitive(CaseInsensitive) {} + void HandleTranslationUnit(ASTContext &Context) override { + CustomNodeVisitor Cnv(CaseInsensitive); + Cnv.TraverseDecl(Context.getTranslationUnitDecl()); + } +}; + +class PluginDeprFunc : public PluginASTAction { + bool CaseInsensitive = false; + std::unique_ptr + CreateASTConsumer(CompilerInstance &Instance, + llvm::StringRef InFile) override { + return std::make_unique(CaseInsensitive); + } + bool ParseArgs(const CompilerInstance &Compiler, + const std::vector &Args) override { + for (const auto &arg : Args) { + if (arg == "-i") { + CaseInsensitive = true; + } + } + return true; + } +}; + +static FrontendPluginRegistry::Add + X("plugin_for_deprecated_functions", + "If the function name contains \"deprecated\" plugin writes a warning"); diff --git a/clang/test/lab1/kostin_artem/depr_plugin_test.cpp b/clang/test/lab1/kostin_artem/depr_plugin_test.cpp new file mode 100644 index 0000000000000..00e5a8f4edc31 --- /dev/null +++ b/clang/test/lab1/kostin_artem/depr_plugin_test.cpp @@ -0,0 +1,40 @@ +// RUN: split-file %s %t +// RUN: %clang_cc1 -load %llvmshlibdir/deprWarnPlugin%pluginext -plugin plugin_for_deprecated_functions %t/with_-i.cpp -plugin-arg-plugin_for_deprecated_functions -i 2>&1 | FileCheck %t/with_-i.cpp +// RUN: %clang_cc1 -load %llvmshlibdir/deprWarnPlugin%pluginext -plugin plugin_for_deprecated_functions %t/without_-i.cpp 2>&1 | FileCheck %t/without_-i.cpp + + +//--- with_-i.cpp + +// CHECK: warning: The function name contains "deprecated" +void deprecatedFunction(); + +// CHECK: warning: The function name contains "deprecated" +void functionWithDeprecatedWord(); + +// CHECK-NOT: warning: The function name contains "deprecated" +void regularFunction(); + +class SomeClass { +// CHECK: warning: The function name contains "deprecated" + void functionWithDePrEcAtEdWord(); +// CHECK-NOT: warning: The function name contains "deprecated" + void regularFunctionAgain(); +}; + +//--- without_-i.cpp + +// CHECK: warning: The function name contains "deprecated" +void deprecatedFunction2(); + +// CHECK-NOT: warning: The function name contains "deprecated" +void functionWithDeprecatedWord2(); + +// CHECK-NOT: warning: The function name contains "deprecated" +void regularFunction2(); + +class SomeClass2 { +// CHECK-NOT: warning: The function name contains "deprecated" + void functionWithDePrEcAtEdWord2(); +// CHECK-NOT: warning: The function name contains "deprecated" + void regularFunctionAgain2(); +}; From e894020741c5a71bf9e009a302ef695dcc26c47c Mon Sep 17 00:00:00 2001 From: CrispiToken <55401919+NikitaKorablev@users.noreply.github.com> Date: Mon, 18 Mar 2024 20:06:48 +0300 Subject: [PATCH 17/18] Fixed CMakeFiles for Korablev Nikita's plugin (#30) --- clang/labs/lab1/korablev_nikita/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/labs/lab1/korablev_nikita/CMakeLists.txt b/clang/labs/lab1/korablev_nikita/CMakeLists.txt index 0fd043f3dd239..7f46ec70603c3 100644 --- a/clang/labs/lab1/korablev_nikita/CMakeLists.txt +++ b/clang/labs/lab1/korablev_nikita/CMakeLists.txt @@ -4,11 +4,11 @@ if(WIN32 OR CYGWIN) set(LLVM_LINK_COMPONENTS Support ) - clang_target_link_libraries(DeprecatedWarningPlugin PRIVATE + clang_target_link_libraries(RenamedIdPlugin PRIVATE clangAST clangBasic clangFrontend ) endif() -set(CLANG_TEST_DEPS "RenamedIdPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) \ No newline at end of file +set(CLANG_TEST_DEPS "RenamedIdPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) From a5842f3b60f003bc3368ec4429910a0398f37d9e Mon Sep 17 00:00:00 2001 From: UlyanovDaniil Date: Sat, 25 May 2024 19:39:30 +0300 Subject: [PATCH 18/18] try1 --- clang/labs/lab1/ulyanov_daniil/CMakeLists.txt | 14 ++ .../lab1/ulyanov_daniil/renameIdentifier.cpp | 193 +++++++++++++++++ clang/test/lab1/ulyanov_daniil/test.cpp | 203 ++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 clang/labs/lab1/ulyanov_daniil/CMakeLists.txt create mode 100644 clang/labs/lab1/ulyanov_daniil/renameIdentifier.cpp create mode 100644 clang/test/lab1/ulyanov_daniil/test.cpp diff --git a/clang/labs/lab1/ulyanov_daniil/CMakeLists.txt b/clang/labs/lab1/ulyanov_daniil/CMakeLists.txt new file mode 100644 index 0000000000000..ccce25632bf86 --- /dev/null +++ b/clang/labs/lab1/ulyanov_daniil/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_library(RenamePluginUlyanov MODULE renameIdentifier.cpp PLUGIN_TOOL clang) + +if(WIN32 OR CYGWIN) + set(LLVM_LINK_COMPONENTS + Support + ) + clang_target_link_libraries(RenamePluginUlyanov PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "RenamePluginUlyanov" ${CLANG_TEST_DEPS} PARENT_SCOPE) diff --git a/clang/labs/lab1/ulyanov_daniil/renameIdentifier.cpp b/clang/labs/lab1/ulyanov_daniil/renameIdentifier.cpp new file mode 100644 index 0000000000000..d94238a48352f --- /dev/null +++ b/clang/labs/lab1/ulyanov_daniil/renameIdentifier.cpp @@ -0,0 +1,193 @@ +#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" + +enum class IdType { Var, Func, Class }; + +class RenameVisitor : public clang::RecursiveASTVisitor { +public: + explicit RenameVisitor(clang::Rewriter rewriter, IdType type, + clang::StringRef first_name, clang::StringRef second_name) + : rewriter(rewriter), type(type), first_name(first_name), second_name(second_name) { + } + + bool VisitFunctionDecl(clang::FunctionDecl *func) { + if (type == IdType::Func && func->getName() == first_name) { + rewriter.ReplaceText(func->getNameInfo().getSourceRange(), second_name); + } + return true; + } + + bool VisitCallExpr(clang::CallExpr *call) { + if (type == IdType::Func) { + clang::FunctionDecl *callee = call->getDirectCallee(); + if (callee && callee->getName() == first_name) { + rewriter.ReplaceText(call->getCallee()->getSourceRange(), second_name); + } + } + return true; + } + + bool VisitVarDecl(clang::VarDecl *var) { + if (type == IdType::Var && var->getName() == first_name) { + rewriter.ReplaceText(var->getLocation(), first_name.size(), second_name); + } + if (type == IdType::Class && + var->getType().getAsString() == first_name + " *") { + rewriter.ReplaceText(var->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), + first_name.size(), second_name); + } + if (type == IdType::Class && var->getType().getAsString() == first_name) { + rewriter.ReplaceText( + var->getTypeSourceInfo()->getTypeLoc().getSourceRange(), second_name); + } + return true; + } + + bool VisitDeclRefExpr(clang::DeclRefExpr *expr) { + clang::VarDecl *var = clang::dyn_cast(expr->getDecl()); + if (type == IdType::Var && var && var->getName() == first_name) { + rewriter.ReplaceText(expr->getSourceRange(), second_name); + } + return true; + } + + bool VisitCXXRecordDecl(clang::CXXRecordDecl *record) { + if (type == IdType::Class && record->getName() == first_name) { + rewriter.ReplaceText(record->getLocation(), second_name); + const auto *destructor = record->getDestructor(); + if (destructor) { + rewriter.ReplaceText(destructor->getLocation(), first_name.size() + 1, + '~' + second_name); + } + } + return true; + } + + bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *constructor) { + if (type == IdType::Class) { + if (constructor->getNameAsString() == first_name) { + rewriter.ReplaceText(constructor->getLocation(), first_name.size(), + second_name); + } + } + return true; + } + + bool VisitCXXNewExpr(clang::CXXNewExpr *newExpr) { + if (type == IdType::Class) { + if (newExpr->getConstructExpr()->getType().getAsString() == first_name) { + rewriter.ReplaceText(newExpr->getExprLoc(), first_name.size() + 4, + "new " + second_name); + } + } + return true; + } + + bool save_changes() { return rewriter.overwriteChangedFiles(); } + +private: + clang::Rewriter rewriter; + IdType type; + std::string first_name; + std::string second_name; +}; + +class RenameASTConsumer : public clang::ASTConsumer { +public: + explicit RenameASTConsumer(clang::CompilerInstance &CI, IdType type, + clang::StringRef first_name, + clang::StringRef second_name) + : Visitor(clang::Rewriter(CI.getSourceManager(), CI.getLangOpts()), type, + first_name, second_name) {} + + void HandleTranslationUnit(clang::ASTContext &context) override { + Visitor.TraverseDecl(context.getTranslationUnitDecl()); + if (Visitor.save_changes()) { + llvm::errs() << "error with saving file!\n"; + } + } + +private: + RenameVisitor Visitor; +}; + +class RenamePlugin : public clang::PluginASTAction { +public: + std::unique_ptr + CreateASTConsumer(clang::CompilerInstance &CI, + clang::StringRef InFile) override { + return std::make_unique(CI, type, first_name, second_name); + } + +protected: + bool ParseArgs(const clang::CompilerInstance &CI, + const std::vector &args) override { + std::vector> params = { + {"type=", ""}, {"first-name=", ""}, {"second-name=", ""}}; + + if (!args.empty() && args[0] == "help") { + llvm::errs() << "Specify three required arguments:\n" + "-plugin-arg-rename type=[\"variable\", \"function\", \"class\"]\n" + "-plugin-arg-rename first-name=\"Current identifier name\"\n" + "-plugin-arg-rename second-name=\"New identifier name\"\n"; + return true; + } + + if (args.size() < 3) { + PrintParamsError(CI); + return false; + } + + for (const auto &arg : args) { + bool is_found = false; + for (auto ¶m : params) { + if (arg.find(param.first) == 0 && param.second.empty()) { + param.second = arg.substr(param.first.size()); + is_found = true; + break; + } + } + if (!is_found) { + PrintParamsError(CI); + return false; + } + } + + std::vector> id_type = { + {"variable", IdType::Var}, {"function", IdType::Func}, {"class", IdType::Class}}; + size_t i; + for (i = 0; i < id_type.size(); i++) { + if (params[0].second == id_type[i].first) { + type = id_type[i].second; + break; + } + } + if (i == id_type.size()) { + PrintParamsError(CI); + return false; + } + first_name = params[1].second; + second_name = params[2].second; + return true; + } + + void PrintParamsError(const clang::CompilerInstance &CI) { + clang::DiagnosticsEngine &D = CI.getDiagnostics(); + + D.Report( + D.getCustomDiagID(clang::DiagnosticsEngine::Error, + "Invalid arguments\n" + "Specify \"-plugin-arg-rename help\" for usage\n")); + } + +private: + IdType type; + std::string first_name; + std::string second_name; +}; + +static clang::FrontendPluginRegistry::Add + X("rename", "Rename variable, function or class"); \ No newline at end of file diff --git a/clang/test/lab1/ulyanov_daniil/test.cpp b/clang/test/lab1/ulyanov_daniil/test.cpp new file mode 100644 index 0000000000000..d2fe9563fa80a --- /dev/null +++ b/clang/test/lab1/ulyanov_daniil/test.cpp @@ -0,0 +1,203 @@ +// RUN: split-file %s %t + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=variable\ +// RUN: -plugin-arg-rename first-name=a\ +// RUN: -plugin-arg-rename second-name=new_var %t/rename_var.cpp +// RUN: FileCheck %s < %t/rename_var.cpp --check-prefix=VAR + +// VAR: int func() { +// VAR-NEXT: int new_var = 2, b = 2, c = 2; +// VAR-NEXT: new_var = new_var + b - c; +// VAR-NEXT: new_var++; +// VAR-NEXT: c = b; +// VAR-NEXT: return new_var; +// VAR-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=variable\ +// RUN: -plugin-arg-rename first-name=d\ +// RUN: -plugin-arg-rename second-name=new_var %t/rename_other_var.cpp +// RUN: FileCheck %s < %t/rename_other_var.cpp --check-prefix=NON_EXIST_VAR + +// NON_EXIST_VAR: int func() { +// NON_EXIST_VAR-NEXT: int a = 2, b = 2, c = 2; +// NON_EXIST_VAR-NEXT: a = a + b - c; +// NON_EXIST_VAR-NEXT: a++; +// NON_EXIST_VAR-NEXT: c = b; +// NON_EXIST_VAR-NEXT: return a; +// NON_EXIST_VAR-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=function\ +// RUN: -plugin-arg-rename first-name=function\ +// RUN: -plugin-arg-rename second-name=new_func %t/rename_func.cpp +// RUN: FileCheck %s < %t/rename_func.cpp --check-prefix=FUNC + +// FUNC: int new_func(int a) { +// FUNC-NEXT: b = 2; +// FUNC-NEXT: return a + b; +// FUNC-NEXT: } +// FUNC-NEXT: int function2(){ +// FUNC-NEXT: int a = new_func(2) + 2; +// FUNC-NEXT: return a; +// FUNC-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=function\ +// RUN: -plugin-arg-rename first-name=function\ +// RUN: -plugin-arg-rename second-name=new_func %t/rename_other_func.cpp +// RUN: FileCheck %s < %t/rename_other_func.cpp --check-prefix=NON_EXIST_FUNC + +// NON_EXIST_FUNC: int func(int a) { +// NON_EXIST_FUNC-NEXT: return a; +// NON_EXIST_FUNC-NEXT: } +// NON_EXIST_FUNC: void func2() { +// NON_EXIST_FUNC-NEXT: int a = func(2); +// NON_EXIST_FUNC-NEXT: int b = func(a) + func(2); +// NON_EXIST_FUNC-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=class\ +// RUN: -plugin-arg-rename first-name=abc\ +// RUN: -plugin-arg-rename second-name=new_class %t/rename_class.cpp +// RUN: FileCheck %s < %t/rename_class.cpp --check-prefix=CLASS + +// CLASS: class new_class{ +// CLASS-NEXT: private: +// CLASS-NEXT: int a; +// CLASS-NEXT: public: +// CLASS-NEXT: new_class() {} +// CLASS-NEXT: new_class(int a): a(a) {} +// CLASS-NEXT: ~new_class(); +// CLASS-NEXT: }; +// CLASS: void func() { +// CLASS-NEXT: new_class a; +// CLASS-NEXT: new_class* var = new new_class(1); +// CLASS-NEXT: delete var; +// CLASS-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=class\ +// RUN: -plugin-arg-rename first-name=B\ +// RUN: -plugin-arg-rename second-name=C %t/rename_other_class.cpp +// RUN: FileCheck %s < %t/rename_other_class.cpp --check-prefix=NON_EXIST_CLASS + +// NON_EXIST_CLASS: class A{ +// NON_EXIST_CLASS-NEXT: private: +// NON_EXIST_CLASS-NEXT: int var1; +// NON_EXIST_CLASS-NEXT: public: +// NON_EXIST_CLASS-NEXT: A() {}; +// NON_EXIST_CLASS-NEXT: ~A() {}; +// NON_EXIST_CLASS-NEXT: }; +// NON_EXIST_CLASS: void func() { +// NON_EXIST_CLASS-NEXT: A var1; +// NON_EXIST_CLASS-NEXT: A* var2 = new A; +// NON_EXIST_CLASS-NEXT: delete var2; +// NON_EXIST_CLASS-NEXT: } + +// RUN: %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename help\ +// RUN: 2>&1 | FileCheck %s --check-prefix=HELP + +// HELP: Specify three required arguments: +// HELP-NEXT: -plugin-arg-rename type=["variable", "function", "class"] +// HELP-NEXT: -plugin-arg-rename first-name="Current identifier name" +// HELP-NEXT: -plugin-arg-rename second-name="New identifier name" + +// RUN: not %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename first-name=B\ +// RUN: -plugin-arg-rename second-name=C\ +// RUN: 2>&1 | FileCheck %s --check-prefix=ERROR + +// RUN: not %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename first-name=B\ +// RUN: -plugin-arg-rename second-name=C\ +// RUN: -plugin-arg-rename param=val\ +// RUN: 2>&1 | FileCheck %s --check-prefix=ERROR + +// RUN: not %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: -plugin-arg-rename type=undefined\ +// RUN: -plugin-arg-rename first-name=B\ +// RUN: -plugin-arg-rename second-name=C\ +// RUN: 2>&1 | FileCheck %s --check-prefix=ERROR + +// RUN: not %clang_cc1 -load %llvmshlibdir/RenamePluginUlyanov%pluginext\ +// RUN: -add-plugin rename\ +// RUN: 2>&1 | FileCheck %s --check-prefix=ERROR + +//ERROR: Invalid arguments +//ERROR-NEXT: Specify "-plugin-arg-rename help" for usage + +//--- rename_var.cpp +int func() { + int a = 2, b = 2, c = 2; + a = a + b - c; + a++; + c = b; + return a; +} +//--- rename_other_var.cpp +int func() { + int a = 2, b = 2, c = 2; + a = a + b - c; + a++; + c = b; + return a; +} +//--- rename_func.cpp +int function(int a) { + int b = 2; + return a + b; +} +int function2(){ + int a = function(2) + 2; + return a; +} +//--- rename_other_func.cpp +int func(int a) { + return a; +} +void func2() { + int a = func(2); + int b = func(a) + func(2); +} +//--- rename_class.cpp +class abc{ + private: + int a; + public: + abc() {} + abc(int a): a(a) {} + ~abc(); +}; + +void func() { + abc a; + abc* var = new abc(1); + delete var; +} +//--- rename_other_class.cpp +class A{ + private: + int var1; + public: + A() {}; + ~A() {}; +}; + +void func() { + A var1; + A* var2 = new A; + delete var2; +} \ No newline at end of file