summaryrefslogtreecommitdiff
path: root/tiger-compiler/lib/misc/contract.hh
blob: 39942a6cc3fdb5b49c756b0e8f9a2f512f9d1d86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
 ** \file  misc/contract.hh
 ** \brief Replacement for cassert.
 **/

#pragma once

// Use GCC magic bits to specify we cannot return from these functions

#ifndef __attribute__
#  if !defined __GNUC__
#    define __attribute__(Spec) /* empty */
#  endif
#endif

[[noreturn]] void __Terminate(const char*, int, const char*);

#define die(Reason) __Terminate(__FILE__, __LINE__, Reason)
#define unreachable() die("unreachable code reached")

#ifdef NDEBUG

// This a trick use to disable assertion and co in the project. We need a stream
// in a 'else' to keep the code syntactically correct. However we do not want
// to print anything. So the 'if' is always true and does nothing.
// 'std::cerr' << "" is here to avoid warnings.
#  define __TestCondition                                                      \
    if (true)                                                                  \
      {                                                                        \
        ;                                                                      \
      }                                                                        \
    else                                                                       \
      std::cerr << ""

#  define assertion(Expr) __TestCondition
#  define invariant(Expr) __TestCondition
#  define precondition(Expr) __TestCondition
#  define postcondition(Expr) __TestCondition

#else // NDEBUG

#  define __TestCondition(CondType, Expr)                                      \
    if (Expr)                                                                  \
      {                                                                        \
        ;                                                                      \
      }                                                                        \
    else                                                                       \
      Contract(#CondType, #Expr, __FILE__, __LINE__)

#  define assertion(Expr) __TestCondition(Assertion, Expr)
#  define invariant(Expr) __TestCondition(Invariant, Expr)
#  define precondition(Expr) __TestCondition(Precondition, Expr)
#  define postcondition(Expr) __TestCondition(Postcondition, Expr)

#endif // ! NDEBUG

class Contract
{
public:
  Contract(const char* condType,
           const char* condText,
           const char* fileName,
           int fileLine);
  [[noreturn]] ~Contract();

  const char* condType;
  const char* condText;
  const char* fileName;
  int fileLine;
};

#include <misc/contract.hxx>