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

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