Skip to content

Commit

Permalink
Fix false positive unsequenced access and modification warning in arr…
Browse files Browse the repository at this point in the history
…ay 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

llvm-svn: 350874
  • Loading branch information
Rakete1111 committed Jan 10, 2019
1 parent 350e6e9 commit 5610cd8
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 16 deletions.
44 changes: 28 additions & 16 deletions clang/lib/Sema/SemaChecking.cpp
Expand Up @@ -11908,30 +11908,42 @@ class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> {
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) {
Expand Down
8 changes: 8 additions & 0 deletions clang/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
}
1 change: 1 addition & 0 deletions clang/test/SemaCXX/warn-unsequenced.cpp
Expand Up @@ -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'}}
Expand Down

1 comment on commit 5610cd8

@chfast
Copy link
Contributor

@chfast chfast commented on 5610cd8 Aug 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @stryku, you are the author of this patch. Are you willing to sign LLVM re-licensing agreement? See https://discourse.llvm.org/t/llvm-relicensing-update-further-suggestions-for-help/64667.

Please sign in to comment.