GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/base/exception.cpp Lines: 59 81 72.8 %
Date: 2021-08-20 Branches: 42 116 36.2 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Tim King, Morgan Deters, Gereon Kremer
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * cvc5's exception base class and some associated utilities.
14
 */
15
16
#include "base/exception.h"
17
18
#include <cstdarg>
19
#include <cstdio>
20
#include <cstdlib>
21
#include <cstring>
22
#include <sstream>
23
#include <string>
24
25
#include "base/check.h"
26
27
using namespace std;
28
29
namespace cvc5 {
30
31
6
std::string Exception::toString() const
32
{
33
12
  std::stringstream ss;
34
6
  toStream(ss);
35
12
  return ss.str();
36
}
37
38
thread_local LastExceptionBuffer* LastExceptionBuffer::s_currentBuffer = nullptr;
39
40
8746
LastExceptionBuffer::LastExceptionBuffer() : d_contents(nullptr) {}
41
42
LastExceptionBuffer::~LastExceptionBuffer() {
43
  if(d_contents != nullptr){
44
    free(d_contents);
45
    d_contents = nullptr;
46
  }
47
}
48
49
4
void LastExceptionBuffer::setContents(const char* string) {
50
4
  if(d_contents != nullptr){
51
    free(d_contents);
52
    d_contents = nullptr;
53
  }
54
55
4
  if(string != nullptr){
56
4
    d_contents = strdup(string);
57
  }
58
4
}
59
60
const char* IllegalArgumentException::s_header = "Illegal argument detected";
61
62
2
std::string IllegalArgumentException::formatVariadic() {
63
2
  return std::string();
64
}
65
66
120
std::string IllegalArgumentException::formatVariadic(const char* format, ...) {
67
  va_list args;
68
120
  va_start(args, format);
69
70
120
  int n = 512;
71
120
  char* buf = nullptr;
72
73
120
  for (int i = 0; i < 2; ++i){
74
120
    Assert(n > 0);
75
120
    delete[] buf;
76
120
    buf = new char[n];
77
78
    va_list args_copy;
79
120
    va_copy(args_copy, args);
80
120
    int size = vsnprintf(buf, n, format, args);
81
120
    va_end(args_copy);
82
83
120
    if(size >= n){
84
      buf[n-1] = '\0';
85
      n = size + 1;
86
    } else {
87
120
      break;
88
    }
89
  }
90
  // buf is not nullptr is an invariant.
91
  // buf is also 0 terminated.
92
120
  Assert(buf != nullptr);
93
120
  std::string result(buf);
94
120
  delete [] buf;
95
120
  va_end(args);
96
120
  return result;
97
}
98
99
154
std::string IllegalArgumentException::format_extra(const char* condStr, const char* argDesc){
100
308
  return ( std::string("`") + argDesc + "' is a bad argument"
101
426
           + (*condStr == '\0' ? std::string() :
102
272
              ( std::string("; expected ") +
103
308
                condStr + " to hold" )) );
104
}
105
106
122
void IllegalArgumentException::construct(const char* header, const char* extra,
107
                                         const char* function, const char* tail) {
108
  // try building the exception msg with a smallish buffer first,
109
  // then with a larger one if sprintf tells us to.
110
122
  int n = 512;
111
  char* buf;
112
113
  for(;;) {
114
122
    buf = new char[n];
115
116
    int size;
117
122
    if(extra == nullptr) {
118
      size = snprintf(buf, n, "%s\n%s\n%s",
119
                      header, function, tail);
120
    } else {
121
122
      size = snprintf(buf, n, "%s\n%s\n\n  %s\n%s",
122
                      header, function, extra, tail);
123
    }
124
125
122
    if(size < n) {
126
122
      break;
127
    } else {
128
      // size >= n
129
      // try again with a buffer that's large enough
130
      n = size + 1;
131
      delete [] buf;
132
    }
133
  }
134
135
122
  setMessage(string(buf));
136
137
#ifdef CVC5_DEBUG
138
122
  LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
139
122
  if(buffer != nullptr){
140
    if(buffer->getContents() == nullptr) {
141
      buffer->setContents(buf);
142
    }
143
  }
144
#endif /* CVC5_DEBUG */
145
122
  delete [] buf;
146
122
}
147
148
32
void IllegalArgumentException::construct(const char* header, const char* extra,
149
                                         const char* function) {
150
  // try building the exception msg with a smallish buffer first,
151
  // then with a larger one if sprintf tells us to.
152
32
  int n = 256;
153
  char* buf;
154
155
  for(;;) {
156
32
    buf = new char[n];
157
158
    int size;
159
32
    if(extra == nullptr) {
160
      size = snprintf(buf, n, "%s.\n%s\n",
161
                      header, function);
162
    } else {
163
32
      size = snprintf(buf, n, "%s.\n%s\n\n  %s\n",
164
                      header, function, extra);
165
    }
166
167
32
    if(size < n) {
168
32
      break;
169
    } else {
170
      // try again with a buffer that's large enough
171
      n = size + 1;
172
      delete [] buf;
173
    }
174
  }
175
176
32
  setMessage(string(buf));
177
178
#ifdef CVC5_DEBUG
179
32
  LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
180
32
  if(buffer != nullptr){
181
    if(buffer->getContents() == nullptr) {
182
      buffer->setContents(buf);
183
    }
184
  }
185
#endif /* CVC5_DEBUG */
186
32
  delete [] buf;
187
32
}
188
189
}  // namespace cvc5