Author: Jann Horn
Date: 2020-12-07T14:48:41-08:00
New Revision: 6dad7ec539cbcf6f59b63753a86b8015bd6ea66f

URL: 
https://github.com/llvm/llvm-project/commit/6dad7ec539cbcf6f59b63753a86b8015bd6ea66f
DIFF: 
https://github.com/llvm/llvm-project/commit/6dad7ec539cbcf6f59b63753a86b8015bd6ea66f.diff

LOG: [clang] Fix noderef for AddrOf on MemberExpr

Committing on behalf of thejh (Jann Horn).

As part of this change, one existing test case has to be adjusted
because it accidentally stripped the NoDeref attribute without
getting caught.

Depends on D92140

Differential Review: https://reviews.llvm.org/D92141

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 3e9d2a056c5c..f5afcb76fc96 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -1810,6 +1810,14 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool 
IsArrow,
     Qualifiers Combined = BaseQuals + MemberQuals;
     if (Combined != MemberQuals)
       MemberType = Context.getQualifiedType(MemberType, Combined);
+
+    // Pick up NoDeref from the base in case we end up using AddrOf on the
+    // result. E.g. the expression
+    //     &someNoDerefPtr->pointerMember
+    // should be a noderef pointer again.
+    if (BaseType->hasAttr(attr::NoDeref))
+      MemberType =
+          Context.getAttributedType(attr::NoDeref, MemberType, MemberType);
   }
 
   auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);

diff  --git a/clang/test/Frontend/noderef.c b/clang/test/Frontend/noderef.c
index b548ffa13273..d136ff0c7192 100644
--- a/clang/test/Frontend/noderef.c
+++ b/clang/test/Frontend/noderef.c
@@ -70,6 +70,12 @@ int test() {
   x = sizeof(s->a + (s->b)); // ok
   x = sizeof(int[++s->a]);   // expected-warning{{dereferencing s; was 
declared with a 'noderef' type}}
 
+  // Struct member access should carry NoDeref type information through to an
+  // enclosing AddrOf.
+  p2 = &s->a;   // expected-warning{{casting to dereferenceable pointer 
removes 'noderef' attribute}}
+  p2 = &(*s).a; // expected-warning{{casting to dereferenceable pointer 
removes 'noderef' attribute}}
+  x = *&s->a;   // expected-warning{{dereferencing expression marked as 
'noderef'}}
+
   // 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
@@ -113,7 +119,7 @@ int test() {
 
   p = s2_arr[1]->a;
   p = s2_arr[1]->b; // expected-warning{{dereferencing expression marked as 
'noderef'}}
-  int **bptr = &s2_arr[1]->b;
+  int *NODEREF *bptr = &s2_arr[1]->b;
 
   x = s2->s2->a;        // expected-warning{{dereferencing expression marked 
as 'noderef'}}
   x = s2_noderef->a[1]; // expected-warning{{dereferencing s2_noderef; was 
declared with a 'noderef' type}}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to