https://github.com/HerrCai0907 created https://github.com/llvm/llvm-project/pull/161396
None >From 9472a9cca3027b43a3b117176ddd3a5063c03f14 Mon Sep 17 00:00:00 2001 From: Congcong Cai <[email protected]> Date: Tue, 30 Sep 2025 23:35:57 +0800 Subject: [PATCH] [ExprMutation] handle return non-const type --- clang-tools-extra/docs/ReleaseNotes.rst | 4 ++ .../const-correctness-pointer-as-pointers.cpp | 4 ++ clang/lib/Analysis/ExprMutationAnalyzer.cpp | 20 ++++++---- .../Analysis/ExprMutationAnalyzerTest.cpp | 38 +++++++++++++++++++ 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index c3a6d2f9b2890..6991aa4153899 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -312,6 +312,10 @@ Changes in existing checks - Improved :doc:`misc-header-include-cycle <clang-tidy/checks/misc/header-include-cycle>` check performance. +- Improved :doc:`misc-const-correctness + <clang-tidy/checks/misc/const-correctness>` check by fixing false positives + when return non-const pointer. + - Improved :doc:`modernize-avoid-c-arrays <clang-tidy/checks/modernize/avoid-c-arrays>` to not diagnose array types which are part of an implicit instantiation of a template. diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp index 2ef47266b02b0..503445c5d3063 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp @@ -48,3 +48,7 @@ void ignore_const_alias() { p_local0 = &a[1]; } +void *return_non_const() { + void *const a = nullptr; + return a; +} diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp index 3fcd3481c2d6b..1524a5369c072 100644 --- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -140,7 +140,8 @@ class ExprPointeeResolve { // explicit cast will be checked in `findPointeeToNonConst` const CastKind kind = ICE->getCastKind(); if (kind == CK_LValueToRValue || kind == CK_DerivedToBase || - kind == CK_UncheckedDerivedToBase) + kind == CK_UncheckedDerivedToBase || + (kind == CK_NoOp && (ICE->getType() == ICE->getSubExpr()->getType()))) return resolveExpr(ICE->getSubExpr()); return false; } @@ -787,13 +788,16 @@ ExprMutationAnalyzer::Analyzer::findPointeeToNonConst(const Expr *Exp) { // FIXME: false positive if the pointee does not change in lambda const auto CaptureNoConst = lambdaExpr(hasCaptureInit(Exp)); - const auto Matches = - match(stmt(anyOf(forEachDescendant( - stmt(anyOf(AssignToNonConst, PassAsNonConstArg, - CastToNonConst, CaptureNoConst)) - .bind("stmt")), - forEachDescendant(InitToNonConst))), - Stm, Context); + const auto ReturnNoCost = + returnStmt(hasReturnValue(canResolveToExprPointee(Exp))); + + const auto Matches = match( + stmt(anyOf(forEachDescendant( + stmt(anyOf(AssignToNonConst, PassAsNonConstArg, + CastToNonConst, CaptureNoConst, ReturnNoCost)) + .bind("stmt")), + forEachDescendant(InitToNonConst))), + Stm, Context); return selectFirst<Stmt>("stmt", Matches); } diff --git a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp index 4e97174c17d95..8cc89181c61ff 100644 --- a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp +++ b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp @@ -2015,4 +2015,42 @@ TEST(ExprMutationAnalyzerTest, PointeeMutatedByConditionOperator) { EXPECT_TRUE(isPointeeMutated(Results, AST.get())); } +TEST(ExprMutationAnalyzerTest, PointeeMutatedByReturn) { + { + const std::string Code = R"( + int * f() { + int *const x = nullptr; + return x; + })"; + auto AST = buildASTFromCodeWithArgs(Code, {"-Wno-everything"}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isPointeeMutated(Results, AST.get())); + } + { + const std::string Code = R"( + int * f() { + int *const x = nullptr; + return x; + })"; + // in C++20, AST will have NoOp cast. + auto AST = + buildASTFromCodeWithArgs(Code, {"-Wno-everything", "-std=c++26"}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isPointeeMutated(Results, AST.get())); + } + { + const std::string Code = R"( + int const* f() { + int *const x = nullptr; + return x; + })"; + auto AST = buildASTFromCodeWithArgs(Code, {"-Wno-everything"}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isPointeeMutated(Results, AST.get())); + } +} + } // namespace clang _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
