[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
This commit is contained in:
Jann Horn 2020-12-07 14:48:41 -08:00 committed by Leonard Chan
parent 641ede93ef
commit 6dad7ec539
2 changed files with 15 additions and 1 deletions

View File

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

View File

@ -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}}