llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-analysis Author: Baranov Victor (vbvictor) <details> <summary>Changes</summary> `ExprPointeeResolve` now resolves through the `int*` to `void*` bitcast when the destination pointee is non-const Fixes https://github.com/llvm/llvm-project/issues/206429. --- Full diff: https://github.com/llvm/llvm-project/pull/206515.diff 4 Files Affected: - (modified) clang-tools-extra/docs/ReleaseNotes.rst (+3) - (modified) clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp (+32) - (modified) clang/lib/Analysis/ExprMutationAnalyzer.cpp (+7) - (modified) clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp (+68) ``````````diff diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 2a980cc089a65..dc10bc59804ea 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -571,6 +571,9 @@ Changes in existing checks - Fixed false positives when pointers were later passed or bound through ``const``-qualified pointer references. + - Fixed false positive where a pointer returned as a non-const ``void *`` + was incorrectly diagnosed as allowing its pointee to be made ``const``. + - Improved :doc:`misc-multiple-inheritance <clang-tidy/checks/misc/multiple-inheritance>` by avoiding false positives when virtual inheritance causes concrete bases to be counted more than once. 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 41df6c44f5bef..f6bfb98c548c3 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 @@ -56,6 +56,38 @@ void *return_non_const() { return a; } +void *return_as_void_pointer() { + int i = 0; + int *p_local0 = &i; + // CHECK-NOT: warning + return p_local0; +} + +const void *return_as_const_void_pointer() { + int i = 0; + int *p_local0 = &i; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: pointee of variable 'p_local0' of type 'int *' can be declared 'const' + // CHECK-FIXES: int const*p_local0 = &i; + return p_local0; +} + +void take_void_pointer(void *); +void pass_as_void_pointer() { + int i = 0; + int *p_local0 = &i; + // CHECK-NOT: warning + take_void_pointer(p_local0); +} + +void take_const_void_pointer(const void *); +void pass_as_const_void_pointer() { + int i = 0; + int *p_local0 = &i; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: pointee of variable 'p_local0' of type 'int *' can be declared 'const' + // CHECK-FIXES: int const*p_local0 = &i; + take_const_void_pointer(p_local0); +} + void function_pointer_basic() { void (*const fp)() = nullptr; fp(); diff --git a/clang/lib/Analysis/ExprMutationAnalyzer.cpp b/clang/lib/Analysis/ExprMutationAnalyzer.cpp index 3709fd0af3486..66d8eacdd54e6 100644 --- a/clang/lib/Analysis/ExprMutationAnalyzer.cpp +++ b/clang/lib/Analysis/ExprMutationAnalyzer.cpp @@ -160,6 +160,13 @@ class ExprPointeeResolve { if (CastType == SubExprType) return resolveExpr(ICE->getSubExpr()); } + if (kind == CK_BitCast) { + const QualType DestType = ICE->getType(); + const QualType SubExprType = ICE->getSubExpr()->getType(); + if (DestType->isPointerType() && SubExprType->isPointerType() && + !DestType->getPointeeType().isConstQualified()) + return resolveExpr(ICE->getSubExpr()); + } return false; } diff --git a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp index 1545310431fd8..c19c8b0fe0b02 100644 --- a/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp +++ b/clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp @@ -1788,6 +1788,21 @@ TEST(ExprMutationAnalyzerTest, PointeeMutatedByInitToNonConst) { match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isPointeeMutated(Results, AST.get())); } + { + const std::string Code = "void f() { int* x = nullptr; void* b = x; }"; + auto AST = buildASTFromCodeWithArgs(Code, {}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isPointeeMutated(Results, AST.get())); + } + { + const std::string Code = + "void f() { int* x = nullptr; const void* b = x; }"; + auto AST = buildASTFromCodeWithArgs(Code, {}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isPointeeMutated(Results, AST.get())); + } } TEST(ExprMutationAnalyzerTest, PointeeMutatedByAssignToNonConst) { @@ -1806,6 +1821,21 @@ TEST(ExprMutationAnalyzerTest, PointeeMutatedByAssignToNonConst) { match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_TRUE(isPointeeMutated(Results, AST.get())); } + { + const std::string Code = "void f() { int* x = nullptr; void* b; b = x; }"; + auto AST = buildASTFromCodeWithArgs(Code, {}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_TRUE(isPointeeMutated(Results, AST.get())); + } + { + const std::string Code = + "void f() { int* x = nullptr; const void* b; b = x; }"; + auto AST = buildASTFromCodeWithArgs(Code, {}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isPointeeMutated(Results, AST.get())); + } } TEST(ExprMutationAnalyzerTest, PointeeMutatedByPassAsArgument) { @@ -1874,6 +1904,22 @@ TEST(ExprMutationAnalyzerTest, PointeeMutatedByPassAsArgument) { match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_TRUE(isPointeeMutated(Results, AST.get())); } + { + const std::string Code = + "void b(void*); 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())); + } + { + const std::string Code = + "void b(const void*); void f() { int* x = nullptr; b(x); }"; + auto AST = buildASTFromCodeWithArgs(Code, {}); + auto Results = + match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); + EXPECT_FALSE(isPointeeMutated(Results, AST.get())); + } { const std::string Code = "namespace std { typedef decltype(sizeof(int)) size_t; }" @@ -2157,6 +2203,28 @@ TEST(ExprMutationAnalyzerTest, PointeeMutatedByReturn) { match(withEnclosingCompound(declRefTo("x")), AST->getASTContext()); EXPECT_FALSE(isPointeeMutated(Results, AST.get())); } + { + const std::string Code = R"( + void * 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"( + const void * 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())); + } } TEST(ExprMutationAnalyzerTest, PointeeMutatedByPointerToMemberOperator) { `````````` </details> https://github.com/llvm/llvm-project/pull/206515 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
