-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[clang-tidy] Added check 'misc-visibility-change-to-virtual-function' #140086
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
65d44a4
f19ab2e
8f1b20e
a63ba1e
db79972
4b279e8
e020fe7
84cc917
c2bb550
69233c1
eeea1b3
b58fabe
434687b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<FunctionDecl>("func"); | ||
const auto *ParentClass = Result.Nodes.getNodeAs<CXXRecordDecl>("class"); | ||
const auto *OverriddenFunction = | ||
Result.Nodes.getNodeAs<FunctionDecl>("base_func"); | ||
const auto *BaseClass = Result.Nodes.getNodeAs<CXXRecordDecl>("base"); | ||
|
||
if (!MatchedFunction->isCanonicalDecl()) | ||
return; | ||
PiotrZSL marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (Elem.Base->getAccessSpecifier() > OverriddenAccess) { | ||
OverriddenAccess = Elem.Base->getAccessSpecifier(); | ||
InheritanceWithStrictVisibility = Elem.Base; | ||
} | ||
} | ||
} | ||
|
||
if (ActualAccess != OverriddenAccess) { | ||
PiotrZSL marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (InheritanceWithStrictVisibility) { | ||
diag(MatchedFunction->getLocation(), | ||
"visibility of function %0 is changed from %1 (through %1 " | ||
"inheritance of class %2) to %3") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider adding "to %3 in class %4" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this not make the message too long? (The message is already located in the class %4.) |
||
<< MatchedFunction << OverriddenAccess | ||
<< InheritanceWithStrictVisibility->getType() << ActualAccess; | ||
diag(InheritanceWithStrictVisibility->getBeginLoc(), | ||
"this inheritance would make %0 %1", DiagnosticIDs::Note) | ||
PiotrZSL marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<< MatchedFunction << OverriddenAccess; | ||
} else { | ||
diag(MatchedFunction->getLocation(), | ||
"visibility of function %0 is changed from %1 in class %2 to %3") | ||
<< MatchedFunction << OverriddenAccess << BaseClass << ActualAccess; | ||
} | ||
diag(OverriddenFunction->getLocation(), "function declared here as %0", | ||
DiagnosticIDs::Note) | ||
<< OverriddenFunction->getAccess(); | ||
} | ||
} | ||
|
||
} // namespace clang::tidy::bugprone |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}; | ||
|
||
} // namespace clang::tidy::bugprone | ||
|
||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FUNCTIONVISIBILITYCHANGECHECK_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
.. 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 | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about when user changes visibility of the function with "using declaration" ? |
||
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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Proxy functions are out of date, in current days "using declaration" can be used for that. |
||
|
||
PiotrZSL marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
Uh oh!
There was an error while loading. Please reload this page.