================ @@ -2392,14 +2392,88 @@ TEST(TransferTest, InitListExprAsUnion) { } F; public: - constexpr target() : F{nullptr} {} + constexpr target() : F{nullptr} { + int *null = nullptr; + F.b; // Make sure we reference 'b' so it is modeled. + // [[p]] + } }; )cc"; runDataflow( Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, ASTContext &ASTCtx) { - // Just verify that it doesn't crash. + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + auto &FLoc = getFieldLoc<RecordStorageLocation>( + *Env.getThisPointeeStorageLocation(), "F", ASTCtx); + auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env)); + EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null")); + EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr); + }); +} + +TEST(TransferTest, EmptyInitListExprForUnion) { + // This is a crash repro. + std::string Code = R"cc( + class target { + union { + int *a; + bool *b; + } F; + + public: + constexpr target() : F{} { + int *null = nullptr; + F.b; // Make sure we reference 'b' so it is modeled. + // [[p]] + } + }; + )cc"; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + auto &FLoc = getFieldLoc<RecordStorageLocation>( + *Env.getThisPointeeStorageLocation(), "F", ASTCtx); + auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env)); ---------------- ymand wrote:
Why is `a` set when the initializer is empty? I'm guessing it's because line 699 in Transfer.cpp uses `front()` and so initializes the first field of the union. If so, perhaps say this explicitly in the comment preceding those lines? https://github.com/llvm/llvm-project/pull/82986 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits