diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -225,12 +225,9 @@ if (MethodDecl && !MethodDecl->isStatic()) { QualType ThisPointeeType = MethodDecl->getThisObjectType(); - // FIXME: Add support for union types. - if (!ThisPointeeType->isUnionType()) { - ThisPointeeLoc = &createStorageLocation(ThisPointeeType); - if (Value *ThisPointeeVal = createValue(ThisPointeeType)) - setValue(*ThisPointeeLoc, *ThisPointeeVal); - } + ThisPointeeLoc = &createStorageLocation(ThisPointeeType); + if (Value *ThisPointeeVal = createValue(ThisPointeeType)) + setValue(*ThisPointeeLoc, *ThisPointeeVal); } } } diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -1518,6 +1518,54 @@ }); } +TEST(TransferTest, UnionThisMember) { + std::string Code = R"( + union A { + int Foo; + double Bar; + + void target() { + (void)0; // [[p]] + } + }; + )"; + runDataflow( + Code, + [](const llvm::StringMap> &Results, + ASTContext &ASTCtx) { + ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + const auto *ThisLoc = dyn_cast( + Env.getThisPointeeStorageLocation()); + ASSERT_THAT(ThisLoc, NotNull()); + + const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); + ASSERT_THAT(FooDecl, NotNull()); + + const auto *FooLoc = + cast(&ThisLoc->getChild(*FooDecl)); + ASSERT_TRUE(isa_and_nonnull(FooLoc)); + + const Value *FooVal = Env.getValue(*FooLoc); + // FIXME: Initialise values inside unions, then change below to + // ASSERT_TRUE. + ASSERT_FALSE(isa_and_nonnull(FooVal)); + + const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); + ASSERT_THAT(BarDecl, NotNull()); + + const auto *BarLoc = + cast(&ThisLoc->getChild(*BarDecl)); + ASSERT_TRUE(isa_and_nonnull(BarLoc)); + + const Value *BarVal = Env.getValue(*BarLoc); + // FIXME: Initialise values inside unions, then change below to + // ASSERT_TRUE. + ASSERT_FALSE(isa_and_nonnull(BarVal)); + }); +} + TEST(TransferTest, StructThisInLambda) { std::string ThisCaptureCode = R"( struct A {