From 23a55bd3f5c9f0483b82f4ecd489d3c0284d34b9 Mon Sep 17 00:00:00 2001 From: Nicolas Lesser Date: Thu, 10 Jan 2019 19:03:33 +0000 Subject: [PATCH] Fix false positive unsequenced access and modification warning in array subscript expression. Summary: In the [expr.sub] p1, we can read that for a given E1[E2], E1 is sequenced before E2. Patch by Mateusz Janek. Reviewers: rsmith, Rakete1111 Reviewed By: rsmith, Rakete1111 Subscribers: riccibruno, lebedev.ri, Rakete1111, hiraditya, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D50766 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@350874 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 44 ++++++++++++++++--------- test/SemaCXX/warn-unsequenced-cxx17.cpp | 8 +++++ test/SemaCXX/warn-unsequenced.cpp | 1 + 3 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 test/SemaCXX/warn-unsequenced-cxx17.cpp diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index cd96200b81..a47c01daf0 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -11908,30 +11908,42 @@ public: notePostUse(O, E); } - void VisitBinComma(BinaryOperator *BO) { - // C++11 [expr.comma]p1: - // Every value computation and side effect associated with the left - // expression is sequenced before every value computation and side - // effect associated with the right expression. - SequenceTree::Seq LHS = Tree.allocate(Region); - SequenceTree::Seq RHS = Tree.allocate(Region); + void VisitSequencedExpressions(Expr *SequencedBefore, Expr *SequencedAfter) { + SequenceTree::Seq BeforeRegion = Tree.allocate(Region); + SequenceTree::Seq AfterRegion = Tree.allocate(Region); SequenceTree::Seq OldRegion = Region; { - SequencedSubexpression SeqLHS(*this); - Region = LHS; - Visit(BO->getLHS()); + SequencedSubexpression SeqBefore(*this); + Region = BeforeRegion; + Visit(SequencedBefore); } - Region = RHS; - Visit(BO->getRHS()); + Region = AfterRegion; + Visit(SequencedAfter); Region = OldRegion; - // Forget that LHS and RHS are sequenced. They are both unsequenced - // with respect to other stuff. - Tree.merge(LHS); - Tree.merge(RHS); + Tree.merge(BeforeRegion); + Tree.merge(AfterRegion); + } + + void VisitArraySubscriptExpr(ArraySubscriptExpr *ASE) { + // C++17 [expr.sub]p1: + // The expression E1[E2] is identical (by definition) to *((E1)+(E2)). The + // expression E1 is sequenced before the expression E2. + if (SemaRef.getLangOpts().CPlusPlus17) + VisitSequencedExpressions(ASE->getLHS(), ASE->getRHS()); + else + Base::VisitStmt(ASE); + } + + void VisitBinComma(BinaryOperator *BO) { + // C++11 [expr.comma]p1: + // Every value computation and side effect associated with the left + // expression is sequenced before every value computation and side + // effect associated with the right expression. + VisitSequencedExpressions(BO->getLHS(), BO->getRHS()); } void VisitBinAssign(BinaryOperator *BO) { diff --git a/test/SemaCXX/warn-unsequenced-cxx17.cpp b/test/SemaCXX/warn-unsequenced-cxx17.cpp new file mode 100644 index 0000000000..3c221fb8d6 --- /dev/null +++ b/test/SemaCXX/warn-unsequenced-cxx17.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wno-unused %s + +void test() { + int xs[10]; + int *p = xs; + // expected-no-diagnostics + p[(long long unsigned)(p = 0)]; // ok +} diff --git a/test/SemaCXX/warn-unsequenced.cpp b/test/SemaCXX/warn-unsequenced.cpp index 9e8a5b46c2..6d4468cabf 100644 --- a/test/SemaCXX/warn-unsequenced.cpp +++ b/test/SemaCXX/warn-unsequenced.cpp @@ -81,6 +81,7 @@ void test() { int *p = xs; a = *(a++, p); // ok a = a++ && a; // ok + p[(long long unsigned)(p = 0)]; // expected-warning {{unsequenced modification and access to 'p'}} A *q = &agg1; (q = &agg2)->y = q->x; // expected-warning {{unsequenced modification and access to 'q'}} -- 2.40.0