Skip to content

Commit da4df03

Browse files
committed
Switch from pointers to optionalt
1 parent 96f2d9e commit da4df03

File tree

4 files changed

+74
-56
lines changed

4 files changed

+74
-56
lines changed

src/util/expr_cast.h

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
/*
2-
Author: Nathan Phillips <[email protected]>
3-
*/
1+
/*******************************************************************\
2+
3+
Module:
4+
5+
Author: Nathan Phillips <[email protected]>
6+
7+
\*******************************************************************/
48

59
#ifndef CPROVER_UTIL_EXPR_CAST_H
610
#define CPROVER_UTIL_EXPR_CAST_H
@@ -10,9 +14,11 @@
1014

1115
#include <typeinfo>
1216
#include <type_traits>
17+
#include <functional>
18+
1319
#include "invariant.h"
1420
#include "expr.h"
15-
21+
#include "optional.h"
1622

1723
/// \brief Check whether a reference to a generic \ref exprt is of a specific
1824
/// derived class.
@@ -25,61 +31,66 @@
2531
template<typename T> bool can_cast_expr(const exprt &base);
2632

2733

28-
/// \brief Cast a constant pointer to a generic exprt to a specific derived
29-
/// class
34+
/// \brief Try to cast a constant reference to a generic exprt to a specific
35+
/// derived class
3036
/// \tparam T The exprt-derived class to cast to
31-
/// \param base Pointer to a generic \ref exprt
32-
/// \return Pointer to object of type \a T or null if \a base is not an
33-
/// instance of \a T
37+
/// \param base Reference to a generic \ref exprt
38+
/// \return Reference to object of type \a T or valueless optional if \a base
39+
/// is not an instance of \a T
3440
template<typename T>
35-
T expr_dynamic_cast(const exprt *base)
41+
optionalt<std::reference_wrapper<typename std::remove_reference<T>::type>>
42+
expr_try_dynamic_cast(const exprt &base)
3643
{
37-
return expr_dynamic_cast<
44+
return expr_try_dynamic_cast<
3845
T,
39-
typename std::remove_const<typename std::remove_pointer<T>::type>::type,
46+
typename std::remove_reference<T>::type,
47+
typename std::remove_const<typename std::remove_reference<T>::type>::type,
4048
const exprt>(base);
4149
}
4250

43-
/// \brief Cast a pointer to a generic exprt to a specific derived class
51+
/// \brief Try to cast a reference to a generic exprt to a specific derived
52+
/// class
4453
/// \tparam T The exprt-derived class to cast to
45-
/// \param base Pointer to a generic \ref exprt
46-
/// \return Pointer to object of type \a T or null if \a base is not an
47-
/// instance of \a T
54+
/// \param base Reference to a generic \ref exprt
55+
/// \return Reference to object of type \a T or valueless optional if \a base is
56+
/// not an instance of \a T
4857
template<typename T>
49-
T expr_dynamic_cast(exprt *base)
58+
optionalt<std::reference_wrapper<typename std::remove_reference<T>::type>>
59+
expr_try_dynamic_cast(exprt &base)
5060
{
51-
return expr_dynamic_cast<
61+
return expr_try_dynamic_cast<
5262
T,
53-
typename std::remove_const<typename std::remove_pointer<T>::type>::type,
63+
typename std::remove_reference<T>::type,
64+
typename std::remove_const<typename std::remove_reference<T>::type>::type,
5465
exprt>(base);
5566
}
5667

57-
/// \brief Cast a pointer to a generic exprt to a specific derived class
58-
/// \tparam T The pointer or const pointer type to \a TUnderlying to cast to
68+
/// \brief Try to cast a reference to a generic exprt to a specific derived
69+
/// class
70+
/// \tparam T The reference or const reference type to \a TUnderlying to cast
71+
/// to
5972
/// \tparam TUnderlying An exprt-derived class type
6073
/// \tparam TExpr The original type to cast from, either exprt or const exprt
61-
/// \param base Pointer to a generic \ref exprt
62-
/// \return Pointer to object of type \a TUnderlying
63-
/// or null if \a base is not an instance of \a TUnderlying
64-
template<typename T, typename TUnderlying, typename TExpr>
65-
T expr_dynamic_cast(TExpr *base)
74+
/// \param base Reference to a generic \ref exprt
75+
/// \return Reference to object of type \a TUnderlying
76+
/// or valueless optional if \a base is not an instance of \a TUnderlying
77+
template<typename T, typename TConst, typename TUnderlying, typename TExpr>
78+
optionalt<std::reference_wrapper<TConst>> expr_try_dynamic_cast(TExpr &base)
6679
{
6780
static_assert(
6881
std::is_same<typename std::remove_const<TExpr>::type, exprt>::value,
69-
"Tried to expr_dynamic_cast from something that wasn't an exprt");
82+
"Tried to expr_try_dynamic_cast from something that wasn't an exprt");
7083
static_assert(
71-
std::is_pointer<T>::value,
72-
"Tried to convert exprt * to non-pointer type");
84+
std::is_reference<T>::value,
85+
"Tried to convert exprt & to non-reference type");
7386
static_assert(
7487
std::is_base_of<exprt, TUnderlying>::value,
7588
"The template argument T must be derived from exprt.");
76-
if(base == nullptr)
77-
return nullptr;
78-
if(!can_cast_expr<TUnderlying>(*base))
79-
return nullptr;
89+
if(!can_cast_expr<TUnderlying>(base))
90+
return optionalt<std::reference_wrapper<TConst>>();
8091
T value=static_cast<T>(base);
81-
validate_expr(*value);
82-
return value;
92+
validate_expr(value);
93+
return optionalt<std::reference_wrapper<TConst>>(value);
8394
}
8495

