Skip to content

Commit 155fca3

Browse files
committed
[clang] Fix noderef for array member of deref expr
Committing on behalf of thejh (Jann Horn). Given an attribute((noderef)) pointer "p" to the struct struct s { int a[2]; }; ensure that the following expressions are treated the same way by the noderef logic: p->a (*p).a Until now, the first expression would be treated correctly (nothing is added to PossibleDerefs because CheckMemberAccessOfNoDeref() bails out on array members), but the second expression would incorrectly warn because "*p" creates a PossibleDerefs entry. Handle this case the same way as for the AddrOf operator. Differential Revision: https://reviews.llvm.org/D92140
1 parent 1d03a54 commit 155fca3

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

clang/lib/Sema/SemaExprMember.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,12 +1739,23 @@ void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) {
17391739

17401740
QualType ResultTy = E->getType();
17411741

1742-
// Do not warn on member accesses to arrays since this returns an array
1743-
// lvalue and does not actually dereference memory.
1744-
if (isa<ArrayType>(ResultTy))
1745-
return;
1746-
1747-
if (E->isArrow()) {
1742+
// Member accesses have four cases:
1743+
// 1: non-array member via "->": dereferences
1744+
// 2: non-array member via ".": nothing interesting happens
1745+
// 3: array member access via "->": nothing interesting happens
1746+
// (this returns an array lvalue and does not actually dereference memory)
1747+
// 4: array member access via ".": *adds* a layer of indirection
1748+
if (ResultTy->isArrayType()) {
1749+
if (!E->isArrow()) {
1750+
// This might be something like:
1751+
// (*structPtr).arrayMember
1752+
// which behaves roughly like:
1753+
// &(*structPtr).pointerMember
1754+
// in that the apparent dereference in the base expression does not
1755+
// actually happen.
1756+
CheckAddressOfNoDeref(E->getBase());
1757+
}
1758+
} else if (E->isArrow()) {
17481759
if (const auto *Ptr = dyn_cast<PointerType>(
17491760
E->getBase()->getType().getDesugaredType(Context))) {
17501761
if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))

clang/test/Frontend/noderef.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ int test() {
7373
// Nested struct access
7474
struct S2 NODEREF *s2_noderef; // expected-note 5 {{s2_noderef declared here}}
7575
p = s2_noderef->a; // ok since result is an array in a struct
76+
p = (*s2_noderef).a; // ok since result is an array in a struct
7677
p = s2_noderef->a2; // ok
7778
p = s2_noderef->b; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
7879
p = s2_noderef->b2; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}

0 commit comments

Comments
 (0)