1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4 // This file is part of Lustre, http://www.lustre.org/
6 // cc-plugins/FindStatic.cpp
8 // Clang plugin to find functions which could be made
11 // Author: Timothy Day <timday@amazon.com>
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>
22 using namespace clang;
26 static std::unordered_map<std::string, int> functionMap;
28 bool isWarnable(FunctionDecl *MethodDecl) {
30 MethodDecl->isThisDeclarationADefinition() && MethodDecl->hasBody();
32 (functionMap.count(MethodDecl->getNameAsString()) == 0);
33 auto isNotStatic = !MethodDecl->isStatic();
35 MethodDecl->getASTContext().getSourceManager().isInMainFile(
36 MethodDecl->getLocation()) &&
37 !MethodDecl->isMain();
39 return isValidDef && isNotDeclared && isNotStatic && couldBeStatic;
42 class FindStaticDeclVisitor : public RecursiveASTVisitor<FindStaticDeclVisitor> {
43 DiagnosticsEngine &Diags;
44 unsigned WarningFoundStatic;
47 FindStaticDeclVisitor(DiagnosticsEngine &Diags) : Diags(Diags) {
48 WarningFoundStatic = Diags.getCustomDiagID(
49 DiagnosticsEngine::Warning, "Should this function be static?");
52 bool VisitFunctionDecl(FunctionDecl *MethodDecl) {
53 if (isWarnable(MethodDecl)) {
54 Diags.Report(MethodDecl->getLocation(), WarningFoundStatic);
61 class ScanDeclVisitor : public RecursiveASTVisitor<ScanDeclVisitor> {
63 bool VisitFunctionDecl(FunctionDecl *MethodDecl) {
64 if (!isWarnable(MethodDecl)) {
65 functionMap.insert({MethodDecl->getNameAsString(), 1});
72 class PrintFunctionsConsumer : public ASTConsumer {
74 void HandleTranslationUnit(ASTContext &Context) override {
75 ScanDeclVisitor Scanner;
76 Scanner.TraverseDecl(Context.getTranslationUnitDecl());
78 FindStaticDeclVisitor Visitor(Context.getDiagnostics());
79 Visitor.TraverseDecl(Context.getTranslationUnitDecl());
83 class FindStaticAction : public PluginASTAction {
84 std::set<std::string> ParsedTemplates;
87 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
88 llvm::StringRef) override {
89 return std::make_unique<PrintFunctionsConsumer>();
92 /// Consume plugin arguments; the plugin has no args, so always
95 /// \returns true when the parsing succeeds
96 bool ParseArgs(const CompilerInstance &CI,
97 const std::vector<std::string> &args) override {
101 /// Determines when to run action, in this case, automatically
102 /// after the main AST action.
104 /// \returns when the action should run
105 PluginASTAction::ActionType getActionType() override {
106 return AddAfterMainAction;
112 static FrontendPluginRegistry::Add<FindStaticAction>
113 X("find-static", "find potential static functions");