Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * Top contributors (to current version): 3 : : * Morgan Deters, Tim King, Aina Niemetz 4 : : * 5 : : * This file is part of the cvc5 project. 6 : : * 7 : : * Copyright (c) 2009-2025 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 "cvc5_public.h" 17 : : 18 : : #ifndef CVC5__EXCEPTION_H 19 : : #define CVC5__EXCEPTION_H 20 : : 21 : : #include <cvc5/cvc5_export.h> 22 : : 23 : : #include <exception> 24 : : #include <iosfwd> 25 : : #include <string> 26 : : 27 : : namespace cvc5::internal { 28 : : 29 : : class CVC5_EXPORT Exception : public std::exception 30 : : { 31 : : protected: 32 : : std::string d_msg; 33 : : 34 : : public: 35 : : // Constructors 36 : 51 : Exception() : d_msg("Unknown exception") {} 37 : 78215 : Exception(const std::string& msg) : d_msg(msg) {} 38 : 27 : Exception(const char* msg) : d_msg(msg) {} 39 : : 40 : : // Destructor 41 : 78293 : virtual ~Exception() {} 42 : : 43 : : // NON-VIRTUAL METHOD for setting and printing the error message 44 : 52 : void setMessage(const std::string& msg) { d_msg = msg; } 45 : 11388 : std::string getMessage() const { return d_msg; } 46 : : 47 : : // overridden from base class std::exception 48 : 1 : const char* what() const noexcept override { return d_msg.c_str(); } 49 : : 50 : : /** 51 : : * Get this exception as a string. Note that 52 : : * cout << ex.toString(); 53 : : * is subtly different from 54 : : * cout << ex; 55 : : * which is equivalent to 56 : : * ex.toStream(cout); 57 : : * That is because with the latter two, the output language (and 58 : : * other preferences) for exprs on the stream is respected. In 59 : : * toString(), there is no stream, so the parameters are default 60 : : * and you'll get exprs and types printed using the AST language. 61 : : */ 62 : : std::string toString() const; 63 : : 64 : : /** 65 : : * Printing: feel free to redefine toStream(). When overridden in 66 : : * a derived class, it's recommended that this method print the 67 : : * type of exception before the actual message. 68 : : */ 69 : : virtual void toStream(std::ostream& os) const; 70 : : 71 : : }; /* class Exception */ 72 : : 73 : : class CVC5_EXPORT IllegalArgumentException : public Exception 74 : : { 75 : : protected: 76 : : IllegalArgumentException() : Exception() {} 77 : : 78 : : void construct(const char* header, const char* extra, 79 : : const char* function, const char* tail); 80 : : 81 : : void construct(const char* header, const char* extra, 82 : : const char* function); 83 : : 84 : : static std::string format_extra(const char* condStr, const char* argDesc); 85 : : 86 : : static const char* s_header; 87 : : 88 : : public: 89 : : 90 : 41 : IllegalArgumentException(const char* condStr, const char* argDesc, 91 : 41 : const char* function, const char* tail) : 92 : 41 : Exception() { 93 : 41 : construct(s_header, format_extra(condStr, argDesc).c_str(), function, tail); 94 : 41 : } 95 : : 96 : 1 : IllegalArgumentException(const char* condStr, const char* argDesc, 97 : 1 : const char* function) : 98 : 1 : Exception() { 99 : 1 : construct(s_header, format_extra(condStr, argDesc).c_str(), function); 100 : 1 : } 101 : : 102 : : /** 103 : : * This is a convenience function for building usages that are variadic. 104 : : * 105 : : * Having IllegalArgumentException itself be variadic is problematic for 106 : : * making sure calls to IllegalArgumentException clean up memory. 107 : : */ 108 : : static std::string formatVariadic(); 109 : : static std::string formatVariadic(const char* format, ...); 110 : : }; /* class IllegalArgumentException */ 111 : : 112 : : inline std::ostream& operator<<(std::ostream& os, const Exception& e); 113 : 7 : inline std::ostream& operator<<(std::ostream& os, const Exception& e) 114 : : { 115 : 7 : e.toStream(os); 116 : 7 : return os; 117 : : } 118 : : 119 : : template <class T> 120 : : inline void CheckArgument(bool cond, const T& arg, const char* tail); 121 : : template <class T> 122 : : inline void CheckArgument(bool cond, 123 : : const T& arg CVC5_UNUSED, 124 : : const char* tail CVC5_UNUSED) 125 : : { 126 : : if(__builtin_expect( ( !cond ), false )) { 127 : : throw cvc5::internal::IllegalArgumentException("", "", tail); 128 : : } 129 : : } 130 : : template <class T> 131 : : inline void CheckArgument(bool cond, const T& arg); 132 : : template <class T> 133 : 1 : inline void CheckArgument(bool cond, const T& arg CVC5_UNUSED) 134 : : { 135 [ + - ]: 1 : if(__builtin_expect( ( !cond ), false )) { 136 : 1 : throw cvc5::internal::IllegalArgumentException("", "", ""); 137 : : } 138 : 0 : } 139 : : 140 : : class CVC5_EXPORT LastExceptionBuffer 141 : : { 142 : : public: 143 : : LastExceptionBuffer(); 144 : : ~LastExceptionBuffer(); 145 : : 146 : : void setContents(const char* string); 147 : 0 : const char* getContents() const { return d_contents; } 148 : : 149 : 294 : static LastExceptionBuffer* getCurrent() { return s_currentBuffer; } 150 : 28355 : static void setCurrent(LastExceptionBuffer* buffer) { s_currentBuffer = buffer; } 151 : : 152 : : static const char* currentContents() { 153 : : return (getCurrent() == nullptr) ? nullptr : getCurrent()->getContents(); 154 : : } 155 : : 156 : : private: 157 : : /* Disallow copies */ 158 : : LastExceptionBuffer(const LastExceptionBuffer&) = delete; 159 : : LastExceptionBuffer& operator=(const LastExceptionBuffer&) = delete; 160 : : 161 : : char* d_contents; 162 : : 163 : : static thread_local LastExceptionBuffer* s_currentBuffer; 164 : : }; /* class LastExceptionBuffer */ 165 : : 166 : : } // namespace cvc5::internal 167 : : 168 : : #endif /* CVC5__EXCEPTION_H */