diff --git a/configure.ac b/configure.ac index d8bb4a30cb..b89067f521 100644 --- a/configure.ac +++ b/configure.ac @@ -870,6 +870,16 @@ dnl if 64-bit mode, then archive tool, ar, needs -X64 option [AC_LANG_PROGRAM(,[[int lp64 = __64BIT__; ]])], [AR_OPTIONS=-X64],) fi + +XE_SAVE_ENV() +CXXFLAGS="$CXXFLAGS -std=c++11" +AC_CACHE_CHECK([whether the C++ compiler understands noexcept], [ac_cv_cxx_noexcept], [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int f(int x) noexcept { return x + 1; }]], [[]])], + [ac_cv_cxx_noexcept=yes], [ac_cv_cxx_noexcept=no])]) +XE_RESTORE_ENV() +if test "$ac_cv_cxx_noexcept" = yes; then + AC_DEFINE([HAS_NOEXCEPT], [1], [Define if the C++ compiler understands noexcept.]) +fi AC_LANG_POP(C++) dnl Check for functions diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index 79c72e745a..4d0b2e78c3 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -7972,49 +7972,100 @@ void SetRoleNode::execute(thread_db* tdbb, dsql_req* request) const namespace { -struct RoundMode +struct TextCode { const char* name; USHORT val; }; -#define FB_RMODE(x) { STRINGIZE(x), x } +//#define FB_TEXTCODE(x) { STRINGIZE(x), x } +#define FB_TEXTCODE(x) { #x, x } -const RoundMode roundModes[] = { - FB_RMODE(DEC_ROUND_CEILING), - FB_RMODE(DEC_ROUND_UP), - FB_RMODE(DEC_ROUND_HALF_UP), - FB_RMODE(DEC_ROUND_HALF_EVEN), - FB_RMODE(DEC_ROUND_HALF_DOWN), - FB_RMODE(DEC_ROUND_DOWN), - FB_RMODE(DEC_ROUND_FLOOR), +const TextCode roundModes[] = { + FB_TEXTCODE(DEC_ROUND_CEILING), + FB_TEXTCODE(DEC_ROUND_UP), + FB_TEXTCODE(DEC_ROUND_HALF_UP), + FB_TEXTCODE(DEC_ROUND_HALF_EVEN), + FB_TEXTCODE(DEC_ROUND_HALF_DOWN), + FB_TEXTCODE(DEC_ROUND_DOWN), + FB_TEXTCODE(DEC_ROUND_FLOOR), { "DEC_ROUND_REROUND", DEC_ROUND_05UP }, { NULL, 0 } }; -#undef FB_RMODE - //DEC_ROUND_ //0123456789 const unsigned FB_RMODE_OFFSET = 10; +const TextCode ieeeTraps[] = { + FB_TEXTCODE(DEC_IEEE_754_Division_by_zero), + FB_TEXTCODE(DEC_IEEE_754_Inexact), + FB_TEXTCODE(DEC_IEEE_754_Invalid_operation), + FB_TEXTCODE(DEC_IEEE_754_Overflow), + FB_TEXTCODE(DEC_IEEE_754_Underflow), + { NULL, 0 } +}; + +//DEC_IEEE_754_ +//0123456789012 +const unsigned FB_TRAPS_OFFSET = 13; + +#undef FB_TEXTCODE + +const TextCode* getCodeByText(const MetaName& text, const TextCode* textCode, unsigned offset) +{ + NoCaseString name(text.c_str(), text.length()); + + for (const TextCode* tc = textCode; tc->name; ++tc) + { + if (name == &tc->name[offset]) + return tc; + } + + return nullptr; } -void SetRoundNode::execute(thread_db* tdbb, dsql_req* request) const +} + + +//-------------------- + + +SetRoundNode::SetRoundNode(MemoryPool& pool, Firebird::MetaName* name) + : SessionManagementNode(pool) +{ + fb_assert(name); + const TextCode* mode = getCodeByText(*name, roundModes, FB_RMODE_OFFSET); + if (!mode) + (Arg::Gds(isc_random) << "Invalid round mode for decfloat").raise(); + rndMode = mode->val; +} + +void SetRoundNode::execute(thread_db* tdbb, dsql_req* /*request*/) const { SET_TDBB(tdbb); Attachment* const attachment = tdbb->getAttachment(); + attachment->att_dec_status.roundingMode = rndMode; +} - for (const RoundMode* r = roundModes; r->name; ++r) - { - if (rndName == &r->name[FB_RMODE_OFFSET]) - { - attachment->att_dec_status.roundingMode = r->val; - return; - } - } - (Arg::Gds(isc_random) << "Invalid round mode for decfloat").raise(); +//-------------------- + + +void SetTrapsNode::trap(Firebird::MetaName* name) +{ + fb_assert(name); + const TextCode* trap = getCodeByText(*name, ieeeTraps, FB_TRAPS_OFFSET); + if (!trap) + (Arg::Gds(isc_random) << "Invalid decfloat trap").raise(); + traps |= trap->val; +} + +void SetTrapsNode::execute(thread_db* tdbb, dsql_req* /*request*/) const +{ + SET_TDBB(tdbb); + Attachment* const attachment = tdbb->getAttachment(); + attachment->att_dec_status.decExtFlag = traps; } diff --git a/src/dsql/StmtNodes.h b/src/dsql/StmtNodes.h index 497d6a839f..43b1d0ddbd 100644 --- a/src/dsql/StmtNodes.h +++ b/src/dsql/StmtNodes.h @@ -1584,9 +1584,31 @@ public: class SetRoundNode : public SessionManagementNode { public: - SetRoundNode(MemoryPool& pool, Firebird::MetaName* name) + SetRoundNode(MemoryPool& pool, Firebird::MetaName* name); + +public: + virtual Firebird::string internalPrint(NodePrinter& printer) const + { + SessionManagementNode::internalPrint(printer); + + NODE_PRINT(printer, rndMode); + + return "SetRoundNode"; + } + + virtual void execute(thread_db* tdbb, dsql_req* request) const; + +public: + USHORT rndMode; +}; + + +class SetTrapsNode : public SessionManagementNode +{ +public: + SetTrapsNode(MemoryPool& pool) : SessionManagementNode(pool), - rndName(pool, *name) + traps(0u) { } @@ -1595,15 +1617,17 @@ public: { SessionManagementNode::internalPrint(printer); - NODE_PRINT(printer, rndName); + NODE_PRINT(printer, traps); - return "SetRoundNode"; + return "SetTrapsNode"; } virtual void execute(thread_db* tdbb, dsql_req* request) const; + void trap(Firebird::MetaName* name); + public: - Firebird::MetaName rndName; + USHORT traps; }; diff --git a/src/dsql/parse.y b/src/dsql/parse.y index 7ad720b22b..38a5bc526e 100644 --- a/src/dsql/parse.y +++ b/src/dsql/parse.y @@ -611,6 +611,7 @@ using namespace Firebird; %token SQL %token SYSTEM %token TIES +%token TRAPS %token UNBOUNDED %token VARBINARY %token WINDOW @@ -756,8 +757,9 @@ using namespace Firebird; Jrd::MappingNode* mappingNode; Jrd::MappingNode::OP mappingOp; Jrd::SetRoleNode* setRoleNode; - Jrd::SetRoundNode* setRoundNode; Jrd::CreateAlterRoleNode* createAlterRoleNode; + Jrd::SetRoundNode* setRoundNode; + Jrd::SetTrapsNode* setTrapsNode; } %include types.y @@ -816,7 +818,7 @@ tra_statement %type mng_statement mng_statement : set_round { $$ = $1; } -// | set_traps { $$ = $1; } + | set_traps { $$ = $1; } | set_role { $$ = $1; } ; @@ -5024,6 +5026,32 @@ set_round { $$ = newNode($4); } ; +%type set_traps +set_traps + : SET DECFLOAT TRAPS TO + { $$ = newNode(); } + traps_list_opt($5) + { $$ = $5; } + ; + +%type traps_list_opt() +traps_list_opt($setTrapsNode) + : // nothing + | traps_list($setTrapsNode) + ; + +%type traps_list() +traps_list($setTrapsNode) + : trap($setTrapsNode) + | traps_list ',' trap($setTrapsNode) + ; + +%type trap() +trap($setTrapsNode) + : valid_symbol_name + { $setTrapsNode->trap($1); } + ; + %type tran_option_list_opt() tran_option_list_opt($setTransactionNode) : // nothing @@ -8280,6 +8308,7 @@ non_reserved_word | SQL | SYSTEM | TIES + | TRAPS ; %% diff --git a/src/yvalve/keywords.cpp b/src/yvalve/keywords.cpp index b21be7b692..e24f2f88bd 100644 --- a/src/yvalve/keywords.cpp +++ b/src/yvalve/keywords.cpp @@ -440,6 +440,7 @@ static const TOK tokens[] = {TOK_TO, "TO", false}, {TOK_TRAILING, "TRAILING", false}, {TOK_TRANSACTION, "TRANSACTION", true}, + {TOK_TRAPS, "TRAPS", true}, {TOK_TRIGGER, "TRIGGER", false}, {TOK_TRIM, "TRIM", false}, {TOK_TRUE, "TRUE", false},