Skip to content

Commit 6afcd4f

Browse files
committed
Fixes exception call stack for C++ exceptions
Also adds support for populating the cppstack for Rcpp::exceptions when using clang and a str method to make printing a little nicer.
1 parent 8e90f89 commit 6afcd4f

File tree

6 files changed

+35
-25
lines changed

6 files changed

+35
-25
lines changed

ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@
2828

2929
* inst/include/Rcpp/date_datetime/newDatetimeVector.h: Added constructor
3030
to instantiate newDatetimeVector from VectorBase.
31+
2016-11-11 Jim Hester <[email protected]>
32+
* inst/include/rcpp/exceptions.h: Return stack trace even if no file
33+
or line is specified. Fix R calls when using Rcpp_eval.
34+
* inst/include/rcpp/routines.h:allow getting a cppstack without specifying a file and line.
35+
* src/api.cpp: Add cppstack support for clang.
36+
* r/exceptions.r:Add a str method for Rcpp_stack_trace objects.
37+
* NAMESPACE: Idem
3138

3239
2016-11-04 Nathan Russell <[email protected]>
3340

NAMESPACE

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ export(Module,
3232
sizeof,
3333
cpp_object_initializer,
3434
cpp_object_dummy,
35-
Rcpp.plugin.maker
35+
Rcpp.plugin.maker,
36+
str.Rcpp_stack_trace
3637
)
3738
S3method(print, bytes)
3839
exportClass(RcppClass)

R/exceptions.R

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,6 @@
3333
warnings
3434
}
3535

36-
36+
`str.Rcpp_stack_trace` <- function(x, ...) {
37+
cat("\n", paste(collapse = "\n ", x$stack), "\n")
38+
}

