diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 6fbc3ec42465c..512e3d991df20 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -100,7 +100,7 @@ LatticeJoinEffect Environment::join(const Environment &Other) { StorageLocation &Environment::createStorageLocation(QualType Type) { assert(!Type.isNull()); - if (Type->isStructureOrClassType()) { + if (Type->isStructureOrClassType() || Type->isUnionType()) { // FIXME: Explore options to avoid eager initialization of fields as some of // them might not be needed for a particular analysis. llvm::DenseMap FieldLocs; diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index cd3e58207680a..0f7ac3af74edd 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -1952,4 +1952,37 @@ TEST_F(TransferTest, AggregateInitialization) { } } +TEST_F(TransferTest, AssignToUnionMember) { + std::string Code = R"( + union A { + int Foo; + }; + + void target(int Bar) { + A Baz; + Baz.Foo = Bar; + // [[p]] + } + )"; + runDataflow(Code, + [](llvm::ArrayRef< + std::pair>> + Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results, ElementsAre(Pair("p", _))); + const Environment &Env = Results[0].second.Env; + + const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); + ASSERT_THAT(BazDecl, NotNull()); + ASSERT_TRUE(BazDecl->getType()->isUnionType()); + + const auto *BazLoc = dyn_cast_or_null( + Env.getStorageLocation(*BazDecl, SkipPast::None)); + ASSERT_THAT(BazLoc, NotNull()); + + // FIXME: Add support for union types. + EXPECT_THAT(Env.getValue(*BazLoc), IsNull()); + }); +} + } // namespace