Skip to content

Commit bd9b57d

Browse files
committed
[clang][dataflow] Fix initializing a reference field with an InitListExpr.
I added a test for this as the ongoing migration to strict handling of value categories (see https://discourse.llvm.org/t/70086) will change the code that handles this case. It turns out we already didn't handle this correctly, so I fixed the existing implementation. Depends On D154961 Reviewed By: xazax.hun Differential Revision: https://reviews.llvm.org/D154965
1 parent b47bdcb commit bd9b57d

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

clang/lib/Analysis/FlowSensitive/Transfer.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -717,14 +717,15 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
717717
if (Type->isStructureOrClassType()) {
718718
std::vector<FieldDecl *> Fields =
719719
getFieldsForInitListExpr(Type->getAsRecordDecl());
720-
for (auto It : llvm::zip(Fields, S->inits())) {
721-
const FieldDecl *Field = std::get<0>(It);
720+
for (auto [Field, Init] : llvm::zip(Fields, S->inits())) {
722721
assert(Field != nullptr);
723-
724-
const Expr *Init = std::get<1>(It);
725722
assert(Init != nullptr);
726723

727-
if (Value *InitVal = Env.getValue(*Init, SkipPast::None))
724+
if (Field->getType()->isReferenceType()) {
725+
if (StorageLocation *Loc = Env.getStorageLocationStrict(*Init))
726+
cast<StructValue>(Val)->setChild(*Field,
727+
Env.create<ReferenceValue>(*Loc));
728+
} else if (Value *InitVal = Env.getValue(*Init, SkipPast::None))
728729
cast<StructValue>(Val)->setChild(*Field, *InitVal);
729730
}
730731
}

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2912,6 +2912,34 @@ TEST(TransferTest, AggregateInitialization) {
29122912
}
29132913
}
29142914

2915+
TEST(TransferTest, AggregateInitializationReferenceField) {
2916+
std::string Code = R"(
2917+
struct S {
2918+
int &RefField;
2919+
};
2920+
2921+
void target(int i) {
2922+
S s = { i };
2923+
/*[[p]]*/
2924+
}
2925+
)";
2926+
runDataflow(
2927+
Code,
2928+
[](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2929+
ASTContext &ASTCtx) {
2930+
const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2931+
2932+
const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
2933+
2934+
auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
2935+
auto &SLoc = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "s");
2936+
2937+
auto &RefValue =
2938+
*cast<ReferenceValue>(getFieldValue(&SLoc, *RefFieldDecl, Env));
2939+
EXPECT_EQ(&RefValue.getReferentLoc(), &ILoc);
2940+
});
2941+
}
2942+
29152943
TEST(TransferTest, AssignToUnionMember) {
29162944
std::string Code = R"(
29172945
union A {

0 commit comments

Comments
 (0)