// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // This file is part of Lustre, http://www.lustre.org/ // // cc-plugins/FindStatic.cpp // // Clang plugin to find functions which could be made // static. // // Author: Timothy Day // #include #include #include #include #include #include #include using namespace clang; namespace { static std::unordered_map functionMap; bool isWarnable(FunctionDecl *MethodDecl) { auto isValidDef = MethodDecl->isThisDeclarationADefinition() && MethodDecl->hasBody(); auto isNotDeclared = (functionMap.count(MethodDecl->getNameAsString()) == 0); auto isNotStatic = !MethodDecl->isStatic(); auto couldBeStatic = MethodDecl->getASTContext().getSourceManager().isInMainFile( MethodDecl->getLocation()) && !MethodDecl->isMain(); return isValidDef && isNotDeclared && isNotStatic && couldBeStatic; } class FindStaticDeclVisitor : public RecursiveASTVisitor { DiagnosticsEngine &Diags; unsigned WarningFoundStatic; public: FindStaticDeclVisitor(DiagnosticsEngine &Diags) : Diags(Diags) { WarningFoundStatic = Diags.getCustomDiagID( DiagnosticsEngine::Warning, "Should this function be static?"); } bool VisitFunctionDecl(FunctionDecl *MethodDecl) { if (isWarnable(MethodDecl)) { Diags.Report(MethodDecl->getLocation(), WarningFoundStatic); } return true; } }; class ScanDeclVisitor : public RecursiveASTVisitor { public: bool VisitFunctionDecl(FunctionDecl *MethodDecl) { if (!isWarnable(MethodDecl)) { functionMap.insert({MethodDecl->getNameAsString(), 1}); } return true; } }; class PrintFunctionsConsumer : public ASTConsumer { public: void HandleTranslationUnit(ASTContext &Context) override { ScanDeclVisitor Scanner; Scanner.TraverseDecl(Context.getTranslationUnitDecl()); FindStaticDeclVisitor Visitor(Context.getDiagnostics()); Visitor.TraverseDecl(Context.getTranslationUnitDecl()); } }; class FindStaticAction : public PluginASTAction { std::set ParsedTemplates; protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) override { return std::make_unique(); } /// Consume plugin arguments; the plugin has no args, so always /// succeed. /// /// \returns true when the parsing succeeds bool ParseArgs(const CompilerInstance &CI, const std::vector &args) override { return true; } /// Determines when to run action, in this case, automatically /// after the main AST action. /// /// \returns when the action should run PluginASTAction::ActionType getActionType() override { return AddAfterMainAction; } }; } // namespace static FrontendPluginRegistry::Add X("find-static", "find potential static functions");