Author: flovent Date: 2025-10-08T15:15:29+08:00 New Revision: 89e2d58ec8189e77c34e39b1e8c9992315ad682f
URL: https://github.com/llvm/llvm-project/commit/89e2d58ec8189e77c34e39b1e8c9992315ad682f DIFF: https://github.com/llvm/llvm-project/commit/89e2d58ec8189e77c34e39b1e8c9992315ad682f.diff LOG: [clang-tidy] Fix false positives about references in `misc-const-correctness` (#160971) It's not legal to cast const pointer type to it's non-const reference type implicitly, and will cause compile error. And for explicit cast, it's legal but the pointer is mutable through this reference. Added: Modified: clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp clang/lib/Analysis/ExprMutationAnalyzer.cpp clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 7e836a7114d50..4197abac273b0 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -318,6 +318,10 @@ Changes in existing checks - ``for`` loops are supported. +- Improved :doc:`misc-const-correctness + <clang-tidy/checks/misc/const-correctness>` check to avoid false + positives when pointers is tranferred to non-const references. + - Improved :doc:`misc-header-include-cycle <clang-tidy/checks/misc/header-include-cycle>` check performance. 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..bcd946e7404c1 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,18 @@ void ignore_const_alias() { p_local0 = &a[1]; } +void takeNonConstRef(int *&r); + +void ignoreNonConstRefOps() { + // init with non-const ref + int* p0 {nullptr}; + int*& r1 = p0; + + // non-const ref param + int* p1 {nullptr}; + takeNonConstRef(p1); + + // cast + int* p2 {nullptr}; + int*& r2 = (int*&)p2; +} diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp index 3fcd3481c2d6b..1e376da1be83d 100644 --- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -755,22 +755,23 @@ ExprMutationAnalyzer::Analyzer::findPointeeMemberMutation(const Expr *Exp) { const Stmt * ExprMutationAnalyzer::Analyzer::findPointeeToNonConst(const Expr *Exp) { - const auto NonConstPointerOrDependentType = - type(anyOf(nonConstPointerType(), isDependentType())); + const auto NonConstPointerOrNonConstRefOrDependentType = type( + anyOf(nonConstPointerType(), nonConstReferenceType(), isDependentType())); // assign const auto InitToNonConst = - varDecl(hasType(NonConstPointerOrDependentType), + varDecl(hasType(NonConstPointerOrNonConstRefOrDependentType), hasInitializer(expr(canResolveToExprPointee(Exp)).bind("stmt"))); - const auto AssignToNonConst = - binaryOperation(hasOperatorName("="), - hasLHS(expr(hasType(NonConstPointerOrDependentType))), - hasRHS(canResolveToExprPointee(Exp))); + const auto AssignToNonConst = binaryOperation( + hasOperatorName("="), + hasLHS(expr(hasType(NonConstPointerOrNonConstRefOrDependentType))), + hasRHS(canResolveToExprPointee(Exp))); // arguments like const auto ArgOfInstantiationDependent = allOf( hasAnyArgument(canResolveToExprPointee(Exp)), isInstantiationDependent()); - const auto ArgOfNonConstParameter = forEachArgumentWithParamType( - canResolveToExprPointee(Exp), NonConstPointerOrDependentType); + const auto ArgOfNonConstParameter = + forEachArgumentWithParamType(canResolveToExprPointee(Exp), + NonConstPointerOrNonConstRefOrDependentType); const auto CallLikeMatcher = anyOf(ArgOfNonConstParameter, ArgOfInstantiationDependent); const auto PassAsNonConstArg = @@ -779,9 +780,9 @@ ExprMutationAnalyzer::Analyzer::findPointeeToNonConst(const Expr *Exp) { parenListExpr(has(canResolveToExprPointee(Exp))), initListExpr(hasAnyInit(canResolveToExprPointee(Exp))))); // cast - const auto CastToNonConst = - explicitCastExpr(hasSourceExpression(canResolveToExprPointee(Exp)), - hasDestinationType(NonConstPointerOrDependentType)); + const auto CastToNonConst = explicitCastExpr( + hasSourceExpression(canResolveToExprPointee(Exp)), + hasDestinationType(NonConstPointerOrNonConstRefOrDependentType)); // capture // FIXME: false positive if the pointee does not change in lambda diff --git a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp index 4e97174c17d95..95f8ae266ae10 100644 --- a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp +++ b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp @@ -1749,6 +1749,13 @@ TEST(ExprMutationAnalyzerTest, PointeeMutatedByInitToNonConst) { match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_TRUE(isPointeeMutated(Results, AST.get())); } + { + const std::string Code = "void f() { int* x = nullptr; int*& b = x; }"; + auto AST = buildASTFromCodeWithArgs(Code, {}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isPointeeMutated(Results, AST.get())); + } } TEST(ExprMutationAnalyzerTest, PointeeMutatedByAssignToNonConst) { @@ -1786,6 +1793,14 @@ TEST(ExprMutationAnalyzerTest, PointeeMutatedByPassAsArgument) { match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_TRUE(isPointeeMutated(Results, AST.get())); } + { + const std::string Code = + "void b(int *&); void f() { int* x = nullptr; b(x); }"; + auto AST = buildASTFromCodeWithArgs(Code, {}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isPointeeMutated(Results, AST.get())); + } } TEST(ExprMutationAnalyzerTest, PointeeMutatedByPassAsArgumentInConstruct) { @@ -1884,6 +1899,14 @@ TEST(ExprMutationAnalyzerTest, PointeeMutatedByExplicitCastToNonConst) { match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_TRUE(isPointeeMutated(Results, AST.get())); } + { + const std::string Code = + "void f() { int* x = nullptr; static_cast<int*&>(x); }"; + auto AST = buildASTFromCodeWithArgs(Code, {"-Wno-everything"}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isPointeeMutated(Results, AST.get())); + } } TEST(ExprMutationAnalyzerTest, PointeeMutatedByConstCastToNonConst) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
