Skip to content

Commit 2902ea3

Browse files
committed
[clang][dataflow] Introduce getFieldValue() test helpers.
These insulate tests against changes to the `getChild()` functions of `AggregateStorageLocation` and `StructValue` that will happen as part of the migration to strict handling of value categories (see https://discourse.llvm.org/t/70086 for details): - `AggregateStorageLocation::getChild()` will soon return a `StorageLocation *` instead of a `StorageLocation &`. When this happens, `getFieldValue()` will be changed to return null if `AggregateStorageLocation::getChild()` returns null; test code will not need to change as it should already be checking whether the return value of `getFieldValue()` is null. - `StructValue::getChild()` will soon return a `StorageLocation *` instead of a `Value *`. When this happens, `getFieldValue()` will be changed to look up the `Value *` in the `Environment`. Again, test code will not need to change. The test helpers will continue to serve a useful purpose once the API changes are complete, so the intent is to leave them in place. This patch changes DataflowEnvironmentTest.cpp and RecordOpsTest.cpp to use the test helpers. TransferTest.cpp will be changed in an upcoming patch to help keep patch sizes manageable for review. Depends On D154934 Reviewed By: ymandel, xazax.hun, gribozavr2 Differential Revision: https://reviews.llvm.org/D154935
1 parent 0014aab commit 2902ea3

File tree

3 files changed

+37
-20
lines changed

3 files changed

+37
-20
lines changed

clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
10+
#include "TestingSupport.h"
1011
#include "clang/AST/DeclCXX.h"
1112
#include "clang/ASTMatchers/ASTMatchFinder.h"
1213
#include "clang/ASTMatchers/ASTMatchers.h"
@@ -23,6 +24,7 @@ namespace {
2324

2425
using namespace clang;
2526
using namespace dataflow;
27+
using ::clang::dataflow::test::getFieldValue;
2628
using ::testing::ElementsAre;
2729
using ::testing::NotNull;
2830
using ::testing::Pair;
@@ -89,14 +91,9 @@ TEST_F(EnvironmentTest, CreateValueRecursiveType) {
8991
// Verify that the struct and the field (`R`) with first appearance of the
9092
// type is created successfully.
9193
Environment Env(DAContext, *Fun);
92-
Value *Val = Env.createValue(Ty);
93-
ASSERT_NE(Val, nullptr);
94-
StructValue *SVal = clang::dyn_cast<StructValue>(Val);
95-
ASSERT_NE(SVal, nullptr);
96-
Val = SVal->getChild(*R);
97-
ASSERT_NE(Val, nullptr);
98-
PointerValue *PV = clang::dyn_cast<PointerValue>(Val);
99-
EXPECT_NE(PV, nullptr);
94+
StructValue *SVal = cast<StructValue>(Env.createValue(Ty));
95+
PointerValue *PV = cast_or_null<PointerValue>(getFieldValue(SVal, *R, Env));
96+
EXPECT_THAT(PV, NotNull());
10097
}
10198

10299
TEST_F(EnvironmentTest, InitGlobalVarsFun) {
@@ -175,8 +172,7 @@ TEST_F(EnvironmentTest, IncludeFieldsFromDefaultInitializers) {
175172
// constructor, even though it is not referenced directly in the constructor.
176173
Environment Env(DAContext, *Constructor);
177174
auto *Val = cast<StructValue>(Env.createValue(QTy));
178-
ASSERT_THAT(Val, NotNull());
179-
EXPECT_THAT(Val->getChild(*XDecl), NotNull());
175+
EXPECT_THAT(getFieldValue(Val, *XDecl, Env), NotNull());
180176
}
181177

182178
TEST_F(EnvironmentTest, InitGlobalVarsFieldFun) {
@@ -221,8 +217,7 @@ TEST_F(EnvironmentTest, InitGlobalVarsFieldFun) {
221217
const auto *GlobalLoc =
222218
cast<AggregateStorageLocation>(Env.getStorageLocation(*GlobalDecl));
223219
const auto *GlobalVal = cast<StructValue>(Env.getValue(*GlobalLoc));
224-
const auto *BarVal = GlobalVal->getChild(*BarDecl);
225-
ASSERT_THAT(BarVal, NotNull());
220+
auto *BarVal = getFieldValue(GlobalVal, *BarDecl, Env);
226221
EXPECT_TRUE(isa<IntegerValue>(BarVal));
227222
}
228223

clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ TEST(RecordOpsTest, CopyRecord) {
6363
auto &Inner1 = cast<AggregateStorageLocation>(S1.getChild(*InnerDecl));
6464
auto &Inner2 = cast<AggregateStorageLocation>(S2.getChild(*InnerDecl));
6565

66-
EXPECT_NE(Env.getValue(S1.getChild(*OuterIntDecl)),
67-
Env.getValue(S2.getChild(*OuterIntDecl)));
66+
EXPECT_NE(getFieldValue(&S1, *OuterIntDecl, Env),
67+
getFieldValue(&S2, *OuterIntDecl, Env));
6868
EXPECT_NE(Env.getValue(S1.getChild(*RefDecl)),
6969
Env.getValue(S2.getChild(*RefDecl)));
70-
EXPECT_NE(Env.getValue(Inner1.getChild(*InnerIntDecl)),
71-
Env.getValue(Inner2.getChild(*InnerIntDecl)));
70+
EXPECT_NE(getFieldValue(&Inner1, *InnerIntDecl, Env),
71+
getFieldValue(&Inner2, *InnerIntDecl, Env));
7272

7373
auto *S1Val = cast<StructValue>(Env.getValue(S1));
7474
auto *S2Val = cast<StructValue>(Env.getValue(S2));
@@ -78,12 +78,12 @@ TEST(RecordOpsTest, CopyRecord) {
7878

7979
copyRecord(S1, S2, Env);
8080

81-
EXPECT_EQ(Env.getValue(S1.getChild(*OuterIntDecl)),
82-
Env.getValue(S2.getChild(*OuterIntDecl)));
81+
EXPECT_EQ(getFieldValue(&S1, *OuterIntDecl, Env),
82+
getFieldValue(&S2, *OuterIntDecl, Env));
8383
EXPECT_EQ(Env.getValue(S1.getChild(*RefDecl)),
8484
Env.getValue(S2.getChild(*RefDecl)));
85-
EXPECT_EQ(Env.getValue(Inner1.getChild(*InnerIntDecl)),
86-
Env.getValue(Inner2.getChild(*InnerIntDecl)));
85+
EXPECT_EQ(getFieldValue(&Inner1, *InnerIntDecl, Env),
86+
getFieldValue(&Inner2, *InnerIntDecl, Env));
8787

8888
S1Val = cast<StructValue>(Env.getValue(S1));
8989
S2Val = cast<StructValue>(Env.getValue(S2));

clang/unittests/Analysis/FlowSensitive/TestingSupport.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,28 @@ ValueT &getValueForDecl(ASTContext &ASTCtx, const Environment &Env,
451451
return *cast<ValueT>(Env.getValue(*VD));
452452
}
453453

454+
/// Returns the value of a `Field` on the record referenced by `Loc.`
455+
/// Returns null if `Loc` is null.
456+
inline Value *getFieldValue(const AggregateStorageLocation *Loc,
457+
const ValueDecl &Field, const Environment &Env) {
458+
if (Loc == nullptr)
459+
return nullptr;
460+
return Env.getValue(Loc->getChild(Field));
461+
}
462+
463+
/// Returns the value of a `Field` on a `Struct.
464+
/// Returns null if `Struct` is null.
465+
///
466+
/// Note: This function currently does not use the `Env` parameter, but it will
467+
/// soon be needed to look up the `Value` when `setChild()` changes to return a
468+
/// `StorageLocation *`.
469+
inline Value *getFieldValue(const StructValue *Struct, const ValueDecl &Field,
470+
const Environment &Env) {
471+
if (Struct == nullptr)
472+
return nullptr;
473+
return Struct->getChild(Field);
474+
}
475+
454476
/// Creates and owns constraints which are boolean values.
455477
class ConstraintContext {
456478
unsigned NextAtom = 0;

0 commit comments

Comments
 (0)