[llvm-branch-commits] [clang] 155fca3 - [clang] Fix noderef for array member of deref expr

Leonard Chan via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Dec 7 14:44:38 PST 2020


Author: Leonard Chan
Date: 2020-12-07T14:39:42-08:00
New Revision: 155fca3cae275562e626d3e4fbfac70b4b75d2e7

URL: https://github.com/llvm/llvm-project/commit/155fca3cae275562e626d3e4fbfac70b4b75d2e7
DIFF: https://github.com/llvm/llvm-project/commit/155fca3cae275562e626d3e4fbfac70b4b75d2e7.diff

LOG:     [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

Added: 
    

Modified: 
    clang/lib/Sema/SemaExprMember.cpp
    clang/test/Frontend/noderef.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 23cfae81df46..3e9d2a056c5c 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -1739,12 +1739,23 @@ void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) {
 
   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))

diff  --git a/clang/test/Frontend/noderef.c b/clang/test/Frontend/noderef.c
index 3388f2a39992..b548ffa13273 100644
--- a/clang/test/Frontend/noderef.c
+++ b/clang/test/Frontend/noderef.c
@@ -73,6 +73,7 @@ int test() {
   // 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}}


        


More information about the llvm-branch-commits mailing list