зеркало из https://github.com/microsoft/clang-1.git
Don't emit a dead store for '++' operations unless it occurs with a return statement. We've never seen any other cases that were real bugs.
Fixes <rdar://problem/6962292>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125419 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0a86d44703
Коммит
f4e532b5a1
|
@ -31,6 +31,7 @@ public:
|
||||||
|
|
||||||
Stmt *getParent(Stmt*) const;
|
Stmt *getParent(Stmt*) const;
|
||||||
Stmt *getParentIgnoreParens(Stmt *) const;
|
Stmt *getParentIgnoreParens(Stmt *) const;
|
||||||
|
Stmt *getParentIgnoreParenCasts(Stmt *) const;
|
||||||
|
|
||||||
const Stmt *getParent(const Stmt* S) const {
|
const Stmt *getParent(const Stmt* S) const {
|
||||||
return getParent(const_cast<Stmt*>(S));
|
return getParent(const_cast<Stmt*>(S));
|
||||||
|
@ -40,6 +41,10 @@ public:
|
||||||
return getParentIgnoreParens(const_cast<Stmt*>(S));
|
return getParentIgnoreParens(const_cast<Stmt*>(S));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Stmt *getParentIgnoreParenCasts(const Stmt *S) const {
|
||||||
|
return getParentIgnoreParenCasts(const_cast<Stmt*>(S));
|
||||||
|
}
|
||||||
|
|
||||||
bool hasParent(Stmt* S) const {
|
bool hasParent(Stmt* S) const {
|
||||||
return getParent(S) != 0;
|
return getParent(S) != 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,15 @@ Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
|
||||||
return S;
|
return S;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
|
||||||
|
do {
|
||||||
|
S = getParent(S);
|
||||||
|
}
|
||||||
|
while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
|
||||||
|
|
||||||
|
return S;
|
||||||
|
}
|
||||||
|
|
||||||
bool ParentMap::isConsumedExpr(Expr* E) const {
|
bool ParentMap::isConsumedExpr(Expr* E) const {
|
||||||
Stmt *P = getParent(E);
|
Stmt *P = getParent(E);
|
||||||
Stmt *DirectChild = E;
|
Stmt *DirectChild = E;
|
||||||
|
|
|
@ -191,6 +191,8 @@ public:
|
||||||
if (S->getLocStart().isMacroID())
|
if (S->getLocStart().isMacroID())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Only cover dead stores from regular assignments. ++/-- dead stores
|
||||||
|
// have never flagged a real bug.
|
||||||
if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
|
if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
|
||||||
if (!B->isAssignmentOp()) return; // Skip non-assignments.
|
if (!B->isAssignmentOp()) return; // Skip non-assignments.
|
||||||
|
|
||||||
|
@ -221,14 +223,11 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
|
else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
|
||||||
if (!U->isIncrementOp())
|
if (!U->isIncrementOp() || U->isPrefix())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Handle: ++x within a subexpression. The solution is not warn
|
Stmt *parent = Parents.getParentIgnoreParenCasts(U);
|
||||||
// about preincrements to dead variables when the preincrement occurs
|
if (!parent || !isa<ReturnStmt>(parent))
|
||||||
// as a subexpression. This can lead to false negatives, e.g. "(++x);"
|
|
||||||
// A generalized dead code checker should find such issues.
|
|
||||||
if (U->isPrefix() && Parents.isConsumedExpr(U))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
|
Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
|
||||||
|
|
|
@ -44,10 +44,11 @@ void f5() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
int f6() {
|
int f6() {
|
||||||
|
|
||||||
int x = 4;
|
int x = 4;
|
||||||
++x; // expected-warning{{never read}}
|
++x; // no-warning
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +232,7 @@ void halt() __attribute__((noreturn));
|
||||||
int f21() {
|
int f21() {
|
||||||
int x = 4;
|
int x = 4;
|
||||||
|
|
||||||
++x; // expected-warning{{never read}}
|
x = x + 1; // expected-warning{{never read}}
|
||||||
if (1) {
|
if (1) {
|
||||||
halt();
|
halt();
|
||||||
(void)x;
|
(void)x;
|
||||||
|
@ -263,7 +264,7 @@ void f22() {
|
||||||
int y19 = 4;
|
int y19 = 4;
|
||||||
int y20 = 4;
|
int y20 = 4;
|
||||||
|
|
||||||
++x; // expected-warning{{never read}}
|
x = x + 1; // expected-warning{{never read}}
|
||||||
++y1;
|
++y1;
|
||||||
++y2;
|
++y2;
|
||||||
++y3;
|
++y3;
|
||||||
|
|
|
@ -12,7 +12,7 @@ int j;
|
||||||
void test1() {
|
void test1() {
|
||||||
int x = 4;
|
int x = 4;
|
||||||
|
|
||||||
++x; // expected-warning{{never read}}
|
x = x + 1; // expected-warning{{never read}}
|
||||||
|
|
||||||
switch (j) {
|
switch (j) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -69,11 +69,11 @@ void test2_b() {
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
void test3_a(int x) {
|
void test3_a(int x) {
|
||||||
++x; // expected-warning{{never read}}
|
x = x + 1; // expected-warning{{never read}}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test3_b(int &x) {
|
void test3_b(int &x) {
|
||||||
++x; // no-warninge
|
x = x + 1; // no-warninge
|
||||||
}
|
}
|
||||||
|
|
||||||
void test3_c(int x) {
|
void test3_c(int x) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче