Index: clang-tidy/llvm/CMakeLists.txt =================================================================== --- clang-tidy/llvm/CMakeLists.txt +++ clang-tidy/llvm/CMakeLists.txt @@ -4,6 +4,7 @@ HeaderGuardCheck.cpp IncludeOrderCheck.cpp LLVMTidyModule.cpp + ProblematicStaticsCheck.cpp TwineLocalCheck.cpp LINK_LIBS Index: clang-tidy/llvm/LLVMTidyModule.cpp =================================================================== --- clang-tidy/llvm/LLVMTidyModule.cpp +++ clang-tidy/llvm/LLVMTidyModule.cpp @@ -13,6 +13,7 @@ #include "../readability/NamespaceCommentCheck.h" #include "HeaderGuardCheck.h" #include "IncludeOrderCheck.h" +#include "ProblematicStaticsCheck.h" #include "TwineLocalCheck.h" namespace clang { @@ -26,6 +27,8 @@ CheckFactories.registerCheck("llvm-include-order"); CheckFactories.registerCheck( "llvm-namespace-comment"); + CheckFactories.registerCheck( + "llvm-problematic-statics"); CheckFactories.registerCheck("llvm-twine-local"); } }; Index: clang-tidy/llvm/ProblematicStaticsCheck.h =================================================================== --- clang-tidy/llvm/ProblematicStaticsCheck.h +++ clang-tidy/llvm/ProblematicStaticsCheck.h @@ -0,0 +1,33 @@ +//===--- ProblematicStaticsCheck.h - clang-tidy ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_PROBLEMATIC_STATICS_CHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_PROBLEMATIC_STATICS_CHECK_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace llvm { + +/// Looks for static variables in LLVM headers that may pose problems for +/// users in other shared libraries. +class ProblematicStaticsCheck : public ClangTidyCheck { +public: + using ClangTidyCheck::ClangTidyCheck; + + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace llvm +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_PROBLEMATIC_STATICS_CHECK_H Index: clang-tidy/llvm/ProblematicStaticsCheck.cpp =================================================================== --- clang-tidy/llvm/ProblematicStaticsCheck.cpp +++ clang-tidy/llvm/ProblematicStaticsCheck.cpp @@ -0,0 +1,41 @@ +//===--- ProblematicStaticsCheck.cpp - clang-tidy -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ProblematicStaticsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace llvm { + +void ProblematicStaticsCheck::registerMatchers(MatchFinder *Finder) { + auto Matcher = returnStmt(hasReturnValue(ignoringImplicit(unaryOperator( + hasOperatorName("&"), + hasUnaryOperand(declRefExpr(to( + varDecl(isStaticLocal()).bind("var"))))))), + isExpansionInFileMatching("/include/.*\\.h")) + .bind("return"); + Finder->addMatcher(Matcher, this); +} + +void ProblematicStaticsCheck::check(const MatchFinder::MatchResult &Result) { + const auto *VD = Result.Nodes.getNodeAs("var"); + const auto *Return = Result.Nodes.getNodeAs("return"); + diag(Return->getBeginLoc(), "address of static local variable %0 may not " + "be identical across library boundaries") + << VD; +} + +} // namespace llvm +} // namespace tidy +} // namespace clang Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -163,6 +163,7 @@ llvm-header-guard llvm-include-order llvm-namespace-comment + llvm-problematic-statics llvm-twine-local misc-definitions-in-headers misc-misplaced-const Index: docs/clang-tidy/checks/llvm-problematic-statics.rst =================================================================== --- docs/clang-tidy/checks/llvm-problematic-statics.rst +++ docs/clang-tidy/checks/llvm-problematic-statics.rst @@ -0,0 +1,16 @@ +.. title:: clang-tidy - llvm-problematic-statics + +llvm-problematic-statics +======================== + + +Looks for functions defined in "public" headers that return the address of a static local. These are not guaranteed to have the addresss across shared libraries and could be problematic for plugins. + +.. code-block:: c++ + + struct ProgramStateTrait { + static void *GDMIndex() { + static int index = 0; + return &index; + } + }; Index: test/clang-tidy/Inputs/Headers/include/ProblematicStatics.h =================================================================== --- test/clang-tidy/Inputs/Headers/include/ProblematicStatics.h +++ test/clang-tidy/Inputs/Headers/include/ProblematicStatics.h @@ -0,0 +1,11 @@ +#ifndef PROBLEMATIC_STATICS_H +#define PROBLEMATIC_STATICS_H + +struct ProgramStateTrait { + static void *GDMIndex() { + static int index = 0; + return &index; + } +}; + +#endif Index: test/clang-tidy/llvm-problematic-statics.cpp =================================================================== --- test/clang-tidy/llvm-problematic-statics.cpp +++ test/clang-tidy/llvm-problematic-statics.cpp @@ -0,0 +1,4 @@ +// RUN: %check_clang_tidy %s llvm-problematic-statics %t -- -header-filter='.*' -- -I %S/Inputs/Headers + +#include "include/ProblematicStatics.h" +// CHECK-MESSAGES: ProblematicStatics.h:7:5: warning: address of static local variable 'index' may not be identical across library boundaries [llvm-problematic-statics]