diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 60a685bfdf158..5580cdf136914 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4751,6 +4751,9 @@ void Sema::CheckAddressOfNoDeref(const Expr *E) { } void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) { + if (isUnevaluatedContext()) + return; + QualType ResultTy = E->getType(); ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back(); @@ -14666,7 +14669,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, OpLoc, CanOverflow, CurFPFeatureOverrides()); if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) && - !isa(UO->getType().getDesugaredType(Context))) + !isa(UO->getType().getDesugaredType(Context)) && + !isUnevaluatedContext()) ExprEvalContexts.back().PossibleDerefs.insert(UO); // Convert the result back to a half vector. diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 93ed756e084bb..23cfae81df461 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1734,6 +1734,9 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, } void Sema::CheckMemberAccessOfNoDeref(const MemberExpr *E) { + if (isUnevaluatedContext()) + return; + QualType ResultTy = E->getType(); // Do not warn on member accesses to arrays since this returns an array diff --git a/clang/test/Frontend/noderef.c b/clang/test/Frontend/noderef.c index b072b995fcf64..3388f2a399924 100644 --- a/clang/test/Frontend/noderef.c +++ b/clang/test/Frontend/noderef.c @@ -57,12 +57,19 @@ int test() { p = &*(p + 1); // Struct member access - struct S NODEREF *s; // expected-note 2 {{s declared here}} + struct S NODEREF *s; // expected-note 3 {{s declared here}} x = s->a; // expected-warning{{dereferencing s; was declared with a 'noderef' type}} x = (*s).b; // expected-warning{{dereferencing s; was declared with a 'noderef' type}} p = &s->a; p = &(*s).b; + // Most things in sizeof() can't actually access memory + x = sizeof(s->a); // ok + x = sizeof(*s); // ok + x = sizeof(s[0]); // ok + x = sizeof(s->a + (s->b)); // ok + x = sizeof(int[++s->a]); // expected-warning{{dereferencing s; was declared with a 'noderef' type}} + // 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 diff --git a/clang/test/Frontend/noderef.cpp b/clang/test/Frontend/noderef.cpp index 32d5ca34d1b1b..68342a8e6467b 100644 --- a/clang/test/Frontend/noderef.cpp +++ b/clang/test/Frontend/noderef.cpp @@ -6,6 +6,11 @@ #define NODEREF __attribute__((noderef)) +// Stub out types for 'typeid' to work. +namespace std { +class type_info {}; +} // namespace std + void Normal() { int NODEREF i; // expected-warning{{'noderef' can only be used on an array or pointer type}} int NODEREF *i_ptr; // expected-note 2 {{i_ptr declared here}} @@ -102,6 +107,18 @@ int ChildCall(NODEREF Child *child) { // expected-note{{child declared here}} return child->func(); // expected-warning{{dereferencing child; was declared with a 'noderef' type}} } +std::type_info TypeIdPolymorphic(NODEREF A *a) { // expected-note{{a declared here}} + return typeid(*a); // expected-warning{{dereferencing a; was declared with a 'noderef' type}} +} + +class SimpleClass { + int a; +}; + +std::type_info TypeIdNonPolymorphic(NODEREF SimpleClass *simple) { + return typeid(*simple); +} + template class B { Ty NODEREF *member;