GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/base/exception.cpp Lines: 60 82 73.2 %
Date: 2021-09-07 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 <ostream>
23
#include <sstream>
24
#include <string>
25
26
#include "base/check.h"
27
28
using namespace std;
29
30
namespace cvc5 {
31
32
6
std::string Exception::toString() const
33
{
34
12
  std::stringstream ss;
35
6
  toStream(ss);
36
12
  return ss.str();
37
}
38
39
12
void Exception::toStream(std::ostream& os) const { os << d_msg; }
40
41
thread_local LastExceptionBuffer* LastExceptionBuffer::s_currentBuffer = nullptr;
42
43
8779
LastExceptionBuffer::LastExceptionBuffer() : d_contents(nullptr) {}
44
45
LastExceptionBuffer::~LastExceptionBuffer() {
46
  if(d_contents != nullptr){
47
    free(d_contents);
48
    d_contents = nullptr;
49
  }
50
}
51
52
4
void LastExceptionBuffer::setContents(const char* string) {
53
4
  if(d_contents != nullptr){
54
    free(d_contents);
55
    d_contents = nullptr;
56
  }
57
58
4
  if(string != nullptr){
59
4
    d_contents = strdup(string);
60
  }
61
4
}
62
63
const char* IllegalArgumentException::s_header = "Illegal argument detected";
64
65
2
std::string IllegalArgumentException::formatVariadic() {
66
2
  return std::string();
67
}
68
69
120
std::string IllegalArgumentException::formatVariadic(const char* format, ...) {
70
  va_list args;
71
120
  va_start(args, format);
72
73
120
  int n = 512;
74
120
  char* buf = nullptr;
75
76
120
  for (int i = 0; i < 2; ++i){
77
120
    Assert(n > 0);
78
120
    delete[] buf;
79
120
    buf = new char[n];
80
81
    va_list args_copy;
82
120
    va_copy(args_copy, args);
83
120
    int size = vsnprintf(buf, n, format, args);
84
120
    va_end(args_copy);
85
86
120
    if(size >= n){
87
      buf[n-1] = '\0';
88
      n = size + 1;
89
    } else {
90
120
      break;
91
    }
92
  }
93
  // buf is not nullptr is an invariant.
94
  // buf is also 0 terminated.
95
120
  Assert(buf != nullptr);
96
120
  std::string result(buf);
97
120
  delete [] buf;
98
120
  va_end(args);
99
120
  return result;
100
}
101
102
154
std::string IllegalArgumentException::format_extra(const char* condStr, const char* argDesc){
103
308
  return ( std::string("`") + argDesc + "' is a bad argument"
104
426
           + (*condStr == '\0' ? std::string() :
105
272
              ( std::string("; expected ") +
106
308
                condStr + " to hold" )) );
107
}
108
109
122
void IllegalArgumentException::construct(const char* header, const char* extra,
110
                                         const char* function, const char* tail) {
111
  // try building the exception msg with a smallish buffer first,
112
  // then with a larger one if sprintf tells us to.
113
122
  int n = 512;
114
  char* buf;
115
116
  for(;;) {
117
122
    buf = new char[n];
118
119
    int size;
120
122
    if(extra == nullptr) {
121
      size = snprintf(buf, n, "%s\n%s\n%s",
122
                      header, function, tail);
123
    } else {
124
122
      size = snprintf(buf, n, "%s\n%s\n\n  %s\n%s",
125
                      header, function, extra, tail);
126
    }
127
128
122
    if(size < n) {
129
122
      break;
130
    } else {
131
      // size >= n
132
      // try again with a buffer that's large enough
133
      n = size + 1;
134
      delete [] buf;
135
    }
136
  }
137
138
122
  setMessage(string(buf));
139
140
#ifdef CVC5_DEBUG
141
122
  LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
142
122
  if(buffer != nullptr){
143
    if(buffer->getContents() == nullptr) {
144
      buffer->setContents(buf);
145
    }
146
  }
147
#endif /* CVC5_DEBUG */
148
122
  delete [] buf;
149
122
}
150
151
32
void IllegalArgumentException::construct(const char* header, const char* extra,
152
                                         const char* function) {
153
  // try building the exception msg with a smallish buffer first,
154
  // then with a larger one if sprintf tells us to.
155
32
  int n = 256;
156
  char* buf;
157
158
  for(;;) {
159
32
    buf = new char[n];
160
161
    int size;
162
32
    if(extra == nullptr) {
163
      size = snprintf(buf, n, "%s.\n%s\n",
164
                      header, function);
165
    } else {
166
32
      size = snprintf(buf, n, "%s.\n%s\n\n  %s\n",
167
                      header, function, extra);
168
    }
169
170
32
    if(size < n) {
171
32
      break;
172
    } else {
173
      // try again with a buffer that's large enough
174
      n = size + 1;
175
      delete [] buf;
176
    }
177
  }
178
179
32
  setMessage(string(buf));
180
181
#ifdef CVC5_DEBUG
182
32
  LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
183
32
  if(buffer != nullptr){
184
    if(buffer->getContents() == nullptr) {
185
      buffer->setContents(buf);
186
    }
187
  }
188
#endif /* CVC5_DEBUG */
189
32
  delete [] buf;
190
32
}
191
192
}  // namespace cvc5