blob: 912f89f733407f11024643df04b5d9e703f9e1b2 [file] [log] [blame]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "lifetime_analysis/points_to_map.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "lifetime_annotations/lifetime.h"
#include "lifetime_annotations/test/run_on_code.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
namespace clang {
namespace tidy {
namespace lifetimes {
namespace {
const clang::CallExpr* getFirstCallExpr(const clang::ASTContext& ast_context) {
using clang::ast_matchers::callExpr;
using clang::ast_matchers::match;
using clang::ast_matchers::selectFirst;
return selectFirst<clang::CallExpr>(
"call", match(callExpr().bind("call"),
const_cast<clang::ASTContext&>(ast_context)));
}
TEST(PointsToMapTest, Equality) {
runOnCodeWithLifetimeHandlers(
"int *return_int_ptr();"
"int* p = return_int_ptr();",
[](const clang::ASTContext& ast_context,
const LifetimeAnnotationContext&) {
Object p1 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
Object p2 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
Object p3 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
const clang::CallExpr* expr = getFirstCallExpr(ast_context);
{
PointsToMap map1, map2;
map1.SetPointerPointsToSet(p1, {p2});
map2.SetPointerPointsToSet(p1, {p3});
EXPECT_EQ(map1, PointsToMap(map1));
EXPECT_NE(map1, PointsToMap());
EXPECT_NE(map1, map2);
}
{
PointsToMap map1, map2;
map1.SetExprObjectSet(expr, {p1});
map2.SetExprObjectSet(expr, {p2});
EXPECT_EQ(map1, PointsToMap(map1));
EXPECT_NE(map1, PointsToMap());
EXPECT_NE(map1, map2);
}
},
{});
}
TEST(PointsToMapTest, Union) {
runOnCodeWithLifetimeHandlers(
"int *return_int_ptr();"
"int* p = return_int_ptr();",
[](const clang::ASTContext& ast_context,
const LifetimeAnnotationContext&) {
Object p1 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
Object p2 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
Object p3 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
const clang::CallExpr* expr = getFirstCallExpr(ast_context);
PointsToMap map1, map2;
map1.SetPointerPointsToSet(p1, {p2});
map2.SetPointerPointsToSet(p1, {p3});
map1.SetExprObjectSet(expr, {p2});
map2.SetExprObjectSet(expr, {p3});
PointsToMap union_map = map1.Union(map2);
EXPECT_EQ(union_map.GetPointerPointsToSet(p1), ObjectSet({p2, p3}));
EXPECT_EQ(union_map.GetExprObjectSet(expr), ObjectSet({p2, p3}));
},
{});
}
TEST(PointsToMapTest, GetPointerPointsToSet) {
runOnCodeWithLifetimeHandlers(
"",
[](const clang::ASTContext& ast_context,
const LifetimeAnnotationContext&) {
Object p1 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
Object p2 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
Object p3 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
Object p4 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
PointsToMap map;
EXPECT_EQ(map.GetPointerPointsToSet(p1), ObjectSet());
map.SetPointerPointsToSet(p1, {p3});
map.SetPointerPointsToSet(p2, {p4});
EXPECT_EQ(map.GetPointerPointsToSet(p1), ObjectSet({p3}));
EXPECT_EQ(map.GetPointerPointsToSet({p1, p2}), ObjectSet({p3, p4}));
},
{});
}
TEST(PointsToMapTest, ExtendPointerPointsToSet) {
runOnCodeWithLifetimeHandlers(
"",
[](const clang::ASTContext& ast_context,
const LifetimeAnnotationContext&) {
Object p1 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
Object p2 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
Object p3 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
PointsToMap map;
EXPECT_EQ(map.GetPointerPointsToSet(p1), ObjectSet());
map.ExtendPointerPointsToSet(p1, {p2});
EXPECT_EQ(map.GetPointerPointsToSet(p1), ObjectSet({p2}));
map.ExtendPointerPointsToSet(p1, {p3});
EXPECT_EQ(map.GetPointerPointsToSet(p1), ObjectSet({p2, p3}));
},
{});
}
TEST(PointsToMapTest, GetExprObjectSet) {
runOnCodeWithLifetimeHandlers(
"int *return_int_ptr();"
"int* p = return_int_ptr();",
[](const clang::ASTContext& ast_context,
const LifetimeAnnotationContext&) {
Object p1 = Object::Create(Lifetime::CreateLocal(), ast_context.IntTy);
const clang::CallExpr* expr = getFirstCallExpr(ast_context);
PointsToMap map;
map.SetExprObjectSet(expr, {p1});
EXPECT_EQ(map.GetExprObjectSet(expr), ObjectSet({p1}));
},
{});
}
} // namespace
} // namespace lifetimes
} // namespace tidy
} // namespace clang