inst/include/Rcpp/exceptions.h

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace Rcpp{
2828

2929
class exception : public std::exception {
3030
public:
31-
explicit exception(const char* message_) : message(message_){}
31+
explicit exception(const char* message_) : message(message_){ rcpp_set_stack_trace(stack_trace()); }
3232
exception(const char* message_, const char* file, int line ) : message(message_){
3333
rcpp_set_stack_trace( stack_trace(file,line) ) ;
3434
}
@@ -127,17 +127,17 @@ namespace Rcpp{
127127
} // namespace Rcpp
128128

129129
inline SEXP get_last_call(){
130-
SEXP sys_calls_symbol = Rf_install( "sys.calls" ) ;
131-
Rcpp::Shield<SEXP> sys_calls_expr( Rf_lang1(sys_calls_symbol) );
130+
SEXP sys_calls_symbol = Rf_install( "sys.call" ) ;
131+
132+
// -9 Skips the wrapped tryCatch from Rcpp_eval
133+
Rcpp::Shield<SEXP> sys_calls_expr( Rf_lang2(sys_calls_symbol, Rf_ScalarInteger(-9)) );
132134
Rcpp::Shield<SEXP> calls( Rcpp_eval( sys_calls_expr, R_GlobalEnv ) );
133-
SEXP res = calls ;
134-
while( !Rf_isNull(CDR(res)) ) res = CDR(res);
135-
return CAR(res) ;
135+
return calls;
136136
}
137137

138138
inline SEXP get_exception_classes( const std::string& ex_class) {
139139
Rcpp::Shield<SEXP> res( Rf_allocVector( STRSXP, 4 ) );
140-
140+
141141
#ifndef RCPP_USING_UTF8_ERROR_STRING
142142
SET_STRING_ELT( res, 0, Rf_mkChar( ex_class.c_str() ) ) ;
143143
#else
@@ -184,7 +184,7 @@ inline SEXP exception_to_r_condition( const std::exception& ex){
184184

185185
inline SEXP string_to_try_error( const std::string& str){
186186
using namespace Rcpp;
187-
187+
188188
#ifndef RCPP_USING_UTF8_ERROR_STRING
189189
Rcpp::Shield<SEXP> simpleErrorExpr( Rf_lang2(::Rf_install("simpleError"), Rf_mkString(str.c_str())) );
190190
Rcpp::Shield<SEXP> tryError( Rf_mkString( str.c_str() ) );
@@ -193,7 +193,7 @@ inline SEXP string_to_try_error( const std::string& str){
193193
SET_STRING_ELT( tryError, 0, Rf_mkCharLenCE( str.c_str(), str.size(), CE_UTF8 ) );
194194
Rcpp::Shield<SEXP> simpleErrorExpr( Rf_lang2(::Rf_install("simpleError"), tryError ));
195195
#endif
196-
196+
197197
Rcpp::Shield<SEXP> simpleError( Rf_eval(simpleErrorExpr, R_GlobalEnv) );
198198
Rf_setAttrib( tryError, R_ClassSymbol, Rf_mkString("try-error") ) ;
199199
Rf_setAttrib( tryError, Rf_install( "condition") , simpleError ) ;
@@ -267,52 +267,52 @@ namespace Rcpp{
267267
inline void NORET stop(const std::string& message) {
268268
throw Rcpp::exception(message.c_str());
269269
}
270-
270+
271271
template <typename T1>
272272
inline void NORET stop(const char* fmt, const T1& arg1) {
273273
throw Rcpp::exception( tfm::format(fmt, arg1 ).c_str() );
274274
}
275-
275+
276276
template <typename T1, typename T2>
277277
inline void NORET stop(const char* fmt, const T1& arg1, const T2& arg2) {
278278
throw Rcpp::exception( tfm::format(fmt, arg1, arg2 ).c_str() );
279279
}
280-
280+
281281
template <typename T1, typename T2, typename T3>
282282
inline void NORET stop(const char* fmt, const T1& arg1, const T2& arg2, const T3& arg3) {
283283
throw Rcpp::exception( tfm::format(fmt, arg1, arg2, arg3).c_str() );
284284
}
285-
285+
286286
template <typename T1, typename T2, typename T3, typename T4>
287287
inline void NORET stop(const char* fmt, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4) {
288288
throw Rcpp::exception( tfm::format(fmt, arg1, arg2, arg3, arg4).c_str() );
289289
}
290-
290+
291291
template <typename T1, typename T2, typename T3, typename T4, typename T5>
292292
inline void NORET stop(const char* fmt, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5) {
293293
throw Rcpp::exception( tfm::format(fmt, arg1, arg2, arg3, arg4, arg5).c_str() );
294294
}
295-
295+
296296
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
297297
inline void NORET stop(const char* fmt, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5, const T6& arg6) {
298298
throw Rcpp::exception( tfm::format(fmt, arg1, arg2, arg3, arg4, arg5, arg6).c_str() );
299299
}
300-
300+
301301
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
302302
inline void NORET stop(const char* fmt, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5, const T6& arg6, const T7& arg7) {
303303
throw Rcpp::exception( tfm::format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7).c_str() );
304304
}
305-
305+
306306
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
307307
inline void NORET stop(const char* fmt, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5, const T6& arg6, const T7& arg7, const T8& arg8) {
308308
throw Rcpp::exception( tfm::format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8).c_str() );
309309
}
310-
310+
311311
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
312312
inline void NORET stop(const char* fmt, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5, const T6& arg6, const T7& arg7, const T8& arg8, const T9& arg9) {
313313
throw Rcpp::exception( tfm::format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9).c_str() );
314314
}
315-
315+
316316
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
317317
inline void NORET stop(const char* fmt, const T1& arg1, const T2& arg2, const T3& arg3, const T4& arg4, const T5& arg5, const T6& arg6, const T7& arg7, const T8& arg8, const T9& arg9, const T10& arg10) {
318318
throw Rcpp::exception( tfm::format(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10).c_str() );

inst/include/Rcpp/routines.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ SEXP rcpp_set_stack_trace(SEXP);
4343
std::string demangle(const std::string& name);
4444
const char* short_file_name(const char* );
4545
int* get_cache(int n);
46-
SEXP stack_trace( const char *file, int line);
46+
SEXP stack_trace( const char *file = "", int line = -1);
4747
SEXP get_string_elt(SEXP s, R_xlen_t i);
4848
const char* char_get_string_elt(SEXP s, R_xlen_t i);
4949
void set_string_elt(SEXP s, R_xlen_t i, SEXP v);
@@ -143,7 +143,7 @@ inline attribute_hidden const char* short_file_name(const char* file) {
143143
return fun(file);
144144
}
145145

146-
inline attribute_hidden SEXP stack_trace( const char *file, int line){
146+
inline attribute_hidden SEXP stack_trace( const char *file = "", int line = -1){
147147
typedef SEXP (*Fun)(const char*, int);
148148
static Fun fun = GET_CALLABLE("stack_trace");
149149
return fun(file, line);

src/api.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ using namespace Rcpp;
3232
#include <cxxabi.h>
3333
#endif
3434

35-
#if defined(__GNUC__)
35+
#if defined(__GNUC__) || defined(__clang__)
3636
#if defined(_WIN32) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__sun) || defined(_AIX) || defined(__MUSL__)
3737
// do nothing
3838
#else
@@ -262,7 +262,7 @@ SEXP rcpp_can_use_cxx11() {
262262

263263
// [[Rcpp::register]]
264264
SEXP stack_trace(const char* file, int line) {
265-
#if defined(__GNUC__)
265+
#if defined(__GNUC__) || defined(__clang__)
266266
#if defined(_WIN32) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__sun) || defined(_AIX) || defined(__MUSL__)
267267
// Simpler version for Windows and *BSD
268268
List trace = List::create(_["file"] = file,

0 commit comments

Comments
 (0)