[clang] b47bdcb - [clang][dataflow] Include fields initialized in an `InitListExpr` in `getModeledFields()`.
Martin Braenne via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 11 21:52:50 PDT 2023
Author: Martin Braenne
Date: 2023-07-12T04:52:29Z
New Revision: b47bdcbc7207aac617d3c35dfc029f79b0a46fd8
URL: https://github.com/llvm/llvm-project/commit/b47bdcbc7207aac617d3c35dfc029f79b0a46fd8
DIFF: https://github.com/llvm/llvm-project/commit/b47bdcbc7207aac617d3c35dfc029f79b0a46fd8.diff
LOG: [clang][dataflow] Include fields initialized in an `InitListExpr` in `getModeledFields()`.
Previously, we were including these fields only in the specific instance that was initialized by the `InitListExpr`, but not in other instances of the same type. This is inconsistent and error-prone.
Depends On D154952
Reviewed By: xazax.hun, gribozavr2
Differential Revision: https://reviews.llvm.org/D154961
Added:
Modified:
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/lib/Analysis/FlowSensitive/Transfer.cpp
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 7c1d01ce816e2b..5bd2e5518a5463 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -644,6 +644,10 @@ getImplicitObjectLocation(const CXXMemberCallExpr &MCE, const Environment &Env);
AggregateStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
const Environment &Env);
+/// Returns the fields of `RD` that are initialized by an `InitListExpr`, in the
+/// order in which they appear in `InitListExpr::inits()`.
+std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD);
+
} // namespace dataflow
} // namespace clang
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 73e20705cff501..9b1fca41e911cc 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -215,6 +215,10 @@ getFieldsGlobalsAndFuncs(const Stmt &S, FieldSet &Fields,
insertIfFunction(*VD, Funcs);
if (const auto *FD = dyn_cast<FieldDecl>(VD))
Fields.insert(FD);
+ } else if (auto *InitList = dyn_cast<InitListExpr>(&S)) {
+ if (RecordDecl *RD = InitList->getType()->getAsRecordDecl())
+ for (const auto *FD : getFieldsForInitListExpr(RD))
+ Fields.insert(FD);
}
}
@@ -958,5 +962,17 @@ AggregateStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
return cast<AggregateStorageLocation>(Loc);
}
+std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD) {
+ // Unnamed bitfields are only used for padding and do not appear in
+ // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s
+ // field list, and we thus need to remove them before mapping inits to
+ // fields to avoid mapping inits to the wrongs fields.
+ std::vector<FieldDecl *> Fields;
+ llvm::copy_if(
+ RD->fields(), std::back_inserter(Fields),
+ [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); });
+ return Fields;
+}
+
} // namespace dataflow
} // namespace clang
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index ac971f69150f1e..e1a2606de81033 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -715,14 +715,8 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
Env.setValue(Loc, *Val);
if (Type->isStructureOrClassType()) {
- // Unnamed bitfields are only used for padding and are not appearing in
- // `InitListExpr`'s inits. However, those fields do appear in RecordDecl's
- // field list, and we thus need to remove them before mapping inits to
- // fields to avoid mapping inits to the wrongs fields.
- std::vector<FieldDecl *> Fields;
- llvm::copy_if(
- Type->getAsRecordDecl()->fields(), std::back_inserter(Fields),
- [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); });
+ std::vector<FieldDecl *> Fields =
+ getFieldsForInitListExpr(Type->getAsRecordDecl());
for (auto It : llvm::zip(Fields, S->inits())) {
const FieldDecl *Field = std::get<0>(It);
assert(Field != nullptr);
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 3ae3106bca4673..254226fd6d3ee9 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2833,6 +2833,7 @@ TEST(TransferTest, AggregateInitialization) {
void target(int BarArg, int FooArg, int QuxArg) {
B Quux{BarArg, {FooArg}, QuxArg};
+ B OtherB;
/*[[p]]*/
}
)";
@@ -2849,6 +2850,7 @@ TEST(TransferTest, AggregateInitialization) {
void target(int BarArg, int FooArg, int QuxArg) {
B Quux = {BarArg, FooArg, QuxArg};
+ B OtherB;
/*[[p]]*/
}
)";
@@ -2898,6 +2900,14 @@ TEST(TransferTest, AggregateInitialization) {
EXPECT_EQ(getFieldValue(QuuxVal, *BarDecl, Env), BarArgVal);
EXPECT_EQ(getFieldValue(BazVal, *FooDecl, Env), FooArgVal);
EXPECT_EQ(getFieldValue(QuuxVal, *QuxDecl, Env), QuxArgVal);
+
+ // Check that fields initialized in an initializer list are always
+ // modeled in other instances of the same type.
+ const auto &OtherBVal =
+ getValueForDecl<StructValue>(ASTCtx, Env, "OtherB");
+ EXPECT_THAT(OtherBVal.getChild(*BarDecl), NotNull());
+ EXPECT_THAT(OtherBVal.getChild(*BazDecl), NotNull());
+ EXPECT_THAT(OtherBVal.getChild(*QuxDecl), NotNull());
});
}
}
More information about the cfe-commits
mailing list