Skip to content

Commit 3da6980

Browse files
committed
[clang][dataflow] Refactor PropagateResultObject() with a switch statement.
See also discussion in #88726.
1 parent 3c6f91e commit 3da6980

File tree

1 file changed

+71
-57
lines changed

1 file changed

+71
-57
lines changed

clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Lines changed: 71 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -500,72 +500,86 @@ class ResultObjectVisitor : public RecursiveASTVisitor<ResultObjectVisitor> {
500500

501501
ResultObjectMap[E] = Loc;
502502

503-
// The following AST node kinds are "original initializers": They are the
504-
// lowest-level AST node that initializes a given object, and nothing
505-
// below them can initialize the same object (or part of it).
506-
if (isa<CXXConstructExpr>(E) || isa<CallExpr>(E) || isa<LambdaExpr>(E) ||
507-
isa<CXXDefaultArgExpr>(E) || isa<CXXDefaultInitExpr>(E) ||
508-
isa<CXXStdInitializerListExpr>(E)) {
509-
return;
510-
}
511-
if (auto *Op = dyn_cast<BinaryOperator>(E);
512-
Op && Op->getOpcode() == BO_Cmp) {
513-
// Builtin `<=>` returns a `std::strong_ordering` object.
514-
return;
515-
}
516-
517-
if (auto *InitList = dyn_cast<InitListExpr>(E)) {
518-
if (!InitList->isSemanticForm())
503+
switch(E->getStmtClass()) {
504+
// The following AST node kinds are "original initializers": They are the
505+
// lowest-level AST node that initializes a given object, and nothing
506+
// below them can initialize the same object (or part of it).
507+
case Stmt::CXXConstructExprClass:
508+
case Stmt::CallExprClass:
509+
case Stmt::LambdaExprClass:
510+
case Stmt::CXXDefaultArgExprClass:
511+
case Stmt::CXXDefaultInitExprClass:
512+
case Stmt::CXXStdInitializerListExprClass:
513+
return;
514+
case Stmt::BinaryOperatorClass: {
515+
auto *Op = cast<BinaryOperator>(E);
516+
if (Op->getOpcode() == BO_Cmp) {
517+
// Builtin `<=>` returns a `std::strong_ordering` object. We
518+
// consider this to be an "original" initializer too (see above).
519+
return;
520+
}
521+
if (Op->isCommaOp()) {
522+
PropagateResultObject(Op->getRHS(), Loc);
523+
return;
524+
}
525+
// We don't expect any other binary operators to produce a record
526+
// prvalue, so if we get here, we've hit some case we don't know
527+
// about.
528+
assert(false);
519529
return;
520-
if (InitList->isTransparent()) {
521-
PropagateResultObject(InitList->getInit(0), Loc);
530+
}
531+
case Stmt::BinaryConditionalOperatorClass:
532+
case Stmt::ConditionalOperatorClass: {
533+
auto *Cond = cast<AbstractConditionalOperator>(E);
534+
PropagateResultObject(Cond->getTrueExpr(), Loc);
535+
PropagateResultObject(Cond->getFalseExpr(), Loc);
522536
return;
523537
}
538+
case Stmt::InitListExprClass: {
539+
auto *InitList = cast<InitListExpr>(E);
540+
if (!InitList->isSemanticForm())
541+
return;
542+
if (InitList->isTransparent()) {
543+
PropagateResultObject(InitList->getInit(0), Loc);
544+
return;
545+
}
524546

525-
RecordInitListHelper InitListHelper(InitList);
547+
RecordInitListHelper InitListHelper(InitList);
526548

527-
for (auto [Base, Init] : InitListHelper.base_inits()) {
528-
assert(Base->getType().getCanonicalType() ==
529-
Init->getType().getCanonicalType());
549+
for (auto [Base, Init] : InitListHelper.base_inits()) {
550+
assert(Base->getType().getCanonicalType() ==
551+
Init->getType().getCanonicalType());
530552

531-
// Storage location for the base class is the same as that of the
532-
// derived class because we "flatten" the object hierarchy and put all
533-
// fields in `RecordStorageLocation` of the derived class.
534-
PropagateResultObject(Init, Loc);
535-
}
553+
// Storage location for the base class is the same as that of the
554+
// derived class because we "flatten" the object hierarchy and put all
555+
// fields in `RecordStorageLocation` of the derived class.
556+
PropagateResultObject(Init, Loc);
557+
}
536558

537-
for (auto [Field, Init] : InitListHelper.field_inits()) {
538-
// Fields of non-record type are handled in
539-
// `TransferVisitor::VisitInitListExpr()`.
540-
if (!Field->getType()->isRecordType())
541-
continue;
542-
PropagateResultObject(
543-
Init, cast<RecordStorageLocation>(Loc->getChild(*Field)));
559+
for (auto [Field, Init] : InitListHelper.field_inits()) {
560+
// Fields of non-record type are handled in
561+
// `TransferVisitor::VisitInitListExpr()`.
562+
if (!Field->getType()->isRecordType())
563+
continue;
564+
PropagateResultObject(
565+
Init, cast<RecordStorageLocation>(Loc->getChild(*Field)));
566+
}
567+
return;
568+
}
569+
default: {
570+
// All other expression nodes that propagate a record prvalue should
571+
// have exactly one child.
572+
SmallVector<Stmt *, 1> Children(E->child_begin(), E->child_end());
573+
LLVM_DEBUG({
574+
if (Children.size() != 1)
575+
E->dump();
576+
});
577+
assert(Children.size() == 1);
578+
for (Stmt *S : Children)
579+
PropagateResultObject(cast<Expr>(S), Loc);
580+
return;
544581
}
545-
return;
546-
}
547-
548-
if (auto *Op = dyn_cast<BinaryOperator>(E); Op && Op->isCommaOp()) {
549-
PropagateResultObject(Op->getRHS(), Loc);
550-
return;
551-
}
552-
553-
if (auto *Cond = dyn_cast<AbstractConditionalOperator>(E)) {
554-
PropagateResultObject(Cond->getTrueExpr(), Loc);
555-
PropagateResultObject(Cond->getFalseExpr(), Loc);
556-
return;
557582
}
558-
559-
// All other expression nodes that propagate a record prvalue should have
560-
// exactly one child.
561-
SmallVector<Stmt *, 1> Children(E->child_begin(), E->child_end());
562-
LLVM_DEBUG({
563-
if (Children.size() != 1)
564-
E->dump();
565-
});
566-
assert(Children.size() == 1);
567-
for (Stmt *S : Children)
568-
PropagateResultObject(cast<Expr>(S), Loc);
569583
}
570584

571585
private:

0 commit comments

Comments
 (0)