[PATCH] D92140: Fix noderef for array member of deref expr
Jann Horn via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 25 15:55:13 PST 2020
thejh created this revision.
thejh added reviewers: leonardchan, aaron.ballman.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
thejh requested review of this revision.
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.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D92140
Files:
clang/lib/Sema/SemaExprMember.cpp
clang/test/Frontend/noderef.c
Index: clang/test/Frontend/noderef.c
===================================================================
--- clang/test/Frontend/noderef.c
+++ clang/test/Frontend/noderef.c
@@ -73,6 +73,7 @@
// Nested struct access
struct S2 NODEREF *s2_noderef; // expected-note 5 {{s2_noderef declared here}}
p = s2_noderef->a; // ok since result is an array in a struct
+ p = (*s2_noderef).a; // ok since result is an array in a struct
p = s2_noderef->a2; // ok
p = s2_noderef->b; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
p = s2_noderef->b2; // expected-warning{{dereferencing s2_noderef; was declared with a 'noderef' type}}
Index: clang/lib/Sema/SemaExprMember.cpp
===================================================================
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1739,12 +1739,23 @@
QualType ResultTy = E->getType();
- // Do not warn on member accesses to arrays since this returns an array
- // lvalue and does not actually dereference memory.
- if (isa<ArrayType>(ResultTy))
- return;
-
- if (E->isArrow()) {
+ // Member accesses have four cases:
+ // 1: non-array member via "->": dereferences
+ // 2: non-array member via ".": nothing interesting happens
+ // 3: array member access via "->": nothing interesting happens
+ // (this returns an array lvalue and does not actually dereference memory)
+ // 4: array member access via ".": *adds* a layer of indirection
+ if (ResultTy->isArrayType()) {
+ if (!E->isArrow()) {
+ // This might be something like:
+ // (*structPtr).arrayMember
+ // which behaves roughly like:
+ // &(*structPtr).pointerMember
+ // in that the apparent dereference in the base expression does not
+ // actually happen.
+ CheckAddressOfNoDeref(E->getBase());
+ }
+ } else if (E->isArrow()) {
if (const auto *Ptr = dyn_cast<PointerType>(
E->getBase()->getType().getDesugaredType(Context))) {
if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D92140.307723.patch
Type: text/x-patch
Size: 2074 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20201125/8caec78e/attachment.bin>
More information about the cfe-commits
mailing list