Whamcloud - gitweb
46b0a5d4277f9fba8b6f3705ed249f7afb734e8e
[fs/lustre-release.git] / FindStatic.cpp
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2
3 //
4 // This file is part of Lustre, http://www.lustre.org/
5 //
6 // cc-plugins/FindStatic.cpp
7 //
8 // Clang plugin to find functions which could be made
9 // static.
10 //
11 // Author: Timothy Day <timday@amazon.com>
12 //
13
14 #include <clang/AST/AST.h>
15 #include <clang/AST/ASTConsumer.h>
16 #include <clang/AST/RecursiveASTVisitor.h>
17 #include <clang/Frontend/CompilerInstance.h>
18 #include <clang/Frontend/FrontendPluginRegistry.h>
19 #include <clang/Sema/Sema.h>
20 #include <llvm/Support/raw_ostream.h>
21
22 using namespace clang;
23
24 namespace {
25
26 static std::unordered_map<std::string, int> functionMap;
27
28 bool isWarnable(FunctionDecl *MethodDecl) {
29   auto isValidDef =
30       MethodDecl->isThisDeclarationADefinition() && MethodDecl->hasBody();
31   auto isNotDeclared =
32       (functionMap.count(MethodDecl->getNameAsString()) == 0);
33   auto isNotStatic = !MethodDecl->isStatic();
34   auto couldBeStatic =
35       MethodDecl->getASTContext().getSourceManager().isInMainFile(
36           MethodDecl->getLocation()) &&
37       !MethodDecl->isMain();
38
39   return isValidDef && isNotDeclared && isNotStatic && couldBeStatic;
40 }
41
42 class FindStaticDeclVisitor : public RecursiveASTVisitor<FindStaticDeclVisitor> {
43   DiagnosticsEngine &Diags;
44   unsigned WarningFoundStatic;
45
46 public:
47   FindStaticDeclVisitor(DiagnosticsEngine &Diags) : Diags(Diags) {
48     WarningFoundStatic = Diags.getCustomDiagID(
49         DiagnosticsEngine::Warning, "Should this function be static?");
50   }
51
52   bool VisitFunctionDecl(FunctionDecl *MethodDecl) {
53     if (isWarnable(MethodDecl)) {
54       Diags.Report(MethodDecl->getLocation(), WarningFoundStatic);
55     }
56
57     return true;
58   }
59 };
60
61 class ScanDeclVisitor : public RecursiveASTVisitor<ScanDeclVisitor> {
62 public:
63   bool VisitFunctionDecl(FunctionDecl *MethodDecl) {
64     if (!isWarnable(MethodDecl)) {
65       functionMap.insert({MethodDecl->getNameAsString(), 1});
66     }
67
68     return true;
69   }
70 };
71
72 class PrintFunctionsConsumer : public ASTConsumer {
73 public:
74   void HandleTranslationUnit(ASTContext &Context) override {
75     ScanDeclVisitor Scanner;
76     Scanner.TraverseDecl(Context.getTranslationUnitDecl());
77
78     FindStaticDeclVisitor Visitor(Context.getDiagnostics());
79     Visitor.TraverseDecl(Context.getTranslationUnitDecl());
80   }
81 };
82
83 class FindStaticAction : public PluginASTAction {
84   std::set<std::string> ParsedTemplates;
85
86 protected:
87   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
88                                                  llvm::StringRef) override {
89     return std::make_unique<PrintFunctionsConsumer>();
90   }
91
92   /// Consume plugin arguments; the plugin has no args, so always
93   /// succeed.
94   ///
95   /// \returns true when the parsing succeeds
96   bool ParseArgs(const CompilerInstance &CI,
97                  const std::vector<std::string> &args) override {
98     return true;
99   }
100
101   /// Determines when to run action, in this case, automatically
102   /// after the main AST action.
103   ///
104   /// \returns when the action should run
105   PluginASTAction::ActionType getActionType() override {
106     return AddAfterMainAction;
107   }
108 };
109
110 } // namespace
111
112 static FrontendPluginRegistry::Add<FindStaticAction>
113     X("find-static", "find potential static functions");