1 /* Implementation of PPL assert-like macros.
2    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3    Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_assert_hh
25 #define PPL_assert_hh 1
26 
27 // The PPL_UNREACHABLE_MSG macro flags a program point as unreachable.
28 // Argument `msg__' is added to output when assertions are turned on.
29 #if defined(NDEBUG)
30 #define PPL_UNREACHABLE_MSG(msg__) Parma_Polyhedra_Library::ppl_unreachable()
31 #else
32 #define PPL_UNREACHABLE_MSG(msg__) Parma_Polyhedra_Library:: \
33   ppl_unreachable_msg(msg__, __FILE__, __LINE__, __func__)
34 #endif
35 
36 // The PPL_UNREACHABLE macro flags a program point as unreachable.
37 #define PPL_UNREACHABLE PPL_UNREACHABLE_MSG("unreachable")
38 
39 // The PPL_ASSERTION_FAILED macro is used to output a message after
40 // an assertion failure and then cause program termination.
41 // (It is meant to be used only when assertions are turned on.)
42 #define PPL_ASSERTION_FAILED(msg__) Parma_Polyhedra_Library:: \
43   ppl_assertion_failed(msg__, __FILE__, __LINE__, __func__)
44 
45 // Helper macro PPL_ASSERT_IMPL_: do not use it directly.
46 #if defined(NDEBUG)
47 #define PPL_ASSERT_IMPL_(cond__) ((void) 0)
48 #else
49 #define PPL_STRING_(s) #s
50 #define PPL_ASSERT_IMPL_(cond__) \
51   ((cond__) ? (void) 0 : PPL_ASSERTION_FAILED(PPL_STRING_(cond__)))
52 #endif
53 
54 
55 // Non zero to detect use of PPL_ASSERT instead of PPL_ASSERT_HEAVY
56 // Note: flag does not affect code built with NDEBUG defined.
57 #define PPL_DEBUG_PPL_ASSERT 1
58 
59 // The PPL_ASSERT macro states that Boolean condition cond__ should hold.
60 // This is meant to replace uses of C assert().
61 #if defined(NDEBUG) || (!PPL_DEBUG_PPL_ASSERT)
62 #define PPL_ASSERT(cond__) PPL_ASSERT_IMPL_(cond__)
63 #else
64 // Note: here we have assertions enabled and PPL_DEBUG_PPL_ASSERT is 1.
65 // Check if the call to PPL_ASSERT should be replaced by PPL_ASSERT_HEAVY
66 // (i.e., if the former may interfere with computational weights).
67 #define PPL_ASSERT(cond__)                                        \
68   do {                                                            \
69     typedef Parma_Polyhedra_Library::Weightwatch_Traits W_Traits; \
70     W_Traits::Threshold old_weight__ = W_Traits::weight;          \
71     PPL_ASSERT_IMPL_(cond__);                                     \
72     PPL_ASSERT_IMPL_(old_weight__ == W_Traits::weight             \
73                      && ("PPL_ASSERT_HEAVY has to be used here" != 0)); \
74   } while (false)
75 #endif // !defined(NDEBUG) && PPL_DEBUG_PPL_ASSERT
76 
77 
78 // Macro PPL_ASSERT_HEAVY is meant to be used when the evaluation of
79 // the assertion may change computational weights (via WEIGHT_ADD).
80 #if defined(NDEBUG)
81 #define PPL_ASSERT_HEAVY(cond__) PPL_ASSERT_IMPL_(cond__)
82 #else
83 #define PPL_ASSERT_HEAVY(cond__)                                \
84   do {                                                          \
85     Parma_Polyhedra_Library::In_Assert guard;                   \
86     PPL_ASSERT_IMPL_(cond__);                                   \
87   } while (false)
88 #endif // !defined(NDEBUG)
89 
90 
91 // Macro PPL_EXPECT (resp., PPL_EXPECT_HEAVY) should be used rather than
92 // PPL_ASSERT (resp., PPL_ASSERT_HEAVY) when the condition is assumed to
93 // hold but it is not under library control (typically, it depends on
94 // user provided input).
95 #define PPL_EXPECT(cond__) PPL_ASSERT(cond__)
96 #define PPL_EXPECT_HEAVY(cond__) PPL_ASSERT_HEAVY(cond__)
97 
98 
99 namespace Parma_Polyhedra_Library {
100 
101 #if PPL_CXX_SUPPORTS_ATTRIBUTE_WEAK
102 #define PPL_WEAK_NORETURN __attribute__((weak, noreturn))
103 #else
104 #define PPL_WEAK_NORETURN __attribute__((noreturn))
105 #endif
106 
107 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
108 //! Helper function causing program termination by calling \c abort.
109 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
110 void ppl_unreachable() PPL_WEAK_NORETURN;
111 
112 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
113 /*! \brief
114   Helper function printing message on \c std::cerr and causing program
115   termination by calling \c abort.
116 */
117 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
118 void ppl_unreachable_msg(const char* msg,
119                          const char* file, unsigned int line,
120                          const char* function) PPL_WEAK_NORETURN;
121 
122 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
123 /*! \brief
124   Helper function printing an assertion failure message on \c std::cerr
125   and causing program termination by calling \c abort.
126 */
127 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
128 void ppl_assertion_failed(const char* assertion_text,
129                           const char* file, unsigned int line,
130                           const char* function) PPL_WEAK_NORETURN;
131 
132 
133 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
134 /*! \brief
135   Returns \c true if and only if \p x_copy contains \p y_copy.
136 
137   \note
138   This is a helper function for debugging purposes, to be used in assertions.
139   The two arguments are meant to be passed by value, i.e., <em>copied</em>,
140   so that their representations will not be affected by the containment check.
141 */
142 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
143 template <typename T>
copy_contains(T x_copy,T y_copy)144 bool copy_contains(T x_copy, T y_copy) {
145   return x_copy.contains(y_copy);
146 }
147 
148 } // namespace Parma_Polyhedra_Library
149 
150 #endif // !defined(PPL_assert_hh)
151