return llvm::isa<CXXMethodDecl>(&Node);
}
AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }
-} // namespace
-static bool isInAnonymousNamespace(const Decl *Decl) {
- const DeclContext *DC = Decl->getDeclContext();
- if (DC && DC->isNamespace()) {
- const auto *ND = llvm::cast<NamespaceDecl>(DC);
- if (ND && ND->isAnonymousNamespace())
- return true;
- }
- return false;
+AST_MATCHER(Decl, isInAnonymousNamespace) {
+ return Node.isInAnonymousNamespace();
}
+} // namespace
template <typename T>
void UseAnonymousNamespaceCheck::processMatch(const T *MatchedDecl) {
StringRef Type = llvm::isa<VarDecl>(MatchedDecl) ? "variable" : "function";
- if (isInAnonymousNamespace(MatchedDecl))
- diag(MatchedDecl->getLocation(), "%0 %1 declared 'static' in "
- "anonymous namespace, remove 'static'")
- << Type << MatchedDecl;
- else
- diag(MatchedDecl->getLocation(),
- "%0 %1 declared 'static', move to anonymous namespace instead")
- << Type << MatchedDecl;
+ diag(MatchedDecl->getLocation(),
+ "%0 %1 declared 'static', move to anonymous namespace instead")
+ << Type << MatchedDecl;
}
void UseAnonymousNamespaceCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- functionDecl(isStatic(), unless(isMemberFunction())).bind("func"), this);
+ functionDecl(isStatic(),
+ unless(anyOf(isInAnonymousNamespace(), isMemberFunction())))
+ .bind("func"),
+ this);
Finder->addMatcher(
- varDecl(isStatic(), unless(anyOf(isStaticLocal(), isStaticDataMember())))
+ varDecl(isStatic(), unless(anyOf(isInAnonymousNamespace(),
+ isStaticLocal(), isStaticDataMember())))
.bind("var"),
this);
}
namespace misc {
/// Warns when using 'static' functions or variables at global scope, and
-/// suggests moving them to an anonymous namespace. It also suggests removing
-/// 'static' if they are already inside an anonymous namespace.
+/// suggests moving them to an anonymous namespace.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-anonymous-namespace.html
============================
Finds instances of ``static`` functions or variables declared at global scope
-that could instead be moved into an anonymous namespace. It also detects
-instances moved to an anonymous namespace that still keep the redundant
-``static``.
+that could instead be moved into an anonymous namespace.
Anonymous namespaces are the "superior alternative" according to the C++
Standard. ``static`` was proposed for deprecation, but later un-deprecated to
int x;
} // namespace
-.. code-block:: c++
-
- // Bad
- namespace {
- static void foo();
- static int x;
- }
-
- // Good
- namespace {
- void foo();
- int x;
- } // namespace
-
[1] `Undeprecating static <https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1012>`_
static int v1;
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: variable 'v1' declared 'static', move to anonymous namespace instead
-namespace {
- static void f2();
- // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: function 'f2' declared 'static' in anonymous namespace, remove 'static'
- static int v2;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: variable 'v2' declared 'static' in anonymous namespace, remove 'static'
-}
-
namespace a {
static void f3();
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: function 'f3' declared 'static', move to anonymous namespace instead
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: variable 'v3' declared 'static', move to anonymous namespace instead
}
-namespace a {
-namespace {
- static void f4();
- // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: function 'f4' declared 'static' in anonymous namespace, remove 'static'
- static int v4;
- // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: variable 'v4' declared 'static' in anonymous namespace, remove 'static'
-}
-}
-
// OK
void f5();
int v5;