[clang-tools-extra] 76aed38 - [clang-tidy] Avoid non-const-parameter fix-it conflicts with overloads (#202490)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 13 02:01:39 PDT 2026
Author: Zeyi Xu
Date: 2026-06-13T17:01:34+08:00
New Revision: 76aed382055b0c07a9ce89d9273cc1f70daecf17
URL: https://github.com/llvm/llvm-project/commit/76aed382055b0c07a9ce89d9273cc1f70daecf17
DIFF: https://github.com/llvm/llvm-project/commit/76aed382055b0c07a9ce89d9273cc1f70daecf17.diff
LOG: [clang-tidy] Avoid non-const-parameter fix-it conflicts with overloads (#202490)
`readability-non-const-parameter` can suggest changing `T *` to `const T
*` when that would conflict with an existing overload. Suppress the
diagnostic in that case by comparing the post-fix parameter list against
other declarations with the same name.
Closes https://github.com/llvm/llvm-project/issues/202478
Added:
Modified:
clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
index fa9184a290273..004df8b9af929 100644
--- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp
@@ -23,6 +23,34 @@ AST_MATCHER_P(VarDecl, hasOwnInitializer, ast_matchers::internal::Matcher<Expr>,
}
} // namespace
+static bool wouldConflictWithExistingDecl(const FunctionDecl &Function,
+ unsigned ParamIndex) {
+ ASTContext &Context = Function.getASTContext();
+ const auto *Proto = Function.getType()->getAs<FunctionProtoType>();
+ if (!Proto)
+ return false;
+
+ // Simulate applying the fix-it to compare against existing overloads.
+ SmallVector<QualType> ParamTypes(Proto->getParamTypes());
+ ParamTypes[ParamIndex] = Context.getPointerType(
+ ParamTypes[ParamIndex]->getPointeeType().withConst());
+
+ return llvm::any_of(
+ Function.getParent()->lookup(Function.getDeclName()), [&](const Decl *D) {
+ if (const auto *Using = dyn_cast<UsingShadowDecl>(D))
+ D = Using->getTargetDecl();
+ const FunctionDecl *Overload = D->getAsFunction();
+ if (!Overload ||
+ Overload->getCanonicalDecl() == Function.getCanonicalDecl())
+ return false;
+
+ const QualType ConstParamFunctionType = Context.getFunctionType(
+ Overload->getReturnType(), ParamTypes, Proto->getExtProtoInfo());
+ return Context.hasSameFunctionTypeIgnoringExceptionSpec(
+ ConstParamFunctionType, Overload->getType());
+ });
+}
+
void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) {
// Add parameters to Parameters.
Finder->addMatcher(parmVarDecl().bind("Parm"), this);
@@ -185,6 +213,9 @@ void NonConstParameterCheck::diagnoseNonConstParameters() {
if (!Function)
continue;
const unsigned Index = Par->getFunctionScopeIndex();
+ if (wouldConflictWithExistingDecl(*Function, Index))
+ continue;
+
for (FunctionDecl *FnDecl : Function->redecls()) {
if (FnDecl->getNumParams() <= Index)
continue;
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 512aced46fedc..c05d336627356 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -812,6 +812,9 @@ Changes in existing checks
- Fixed a false positive in array subscript expressions where the types are
not yet resolved.
+ - Fixed a false positive when adding ``const`` to a pointer parameter would
+ conflict with an existing overload.
+
- Fixed a crash when analyzing a redeclaration whose initializer is attached
to another declaration.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
index b4918df347e5c..43bd8e72cd568 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/non-const-parameter.cpp
@@ -449,3 +449,78 @@ struct StaticDepOutOfClassInit {
template <class T>
const T StaticDepOutOfClassInit<T>::X = 0;
+
+double overloadConflict(double *overloadConflictPtr) {
+ return *overloadConflictPtr;
+}
+
+double overloadConflict(const double *overloadConflictPtr) {
+ return *overloadConflictPtr;
+}
+
+double topLevelConstPointerOverload(double *topLevelConstPtr) {
+ return *topLevelConstPtr;
+}
+
+double topLevelConstPointerOverload(const double *const topLevelConstPtr) {
+ return *topLevelConstPtr;
+}
+
+void arrayOverloadConflict(double arrayOut[2],
+ double arrayConflictParam[2]) {
+ arrayOut[0] = arrayConflictParam[0];
+}
+
+void arrayOverloadConflict(double arrayOut[2],
+ const double arrayConflictParam[2]) {
+ arrayOut[0] = arrayConflictParam[0];
+}
+
+int returnTypeConflict(int *returnTypePtr) { return *returnTypePtr; }
+
+long returnTypeConflict(const int *returnTypePtr) { return *returnTypePtr; }
+
+namespace UsingOverloadConflict {
+int usingConflict(const int *usingConflictPtr) { return *usingConflictPtr; }
+} // namespace UsingOverloadConflict
+
+using UsingOverloadConflict::usingConflict;
+int usingConflict(int *usingConflictPtr) { return *usingConflictPtr; }
+
+template <int>
+int templateOverloadConflict(int *templateConflictPtr) {
+ return *templateConflictPtr;
+}
+
+template <int>
+int templateOverloadConflict(const int *templateConflictPtr) {
+ return *templateConflictPtr;
+}
+
+struct ConstructorOverloadConflict {
+ ConstructorOverloadConflict(int *ctorConflictPtr) {
+ (void)*ctorConflictPtr;
+ }
+ ConstructorOverloadConflict(const int *ctorConflictPtr) {}
+};
+
+struct MemberOverloadConflict {
+ void withConflictingOverload(int *memberConflictPtr) {
+ (void)*memberConflictPtr;
+ }
+ void withConflictingOverload(const int *memberConflictPtr) {}
+};
+
+struct OperatorCallConflict {
+ int operator()(int *operatorCallPtr) { return *operatorCallPtr; }
+ int operator()(const int *operatorCallPtr) { return *operatorCallPtr; }
+};
+
+struct QualifiedMemberOverload {
+ // CHECK-MESSAGES: :[[@LINE+1]]:32: warning: pointer parameter 'qualifiedMemberPtr' can be pointer to const
+ void withConstQualifier(int *qualifiedMemberPtr) const {
+ // CHECK-FIXES: void withConstQualifier(const int *qualifiedMemberPtr) const {
+ (void)*qualifiedMemberPtr;
+ }
+ void withConstQualifier(const int *qualifiedMemberPtr) {}
+};
More information about the cfe-commits
mailing list