[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