8596
/// \brief Cast a constant reference to a generic exprt to a specific derived

unit/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ list(REMOVE_ITEM sources
2121
${CMAKE_CURRENT_SOURCE_DIR}/cpp_scanner.cpp
2222
${CMAKE_CURRENT_SOURCE_DIR}/float_utils.cpp
2323
${CMAKE_CURRENT_SOURCE_DIR}/ieee_float.cpp
24+
25+
# Intended to fail to compile
26+
${CMAKE_CURRENT_SOURCE_DIR}/util/expr_cast/expr_undefined_casts.cpp
2427
)
2528

2629
add_executable(unit ${sources} ${headers})

unit/util/expr_cast/expr_cast.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,35 @@ SCENARIO("expr_dynamic_cast",
1616
{
1717
symbol_exprt symbol_expr;
1818

19-
GIVEN("A const exprt pointer to a symbolt")
19+
GIVEN("A const exprt reference to a symbolt")
2020
{
21-
const exprt *expr_ptr=&symbol_expr;
21+
const exprt &expr=symbol_expr;
2222

23-
THEN("Casting from exprt pointer to symbol_exprt pointer returns non-null")
23+
THEN("Try-casting from exprt reference to symbol_exprt pointer "
24+
"returns a value")
2425
{
25-
REQUIRE(expr_dynamic_cast<const symbol_exprt *>(expr_ptr)!=nullptr);
26+
REQUIRE(expr_try_dynamic_cast<const symbol_exprt &>(expr).has_value());
2627
}
2728

28-
THEN("Casting from exprt pointer to transt pointer returns null")
29+
THEN("Casting from exprt pointer to transt pointer doesn't return a value")
2930
{
30-
REQUIRE(expr_dynamic_cast<const transt *>(expr_ptr)==nullptr);
31+
REQUIRE(!expr_try_dynamic_cast<const transt &>(expr).has_value());
3132
}
3233
}
33-
GIVEN("A exprt pointer to a symbolt")
34+
GIVEN("A exprt reference to a symbolt")
3435
{
35-
exprt *expr_ptr=&symbol_expr;
36+
exprt &expr=symbol_expr;
3637

37-
THEN("Casting from exprt pointer to symbol_exprt pointer returns non-null")
38+
THEN("Casting from exprt reference to symbol_exprt reference "
39+
"returns a value")
3840
{
39-
REQUIRE(expr_dynamic_cast<symbol_exprt *>(expr_ptr)!=nullptr);
41+
REQUIRE(expr_try_dynamic_cast<symbol_exprt &>(expr).has_value());
4042
}
4143

42-
THEN("Casting from exprt pointer to transt pointer returns null")
44+
THEN("Casting from exprt reference to transt reference "
45+
"doesn't return a value")
4346
{
44-
REQUIRE(expr_dynamic_cast<transt *>(expr_ptr)==nullptr);
47+
REQUIRE(!expr_try_dynamic_cast<transt &>(expr).has_value());
4548
}
4649
}
4750
GIVEN("A const exprt reference to a symbolt")

unit/util/expr_cast/expr_undefined_casts.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,32 @@ SCENARIO("expr_dynamic_cast",
1919
{
2020
symbol_exprt symbol_expr;
2121

22-
GIVEN("A const exprt pointer to a symbolt")
22+
GIVEN("A const exprt reference to a symbolt")
2323
{
24-
const exprt *expr_ptr=&symbol_expr;
24+
const exprt &expr=symbol_expr;
2525

26-
THEN("Casting from exprt pointer to ieee_float_op_exprt should not compile")
26+
THEN("Casting from exprt reference to ieee_float_op_exprt "
27+
"should not compile")
2728
{
2829
// This shouldn't compile
29-
expr_dynamic_cast<const ieee_float_op_exprt *>(expr_ptr);
30+
expr_dynamic_cast<const ieee_float_op_exprt &>(expr);
3031
}
31-
THEN("Casting from exprt pointer to shift_exprt should not compile")
32+
THEN("Casting from exprt reference to shift_exprt should not compile")
3233
{
3334
// This shouldn't compile
34-
expr_dynamic_cast<const shift_exprt *>(expr_ptr);
35+
expr_dynamic_cast<const shift_exprt &>(expr);
3536
}
3637
THEN(
37-
"Casting from exprt pointer to non-pointer/reference should not compile")
38+
"Casting from exprt reference to non-reference should not compile")
3839
{
3940
// This shouldn't compile
40-
expr_dynamic_cast<symbol_exprt>(expr_ptr);
41+
expr_dynamic_cast<symbol_exprt>(expr);
4142
}
4243
THEN(
4344
"Casting from const exprt reference to non-const symbol_exprt reference "
4445
"should not compile")
4546
{
46-
expr_dynamic_cast<symbol_exprt *>(expr_ptr);
47+
expr_dynamic_cast<symbol_exprt &>(expr);
4748
}
4849
}
4950
}

0 commit comments

Comments
 (0)