1//Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc.
2
3//Distributed under the Boost Software License, Version 1.0. (See accompanying
4//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef BOOST_EXCEPTION_0552D49838DD11DD90146B8956D89593
7#define BOOST_EXCEPTION_0552D49838DD11DD90146B8956D89593
8
9#include <boost/config.hpp>
10#include <boost/exception/get_error_info.hpp>
11#include <boost/exception/info.hpp>
12#include <boost/utility/enable_if.hpp>
13#ifndef BOOST_NO_RTTI
14#include <boost/core/demangle.hpp>
15#endif
16#include <exception>
17#include <sstream>
18#include <string>
19#ifndef BOOST_NO_EXCEPTIONS
20#include <boost/exception/current_exception_cast.hpp>
21#endif
22
23#ifndef BOOST_EXCEPTION_ENABLE_WARNINGS
24#if __GNUC__*100+__GNUC_MINOR__>301
25#pragma GCC system_header
26#endif
27#ifdef __clang__
28#pragma clang system_header
29#endif
30#ifdef _MSC_VER
31#pragma warning(push,1)
32#endif
33#endif
34
35#ifndef BOOST_NO_EXCEPTIONS
36namespace
37boost
38 {
39 namespace
40 exception_detail
41 {
42 std::string diagnostic_information_impl( boost::exception const *, std::exception const *, bool, bool );
43 }
44
45 inline
46 std::string
47 current_exception_diagnostic_information( bool verbose=true)
48 {
49 boost::exception const * be=current_exception_cast<boost::exception const>();
50 std::exception const * se=current_exception_cast<std::exception const>();
51 if( be || se )
52 return exception_detail::diagnostic_information_impl(be,se,true,verbose);
53#if defined(__GLIBCXX__) && __cplusplus >= 201103L && !defined(BOOST_NO_RTTI)
54 else if (auto* p=std::current_exception().__cxa_exception_type())
55 return "Dynamic exception type: "+boost::core::demangle(name: p->name());
56#endif
57 else
58 return "No diagnostic information available.";
59 }
60 }
61#endif
62
63namespace
64boost
65 {
66 namespace
67 exception_detail
68 {
69 inline
70 exception const *
71 get_boost_exception( exception const * e )
72 {
73 return e;
74 }
75
76 inline
77 exception const *
78 get_boost_exception( ... )
79 {
80 return 0;
81 }
82
83 inline
84 std::exception const *
85 get_std_exception( std::exception const * e )
86 {
87 return e;
88 }
89
90 inline
91 std::exception const *
92 get_std_exception( ... )
93 {
94 return 0;
95 }
96
97 inline
98 char const *
99 get_diagnostic_information( exception const & x, char const * header )
100 {
101#ifndef BOOST_NO_EXCEPTIONS
102 try
103 {
104#endif
105 error_info_container * c=x.data_.get();
106 if( !c )
107 x.data_.adopt(px: c=new exception_detail::error_info_container_impl);
108 char const * di=c->diagnostic_information(header);
109 BOOST_ASSERT(di!=0);
110 return di;
111#ifndef BOOST_NO_EXCEPTIONS
112 }
113 catch(...)
114 {
115 return 0;
116 }
117#endif
118 }
119
120 inline
121 std::string
122 diagnostic_information_impl( boost::exception const * be, std::exception const * se, bool with_what, bool verbose )
123 {
124 if( !be && !se )
125 return "Unknown exception.";
126#ifndef BOOST_NO_RTTI
127 if( !be )
128 be=dynamic_cast<boost::exception const *>(se);
129 if( !se )
130 se=dynamic_cast<std::exception const *>(be);
131#endif
132 char const * wh=0;
133 if( with_what && se )
134 {
135 wh=se->what();
136 if( be && exception_detail::get_diagnostic_information(x: *be,header: 0)==wh )
137 return wh;
138 }
139 std::ostringstream tmp;
140 if( be && verbose )
141 {
142 char const * const * f=get_error_info<throw_file>(some_exception: *be);
143 int const * l=get_error_info<throw_line>(some_exception: *be);
144 char const * const * fn=get_error_info<throw_function>(some_exception: *be);
145 if( !f && !l && !fn )
146 tmp << "Throw location unknown (consider using BOOST_THROW_EXCEPTION)\n";
147 else
148 {
149 if( f )
150 {
151 tmp << *f;
152 if( int const * l=get_error_info<throw_line>(some_exception: *be) )
153 tmp << '(' << *l << "): ";
154 }
155 tmp << "Throw in function ";
156 if( char const * const * fn=get_error_info<throw_function>(some_exception: *be) )
157 tmp << *fn;
158 else
159 tmp << "(unknown)";
160 tmp << '\n';
161 }
162 }
163#ifndef BOOST_NO_RTTI
164 if ( verbose )
165 tmp << std::string("Dynamic exception type: ") <<
166 core::demangle(name: (be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n';
167#endif
168 if( with_what && se && verbose )
169 tmp << "std::exception::what: " << (wh ? wh : "(null)") << '\n';
170 if( be )
171 if( char const * s=exception_detail::get_diagnostic_information(x: *be,header: tmp.str().c_str()) )
172 if( *s )
173 return std::string(s);
174 return tmp.str();
175 }
176 }
177
178 template <class T>
179 std::string
180 diagnostic_information( T const & e, bool verbose=true )
181 {
182 return exception_detail::diagnostic_information_impl(be: exception_detail::get_boost_exception(&e),se: exception_detail::get_std_exception(&e),with_what: true,verbose);
183 }
184
185 inline
186 char const *
187 diagnostic_information_what( exception const & e, bool verbose=true ) BOOST_NOEXCEPT_OR_NOTHROW
188 {
189 char const * w=0;
190#ifndef BOOST_NO_EXCEPTIONS
191 try
192 {
193#endif
194 (void) exception_detail::diagnostic_information_impl(be: &e,se: 0,with_what: false,verbose);
195 if( char const * di=exception_detail::get_diagnostic_information(x: e,header: 0) )
196 return di;
197 else
198 return "Failed to produce boost::diagnostic_information_what()";
199#ifndef BOOST_NO_EXCEPTIONS
200 }
201 catch(
202 ... )
203 {
204 }
205#endif
206 return w;
207 }
208 }
209
210#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
211#pragma warning(pop)
212#endif
213#endif
214

source code of include/boost/exception/diagnostic_information.hpp