llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-tidy Author: Baranov Victor (vbvictor) <details> <summary>Changes</summary> When having this code: ```cpp namespace { class MyClassOutOfAnon { public: MyClassOutOfAnon(); } // namespace MyClassOutOfAnon::MyClassOutOfAnon() {} ``` `MyClassOutOfAnon::MyClassOutOfAnon` is located in anonymous namespace in `DeclContext` but outside anonymous namespace in `LexicalDeclContext`. For this check to work correctly, we need to check if definition is located inside `LexicalDeclContext`. I somehow forgot to add these test cases.. Thus, there are FPs that I didn't see when initially ran the check over LLVM codebase. No new release notes because it's a new check. cc @<!-- -->carlosgalvezp @<!-- -->5chmidti as original reviews, test structure is essentially the same but now handles this case. --- Full diff: https://github.com/llvm/llvm-project/pull/148357.diff 2 Files Affected: - (modified) clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp (+11) - (modified) clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp (+89) ``````````diff diff --git a/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp index 592f0986292f2..6c7b5dc374cec 100644 --- a/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp @@ -21,6 +21,17 @@ AST_MATCHER(NamedDecl, isInMacro) { AST_MATCHER(VarDecl, isLocalVariable) { return Node.isLocalVarDecl(); } +AST_MATCHER(Decl, isLexicallyInAnonymousNamespace) { + for (const DeclContext *DC = Node.getLexicalDeclContext(); DC != nullptr; + DC = DC->getLexicalParent()) { + if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) + if (ND->isAnonymousNamespace()) + return true; + } + + return false; +} + } // namespace PreferStaticOverAnonymousNamespaceCheck:: diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp index f0ffafcf18e67..71dce6ea4f01c 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/prefer-static-over-anonymous-namespace.cpp @@ -178,6 +178,95 @@ void OuterClass::NestedClass::nestedMemberFunc() {} } // namespace +namespace { + +class MyClassOutOfAnon { +public: + MyClassOutOfAnon(); + MyClassOutOfAnon(const MyClassOutOfAnon&) {} + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:3: warning: place definition of method 'MyClassOutOfAnon' outside of an anonymous namespace + MyClassOutOfAnon(MyClassOutOfAnon&&) = default; + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:3: warning: place definition of method 'MyClassOutOfAnon' outside of an anonymous namespace + MyClassOutOfAnon& operator=(const MyClassOutOfAnon&); + MyClassOutOfAnon& operator=(MyClassOutOfAnon&&); + bool operator<(const MyClassOutOfAnon&) const; + void memberFunction(); + static void staticMemberFunction(); + void memberDefinedInClass() {} + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:8: warning: place definition of method 'memberDefinedInClass' outside of an anonymous namespace + static void staticMemberDefinedInClass() {} + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:15: warning: place definition of method 'staticMemberDefinedInClass' outside of an anonymous namespace + template <typename T> + void templateFunction(); + template <typename T> + void templateFunctionInClass() {} + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:8: warning: place definition of method 'templateFunctionInClass' outside of an anonymous namespace +}; + +} // namespace + +MyClassOutOfAnon::MyClassOutOfAnon() {} + +MyClassOutOfAnon& MyClassOutOfAnon::operator=(const MyClassOutOfAnon&) { return *this; } + +MyClassOutOfAnon& MyClassOutOfAnon::operator=(MyClassOutOfAnon&&) = default; + +bool MyClassOutOfAnon::operator<(const MyClassOutOfAnon&) const { return true; } + +void MyClassOutOfAnon::memberFunction() {} + +void MyClassOutOfAnon::staticMemberFunction() {} + +template <typename T> +void MyClassOutOfAnon::templateFunction() {} + +namespace { + +template<typename T> +class TemplateClassOutOfAnon { + public: + TemplateClassOutOfAnon(); + TemplateClassOutOfAnon(const TemplateClassOutOfAnon&) {} + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:3: warning: place definition of method 'TemplateClassOutOfAnon<T>' outside of an anonymous namespace + TemplateClassOutOfAnon(TemplateClassOutOfAnon&&) = default; + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:3: warning: place definition of method 'TemplateClassOutOfAnon<T>' outside of an anonymous namespace + TemplateClassOutOfAnon& operator=(const TemplateClassOutOfAnon&); + TemplateClassOutOfAnon& operator=(TemplateClassOutOfAnon&&); + bool operator<(const TemplateClassOutOfAnon&) const; + void memberFunc(); + T getValue() const; + void memberDefinedInClass() {} + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:8: warning: place definition of method 'memberDefinedInClass' outside of an anonymous namespace + static void staticMemberDefinedInClass() {} + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:15: warning: place definition of method 'staticMemberDefinedInClass' outside of an anonymous namespace + template <typename U> + void templateMethodInTemplateClass() {} + // CHECK-MESSAGES-MEM: :[[@LINE-1]]:8: warning: place definition of method 'templateMethodInTemplateClass' outside of an anonymous namespace + private: + T Value; +}; + +} // namespace + +template<typename T> +TemplateClassOutOfAnon<T>::TemplateClassOutOfAnon() {} + +template<typename T> +TemplateClassOutOfAnon<T>& TemplateClassOutOfAnon<T>::operator=(const TemplateClassOutOfAnon&) { return *this; } + +template<typename T> +TemplateClassOutOfAnon<T>& TemplateClassOutOfAnon<T>::operator=(TemplateClassOutOfAnon&&) = default; + +template<typename T> +bool TemplateClassOutOfAnon<T>::operator<(const TemplateClassOutOfAnon&) const { return true; } + +template<typename T> +void TemplateClassOutOfAnon<T>::memberFunc() {} + +template<typename T> +T TemplateClassOutOfAnon<T>::getValue() const { return Value; } + + #define DEFINE_FUNCTION(name) \ namespace { \ void name() {} \ `````````` </details> https://github.com/llvm/llvm-project/pull/148357 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits