forked from OSchip/llvm-project
[clang-tidy] Sequence init statements, declarations, and conditions correctly in if, switch, and while
Summary: Fixes https://bugs.llvm.org/show_bug.cgi?id=36516. Reviewers: ilya-biryukov, alexfh, aaron.ballman, hokein Reviewed By: alexfh Subscribers: xazax.hun, cfe-commits Tags: #clang-tools-extra Differential Revision: https://reviews.llvm.org/D49918 llvm-svn: 338932
This commit is contained in:
parent
7499610e1b
commit
b7d621b7b6
|
@ -139,11 +139,26 @@ const Stmt *ExprSequence::getSequenceSuccessor(const Stmt *S) const {
|
|||
if (S == ForRange->getLoopVarStmt())
|
||||
return ForRange->getBody();
|
||||
} else if (const auto *TheIfStmt = dyn_cast<IfStmt>(Parent)) {
|
||||
// If statement: If a variable is declared inside the condition, the
|
||||
// expression used to initialize the variable is sequenced before the
|
||||
// evaluation of the condition.
|
||||
// If statement:
|
||||
// - Sequence init statement before variable declaration.
|
||||
// - Sequence variable declaration (along with the expression used to
|
||||
// initialize it) before the evaluation of the condition.
|
||||
if (S == TheIfStmt->getInit())
|
||||
return TheIfStmt->getConditionVariableDeclStmt();
|
||||
if (S == TheIfStmt->getConditionVariableDeclStmt())
|
||||
return TheIfStmt->getCond();
|
||||
} else if (const auto *TheSwitchStmt = dyn_cast<SwitchStmt>(Parent)) {
|
||||
// Ditto for switch statements.
|
||||
if (S == TheSwitchStmt->getInit())
|
||||
return TheSwitchStmt->getConditionVariableDeclStmt();
|
||||
if (S == TheSwitchStmt->getConditionVariableDeclStmt())
|
||||
return TheSwitchStmt->getCond();
|
||||
} else if (const auto *TheWhileStmt = dyn_cast<WhileStmt>(Parent)) {
|
||||
// While statement: Sequence variable declaration (along with the
|
||||
// expression used to initialize it) before the evaluation of the
|
||||
// condition.
|
||||
if (S == TheWhileStmt->getConditionVariableDeclStmt())
|
||||
return TheWhileStmt->getCond();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %check_clang_tidy %s bugprone-use-after-move %t -- -- -std=c++11 -fno-delayed-template-parsing
|
||||
// RUN: %check_clang_tidy %s bugprone-use-after-move %t -- -- -std=c++17 -fno-delayed-template-parsing
|
||||
|
||||
typedef decltype(nullptr) nullptr_t;
|
||||
|
||||
|
@ -1132,13 +1132,30 @@ void forRangeSequences() {
|
|||
}
|
||||
}
|
||||
|
||||
// If a variable is declared in an if statement, the declaration of the variable
|
||||
// (which is treated like a reinitialization by the check) is sequenced before
|
||||
// the evaluation of the condition (which constitutes a use).
|
||||
void ifStmtSequencesDeclAndCondition() {
|
||||
// If a variable is declared in an if, while or switch statement, the init
|
||||
// statement (for if and switch) is sequenced before the variable declaration,
|
||||
// which in turn is sequenced before the evaluation of the condition.
|
||||
void ifWhileAndSwitchSequenceInitDeclAndCondition() {
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
if (A a = A()) {
|
||||
std::move(a);
|
||||
A a1;
|
||||
if (A a2 = std::move(a1)) {
|
||||
std::move(a2);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
A a1;
|
||||
if (A a2 = std::move(a1); A a3 = std::move(a2)) {
|
||||
std::move(a3);
|
||||
}
|
||||
}
|
||||
while (A a = A()) {
|
||||
std::move(a);
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
A a1;
|
||||
switch (A a2 = a1; A a3 = std::move(a2)) {
|
||||
case true:
|
||||
std::move(a3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue