diff --git a/.github/workflows/nn-cmplr-tidy.yml b/.github/workflows/nn-cmplr-tidy.yml index ff1432a3b68cb..5d0cf93c7e3ed 100644 --- a/.github/workflows/nn-cmplr-tidy.yml +++ b/.github/workflows/nn-cmplr-tidy.yml @@ -7,12 +7,15 @@ 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} 2>&1 | tee log.txt + exit `grep -c diff log.txt` clang-tidy: runs-on: ubuntu-latest steps: 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/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/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/labs/lab1/korablev_nikita/CMakeLists.txt b/clang/labs/lab1/korablev_nikita/CMakeLists.txt new file mode 100644 index 0000000000000..7f46ec70603c3 --- /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(RenamedIdPlugin PRIVATE + clangAST + clangBasic + clangFrontend + ) +endif() + +set(CLANG_TEST_DEPS "RenamedIdPlugin" ${CLANG_TEST_DEPS} PARENT_SCOPE) 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/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/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/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/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/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/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/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/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/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..6b2d1b426468c --- /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/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/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 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 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 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(); +}; 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}} 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 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 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() {} +}; 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); 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 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 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 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; +}