Skip to content

Commit 10e69fd

Browse files
committed
Fix comments and add two more tests.
- a test for an accessor returning a record type - a test for calling accessors of different objects
1 parent 4885d65 commit 10e69fd

File tree

2 files changed

+96
-4
lines changed

2 files changed

+96
-4
lines changed

clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ template <typename Base> class CachedConstAccessorsLattice : public Base {
5050
using Base::Base; // inherit all constructors
5151

5252
/// Creates or returns a previously created `Value` associated with a const
53-
/// method call `obj.getFoo()` where `RecordLoc` is the
53+
/// method call `obj.getFoo()` where `RecordLoc` is the
5454
/// `RecordStorageLocation` of `obj`.
5555
/// Returns nullptr if unable to find or create a value.
5656
///
@@ -61,8 +61,8 @@ template <typename Base> class CachedConstAccessorsLattice : public Base {
6161
getOrCreateConstMethodReturnValue(const RecordStorageLocation &RecordLoc,
6262
const CallExpr *CE, Environment &Env);
6363

64-
/// Creates or returns a previously created `StorageLocation` associated a
65-
/// const method call `obj.getFoo()` where `RecordLoc` is the
64+
/// Creates or returns a previously created `StorageLocation` associated with
65+
/// a const method call `obj.getFoo()` where `RecordLoc` is the
6666
/// `RecordStorageLocation` of `obj`.
6767
///
6868
/// The callback `Initialize` runs on the storage location if newly created.

clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
namespace clang::dataflow {
3333
namespace {
3434

35+
using ast_matchers::BoundNodes;
3536
using ast_matchers::callee;
3637
using ast_matchers::cxxMemberCallExpr;
3738
using ast_matchers::functionDecl;
@@ -46,6 +47,8 @@ using dataflow::RecordStorageLocation;
4647
using dataflow::Value;
4748
using dataflow::WatchedLiteralsSolver;
4849

50+
using testing::SizeIs;
51+
4952
NamedDecl *lookup(StringRef Name, const DeclContext &DC) {
5053
auto Result = DC.lookup(&DC.getParentASTContext().Idents.get(Name));
5154
EXPECT_TRUE(Result.isSingleResult()) << Name;
@@ -99,7 +102,8 @@ struct CommonTestInputs {
99102
const CallExpr *CallRef;
100103
};
101104

102-
TEST_F(CachedConstAccessorsLatticeTest, SameValBeforeClearOrDiffAfterClear) {
105+
TEST_F(CachedConstAccessorsLatticeTest,
106+
SamePrimitiveValBeforeClearOrDiffAfterClear) {
103107
CommonTestInputs Inputs;
104108
auto *CE = Inputs.CallVal;
105109
RecordStorageLocation Loc(Inputs.SType, RecordStorageLocation::FieldToLoc(),
@@ -144,6 +148,51 @@ TEST_F(CachedConstAccessorsLatticeTest, SameLocBeforeClearOrDiffAfterClear) {
144148
EXPECT_NE(Loc3, Loc2);
145149
}
146150

151+
TEST_F(CachedConstAccessorsLatticeTest,
152+
SameStructValBeforeClearOrDiffAfterClear) {
153+
TestAST AST(R"cpp(
154+
struct S {
155+
S structValProperty() const;
156+
};
157+
void target() {
158+
S s;
159+
s.structValProperty();
160+
}
161+
)cpp");
162+
auto *SDecl =
163+
cast<CXXRecordDecl>(lookup("S", *AST.context().getTranslationUnitDecl()));
164+
QualType SType = AST.context().getRecordType(SDecl);
165+
const CallExpr *CE = selectFirst<CallExpr>(
166+
"call", match(cxxMemberCallExpr(
167+
callee(functionDecl(hasName("structValProperty"))))
168+
.bind("call"),
169+
AST.context()));
170+
ASSERT_NE(CE, nullptr);
171+
172+
RecordStorageLocation Loc(SType, RecordStorageLocation::FieldToLoc(), {});
173+
174+
LatticeT Lattice;
175+
// Accessors that return a record by value are modeled by a record storage
176+
// location (instead of a Value).
177+
auto NopInit = [](StorageLocation &) {};
178+
StorageLocation *Loc1 = Lattice.getOrCreateConstMethodReturnStorageLocation(
179+
Loc, CE, Env, NopInit);
180+
auto NotCalled = [](StorageLocation &) {
181+
ASSERT_TRUE(false) << "Not reached";
182+
};
183+
StorageLocation *Loc2 = Lattice.getOrCreateConstMethodReturnStorageLocation(
184+
Loc, CE, Env, NotCalled);
185+
186+
EXPECT_EQ(Loc1, Loc2);
187+
188+
Lattice.clearConstMethodReturnStorageLocations(Loc);
189+
StorageLocation *Loc3 = Lattice.getOrCreateConstMethodReturnStorageLocation(
190+
Loc, CE, Env, NopInit);
191+
192+
EXPECT_NE(Loc3, Loc1);
193+
EXPECT_NE(Loc3, Loc1);
194+
}
195+
147196
TEST_F(CachedConstAccessorsLatticeTest, ClearDifferentLocs) {
148197
CommonTestInputs Inputs;
149198
auto *CE = Inputs.CallRef;
@@ -168,6 +217,49 @@ TEST_F(CachedConstAccessorsLatticeTest, ClearDifferentLocs) {
168217
EXPECT_EQ(RetLoc1, RetLoc2);
169218
}
170219

220+
TEST_F(CachedConstAccessorsLatticeTest, DifferentValsFromDifferentLocs) {
221+
TestAST AST(R"cpp(
222+
struct S {
223+
int *valProperty() const;
224+
};
225+
void target() {
226+
S s1;
227+
s1.valProperty();
228+
S s2;
229+
s2.valProperty();
230+
}
231+
)cpp");
232+
auto *SDecl =
233+
cast<CXXRecordDecl>(lookup("S", *AST.context().getTranslationUnitDecl()));
234+
QualType SType = AST.context().getRecordType(SDecl);
235+
SmallVector<BoundNodes, 1> valPropertyCalls =
236+
match(cxxMemberCallExpr(callee(functionDecl(hasName("valProperty"))))
237+
.bind("call"),
238+
AST.context());
239+
ASSERT_THAT(valPropertyCalls, SizeIs(2));
240+
241+
const CallExpr *CE1 = selectFirst<CallExpr>(
242+
"call", valPropertyCalls);
243+
ASSERT_NE(CE1, nullptr);
244+
245+
valPropertyCalls.erase(valPropertyCalls.begin());
246+
const CallExpr *CE2 = selectFirst<CallExpr>(
247+
"call", valPropertyCalls);
248+
ASSERT_NE(CE2, nullptr);
249+
ASSERT_NE(CE1, CE2);
250+
251+
RecordStorageLocation LocS1(SType, RecordStorageLocation::FieldToLoc(), {});
252+
RecordStorageLocation LocS2(SType, RecordStorageLocation::FieldToLoc(), {});
253+
254+
LatticeT Lattice;
255+
Value *Val1 =
256+
Lattice.getOrCreateConstMethodReturnValue(LocS1, CE1, Env);
257+
Value *Val2 =
258+
Lattice.getOrCreateConstMethodReturnValue(LocS2, CE2, Env);
259+
260+
EXPECT_NE(Val1, Val2);
261+
}
262+
171263
TEST_F(CachedConstAccessorsLatticeTest, JoinSameNoop) {
172264
CommonTestInputs Inputs;
173265
auto *CE = Inputs.CallVal;

0 commit comments

Comments
 (0)