diff options
| -rw-r--r-- | clang/lib/Analysis/FlowSensitive/Transfer.cpp | 11 | ||||
| -rw-r--r-- | clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | 28 |
2 files changed, 34 insertions, 5 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index e1a2606..4c97e81 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -717,14 +717,15 @@ public: if (Type->isStructureOrClassType()) { std::vector<FieldDecl *> Fields = getFieldsForInitListExpr(Type->getAsRecordDecl()); - for (auto It : llvm::zip(Fields, S->inits())) { - const FieldDecl *Field = std::get<0>(It); + for (auto [Field, Init] : llvm::zip(Fields, S->inits())) { assert(Field != nullptr); - - const Expr *Init = std::get<1>(It); assert(Init != nullptr); - if (Value *InitVal = Env.getValue(*Init, SkipPast::None)) + if (Field->getType()->isReferenceType()) { + if (StorageLocation *Loc = Env.getStorageLocationStrict(*Init)) + cast<StructValue>(Val)->setChild(*Field, + Env.create<ReferenceValue>(*Loc)); + } else if (Value *InitVal = Env.getValue(*Init, SkipPast::None)) cast<StructValue>(Val)->setChild(*Field, *InitVal); } } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index 254226f..a89ff8e 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2912,6 +2912,34 @@ TEST(TransferTest, AggregateInitialization) { } } +TEST(TransferTest, AggregateInitializationReferenceField) { + std::string Code = R"( + struct S { + int &RefField; + }; + + void target(int i) { + S s = { i }; + /*[[p]]*/ + } + )"; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField"); + + auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i"); + auto &SLoc = getLocForDecl<AggregateStorageLocation>(ASTCtx, Env, "s"); + + auto &RefValue = + *cast<ReferenceValue>(getFieldValue(&SLoc, *RefFieldDecl, Env)); + EXPECT_EQ(&RefValue.getReferentLoc(), &ILoc); + }); +} + TEST(TransferTest, AssignToUnionMember) { std::string Code = R"( union A { |
