From 6dad7ec539cbcf6f59b63753a86b8015bd6ea66f Mon Sep 17 00:00:00 2001 From: Jann Horn Date: Mon, 7 Dec 2020 14:48:41 -0800 Subject: [PATCH] [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 --- clang/lib/Sema/SemaExprMember.cpp | 8 ++++++++ clang/test/Frontend/noderef.c | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 3e9d2a0..f5afcb7 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(CurContext); diff --git a/clang/test/Frontend/noderef.c b/clang/test/Frontend/noderef.c index b548ffa..d136ff0 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}} -- 2.7.4