================ @@ -0,0 +1,79 @@ +//===--- UseInternalLinkageCheck.cpp - clang-tidy--------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "UseInternalLinkageCheck.h" +#include "clang/AST/Decl.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "clang/Basic/Specifiers.h" +#include "llvm/ADT/STLExtras.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::misc { + +namespace { + +AST_POLYMORPHIC_MATCHER(isFirstDecl, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + VarDecl)) { + return Node.isFirstDecl(); +} + +AST_MATCHER(Decl, isInMainFile) { + return llvm::all_of(Node.redecls(), [&](const Decl *D) { + return Finder->getASTContext().getSourceManager().isInMainFile( + D->getLocation()); + }); +} + +AST_POLYMORPHIC_MATCHER(isExternStorageClass, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + VarDecl)) { + return Node.getStorageClass() == SC_Extern; +} + +} // namespace + +void UseInternalLinkageCheck::registerMatchers(MatchFinder *Finder) { + auto Common = allOf(isFirstDecl(), isInMainFile(), + unless(anyOf( + // 1. internal linkage + isStaticStorageClass(), isInAnonymousNamespace(), + // 2. explicit external linkage + isExternStorageClass(), isExternC(), + // 3. template + isExplicitTemplateSpecialization(), + clang::ast_matchers::isTemplateInstantiation(), + // 4. friend + hasAncestor(friendDecl())))); + Finder->addMatcher( + functionDecl(Common, unless(cxxMethodDecl()), unless(isMain())) + .bind("fn"), + this); + Finder->addMatcher(varDecl(Common, hasGlobalStorage()).bind("var"), this); +} + +static constexpr StringRef Message = + "%0 %1 can be made static or moved into an anonymous namespace " + "to enforce internal linkage"; + +void UseInternalLinkageCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("fn")) { + diag(FD->getLocation(), Message) << "function" << FD; + return; + } + if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var")) { + diag(VD->getLocation(), Message) << "variable" << VD; + return; + } ---------------- 5chmidti wrote:
Please stream `SourceRange`s into the diagnostics. For the `FunctionDecl` you could use `SourceRange(FD->getBeginLoc(), FD->getTypeSpecEndLoc())`, which would not highlight the body (that would be quite noisy). https://github.com/llvm/llvm-project/pull/90830 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits