2013-09-07 01:18:14 +04:00
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Baozeng Ding <sploving1@gmail.com>
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
2014-01-07 14:08:37 +04:00
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
2013-09-07 01:18:14 +04:00
//------------------------------------------------------------------------------
2015-11-27 15:54:20 +03:00
# include "cling/Interpreter/Exception.h"
2013-09-07 01:18:14 +04:00
2016-12-19 16:57:41 +03:00
# include "cling/Interpreter/InterpreterCallbacks.h"
# include "cling/Interpreter/Interpreter.h"
2021-05-19 12:55:39 +03:00
# include "cling/Interpreter/Visibility.h"
2016-12-19 16:57:41 +03:00
# include "cling/Utils/Validation.h"
# include "clang/Frontend/CompilerInstance.h"
2013-09-07 01:18:14 +04:00
# include "clang/Basic/SourceLocation.h"
# include "clang/Sema/Sema.h"
# include "clang/Sema/SemaDiagnostic.h"
2013-09-12 01:04:36 +04:00
2016-12-19 16:57:41 +03:00
extern " C " {
/// Throw an InvalidDerefException if the Arg pointer is invalid.
///\param Interp: The interpreter that has compiled the code.
///\param Expr: The expression corresponding determining the pointer value.
///\param Arg: The pointer to be checked.
///\returns void*, const-cast from Arg, to reduce the complexity in the
/// calling AST nodes, at the expense of possibly doing a
/// T* -> const void* -> const_cast<void*> -> T* round trip.
2021-05-19 12:55:39 +03:00
CLING_LIB_EXPORT
2016-12-19 16:57:41 +03:00
void * cling_runtime_internal_throwIfInvalidPointer ( void * Interp , void * Expr ,
const void * Arg ) {
2021-03-31 16:25:08 +03:00
# if defined(__APPLE__) && defined(__arm64__)
// See https://github.com/root-project/root/issues/7541 and
// https://bugs.llvm.org/show_bug.cgi?id=49692 :
// llvm JIT fails to catch exceptions on M1, so let's throw less.
// This might still better than `terminate`...
( void ) Interp ;
( void ) Expr ;
# else
2022-02-14 14:43:14 +03:00
const clang : : Expr * const E = ( const clang : : Expr * ) Expr ;
2016-12-19 16:57:41 +03:00
// The isValidAddress function return true even when the pointer is
// null thus the checks have to be done before returning successfully from the
// function in this specific order.
if ( ! Arg ) {
cling : : Interpreter * I = ( cling : : Interpreter * ) Interp ;
clang : : Sema & S = I - > getCI ( ) - > getSema ( ) ;
// Print a nice backtrace.
2022-01-11 14:43:57 +03:00
// FIXME: re-enable once we have JIT debug symbols!
//I->getCallbacks()->PrintStackTrace();
2016-12-19 16:57:41 +03:00
throw cling : : InvalidDerefException ( & S , E ,
cling : : InvalidDerefException : : DerefType : : NULL_DEREF ) ;
} else if ( ! cling : : utils : : isAddressValid ( Arg ) ) {
cling : : Interpreter * I = ( cling : : Interpreter * ) Interp ;
clang : : Sema & S = I - > getCI ( ) - > getSema ( ) ;
// Print a nice backtrace.
2022-01-11 14:43:57 +03:00
// FIXME: re-enable once we have JIT debug symbols!
//I->getCallbacks()->PrintStackTrace();
2016-12-19 16:57:41 +03:00
throw cling : : InvalidDerefException ( & S , E ,
cling : : InvalidDerefException : : DerefType : : INVALID_MEM ) ;
}
2021-03-31 16:25:08 +03:00
# endif
2016-12-19 16:57:41 +03:00
return const_cast < void * > ( Arg ) ;
}
}
2013-09-07 01:18:14 +04:00
namespace cling {
2016-12-19 16:57:41 +03:00
InterpreterException : : InterpreterException ( const std : : string & What ) :
std : : runtime_error ( What ) , m_Sema ( nullptr ) { }
InterpreterException : : InterpreterException ( const char * What , clang : : Sema * S ) :
std : : runtime_error ( What ) , m_Sema ( S ) { }
bool InterpreterException : : diagnose ( ) const { return false ; }
2017-05-18 16:16:30 +03:00
InterpreterException : : ~ InterpreterException ( ) noexcept { }
2016-12-19 16:57:41 +03:00
2013-09-07 01:18:14 +04:00
2016-12-19 16:57:41 +03:00
InvalidDerefException : : InvalidDerefException ( clang : : Sema * S ,
const clang : : Expr * E ,
DerefType type )
: InterpreterException ( type = = INVALID_MEM ?
" Trying to access a pointer that points to an invalid memory address. " :
" Trying to dereference null pointer or trying to call routine taking "
" non-null arguments " , S ) ,
m_Arg ( E ) , m_Type ( type ) { }
2017-05-18 16:16:30 +03:00
InvalidDerefException : : ~ InvalidDerefException ( ) noexcept { }
2016-12-19 16:57:41 +03:00
bool InvalidDerefException : : diagnose ( ) const {
2015-12-11 17:06:13 +03:00
// Construct custom diagnostic: warning for invalid memory address;
// no equivalent in clang.
2015-12-08 15:26:13 +03:00
if ( m_Type = = cling : : InvalidDerefException : : DerefType : : INVALID_MEM ) {
2016-12-19 16:57:41 +03:00
clang : : DiagnosticsEngine & Diags = m_Sema - > getDiagnostics ( ) ;
2015-12-11 17:06:13 +03:00
unsigned DiagID =
2016-12-19 16:57:41 +03:00
Diags . getCustomDiagID ( clang : : DiagnosticsEngine : : Warning ,
2015-12-11 17:06:13 +03:00
" invalid memory pointer passed to a callee: " ) ;
2020-03-15 15:30:01 +03:00
Diags . Report ( m_Arg - > getBeginLoc ( ) , DiagID ) < < m_Arg - > getSourceRange ( ) ;
2015-12-08 15:26:13 +03:00
}
else
2020-03-15 15:30:01 +03:00
m_Sema - > Diag ( m_Arg - > getBeginLoc ( ) , clang : : diag : : warn_null_arg )
2016-12-19 16:57:41 +03:00
< < m_Arg - > getSourceRange ( ) ;
return true ;
}
CompilationException : : CompilationException ( const std : : string & Reason ) :
InterpreterException ( Reason ) { }
2017-05-18 16:16:30 +03:00
CompilationException : : ~ CompilationException ( ) noexcept { }
2016-12-19 16:57:41 +03:00
void CompilationException : : throwingHandler ( void * /*user_data*/ ,
2023-07-10 09:52:15 +03:00
const char * reason ,
2016-12-19 16:57:41 +03:00
bool /*gen_crash_diag*/ ) {
2022-05-11 15:05:50 +03:00
// See https://github.com/root-project/root/issues/7541 and
// https://bugs.llvm.org/show_bug.cgi?id=49692 :
// We cannot catch exceptions that traverse JITted code on M1, so let's throw less.
// This might still better than `terminate`...
# if !defined(_MSC_VER) && (!defined(__APPLE__) || !defined(__arm64__))
2016-12-19 16:57:41 +03:00
throw cling : : CompilationException ( reason ) ;
2019-09-23 18:38:33 +03:00
# endif
2015-11-27 15:54:20 +03:00
}
2013-09-07 01:18:14 +04:00
} // end namespace cling