diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp --- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" +#include "TestingSupport.h" #include "clang/AST/DeclCXX.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -23,6 +24,7 @@ using namespace clang; using namespace dataflow; +using test::getFieldValue; using ::testing::ElementsAre; using ::testing::NotNull; using ::testing::Pair; @@ -89,14 +91,9 @@ // Verify that the struct and the field (`R`) with first appearance of the // type is created successfully. Environment Env(DAContext, *Fun); - Value *Val = Env.createValue(Ty); - ASSERT_NE(Val, nullptr); - StructValue *SVal = clang::dyn_cast(Val); - ASSERT_NE(SVal, nullptr); - Val = SVal->getChild(*R); - ASSERT_NE(Val, nullptr); - PointerValue *PV = clang::dyn_cast(Val); - EXPECT_NE(PV, nullptr); + StructValue *SVal = clang::cast(Env.createValue(Ty)); + PointerValue *PV = cast_or_null(getFieldValue(SVal, *R, Env)); + EXPECT_THAT(PV, NotNull()); } TEST_F(EnvironmentTest, InitGlobalVarsFun) { @@ -175,8 +172,7 @@ // constructor, even though it is not referenced directly in the constructor. Environment Env(DAContext, *Constructor); auto *Val = cast(Env.createValue(QTy)); - ASSERT_THAT(Val, NotNull()); - EXPECT_THAT(Val->getChild(*XDecl), NotNull()); + EXPECT_THAT(getFieldValue(Val, *XDecl, Env), NotNull()); } TEST_F(EnvironmentTest, InitGlobalVarsFieldFun) { @@ -221,8 +217,7 @@ const auto *GlobalLoc = cast(Env.getStorageLocation(*GlobalDecl)); const auto *GlobalVal = cast(Env.getValue(*GlobalLoc)); - const auto *BarVal = GlobalVal->getChild(*BarDecl); - ASSERT_THAT(BarVal, NotNull()); + auto *BarVal = getFieldValue(GlobalVal, *BarDecl, Env); EXPECT_TRUE(isa(BarVal)); } diff --git a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp --- a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp @@ -63,12 +63,12 @@ auto &Inner1 = cast(S1.getChild(*InnerDecl)); auto &Inner2 = cast(S2.getChild(*InnerDecl)); - EXPECT_NE(Env.getValue(S1.getChild(*OuterIntDecl)), - Env.getValue(S2.getChild(*OuterIntDecl))); + EXPECT_NE(getFieldValue(&S1, *OuterIntDecl, Env), + getFieldValue(&S2, *OuterIntDecl, Env)); EXPECT_NE(Env.getValue(S1.getChild(*RefDecl)), Env.getValue(S2.getChild(*RefDecl))); - EXPECT_NE(Env.getValue(Inner1.getChild(*InnerIntDecl)), - Env.getValue(Inner2.getChild(*InnerIntDecl))); + EXPECT_NE(getFieldValue(&Inner1, *InnerIntDecl, Env), + getFieldValue(&Inner2, *InnerIntDecl, Env)); auto *S1Val = cast(Env.getValue(S1)); auto *S2Val = cast(Env.getValue(S2)); @@ -78,12 +78,12 @@ copyRecord(S1, S2, Env); - EXPECT_EQ(Env.getValue(S1.getChild(*OuterIntDecl)), - Env.getValue(S2.getChild(*OuterIntDecl))); + EXPECT_EQ(getFieldValue(&S1, *OuterIntDecl, Env), + getFieldValue(&S2, *OuterIntDecl, Env)); EXPECT_EQ(Env.getValue(S1.getChild(*RefDecl)), Env.getValue(S2.getChild(*RefDecl))); - EXPECT_EQ(Env.getValue(Inner1.getChild(*InnerIntDecl)), - Env.getValue(Inner2.getChild(*InnerIntDecl))); + EXPECT_EQ(getFieldValue(&Inner1, *InnerIntDecl, Env), + getFieldValue(&Inner2, *InnerIntDecl, Env)); S1Val = cast(Env.getValue(S1)); S2Val = cast(Env.getValue(S2)); diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h --- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h +++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h @@ -451,6 +451,28 @@ return *cast(Env.getValue(*VD)); } +/// Returns the value of a `Field` on the record referenced by `Loc.` +/// Returns null if `Loc` is null. +inline Value *getFieldValue(const AggregateStorageLocation *Loc, + const ValueDecl &Field, const Environment &Env) { + if (Loc == nullptr) + return nullptr; + return Env.getValue(Loc->getChild(Field)); +} + +/// Returns the value of a `Field` on a `Struct. +/// Returns null if `Struct` is null. +/// +/// Note: This function currently does not use the `Env` parameter, but it will +/// soon be needed to look up the `Value` when `setChild()` changes to return a +/// `StorageLocation *`. +inline Value *getFieldValue(const StructValue *Struct, const ValueDecl &Field, + const Environment &Env) { + if (Struct == nullptr) + return nullptr; + return Struct->getChild(Field); +} + /// Creates and owns constraints which are boolean values. class ConstraintContext { unsigned NextAtom = 0;