thejh created this revision. thejh added reviewers: leonardchan, aaron.ballman. Herald added a project: clang. Herald added a subscriber: cfe-commits. thejh requested review of this revision.
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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D92140 Files: clang/lib/Sema/SemaExprMember.cpp clang/test/Frontend/noderef.c Index: clang/test/Frontend/noderef.c =================================================================== --- clang/test/Frontend/noderef.c +++ clang/test/Frontend/noderef.c @@ -73,6 +73,7 @@ // 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}} Index: clang/lib/Sema/SemaExprMember.cpp =================================================================== --- clang/lib/Sema/SemaExprMember.cpp +++ clang/lib/Sema/SemaExprMember.cpp @@ -1739,12 +1739,23 @@ 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))
Index: clang/test/Frontend/noderef.c =================================================================== --- clang/test/Frontend/noderef.c +++ clang/test/Frontend/noderef.c @@ -73,6 +73,7 @@ // 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}} Index: clang/lib/Sema/SemaExprMember.cpp =================================================================== --- clang/lib/Sema/SemaExprMember.cpp +++ clang/lib/Sema/SemaExprMember.cpp @@ -1739,12 +1739,23 @@ 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))
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits