[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-06-30 Thread Balázs Kéri via cfe-commits

https://github.com/balazske updated 
https://github.com/llvm/llvm-project/pull/140086

From 65d44a4eb9621e49a96f1ac43e5a1bbd6691dc13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= 
Date: Thu, 15 May 2025 17:41:16 +0200
Subject: [PATCH 1/9] [clang-tidy] Added check
 'bugprone-function-visibility-change'

---
 .../bugprone/BugproneTidyModule.cpp   |   3 +
 .../clang-tidy/bugprone/CMakeLists.txt|   1 +
 .../FunctionVisibilityChangeCheck.cpp |  74 ++
 .../bugprone/FunctionVisibilityChangeCheck.h  |  33 +++
 clang-tools-extra/docs/ReleaseNotes.rst   |   5 +
 .../bugprone/function-visibility-change.rst   |  43 
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../bugprone/function-visibility-change.cpp   | 234 ++
 8 files changed, 394 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/bugprone/function-visibility-change.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/function-visibility-change.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index b780a85bdf3fe..7cf58c5218969 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
 #include "ForwardingReferenceOverloadCheck.h"
+#include "FunctionVisibilityChangeCheck.h"
 #include "ImplicitWideningOfMultiplicationResultCheck.h"
 #include "InaccurateEraseCheck.h"
 #include "IncDecInConditionsCheck.h"
@@ -143,6 +144,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-forward-declaration-namespace");
 CheckFactories.registerCheck(
 "bugprone-forwarding-reference-overload");
+CheckFactories.registerCheck(
+"bugprone-function-visibility-change");
 CheckFactories.registerCheck(
 "bugprone-implicit-widening-of-multiplication-result");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index e310ea9c94543..b4f7ba76f4cee 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   FoldInitTypeCheck.cpp
   ForwardDeclarationNamespaceCheck.cpp
   ForwardingReferenceOverloadCheck.cpp
+  FunctionVisibilityChangeCheck.cpp
   ImplicitWideningOfMultiplicationResultCheck.cpp
   InaccurateEraseCheck.cpp
   IncorrectEnableIfCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
new file mode 100644
index 0..7ea4ed20705ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem

[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-06-05 Thread via cfe-commits
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= 
Message-ID:
In-Reply-To: 



@@ -1,41 +1,55 @@
-//===--- FunctionVisibilityChangeCheck.cpp - clang-tidy 
---===//
+//===--- VisibilityChangeToVirtualFunctionCheck.cpp - clang-tidy
+//---===//

EugeneZelenko wrote:

Please merge with previous line.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-06-05 Thread Balázs Kéri via cfe-commits

https://github.com/balazske updated 
https://github.com/llvm/llvm-project/pull/140086

From 65d44a4eb9621e49a96f1ac43e5a1bbd6691dc13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= 
Date: Thu, 15 May 2025 17:41:16 +0200
Subject: [PATCH 1/8] [clang-tidy] Added check
 'bugprone-function-visibility-change'

---
 .../bugprone/BugproneTidyModule.cpp   |   3 +
 .../clang-tidy/bugprone/CMakeLists.txt|   1 +
 .../FunctionVisibilityChangeCheck.cpp |  74 ++
 .../bugprone/FunctionVisibilityChangeCheck.h  |  33 +++
 clang-tools-extra/docs/ReleaseNotes.rst   |   5 +
 .../bugprone/function-visibility-change.rst   |  43 
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../bugprone/function-visibility-change.cpp   | 234 ++
 8 files changed, 394 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/bugprone/function-visibility-change.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/function-visibility-change.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index b780a85bdf3fe..7cf58c5218969 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
 #include "ForwardingReferenceOverloadCheck.h"
+#include "FunctionVisibilityChangeCheck.h"
 #include "ImplicitWideningOfMultiplicationResultCheck.h"
 #include "InaccurateEraseCheck.h"
 #include "IncDecInConditionsCheck.h"
@@ -143,6 +144,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-forward-declaration-namespace");
 CheckFactories.registerCheck(
 "bugprone-forwarding-reference-overload");
+CheckFactories.registerCheck(
+"bugprone-function-visibility-change");
 CheckFactories.registerCheck(
 "bugprone-implicit-widening-of-multiplication-result");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index e310ea9c94543..b4f7ba76f4cee 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   FoldInitTypeCheck.cpp
   ForwardDeclarationNamespaceCheck.cpp
   ForwardingReferenceOverloadCheck.cpp
+  FunctionVisibilityChangeCheck.cpp
   ImplicitWideningOfMultiplicationResultCheck.cpp
   InaccurateEraseCheck.cpp
   IncorrectEnableIfCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
new file mode 100644
index 0..7ea4ed20705ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem

[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-06-04 Thread Balázs Kéri via cfe-commits

balazske wrote:

> > In my opinion, it should not be bugprone because I don't find any potential 
> > bug in this code style. Maybe it more like a readability issue? @PiotrZSL 
> > @EugeneZelenko what do you think?
> 
> Sorry, I don't have strong opinion on this matter.

I think the "misc" module would be the best place for this check.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-06-02 Thread Congcong Cai via cfe-commits
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,136 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy {
+
+template <>
+struct OptionEnumMapping {
+  static llvm::ArrayRef<
+  std::pair>
+  getEnumMapping() {
+static constexpr std::pair<
+bugprone::FunctionVisibilityChangeCheck::ChangeKind, StringRef>
+Mapping[] = {
+{bugprone::FunctionVisibilityChangeCheck::ChangeKind::Any, "any"},
+{bugprone::FunctionVisibilityChangeCheck::ChangeKind::Widening,
+ "widening"},
+{bugprone::FunctionVisibilityChangeCheck::ChangeKind::Narrowing,
+ "narrowing"},
+};
+return {Mapping};
+  }
+};
+
+namespace bugprone {
+
+FunctionVisibilityChangeCheck::FunctionVisibilityChangeCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  DetectVisibilityChange(
+  Options.get("DisallowedVisibilityChange", ChangeKind::Any)),
+  CheckDestructors(Options.get("CheckDestructors", false)),
+  CheckOperators(Options.get("CheckOperators", false)),
+  IgnoredFunctions(utils::options::parseStringList(
+  Options.get("IgnoredFunctions", ""))) {}
+
+void FunctionVisibilityChangeCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "DisallowedVisibilityChange", DetectVisibilityChange);
+  Options.store(Opts, "CheckDestructors", CheckDestructors);
+  Options.store(Opts, "CheckOperators", CheckOperators);
+  Options.store(Opts, "IgnoredFunctions",
+utils::options::serializeStringList(IgnoredFunctions));
+}
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  auto IgnoredDecl =
+  namedDecl(matchers::matchesAnyListedName(IgnoredFunctions));
+  Finder->addMatcher(
+  cxxMethodDecl(
+  isVirtual(),
+  ofClass(
+  
cxxRecordDecl(unless(isExpansionInSystemHeader())).bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")),
+  unless(IgnoredDecl))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+  DeclarationName::NameKind NK = MatchedFunction->getDeclName().getNameKind();
+  if (!CheckDestructors && NK == DeclarationName::CXXDestructorName)
+return;
+  if (!CheckOperators && NK != DeclarationName::Identifier &&
+  NK != DeclarationName::CXXConstructorName &&
+  NK != DeclarationName::CXXDestructorName)
+return;

HerrCai0907 wrote:

something like `auto M = CheckDestructors ? () : decl();`

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-06-02 Thread Balázs Kéri via cfe-commits


@@ -0,0 +1,136 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy {
+
+template <>
+struct OptionEnumMapping {
+  static llvm::ArrayRef<
+  std::pair>
+  getEnumMapping() {
+static constexpr std::pair<
+bugprone::FunctionVisibilityChangeCheck::ChangeKind, StringRef>
+Mapping[] = {
+{bugprone::FunctionVisibilityChangeCheck::ChangeKind::Any, "any"},
+{bugprone::FunctionVisibilityChangeCheck::ChangeKind::Widening,
+ "widening"},
+{bugprone::FunctionVisibilityChangeCheck::ChangeKind::Narrowing,
+ "narrowing"},
+};
+return {Mapping};
+  }
+};
+
+namespace bugprone {
+
+FunctionVisibilityChangeCheck::FunctionVisibilityChangeCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  DetectVisibilityChange(
+  Options.get("DisallowedVisibilityChange", ChangeKind::Any)),
+  CheckDestructors(Options.get("CheckDestructors", false)),
+  CheckOperators(Options.get("CheckOperators", false)),
+  IgnoredFunctions(utils::options::parseStringList(
+  Options.get("IgnoredFunctions", ""))) {}
+
+void FunctionVisibilityChangeCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "DisallowedVisibilityChange", DetectVisibilityChange);
+  Options.store(Opts, "CheckDestructors", CheckDestructors);
+  Options.store(Opts, "CheckOperators", CheckOperators);
+  Options.store(Opts, "IgnoredFunctions",
+utils::options::serializeStringList(IgnoredFunctions));
+}
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  auto IgnoredDecl =
+  namedDecl(matchers::matchesAnyListedName(IgnoredFunctions));
+  Finder->addMatcher(
+  cxxMethodDecl(
+  isVirtual(),
+  ofClass(
+  
cxxRecordDecl(unless(isExpansionInSystemHeader())).bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")),
+  unless(IgnoredDecl))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+  DeclarationName::NameKind NK = MatchedFunction->getDeclName().getNameKind();
+  if (!CheckDestructors && NK == DeclarationName::CXXDestructorName)
+return;
+  if (!CheckOperators && NK != DeclarationName::Identifier &&
+  NK != DeclarationName::CXXConstructorName &&
+  NK != DeclarationName::CXXDestructorName)
+return;

balazske wrote:

I did not find a much better way to check the condition, a conditionally added 
matcher can be used but I did not see this pattern in other checker code.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-06-02 Thread Balázs Kéri via cfe-commits

https://github.com/balazske updated 
https://github.com/llvm/llvm-project/pull/140086

From 65d44a4eb9621e49a96f1ac43e5a1bbd6691dc13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= 
Date: Thu, 15 May 2025 17:41:16 +0200
Subject: [PATCH 1/6] [clang-tidy] Added check
 'bugprone-function-visibility-change'

---
 .../bugprone/BugproneTidyModule.cpp   |   3 +
 .../clang-tidy/bugprone/CMakeLists.txt|   1 +
 .../FunctionVisibilityChangeCheck.cpp |  74 ++
 .../bugprone/FunctionVisibilityChangeCheck.h  |  33 +++
 clang-tools-extra/docs/ReleaseNotes.rst   |   5 +
 .../bugprone/function-visibility-change.rst   |  43 
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../bugprone/function-visibility-change.cpp   | 234 ++
 8 files changed, 394 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/bugprone/function-visibility-change.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/function-visibility-change.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index b780a85bdf3fe..7cf58c5218969 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
 #include "ForwardingReferenceOverloadCheck.h"
+#include "FunctionVisibilityChangeCheck.h"
 #include "ImplicitWideningOfMultiplicationResultCheck.h"
 #include "InaccurateEraseCheck.h"
 #include "IncDecInConditionsCheck.h"
@@ -143,6 +144,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-forward-declaration-namespace");
 CheckFactories.registerCheck(
 "bugprone-forwarding-reference-overload");
+CheckFactories.registerCheck(
+"bugprone-function-visibility-change");
 CheckFactories.registerCheck(
 "bugprone-implicit-widening-of-multiplication-result");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index e310ea9c94543..b4f7ba76f4cee 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   FoldInitTypeCheck.cpp
   ForwardDeclarationNamespaceCheck.cpp
   ForwardingReferenceOverloadCheck.cpp
+  FunctionVisibilityChangeCheck.cpp
   ImplicitWideningOfMultiplicationResultCheck.cpp
   InaccurateEraseCheck.cpp
   IncorrectEnableIfCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
new file mode 100644
index 0..7ea4ed20705ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem

[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-29 Thread via cfe-commits
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-29 Thread Balázs Kéri via cfe-commits

https://github.com/balazske updated 
https://github.com/llvm/llvm-project/pull/140086

From 65d44a4eb9621e49a96f1ac43e5a1bbd6691dc13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= 
Date: Thu, 15 May 2025 17:41:16 +0200
Subject: [PATCH 1/5] [clang-tidy] Added check
 'bugprone-function-visibility-change'

---
 .../bugprone/BugproneTidyModule.cpp   |   3 +
 .../clang-tidy/bugprone/CMakeLists.txt|   1 +
 .../FunctionVisibilityChangeCheck.cpp |  74 ++
 .../bugprone/FunctionVisibilityChangeCheck.h  |  33 +++
 clang-tools-extra/docs/ReleaseNotes.rst   |   5 +
 .../bugprone/function-visibility-change.rst   |  43 
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../bugprone/function-visibility-change.cpp   | 234 ++
 8 files changed, 394 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/bugprone/function-visibility-change.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/function-visibility-change.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index b780a85bdf3fe..7cf58c5218969 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
 #include "ForwardingReferenceOverloadCheck.h"
+#include "FunctionVisibilityChangeCheck.h"
 #include "ImplicitWideningOfMultiplicationResultCheck.h"
 #include "InaccurateEraseCheck.h"
 #include "IncDecInConditionsCheck.h"
@@ -143,6 +144,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-forward-declaration-namespace");
 CheckFactories.registerCheck(
 "bugprone-forwarding-reference-overload");
+CheckFactories.registerCheck(
+"bugprone-function-visibility-change");
 CheckFactories.registerCheck(
 "bugprone-implicit-widening-of-multiplication-result");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index e310ea9c94543..b4f7ba76f4cee 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   FoldInitTypeCheck.cpp
   ForwardDeclarationNamespaceCheck.cpp
   ForwardingReferenceOverloadCheck.cpp
+  FunctionVisibilityChangeCheck.cpp
   ImplicitWideningOfMultiplicationResultCheck.cpp
   InaccurateEraseCheck.cpp
   IncorrectEnableIfCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
new file mode 100644
index 0..7ea4ed20705ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem

[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-24 Thread Baranov Victor via cfe-commits
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= 
Message-ID:
In-Reply-To: 


https://github.com/vbvictor edited 
https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-24 Thread Baranov Victor via cfe-commits
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= 
Message-ID:
In-Reply-To: 


https://github.com/vbvictor edited 
https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-23 Thread Baranov Victor via cfe-commits
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,136 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy {
+
+template <>
+struct OptionEnumMapping {
+  static llvm::ArrayRef<
+  std::pair>
+  getEnumMapping() {
+static constexpr std::pair<
+bugprone::FunctionVisibilityChangeCheck::ChangeKind, StringRef>
+Mapping[] = {
+{bugprone::FunctionVisibilityChangeCheck::ChangeKind::Any, "any"},
+{bugprone::FunctionVisibilityChangeCheck::ChangeKind::Widening,
+ "widening"},
+{bugprone::FunctionVisibilityChangeCheck::ChangeKind::Narrowing,
+ "narrowing"},
+};
+return {Mapping};
+  }
+};
+
+namespace bugprone {
+
+FunctionVisibilityChangeCheck::FunctionVisibilityChangeCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  DetectVisibilityChange(
+  Options.get("DisallowedVisibilityChange", ChangeKind::Any)),
+  CheckDestructors(Options.get("CheckDestructors", false)),
+  CheckOperators(Options.get("CheckOperators", false)),
+  IgnoredFunctions(utils::options::parseStringList(
+  Options.get("IgnoredFunctions", ""))) {}
+
+void FunctionVisibilityChangeCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "DisallowedVisibilityChange", DetectVisibilityChange);
+  Options.store(Opts, "CheckDestructors", CheckDestructors);
+  Options.store(Opts, "CheckOperators", CheckOperators);
+  Options.store(Opts, "IgnoredFunctions",
+utils::options::serializeStringList(IgnoredFunctions));
+}
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  auto IgnoredDecl =
+  namedDecl(matchers::matchesAnyListedName(IgnoredFunctions));
+  Finder->addMatcher(
+  cxxMethodDecl(
+  isVirtual(),
+  ofClass(
+  
cxxRecordDecl(unless(isExpansionInSystemHeader())).bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")),
+  unless(IgnoredDecl))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+  DeclarationName::NameKind NK = MatchedFunction->getDeclName().getNameKind();
+  if (!CheckDestructors && NK == DeclarationName::CXXDestructorName)
+return;
+  if (!CheckOperators && NK != DeclarationName::Identifier &&
+  NK != DeclarationName::CXXConstructorName &&
+  NK != DeclarationName::CXXDestructorName)
+return;

vbvictor wrote:

This can possibly go into the ast-matchers part. You can look for checks that 
use options inside mathers with "? unless", "? is" or "? has" strings.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-23 Thread Baranov Victor via cfe-commits
=?utf-8?q?Balázs_Kéri?= ,
=?utf-8?q?Balázs_Kéri?= 
Message-ID:
In-Reply-To: 



@@ -124,6 +124,11 @@ New checks
   pointer and store it as class members without handle the copy and move
   constructors and the assignments.
 
+- New :doc:`bugprone-function-visibility-change
+  ` check.
+
+  Checks function visibility changes in subclasses.

vbvictor wrote:

Nit suggestion: make this doc line similar to already existing checks in 
ReleaseNotes, it should start with "Finds..."
Please sync this also with check .rst doc and comment in check header file.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-23 Thread Baranov Victor via cfe-commits
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-21 Thread Balázs Kéri via cfe-commits

balazske wrote:

I have renamed the check, if OK the class name will be changed too (in a new 
commit).

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-21 Thread Balázs Kéri via cfe-commits

https://github.com/balazske updated 
https://github.com/llvm/llvm-project/pull/140086

From 65d44a4eb9621e49a96f1ac43e5a1bbd6691dc13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= 
Date: Thu, 15 May 2025 17:41:16 +0200
Subject: [PATCH 1/3] [clang-tidy] Added check
 'bugprone-function-visibility-change'

---
 .../bugprone/BugproneTidyModule.cpp   |   3 +
 .../clang-tidy/bugprone/CMakeLists.txt|   1 +
 .../FunctionVisibilityChangeCheck.cpp |  74 ++
 .../bugprone/FunctionVisibilityChangeCheck.h  |  33 +++
 clang-tools-extra/docs/ReleaseNotes.rst   |   5 +
 .../bugprone/function-visibility-change.rst   |  43 
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../bugprone/function-visibility-change.cpp   | 234 ++
 8 files changed, 394 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/bugprone/function-visibility-change.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/function-visibility-change.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index b780a85bdf3fe..7cf58c5218969 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
 #include "ForwardingReferenceOverloadCheck.h"
+#include "FunctionVisibilityChangeCheck.h"
 #include "ImplicitWideningOfMultiplicationResultCheck.h"
 #include "InaccurateEraseCheck.h"
 #include "IncDecInConditionsCheck.h"
@@ -143,6 +144,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-forward-declaration-namespace");
 CheckFactories.registerCheck(
 "bugprone-forwarding-reference-overload");
+CheckFactories.registerCheck(
+"bugprone-function-visibility-change");
 CheckFactories.registerCheck(
 "bugprone-implicit-widening-of-multiplication-result");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index e310ea9c94543..b4f7ba76f4cee 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   FoldInitTypeCheck.cpp
   ForwardDeclarationNamespaceCheck.cpp
   ForwardingReferenceOverloadCheck.cpp
+  FunctionVisibilityChangeCheck.cpp
   ImplicitWideningOfMultiplicationResultCheck.cpp
   InaccurateEraseCheck.cpp
   IncorrectEnableIfCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
new file mode 100644
index 0..7ea4ed20705ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem

[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread Balázs Kéri via cfe-commits

balazske wrote:

The current code is not finished. I want to check for false positives and 
probably add options to disable check at destructors and operators.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread Balázs Kéri via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem.Base->getAccessSpecifier();
+InheritanceWithStrictVisibility = Elem.Base;
+  }
+}
+  }
+
+  if (ActualAccess != OverriddenAccess) {
+if (InheritanceWithStrictVisibility) {
+  diag(MatchedFunction->getLocation(),
+   "visibility of function %0 is changed from %1 (through %1 "
+   "inheritance of class %2) to %3")
+  << MatchedFunction << OverriddenAccess
+  << InheritanceWithStrictVisibility->getType() << ActualAccess;
+  diag(InheritanceWithStrictVisibility->getBeginLoc(),
+   "this inheritance would make %0 %1", DiagnosticIDs::Note)

balazske wrote:

fixed

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread Balázs Kéri via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(

balazske wrote:

fixed (inheritance from system code in non-system code is detected now)

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread Balázs Kéri via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {

balazske wrote:

fixed

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread Balázs Kéri via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem.Base->getAccessSpecifier();
+InheritanceWithStrictVisibility = Elem.Base;
+  }
+}
+  }
+
+  if (ActualAccess != OverriddenAccess) {

balazske wrote:

Option is added now to set the type of change.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread via cfe-commits
=?utf-8?q?Balázs_Kéri?= 
Message-ID:
In-Reply-To: 



@@ -3,10 +3,13 @@
 bugprone-function-visibility-change
 ===
 
-Check changes in visibility of C++ member functions in subclasses. The check
-detects if a virtual function is overridden with a different visibility than in
-the base class declaration. Only normal functions are detected, no 
constructors,
-operators, conversions or other special functions.
+Checks changes in visibility of C++ member functions in subclasses. This
+includes for example if a virtual function declared as `private` is overridden
+and declared as `public` in a subclass. The detected change is the modification
+of visibility resulting from keywords `public`, `protected`, `private` at
+overridden virtual functions. Use of the `using` keyword is not considered by

EugeneZelenko wrote:

```suggestion
and declared as ``public`` in a subclass. The detected change is the 
modification
of visibility resulting from keywords ``public``, ``protected``, ``private`` at
overridden virtual functions. Use of the ``using`` keyword is not considered by
```

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread via cfe-commits
=?utf-8?q?Balázs_Kéri?= 
Message-ID:
In-Reply-To: 



@@ -232,3 +238,52 @@ C fC() {
 }
 
 }
+
+namespace test_system_header {
+
+struct SysDerived: public sys::Base {
+private:
+  void publicF();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 'publicF' 
is changed from public in class 'Base' to private
+};
+
+}
+
+namespace test_destructor {
+
+class A {
+public:
+  virtual ~A();
+};
+
+class B: public A {
+protected:
+  ~B();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: visibility of function '~B'
+  // CHECK-MESSAGES: :[[@LINE-7]]:11: note: function declared here
+};
+
+}
+
+namespace test_operator {
+
+class A {
+  virtual int operator()(int);
+  virtual A& operator++();
+  virtual operator double() const;
+};
+
+class B: public A {
+protected:
+  int operator()(int);
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: visibility of function 
'operator()'
+  // CHECK-MESSAGES: :[[@LINE-9]]:15: note: function declared here
+  A& operator++();
+  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: visibility of function 
'operator++'
+  // CHECK-MESSAGES: :[[@LINE-11]]:14: note: function declared here
+  operator double() const;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: visibility of function 'operator 
double'
+  // CHECK-MESSAGES: :[[@LINE-13]]:11: note: function declared here
+};
+
+}

EugeneZelenko wrote:

Please add newline.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread Balázs Kéri via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem.Base->getAccessSpecifier();
+InheritanceWithStrictVisibility = Elem.Base;
+  }
+}
+  }
+
+  if (ActualAccess != OverriddenAccess) {
+if (InheritanceWithStrictVisibility) {
+  diag(MatchedFunction->getLocation(),
+   "visibility of function %0 is changed from %1 (through %1 "
+   "inheritance of class %2) to %3")

balazske wrote:

Will this not make the message too long? (The message is already located in the 
class %4.)

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread Balázs Kéri via cfe-commits


@@ -0,0 +1,43 @@
+.. title:: clang-tidy - bugprone-function-visibility-change
+
+bugprone-function-visibility-change
+===
+
+Check changes in visibility of C++ member functions in subclasses. The check

balazske wrote:

fixed

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread Balázs Kéri via cfe-commits


@@ -124,6 +124,11 @@ New checks
   pointer and store it as class members without handle the copy and move
   constructors and the assignments.
 
+- New :doc:`bugprone-function-visibility-change
+  ` check.
+
+  Check function visibility changes in subclasses.

balazske wrote:

fixed

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-19 Thread Balázs Kéri via cfe-commits

https://github.com/balazske updated 
https://github.com/llvm/llvm-project/pull/140086

From 65d44a4eb9621e49a96f1ac43e5a1bbd6691dc13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= 
Date: Thu, 15 May 2025 17:41:16 +0200
Subject: [PATCH 1/2] [clang-tidy] Added check
 'bugprone-function-visibility-change'

---
 .../bugprone/BugproneTidyModule.cpp   |   3 +
 .../clang-tidy/bugprone/CMakeLists.txt|   1 +
 .../FunctionVisibilityChangeCheck.cpp |  74 ++
 .../bugprone/FunctionVisibilityChangeCheck.h  |  33 +++
 clang-tools-extra/docs/ReleaseNotes.rst   |   5 +
 .../bugprone/function-visibility-change.rst   |  43 
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../bugprone/function-visibility-change.cpp   | 234 ++
 8 files changed, 394 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/bugprone/function-visibility-change.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/function-visibility-change.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index b780a85bdf3fe..7cf58c5218969 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
 #include "ForwardingReferenceOverloadCheck.h"
+#include "FunctionVisibilityChangeCheck.h"
 #include "ImplicitWideningOfMultiplicationResultCheck.h"
 #include "InaccurateEraseCheck.h"
 #include "IncDecInConditionsCheck.h"
@@ -143,6 +144,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-forward-declaration-namespace");
 CheckFactories.registerCheck(
 "bugprone-forwarding-reference-overload");
+CheckFactories.registerCheck(
+"bugprone-function-visibility-change");
 CheckFactories.registerCheck(
 "bugprone-implicit-widening-of-multiplication-result");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index e310ea9c94543..b4f7ba76f4cee 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   FoldInitTypeCheck.cpp
   ForwardDeclarationNamespaceCheck.cpp
   ForwardingReferenceOverloadCheck.cpp
+  FunctionVisibilityChangeCheck.cpp
   ImplicitWideningOfMultiplicationResultCheck.cpp
   InaccurateEraseCheck.cpp
   IncorrectEnableIfCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
new file mode 100644
index 0..7ea4ed20705ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem

[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor edited 
https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;

vbvictor wrote:

nit: Consider moving this lines before `const auto *ParentClass` declaration as 
not to declare unused variables

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor commented:

I think we should make change the name of the check to include "method" or 
"member-function" words in it. It will make clear that we check for methods 
visibility and not some visibility attributes on functions.
Possible names:
bugprone-member-function-visibility-change
bugprone-virtual-member-function-visibility-change
bugprone-visibility-change-to-virtual-member-function (imho the best)
 

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {

vbvictor wrote:

We should favor explicit type over `auto`

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL requested changes to this pull request.

Idea is ok.

Missing some tests (scenarios not covered).
Maybe some options to deal with big number of false-positives would be needed.
Maybe some option to allow changing visibility to less visible would be needed.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,43 @@
+.. title:: clang-tidy - bugprone-function-visibility-change
+
+bugprone-function-visibility-change
+===
+
+Check changes in visibility of C++ member functions in subclasses. The check
+detects if a virtual function is overridden with a different visibility than in
+the base class declaration. Only normal functions are detected, no 
constructors,
+operators, conversions or other special functions.
+
+.. code-block:: c++
+
+  class A {
+  public:
+virtual void f_pub();
+  private:
+virtual void f_priv();
+  };
+  
+  class B: public A {
+  public:
+void f_priv(); // warning: changed visibility from private to public
+  private:
+void f_pub(); // warning: changed visibility from public to private
+  };
+
+  class C: private A {
+// no warning: f_pub becomes private in this case but this is from the
+// private inheritance
+  };
+
+  class D: private A {
+  public:
+void f_pub(); // warning: changed visibility from private to public
+  // 'f_pub' would have private access but is forced to be
+  // public
+  };
+

PiotrZSL wrote:

what about when user changes visibility of the function with "using 
declaration" ?

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,33 @@
+//===--- FunctionVisibilityChangeCheck.h - clang-tidy ---*- C++ 
-*-===//
+//
+// 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
+//
+//===--===//
+
+#ifndef 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FUNCTIONVISIBILITYCHANGECHECK_H
+#define 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FUNCTIONVISIBILITYCHANGECHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::bugprone {
+
+/// Check function visibility changes in subclasses.
+///
+/// For the user-facing documentation see:
+/// 
http://clang.llvm.org/extra/clang-tidy/checks/bugprone/function-visibility-change.html
+class FunctionVisibilityChangeCheck : public ClangTidyCheck {
+public:
+  FunctionVisibilityChangeCheck(StringRef Name, ClangTidyContext *Context)
+  : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+return LangOpts.CPlusPlus;
+  }

PiotrZSL wrote:

Consider adding some option to exclude some methods by name, for example if I 
would have some generic method like "process_event" that I change visibility on 
prupose, then maybe would be good to have option for that, or option to allow 
of changing visibility for some base classes.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,43 @@
+.. title:: clang-tidy - bugprone-function-visibility-change
+
+bugprone-function-visibility-change
+===
+
+Check changes in visibility of C++ member functions in subclasses. The check
+detects if a virtual function is overridden with a different visibility than in
+the base class declaration. Only normal functions are detected, no 
constructors,
+operators, conversions or other special functions.

PiotrZSL wrote:

Source code of the check does not verify against operators, and destructors.
Probably tests are missing.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem.Base->getAccessSpecifier();
+InheritanceWithStrictVisibility = Elem.Base;
+  }
+}
+  }
+
+  if (ActualAccess != OverriddenAccess) {
+if (InheritanceWithStrictVisibility) {
+  diag(MatchedFunction->getLocation(),
+   "visibility of function %0 is changed from %1 (through %1 "
+   "inheritance of class %2) to %3")
+  << MatchedFunction << OverriddenAccess
+  << InheritanceWithStrictVisibility->getType() << ActualAccess;
+  diag(InheritanceWithStrictVisibility->getBeginLoc(),
+   "this inheritance would make %0 %1", DiagnosticIDs::Note)

PiotrZSL wrote:

maybe better "%0 is inherited as %1 here".
I do not like that "this" at the begining

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,43 @@
+.. title:: clang-tidy - bugprone-function-visibility-change
+
+bugprone-function-visibility-change
+===
+
+Check changes in visibility of C++ member functions in subclasses. The check

PiotrZSL wrote:

And avoid "The check", documentation is in scope of check.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,234 @@
+// RUN: %check_clang_tidy %s bugprone-function-visibility-change %t
+
+class A {
+public:
+  virtual void pub_foo1() {}
+  virtual void pub_foo2() {}
+  virtual void pub_foo3() {}
+protected:
+  virtual void prot_foo1();
+  virtual void prot_foo2();
+  virtual void prot_foo3();
+private:
+  virtual void priv_foo1() {}
+  virtual void priv_foo2() {}
+  virtual void priv_foo3() {}
+};
+
+void A::prot_foo1() {}
+void A::prot_foo2() {}
+void A::prot_foo3() {}
+
+namespace test1 {
+
+class B: public A {
+public:
+  void pub_foo1() override {}
+  void prot_foo1() override {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'prot_foo1' is changed from protected in class 'A' to public 
[bugprone-function-visibility-change]
+  // CHECK-MESSAGES: :9:16: note: function declared here as protected
+  void priv_foo1() override {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'priv_foo1' is changed from private in class 'A' to public 
[bugprone-function-visibility-change]
+  // CHECK-MESSAGES: :13:16: note: function declared here as private
+protected:
+  void pub_foo2() override {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'pub_foo2' is changed from public in class 'A' to protected 
[bugprone-function-visibility-change]
+  // CHECK-MESSAGES: :6:16: note: function declared here as public
+  void prot_foo2() override {}
+  void priv_foo2() override {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'priv_foo2' is changed from private in class 'A' to protected 
[bugprone-function-visibility-change]
+  // CHECK-MESSAGES: :14:16: note: function declared here as private
+private:
+  void pub_foo3() override {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'pub_foo3' is changed from public in class 'A' to private 
[bugprone-function-visibility-change]
+  // CHECK-MESSAGES: :7:16: note: function declared here as public
+  void prot_foo3() override {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'prot_foo3' is changed from protected in class 'A' to private 
[bugprone-function-visibility-change]
+  // CHECK-MESSAGES: :11:16: note: function declared here as protected
+  void priv_foo3() override {}
+};
+
+class C: public B {
+public:
+  void pub_foo1() override;
+protected:
+  void prot_foo1() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'prot_foo1' is changed from public in class 'B' to protected 
[bugprone-function-visibility-change]
+  // CHECK-MESSAGES: :27:8: note: function declared here as public
+private:
+  void priv_foo1() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'priv_foo1' is changed from public in class 'B' to private 
[bugprone-function-visibility-change]
+  // CHECK-MESSAGES: :30:8: note: function declared here as public
+};
+
+void C::prot_foo1() {}
+void C::priv_foo1() {}
+
+}
+
+namespace test2 {
+
+class B: public A {
+public:
+  void pub_foo1() override;
+protected:
+  void prot_foo1() override;
+private:
+  void priv_foo1() override;
+};
+
+class C: public B {
+public:
+  void pub_foo1() override;
+  void prot_foo1() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'prot_foo1' is changed from protected in class 'B' to public
+  // CHECK-MESSAGES: :75:8: note: function declared here as protected
+  void priv_foo1() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'priv_foo1' is changed from private in class 'B' to public
+  // CHECK-MESSAGES: :77:8: note: function declared here as private
+
+  void pub_foo2() override;
+  void prot_foo2() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'prot_foo2' is changed from protected in class 'A' to public
+  // CHECK-MESSAGES: :10:16: note: function declared here as protected
+  void priv_foo2() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'priv_foo2' is changed from private in class 'A' to public
+  // CHECK-MESSAGES: :14:16: note: function declared here as private
+};
+
+}
+
+namespace test3 {
+
+class B: private A {
+public:
+  void pub_foo1() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'pub_foo1' is changed from private (through private inheritance of class 'A') 
to public
+  // CHECK-MESSAGES: :103:10: note: this inheritance would make 'pub_foo1' 
private
+  // CHECK-MESSAGES: :5:16: note: function declared here as public
+protected:
+  void prot_foo1() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: visibility of function 
'prot_foo1' is changed from private (through private inheritance of class 'A') 
to protected
+  // CHECK-MESSAGES: :103:10: note: this inheritance would make 'prot_foo1' 
private
+  // CHECK-MESSAGES: :9:16: note: function declared here as protected
+private:
+  void priv_foo1() override;
+
+public:
+  void prot_f

[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -98,6 +98,7 @@ Clang-Tidy Checks
:doc:`bugprone-fold-init-type `,
:doc:`bugprone-forward-declaration-namespace 
`,
:doc:`bugprone-forwarding-reference-overload 
`,
+   :doc:`bugprone-function-visibility-change 
`, "Yes"

PiotrZSL wrote:

check does not provide fixes, remove "Yes"

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem.Base->getAccessSpecifier();
+InheritanceWithStrictVisibility = Elem.Base;
+  }
+}
+  }
+
+  if (ActualAccess != OverriddenAccess) {
+if (InheritanceWithStrictVisibility) {
+  diag(MatchedFunction->getLocation(),
+   "visibility of function %0 is changed from %1 (through %1 "
+   "inheritance of class %2) to %3")

PiotrZSL wrote:

consider adding "to %3 in class %4"

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem.Base->getAccessSpecifier();
+InheritanceWithStrictVisibility = Elem.Base;
+  }
+}
+  }
+
+  if (ActualAccess != OverriddenAccess) {

PiotrZSL wrote:

Consider allowing changing access from wider to narrower, maybe some config 
option for that.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {

PiotrZSL wrote:

```suggestion
for (const auto& Elem : Elem : Path) {
```

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL edited 
https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,43 @@
+.. title:: clang-tidy - bugprone-function-visibility-change
+
+bugprone-function-visibility-change
+===
+
+Check changes in visibility of C++ member functions in subclasses. The check
+detects if a virtual function is overridden with a different visibility than in
+the base class declaration. Only normal functions are detected, no 
constructors,
+operators, conversions or other special functions.
+
+.. code-block:: c++
+
+  class A {
+  public:
+virtual void f_pub();
+  private:
+virtual void f_priv();
+  };
+  
+  class B: public A {
+  public:
+void f_priv(); // warning: changed visibility from private to public
+  private:
+void f_pub(); // warning: changed visibility from public to private
+  };
+
+  class C: private A {
+// no warning: f_pub becomes private in this case but this is from the
+// private inheritance
+  };
+
+  class D: private A {
+  public:
+void f_pub(); // warning: changed visibility from private to public
+  // 'f_pub' would have private access but is forced to be
+  // public
+  };
+
+The changed visibility can be an indicator of bad design or a result of
+coding error or code changes. If it is intentional, it can be avoided by
+adding an additional virtual function with the new access.

PiotrZSL wrote:

Proxy functions are out of date, in current days "using declaration" can be 
used for that.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-17 Thread Donát Nagy via cfe-commits

https://github.com/NagyDonat approved this pull request.

LGTM if you implement the changes suggested by EugeneZelenko.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-16 Thread via cfe-commits


@@ -0,0 +1,43 @@
+.. title:: clang-tidy - bugprone-function-visibility-change
+
+bugprone-function-visibility-change
+===
+
+Check changes in visibility of C++ member functions in subclasses. The check
+detects if a virtual function is overridden with a different visibility than in
+the base class declaration. Only normal functions are detected, no 
constructors,
+operators, conversions or other special functions.
+
+.. code-block:: c++
+
+  class A {
+  public:
+virtual void f_pub();
+  private:
+virtual void f_priv();
+  };
+  
+  class B: public A {
+  public:
+void f_priv(); // warning: changed visibility from private to public
+  private:
+void f_pub(); // warning: changed visibility from public to private
+  };
+
+  class C: private A {
+// no warning: f_pub becomes private in this case but this is from the
+// private inheritance
+  };
+
+  class D: private A {
+  public:
+void f_pub(); // warning: changed visibility from private to public
+  // 'f_pub' would have private access but is forced to be
+  // public
+  };
+
+The changed visibility can be an indicator of bad design or a result of
+coding error or code changes. If it is intentional, it can be avoided by
+adding an additional virtual function with the new access.
+

EugeneZelenko wrote:

Excessive trailing newlines.

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-16 Thread via cfe-commits


@@ -0,0 +1,43 @@
+.. title:: clang-tidy - bugprone-function-visibility-change
+
+bugprone-function-visibility-change
+===
+
+Check changes in visibility of C++ member functions in subclasses. The check

EugeneZelenko wrote:

```suggestion
Checks changes in visibility of C++ member functions in subclasses. The check
```

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-16 Thread via cfe-commits


@@ -124,6 +124,11 @@ New checks
   pointer and store it as class members without handle the copy and move
   constructors and the assignments.
 
+- New :doc:`bugprone-function-visibility-change
+  ` check.
+
+  Check function visibility changes in subclasses.

EugeneZelenko wrote:

```suggestion
  Checks function visibility changes in subclasses.
```

https://github.com/llvm/llvm-project/pull/140086
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-15 Thread via cfe-commits

llvmbot wrote:



@llvm/pr-subscribers-clang-tidy

@llvm/pr-subscribers-clang-tools-extra

Author: Balázs Kéri (balazske)


Changes



---
Full diff: https://github.com/llvm/llvm-project/pull/140086.diff


8 Files Affected:

- (modified) clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp (+3) 
- (modified) clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt (+1) 
- (added) 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp (+74) 
- (added) clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.h 
(+33) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5) 
- (added) 
clang-tools-extra/docs/clang-tidy/checks/bugprone/function-visibility-change.rst
 (+43) 
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1) 
- (added) 
clang-tools-extra/test/clang-tidy/checkers/bugprone/function-visibility-change.cpp
 (+234) 


``diff
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index b780a85bdf3fe..7cf58c5218969 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
 #include "ForwardingReferenceOverloadCheck.h"
+#include "FunctionVisibilityChangeCheck.h"
 #include "ImplicitWideningOfMultiplicationResultCheck.h"
 #include "InaccurateEraseCheck.h"
 #include "IncDecInConditionsCheck.h"
@@ -143,6 +144,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-forward-declaration-namespace");
 CheckFactories.registerCheck(
 "bugprone-forwarding-reference-overload");
+CheckFactories.registerCheck(
+"bugprone-function-visibility-change");
 CheckFactories.registerCheck(
 "bugprone-implicit-widening-of-multiplication-result");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index e310ea9c94543..b4f7ba76f4cee 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   FoldInitTypeCheck.cpp
   ForwardDeclarationNamespaceCheck.cpp
   ForwardingReferenceOverloadCheck.cpp
+  FunctionVisibilityChangeCheck.cpp
   ImplicitWideningOfMultiplicationResultCheck.cpp
   InaccurateEraseCheck.cpp
   IncorrectEnableIfCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
new file mode 100644
index 0..7ea4ed20705ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = Elem.Base->getAccessSpecifier();
+InheritanceWithStrictVisibility = Elem.Base;
+  }
+}
+  }
+
+  if (ActualAccess != OverriddenAccess) {
+if (InheritanceWithStrictVisibility) {
+  diag(MatchedFunction->getLocation(),
+   "visibility of function %0 is changed from %1 (through %1 "
+  

[clang-tools-extra] [clang-tidy] Added check 'bugprone-function-visibility-change' (PR #140086)

2025-05-15 Thread Balázs Kéri via cfe-commits

https://github.com/balazske created 
https://github.com/llvm/llvm-project/pull/140086

None

From 65d44a4eb9621e49a96f1ac43e5a1bbd6691dc13 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= 
Date: Thu, 15 May 2025 17:41:16 +0200
Subject: [PATCH] [clang-tidy] Added check
 'bugprone-function-visibility-change'

---
 .../bugprone/BugproneTidyModule.cpp   |   3 +
 .../clang-tidy/bugprone/CMakeLists.txt|   1 +
 .../FunctionVisibilityChangeCheck.cpp |  74 ++
 .../bugprone/FunctionVisibilityChangeCheck.h  |  33 +++
 clang-tools-extra/docs/ReleaseNotes.rst   |   5 +
 .../bugprone/function-visibility-change.rst   |  43 
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../bugprone/function-visibility-change.cpp   | 234 ++
 8 files changed, 394 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/bugprone/function-visibility-change.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/bugprone/function-visibility-change.cpp

diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index b780a85bdf3fe..7cf58c5218969 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -30,6 +30,7 @@
 #include "FoldInitTypeCheck.h"
 #include "ForwardDeclarationNamespaceCheck.h"
 #include "ForwardingReferenceOverloadCheck.h"
+#include "FunctionVisibilityChangeCheck.h"
 #include "ImplicitWideningOfMultiplicationResultCheck.h"
 #include "InaccurateEraseCheck.h"
 #include "IncDecInConditionsCheck.h"
@@ -143,6 +144,8 @@ class BugproneModule : public ClangTidyModule {
 "bugprone-forward-declaration-namespace");
 CheckFactories.registerCheck(
 "bugprone-forwarding-reference-overload");
+CheckFactories.registerCheck(
+"bugprone-function-visibility-change");
 CheckFactories.registerCheck(
 "bugprone-implicit-widening-of-multiplication-result");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index e310ea9c94543..b4f7ba76f4cee 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   FoldInitTypeCheck.cpp
   ForwardDeclarationNamespaceCheck.cpp
   ForwardingReferenceOverloadCheck.cpp
+  FunctionVisibilityChangeCheck.cpp
   ImplicitWideningOfMultiplicationResultCheck.cpp
   InaccurateEraseCheck.cpp
   IncorrectEnableIfCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
new file mode 100644
index 0..7ea4ed20705ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/FunctionVisibilityChangeCheck.cpp
@@ -0,0 +1,74 @@
+//===--- FunctionVisibilityChangeCheck.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 "FunctionVisibilityChangeCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void FunctionVisibilityChangeCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  cxxMethodDecl(
+  ofClass(cxxRecordDecl().bind("class")),
+  
forEachOverridden(cxxMethodDecl(ofClass(cxxRecordDecl().bind("base")))
+.bind("base_func")))
+  .bind("func"),
+  this);
+}
+
+void FunctionVisibilityChangeCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MatchedFunction = Result.Nodes.getNodeAs("func");
+  const auto *ParentClass = Result.Nodes.getNodeAs("class");
+  const auto *OverriddenFunction =
+  Result.Nodes.getNodeAs("base_func");
+  const auto *BaseClass = Result.Nodes.getNodeAs("base");
+
+  if (!MatchedFunction->isCanonicalDecl())
+return;
+
+  AccessSpecifier ActualAccess = MatchedFunction->getAccess();
+  AccessSpecifier OverriddenAccess = OverriddenFunction->getAccess();
+
+  CXXBasePaths Paths;
+  if (!ParentClass->isDerivedFrom(BaseClass, Paths))
+return;
+  const CXXBaseSpecifier *InheritanceWithStrictVisibility = nullptr;
+  for (const CXXBasePath &Path : Paths) {
+for (auto Elem : Path) {
+  if (Elem.Base->getAccessSpecifier() > OverriddenAccess) {
+OverriddenAccess = El