https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/202490
>From b28426d8567105b757d4767f418d91aad1530449 Mon Sep 17 00:00:00 2001 From: Zeyi Xu <[email protected]> Date: Tue, 9 Jun 2026 11:20:49 +0800 Subject: [PATCH 1/3] [clang-tidy] Avoid non-const-parameter fix-it conflicts with overloads --- .../readability/NonConstParameterCheck.cpp | 29 +++++++++++++ clang-tools-extra/docs/ReleaseNotes.rst | 3 ++ .../readability/non-const-parameter.cpp | 41 +++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp index fa9184a290273..f5abe02eb2674 100644 --- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp @@ -23,6 +23,32 @@ AST_MATCHER_P(VarDecl, hasOwnInitializer, ast_matchers::internal::Matcher<Expr>, } } // namespace +static bool wouldConflictWithOverload(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) { + const FunctionDecl *Overload = D->getAsFunction(); + if (!Overload || + Overload->getCanonicalDecl() == Function.getCanonicalDecl()) + return false; + + 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 +211,9 @@ void NonConstParameterCheck::diagnoseNonConstParameters() { if (!Function) continue; const unsigned Index = Par->getFunctionScopeIndex(); + if (wouldConflictWithOverload(*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 9703bb8f17208..8f4e2cf251e94 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -785,6 +785,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..9639b40ae4d16 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,44 @@ struct StaticDepOutOfClassInit { template <class T> const T StaticDepOutOfClassInit<T>::X = 0; + +double overloadConflict(double *overloadConflictPtr) { + return *overloadConflictPtr; +} + +double overloadConflict(const double *overloadConflictPtr) { + return *overloadConflictPtr; +} + +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 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) {} +}; >From aa62fb323c4bbdfbd29f2284ff7d7b3969ce931f Mon Sep 17 00:00:00 2001 From: Zeyi Xu <[email protected]> Date: Tue, 9 Jun 2026 11:29:34 +0800 Subject: [PATCH 2/3] make tidy happy --- .../clang-tidy/readability/NonConstParameterCheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp index f5abe02eb2674..5aaf28a22a776 100644 --- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp @@ -42,7 +42,7 @@ static bool wouldConflictWithOverload(const FunctionDecl &Function, Overload->getCanonicalDecl() == Function.getCanonicalDecl()) return false; - QualType ConstParamFunctionType = Context.getFunctionType( + const QualType ConstParamFunctionType = Context.getFunctionType( Overload->getReturnType(), ParamTypes, Proto->getExtProtoInfo()); return Context.hasSameFunctionTypeIgnoringExceptionSpec( ConstParamFunctionType, Overload->getType()); >From 88eb638083704e28ea33916b9efdf3ad8bfd2d16 Mon Sep 17 00:00:00 2001 From: Zeyi Xu <[email protected]> Date: Tue, 9 Jun 2026 14:56:33 +0800 Subject: [PATCH 3/3] add more test cases --- .../readability/non-const-parameter.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) 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 9639b40ae4d16..2d28ef904282a 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 @@ -458,6 +458,28 @@ 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; } + template <int> int templateOverloadConflict(int *templateConflictPtr) { return *templateConflictPtr; @@ -482,6 +504,11 @@ struct MemberOverloadConflict { 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 { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
