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);
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
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}}