Skip to content

Commit

Permalink
[clang][dataflow] Treat comma operator correctly in `getResultObjectL…
Browse files Browse the repository at this point in the history
…ocation()`. (#78427)
  • Loading branch information
martinboehme committed Jan 22, 2024
1 parent 3b943c0 commit a2caa49
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 8 deletions.
9 changes: 7 additions & 2 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,8 +782,13 @@ Environment::getResultObjectLocation(const Expr &RecordPRValue) const {
return Val->getLoc();
}

// Expression nodes that propagate a record prvalue should have exactly one
// child.
if (auto *Op = dyn_cast<BinaryOperator>(&RecordPRValue);
Op && Op->isCommaOp()) {
return getResultObjectLocation(*Op->getRHS());
}

// All other expression nodes that propagate a record prvalue should have
// exactly one child.
llvm::SmallVector<const Stmt *> children(RecordPRValue.child_begin(),
RecordPRValue.child_end());
assert(children.size() == 1);
Expand Down
22 changes: 16 additions & 6 deletions clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2642,14 +2642,17 @@ TEST(TransferTest, ResultObjectLocation) {
};
void target() {
A();
0, A();
(void)0; // [[p]]
}
)";
using ast_matchers::binaryOperator;
using ast_matchers::cxxBindTemporaryExpr;
using ast_matchers::cxxTemporaryObjectExpr;
using ast_matchers::exprWithCleanups;
using ast_matchers::has;
using ast_matchers::hasOperatorName;
using ast_matchers::hasRHS;
using ast_matchers::match;
using ast_matchers::selectFirst;
using ast_matchers::traverse;
Expand All @@ -2659,26 +2662,33 @@ TEST(TransferTest, ResultObjectLocation) {
ASTContext &ASTCtx) {
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");

// The expresssion `A()` in the code above produces the following
// structure, consisting of three prvalues of record type.
// The expression `0, A()` in the code above produces the following
// structure, consisting of four prvalues of record type.
// `Env.getResultObjectLocation()` should return the same location for
// all of these.
auto MatchResult = match(
traverse(TK_AsIs,
exprWithCleanups(
has(cxxBindTemporaryExpr(
has(cxxTemporaryObjectExpr().bind("toe")))
.bind("bte")))
has(binaryOperator(
hasOperatorName(","),
hasRHS(cxxBindTemporaryExpr(
has(cxxTemporaryObjectExpr().bind(
"toe")))
.bind("bte")))
.bind("comma")))
.bind("ewc")),
ASTCtx);
auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
ASSERT_NE(TOE, nullptr);
auto *Comma = selectFirst<BinaryOperator>("comma", MatchResult);
ASSERT_NE(Comma, nullptr);
auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
ASSERT_NE(EWC, nullptr);
auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
ASSERT_NE(BTE, nullptr);

RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*Comma));
EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
});
Expand Down

0 comments on commit a2caa49

Please sign in to comment.