Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Potentially Breaking Changes
- `CharTypdefsToIgnore` to `CharTypedefsToIgnore` in
:doc:`bugprone-signed-char-misuse
<clang-tidy/checks/bugprone/signed-char-misuse>`

- Modified the custom message format of :doc:`bugprone-unsafe-functions
<clang-tidy/checks/bugprone/unsafe-functions>` by assigning a special meaning
to the character ``>`` at the start of the value of the option
Expand Down Expand Up @@ -394,7 +394,7 @@ Changes in existing checks
<clang-tidy/checks/bugprone/unhandled-self-assignment>` check by adding
an additional matcher that generalizes the copy-and-swap idiom pattern
detection.

- Improved :doc:`bugprone-unsafe-functions
<clang-tidy/checks/bugprone/unsafe-functions>` check by hiding the default
suffix when the reason starts with the character `>` in the `CustomFunctions`
Expand Down Expand Up @@ -447,7 +447,8 @@ Changes in existing checks
positives when pointers is transferred to non-const references
and avoid false positives of function pointer and fix false
positives on return of non-const pointer and fix false positives on
pointer-to-member operator.
pointer-to-member operator and avoid false positives when the address
of a variable is taken to be passed to a function.

- Improved :doc:`misc-coroutine-hostile-raii
<clang-tidy/checks/misc/coroutine-hostile-raii>` check by adding the option
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,18 @@ void ignoreNonConstRefOps() {
int* p2 {nullptr};
int*& r2 = (int*&)p2;
}

void pointer_to_pointer_param(int**);
void pass_address_to_pointer_to_pointer() {
int i = 0;
int* ip = &i;
// CHECK-NOT: warning
pointer_to_pointer_param(&ip);
}

void void_pointer_to_pointer_param(void**);
void pass_address_to_void_pointer_to_pointer() {
void* ptr = nullptr;
// CHECK-NOT: warning
void_pointer_to_pointer_param(&ptr);
}
5 changes: 5 additions & 0 deletions clang/lib/Analysis/ExprMutationAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ class ExprPointeeResolve {
if (const auto *PE = dyn_cast<ParenExpr>(E))
return resolveExpr(PE->getSubExpr());

if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
if (UO->getOpcode() == UO_AddrOf)
return resolveExpr(UO->getSubExpr());
}

if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
// only implicit cast needs to be treated as resolvable.
// explicit cast will be checked in `findPointeeToNonConst`
Expand Down
17 changes: 17 additions & 0 deletions clang/unittests/Analysis/ExprMutationAnalyzerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2091,4 +2091,21 @@ TEST(ExprMutationAnalyzerTest, PointeeMutatedByPointerToMemberOperator) {
EXPECT_TRUE(isPointeeMutated(Results, AST.get()));
}

TEST(ExprMutationAnalyzerTest, PointeeMutatedByPassAsPointerToPointer) {
{
const std::string Code = "void f(int**); void g() { int* ip; f(&ip); }";
auto AST = buildASTFromCode(Code);
auto Results =
match(withEnclosingCompound(declRefTo("ip")), AST->getASTContext());
EXPECT_TRUE(isPointeeMutated(Results, AST.get()));
}
{
const std::string Code = "void f(void**); void g() { void* ip; f(&ip); }";
auto AST = buildASTFromCode(Code);
auto Results =
match(withEnclosingCompound(declRefTo("ip")), AST->getASTContext());
EXPECT_TRUE(isPointeeMutated(Results, AST.get()));
}
}

} // namespace clang