Skip to content

Commit

Permalink
Merge branch 'master' into test_intel
Browse files Browse the repository at this point in the history
  • Loading branch information
GiovanniBussi committed Nov 30, 2023
2 parents 42a8d3c + 65c503d commit 34139d7
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 6 deletions.
35 changes: 35 additions & 0 deletions regtest/basic/rt-make-exceptions/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// In order to correctly catch the thrown C++11 exceptions,
// we notify the Plumed wrapper that those exceptions are recognized by the compiler.
#define __PLUMED_WRAPPER_LIBCXX11 1
#define __PLUMED_WRAPPER_LIBCXX17 1
#include "plumed/tools/Stopwatch.h"
#include "plumed/wrapper/Plumed.h"
#include <fstream>
Expand Down Expand Up @@ -171,6 +172,11 @@ int main(){
TEST_STD_NOMSG(std::bad_array_new_length);
TEST_STD_NOMSG(std::bad_exception);

TEST_STD_NOMSG(std::bad_variant_access);
TEST_STD_NOMSG(std::bad_optional_access);
TEST_STD_NOMSG(std::bad_any_cast);


#define TEST_REGEX(type) try { p.cmd("throw", "std::regex_error std::regex_constants::error_" #type);} catch (std::regex_error & e) { plumed_assert(e.code()==std::regex_constants::error_ ##type); }
TEST_REGEX(collate);
TEST_REGEX(ctype);
Expand All @@ -186,6 +192,13 @@ int main(){
TEST_REGEX(complexity);
TEST_REGEX(stack);

#define TEST_FUTURE(type) try { p.cmd("throw", "std::future_error std::future_errc::" #type);} catch (std::future_error & e) { plumed_assert(e.code()==std::make_error_code(std::future_errc::type)); }

TEST_FUTURE(broken_promise);
TEST_FUTURE(future_already_retrieved);
TEST_FUTURE(promise_already_satisfied);
TEST_FUTURE(no_state);

try { p.cmd("throw","PLMD::Exception msg"); } catch (PLMD::Plumed::Exception &e) {
}
try { p.cmd("throw","PLMD::ExceptionError msg"); } catch (PLMD::Plumed::ExceptionError &e) {
Expand Down Expand Up @@ -214,6 +227,28 @@ int main(){
try { p.cmd("throw","std::ios_base::failure"); } catch (std::ios_base::failure & e) {
}

try { p.cmd("throw","std::filesystem::filesystem_error std::generic_category 100 a/b/c x/y/z"); } catch (std::filesystem::filesystem_error & e) {
plumed_assert(e.code().value()==100);
plumed_assert(e.code().category()==std::generic_category());
plumed_assert(!e.path1().empty());
plumed_assert(!e.path2().empty());
plumed_assert(e.path1().native()=="a/b/c");
plumed_assert(e.path2().native()=="x/y/z");
}
try { p.cmd("throw","std::filesystem::filesystem_error std::generic_category 200 a/b/c"); } catch (std::filesystem::filesystem_error & e) {
plumed_assert(e.code().value()==200);
plumed_assert(e.code().category()==std::generic_category());
plumed_assert(!e.path1().empty());
plumed_assert(e.path2().empty());
plumed_assert(e.path1().native()=="a/b/c");
}
try { p.cmd("throw","std::filesystem::filesystem_error std::generic_category 300"); } catch (std::filesystem::filesystem_error & e) {
plumed_assert(e.code().value()==300);
plumed_assert(e.code().category()==std::generic_category());
plumed_assert(e.path1().empty());
plumed_assert(e.path2().empty());
}

try { p.cmd("throw","unknown_name"); } catch (PLMD::Plumed::Exception &e) {
}

Expand Down
33 changes: 33 additions & 0 deletions src/core/PlumedMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@
#include <memory>
#include <functional>
#include <regex>
#include <any>
#include <optional>
#include <variant>
#include <filesystem>


namespace PLMD {
Expand All @@ -81,6 +85,9 @@ namespace PLMD {
__PLUMED_THROW_NOMSG(std::bad_weak_ptr);
__PLUMED_THROW_NOMSG(std::bad_cast);
__PLUMED_THROW_NOMSG(std::bad_typeid);
__PLUMED_THROW_NOMSG(std::bad_variant_access);
__PLUMED_THROW_NOMSG(std::bad_optional_access);
__PLUMED_THROW_NOMSG(std::bad_any_cast);
__PLUMED_THROW_MSG(std::underflow_error);
__PLUMED_THROW_MSG(std::overflow_error);
__PLUMED_THROW_MSG(std::range_error);
Expand All @@ -91,6 +98,8 @@ namespace PLMD {
__PLUMED_THROW_MSG(std::invalid_argument);
__PLUMED_THROW_MSG(std::logic_error);



if(words[0]=="std::system_error") {
plumed_assert(words.size()>2);
int error_code;
Expand All @@ -101,6 +110,21 @@ namespace PLMD {
if(words[1]=="std::future_category") throw std::system_error(error_code,std::future_category(),what);
}

if(words[0]=="std::filesystem::filesystem_error") {
int error_code;
plumed_assert(words.size()>2);
Tools::convert(words[2],error_code);
std::error_code x_error_code;
if(words[1]=="std::generic_category") x_error_code=::std::error_code(error_code,::std::generic_category());
if(words[1]=="std::system_category") x_error_code=::std::error_code(error_code,::std::system_category());
if(words[1]=="std::iostream_category") x_error_code=::std::error_code(error_code,::std::iostream_category());
if(words[1]=="std::future_category") x_error_code=::std::error_code(error_code,::std::future_category());

if(words.size()<4) throw std::filesystem::filesystem_error(what,x_error_code);
if(words.size()<5) throw std::filesystem::filesystem_error(what,std::filesystem::path(words[3]),x_error_code);
throw std::filesystem::filesystem_error(what,std::filesystem::path(words[3]),std::filesystem::path(words[4]),x_error_code);
}

#define __PLUMED_THROW_REGEX(name) if(words[1]=="std::regex_constants::error_" #name) throw std::regex_error(std::regex_constants::error_ ##name)
if(words[0]=="std::regex_error") {
plumed_assert(words.size()>1);
Expand All @@ -119,6 +143,15 @@ namespace PLMD {
__PLUMED_THROW_REGEX(stack);
}

#define __PLUMED_THROW_FUTURE(name) if(words[1]=="std::future_errc::" #name) throw std::future_error(::std::future_errc::name)
if(words[0]=="std::future_error") {
plumed_assert(words.size()>1);
__PLUMED_THROW_FUTURE(broken_promise);
__PLUMED_THROW_FUTURE(future_already_retrieved);
__PLUMED_THROW_FUTURE(promise_already_satisfied);
__PLUMED_THROW_FUTURE(no_state);
}

if(words[0]=="std::ios_base::failure") {
int error_code=0;
if(words.size()>2) Tools::convert(words[2],error_code);
Expand Down
72 changes: 69 additions & 3 deletions src/core/PlumedMainInitializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
#include <memory>
#include <functional>
#include <regex>
#include <any>
#include <variant>
#include <optional>
#include <filesystem>
#include "tools/TypesafePtr.h"
#include "tools/Log.h"
#include "tools/Tools.h"
Expand Down Expand Up @@ -119,7 +123,7 @@ extern "C" {
/// be called on the nested exception
/// If msg is not null, it overrides the message. Can be used to build a concatenated message.
static void translate_current(plumed_nothrow_handler_x nothrow,void**nested=nullptr,const char*msg=nullptr) {
const void* opt[5]= {"n",nested,nullptr,nullptr,nullptr};
const void* opt[11]= {"n",nested,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr};
try {
// this function needs to be called while catching an exception
// cppcheck-suppress rethrowNoCurrentException
Expand All @@ -140,6 +144,12 @@ static void translate_current(plumed_nothrow_handler_x nothrow,void**nested=null
if(!msg) msg=e.what();
nothrow.handler(nothrow.ptr,19900,msg,opt);
// 11000 to 12000 are "bad exceptions". message will be copied without new allocations
} catch(const std::bad_variant_access & e) {
if(!msg) msg=e.what();
nothrow.handler(nothrow.ptr,11700,msg,opt);
} catch(const std::bad_optional_access & e) {
if(!msg) msg=e.what();
nothrow.handler(nothrow.ptr,11600,msg,opt);
} catch(const std::bad_exception & e) {
if(!msg) msg=e.what();
nothrow.handler(nothrow.ptr,11500,msg,opt);
Expand All @@ -155,6 +165,9 @@ static void translate_current(plumed_nothrow_handler_x nothrow,void**nested=null
} catch(const std::bad_weak_ptr & e) {
if(!msg) msg=e.what();
nothrow.handler(nothrow.ptr,11200,msg,opt);
} catch(const std::bad_any_cast & e) {
if(!msg) msg=e.what();
nothrow.handler(nothrow.ptr,11150,msg,opt);
} catch(const std::bad_cast & e) {
if(!msg) msg=e.what();
nothrow.handler(nothrow.ptr,11100,msg,opt);
Expand All @@ -178,6 +191,53 @@ static void translate_current(plumed_nothrow_handler_x nothrow,void**nested=null
else if(e.code()==std::regex_constants::error_stack) nothrow.handler(nothrow.ptr,10252,msg,opt);
// fallback to generic runtime_error
else nothrow.handler(nothrow.ptr,10200,msg,opt);
} catch(const std::filesystem::filesystem_error & e) {
if(!msg) msg=e.what();
int value=e.code().value();

opt[2]="c"; // "c" passes the error code.
opt[3]=&value;

opt[4]="C"; // "C" passes the error category
int generic_category=1;
int system_category=2;
int iostream_category=3;
int future_category=4;
if(e.code().category()==std::generic_category()) opt[5]=&generic_category;
else if(e.code().category()==std::system_category()) opt[5]=&system_category;
else if(e.code().category()==std::iostream_category()) opt[5]=&iostream_category;
else if(e.code().category()==std::future_category()) opt[5]=&future_category;
else opt[5]=nullptr;

// local class, just needed to propely pass path information
// path is stored as a span of bytes.
// in theory, could be wchar type (on Windows, not tested),
// so we explicitly store the number of bytes
struct Path {
std::size_t numbytes=0;
const void* ptr=nullptr;
Path(const std::filesystem::path & path):
numbytes(sizeof(std::filesystem::path::value_type)*path.native().length()),
ptr(path.c_str())
{}
Path() = default;
};

opt[6]="p"; // path1
Path path1; // declared here since it should survive till the end of this function
if(!e.path1().empty()) {
path1=Path(e.path1());
opt[7]=&path1;
}

opt[8]="q"; // path2
Path path2; // declared here since it should survive till the end of this function
if(!e.path2().empty()) {
path2=Path(e.path2());
opt[9]=&path2;
}

nothrow.handler(nothrow.ptr,10229,msg,opt);
} catch(const std::ios_base::failure & e) {
if(!msg) msg=e.what();
int value=e.code().value();
Expand Down Expand Up @@ -213,8 +273,14 @@ static void translate_current(plumed_nothrow_handler_x nothrow,void**nested=null
} catch(const std::runtime_error & e) {
if(!msg) msg=e.what();
nothrow.handler(nothrow.ptr,10200,msg,opt);
// not implemented yet: std::future_error
// not clear how useful it would be.
} catch(const std::future_error & e) {
if(!msg) msg=e.what();
if(e.code()==std::make_error_code(std::future_errc::broken_promise)) nothrow.handler(nothrow.ptr,10125,msg,opt);
else if(e.code()==std::make_error_code(std::future_errc::future_already_retrieved)) nothrow.handler(nothrow.ptr,10126,msg,opt);
else if(e.code()==std::make_error_code(std::future_errc::promise_already_satisfied)) nothrow.handler(nothrow.ptr,10127,msg,opt);
else if(e.code()==std::make_error_code(std::future_errc::no_state)) nothrow.handler(nothrow.ptr,10128,msg,opt);
// fallback to generic logic_error
else nothrow.handler(nothrow.ptr,10100,msg,opt);
} catch(const std::out_of_range & e) {
if(!msg) msg=e.what();
nothrow.handler(nothrow.ptr,10120,msg,opt);
Expand Down
5 changes: 3 additions & 2 deletions src/vatom/Center.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "core/PlumedMain.h"
#include "core/Atoms.h"
#include <cmath>
#include <limits>

namespace PLMD {
namespace vatom {
Expand Down Expand Up @@ -152,7 +153,7 @@ void Center::registerKeywords(Keywords& keys) {
Center::Center(const ActionOptions&ao):
Action(ao),
ActionWithVirtualAtom(ao),
charge_(nan("")),
charge_(std::numeric_limits<double>::lowest()),
mass_(-1),
isChargeSet_(false),
isMassSet_(false),
Expand All @@ -169,7 +170,7 @@ Center::Center(const ActionOptions&ao):
parseFlag("NOPBC",nopbc);
parseFlag("PHASES",phases);
parse("SET_CHARGE",charge_);
if(!std::isnan(charge_)) isChargeSet_=true;
if(charge_!=std::numeric_limits<double>::lowest()) isChargeSet_=true;
parse("SET_MASS",mass_);
if(mass_>0.) isMassSet_=true;
if(mass_==0.) error("SETMASS must be greater than 0");
Expand Down
Loading

0 comments on commit 34139d7

Please sign in to comment.