From 0cdc55f5ed881436c49d313b6cead244bdcf0654 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Fri, 5 Jun 2020 19:27:29 +0200 Subject: [PATCH] d: Merge upstream dmd f5638c7b8. Adds a CHECKENABLE enum, uses it for all contract parameters for consistency in state checking. gcc/d/ChangeLog: * dmd/MERGE: Merge upstream dmd f5638c7b8. * d-builtins.cc (d_init_versions): Use new CHECKENABLE enum. * d-codegen.cc (array_bounds_check): Likewise. (build_frame_type): Likewise. (get_frameinfo): Likewise. * d-lang.cc (d_init_options): Likewise. (d_init_options_struct): Don't initialize x_flag_bounds_check. (d_handle_option): Use new CHECKENABLE enum. (d_post_options): Likewise. Set flag_bounds_check here. * expr.cc (ExprVisitor::visit(AssertExp *)): Use new CHECKENABLE enum. --- gcc/d/d-builtins.cc | 4 +- gcc/d/d-codegen.cc | 14 +++---- gcc/d/d-lang.cc | 83 ++++++++++++++++++++++----------------- gcc/d/dmd/MERGE | 2 +- gcc/d/dmd/expressionsem.c | 2 +- gcc/d/dmd/func.c | 18 ++++----- gcc/d/dmd/globals.h | 25 ++++++------ gcc/d/dmd/statementsem.c | 4 +- gcc/d/expr.cc | 6 +-- 9 files changed, 87 insertions(+), 71 deletions(-) diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc index cbc74558106..bd7e3eb15d7 100644 --- a/gcc/d/d-builtins.cc +++ b/gcc/d/d-builtins.cc @@ -472,10 +472,10 @@ d_init_versions (void) if (global.params.useUnitTests) VersionCondition::addPredefinedGlobalIdent ("unittest"); - if (global.params.useAssert) + if (global.params.useAssert == CHECKENABLEon) VersionCondition::addPredefinedGlobalIdent ("assert"); - if (global.params.useArrayBounds == BOUNDSCHECKoff) + if (global.params.useArrayBounds == CHECKENABLEoff) VersionCondition::addPredefinedGlobalIdent ("D_NoBoundsChecks"); if (global.params.betterC) diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index cf98d4be7e9..301793f1b74 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -1749,13 +1749,13 @@ array_bounds_check (void) switch (global.params.useArrayBounds) { - case BOUNDSCHECKoff: + case CHECKENABLEoff: return false; - case BOUNDSCHECKon: + case CHECKENABLEon: return true; - case BOUNDSCHECKsafeonly: + case CHECKENABLEsafeonly: /* For D2 safe functions only. */ fd = d_function_chain->function; if (fd && fd->type->ty == Tfunction) @@ -2376,8 +2376,8 @@ build_frame_type (tree ffi, FuncDeclaration *fd) of the calling function non-locally. So we add all parameters with nested refs to the function frame, this should also mean overriding methods will have the same frame layout when inheriting a contract. */ - if ((global.params.useIn && fd->frequire) - || (global.params.useOut && fd->fensure)) + if ((global.params.useIn == CHECKENABLEon && fd->frequire) + || (global.params.useOut == CHECKENABLEon && fd->fensure)) { if (fd->parameters) { @@ -2563,8 +2563,8 @@ get_frameinfo (FuncDeclaration *fd) /* In checkNestedReference, references from contracts are not added to the closureVars array, so assume all parameters referenced. */ - if ((global.params.useIn && fd->frequire) - || (global.params.useOut && fd->fensure)) + if ((global.params.useIn == CHECKENABLEon && fd->frequire) + || (global.params.useOut == CHECKENABLEon && fd->fensure)) FRAMEINFO_CREATES_FRAME (ffi) = 1; /* If however `fd` is nested (deeply) in a function that creates a diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index 51a87a01813..203039e9ecf 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -279,12 +279,12 @@ d_init_options (unsigned int, cl_decoded_option *decoded_options) global.vendor = lang_hooks.name; global.params.argv0 = xstrdup (decoded_options[0].arg); global.params.link = true; - global.params.useAssert = true; - global.params.useInvariants = true; - global.params.useIn = true; - global.params.useOut = true; - global.params.useArrayBounds = BOUNDSCHECKdefault; - global.params.useSwitchError = true; + global.params.useAssert = CHECKENABLEdefault; + global.params.useInvariants = CHECKENABLEdefault; + global.params.useIn = CHECKENABLEdefault; + global.params.useOut = CHECKENABLEdefault; + global.params.useArrayBounds = CHECKENABLEdefault; + global.params.useSwitchError = CHECKENABLEdefault; global.params.useModuleInfo = true; global.params.useTypeInfo = true; global.params.useExceptions = true; @@ -339,9 +339,6 @@ d_init_options_struct (gcc_options *opts) opts->x_flag_errno_math = 0; opts->frontend_set_flag_errno_math = true; - /* Keep in sync with existing -fbounds-check flag. */ - opts->x_flag_bounds_check = global.params.useArrayBounds; - /* D says that signed overflow is precisely defined. */ opts->x_flag_wrapv = 1; } @@ -424,17 +421,16 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, break; case OPT_fassert: - global.params.useAssert = value; + global.params.useAssert = value ? CHECKENABLEon : CHECKENABLEoff; break; case OPT_fbounds_check: - global.params.useArrayBounds = value - ? BOUNDSCHECKon : BOUNDSCHECKoff; + global.params.useArrayBounds = value ? CHECKENABLEon : CHECKENABLEoff; break; case OPT_fbounds_check_: - global.params.useArrayBounds = (value == 2) ? BOUNDSCHECKon - : (value == 1) ? BOUNDSCHECKsafeonly : BOUNDSCHECKoff; + global.params.useArrayBounds = (value == 2) ? CHECKENABLEon + : (value == 1) ? CHECKENABLEsafeonly : CHECKENABLEoff; break; case OPT_fdebug: @@ -496,7 +492,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, break; case OPT_finvariants: - global.params.useInvariants = value; + global.params.useInvariants = value ? CHECKENABLEon : CHECKENABLEoff; break; case OPT_fmain: @@ -518,11 +514,11 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, break; case OPT_fpostconditions: - global.params.useOut = value; + global.params.useOut = value ? CHECKENABLEon : CHECKENABLEoff; break; case OPT_fpreconditions: - global.params.useIn = value; + global.params.useIn = value ? CHECKENABLEon : CHECKENABLEoff; break; case OPT_frelease: @@ -534,7 +530,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, break; case OPT_fswitch_errors: - global.params.useSwitchError = value; + global.params.useSwitchError = value ? CHECKENABLEon : CHECKENABLEoff; break; case OPT_ftransition_all: @@ -727,29 +723,46 @@ d_post_options (const char ** fn) *fn = filename; /* Release mode doesn't turn off bounds checking for safe functions. */ - if (global.params.useArrayBounds == BOUNDSCHECKdefault) + if (global.params.useArrayBounds == CHECKENABLEdefault) { global.params.useArrayBounds = global.params.release - ? BOUNDSCHECKsafeonly : BOUNDSCHECKon; - flag_bounds_check = !global.params.release; + ? CHECKENABLEsafeonly : CHECKENABLEon; } - if (global.params.release) + /* Assert code is generated if unittests are being compiled also, even if + release mode is turned on. */ + if (global.params.useAssert == CHECKENABLEdefault) { - if (!global_options_set.x_flag_invariants) - global.params.useInvariants = false; + if (global.params.useUnitTests || !global.params.release) + global.params.useAssert = CHECKENABLEon; + else + global.params.useAssert = CHECKENABLEoff; + } - if (!global_options_set.x_flag_preconditions) - global.params.useIn = false; + /* Checks for switches without a default are turned off in release mode. */ + if (global.params.useSwitchError == CHECKENABLEdefault) + { + global.params.useSwitchError = global.params.release + ? CHECKENABLEoff : CHECKENABLEon; + } - if (!global_options_set.x_flag_postconditions) - global.params.useOut = false; + /* Contracts are turned off in release mode. */ + if (global.params.useInvariants == CHECKENABLEdefault) + { + global.params.useInvariants = global.params.release + ? CHECKENABLEoff : CHECKENABLEon; + } - if (!global_options_set.x_flag_assert) - global.params.useAssert = false; + if (global.params.useIn == CHECKENABLEdefault) + { + global.params.useIn = global.params.release + ? CHECKENABLEoff : CHECKENABLEon; + } - if (!global_options_set.x_flag_switch_errors) - global.params.useSwitchError = false; + if (global.params.useOut == CHECKENABLEdefault) + { + global.params.useOut = global.params.release + ? CHECKENABLEoff : CHECKENABLEon; } if (global.params.betterC) @@ -766,6 +779,9 @@ d_post_options (const char ** fn) global.params.checkAction = CHECKACTION_halt; } + /* Keep in sync with existing -fbounds-check flag. */ + flag_bounds_check = (global.params.useArrayBounds == CHECKENABLEon); + /* Turn off partitioning unless it was explicitly requested, as it doesn't work with D exception chaining, where EH handler uses LSDA to determine whether two thrown exception are in the same context. */ @@ -784,9 +800,6 @@ d_post_options (const char ** fn) if (flag_excess_precision == EXCESS_PRECISION_DEFAULT) flag_excess_precision = EXCESS_PRECISION_STANDARD; - if (global.params.useUnitTests) - global.params.useAssert = true; - global.params.symdebug = write_symbols != NO_DEBUG; global.params.useInline = flag_inline_functions; global.params.showColumns = flag_show_column; diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index f413bd17514..3248bf7c982 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -56f0a65c493463633a293d71faf37cdf710041ef +f5638c7b8a6912858a9b51987df6a725e6796dc9 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c index ffcfeb4e6cd..75e4d130564 100644 --- a/gcc/d/dmd/expressionsem.c +++ b/gcc/d/dmd/expressionsem.c @@ -2451,7 +2451,7 @@ public: sc->fieldinit[i] |= CSXhalt; } - if (!global.params.useAssert) + if (global.params.useAssert == CHECKENABLEoff) { Expression *e = new HaltExp(exp->loc); e = semantic(e, sc); diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c index 807565df12b..eb8d5dbf2dd 100644 --- a/gcc/d/dmd/func.c +++ b/gcc/d/dmd/func.c @@ -1668,7 +1668,7 @@ void FuncDeclaration::semantic3(Scope *sc) Scope *scout = NULL; if (needEnsure || addPostInvariant()) { - if ((needEnsure && global.params.useOut) || fpostinv) + if ((needEnsure && global.params.useOut == CHECKENABLEon) || fpostinv) { returnLabel = new LabelDsymbol(Id::returnLabel); } @@ -1915,7 +1915,7 @@ void FuncDeclaration::semantic3(Scope *sc) error("has no return statement, but is expected to return a value of type %s", f->next->toChars()); else error("no return exp; or assert(0); at end of function"); - if (global.params.useAssert && + if (global.params.useAssert == CHECKENABLEon && !global.params.useInline) { /* Add an assert(0, msg); where the missing return @@ -2048,7 +2048,7 @@ void FuncDeclaration::semantic3(Scope *sc) sc2 = sc2->pop(); - if (!global.params.useIn) + if (global.params.useIn == CHECKENABLEoff) freq = NULL; } @@ -2072,7 +2072,7 @@ void FuncDeclaration::semantic3(Scope *sc) sc2 = sc2->pop(); - if (!global.params.useOut) + if (global.params.useOut == CHECKENABLEoff) fens = NULL; } @@ -4135,7 +4135,7 @@ bool FuncDeclaration::addPreInvariant() AggregateDeclaration *ad = isThis(); ClassDeclaration *cd = ad ? ad->isClassDeclaration() : NULL; return (ad && !(cd && cd->isCPPclass()) && - global.params.useInvariants && + global.params.useInvariants == CHECKENABLEon && (protection.kind == PROTprotected || protection.kind == PROTpublic || protection.kind == PROTexport) && !naked); } @@ -4146,7 +4146,7 @@ bool FuncDeclaration::addPostInvariant() ClassDeclaration *cd = ad ? ad->isClassDeclaration() : NULL; return (ad && !(cd && cd->isCPPclass()) && ad->inv && - global.params.useInvariants && + global.params.useInvariants == CHECKENABLEon && (protection.kind == PROTprotected || protection.kind == PROTpublic || protection.kind == PROTexport) && !naked); } @@ -4927,7 +4927,7 @@ bool CtorDeclaration::addPreInvariant() bool CtorDeclaration::addPostInvariant() { - return (isThis() && vthis && global.params.useInvariants); + return (isThis() && vthis && global.params.useInvariants == CHECKENABLEon); } @@ -4995,7 +4995,7 @@ bool PostBlitDeclaration::addPreInvariant() bool PostBlitDeclaration::addPostInvariant() { - return (isThis() && vthis && global.params.useInvariants); + return (isThis() && vthis && global.params.useInvariants == CHECKENABLEon); } bool PostBlitDeclaration::isVirtual() @@ -5067,7 +5067,7 @@ bool DtorDeclaration::overloadInsert(Dsymbol *) bool DtorDeclaration::addPreInvariant() { - return (isThis() && vthis && global.params.useInvariants); + return (isThis() && vthis && global.params.useInvariants == CHECKENABLEon); } bool DtorDeclaration::addPostInvariant() diff --git a/gcc/d/dmd/globals.h b/gcc/d/dmd/globals.h index aac4abcd339..be75fc09d2e 100644 --- a/gcc/d/dmd/globals.h +++ b/gcc/d/dmd/globals.h @@ -28,12 +28,13 @@ enum }; // The state of array bounds checking -enum BOUNDSCHECK +typedef unsigned char CHECKENABLE; +enum { - BOUNDSCHECKdefault, // initial value - BOUNDSCHECKoff, // never do bounds checking - BOUNDSCHECKon, // always do bounds checking - BOUNDSCHECKsafeonly // do bounds checking only in @safe functions + CHECKENABLEdefault, // initial value + CHECKENABLEoff, // never do bounds checking + CHECKENABLEon, // always do bounds checking + CHECKENABLEsafeonly // do bounds checking only in @safe functions }; typedef unsigned char CHECKACTION; @@ -105,12 +106,7 @@ struct Param bool hasObjectiveC; // target supports Objective-C bool mscoff; // for Win32: write COFF object files instead of OMF Diagnostic useDeprecated; - bool useAssert; // generate runtime code for assert()'s - bool useInvariants; // generate class invariant checks - bool useIn; // generate precondition checks - bool useOut; // generate postcondition checks bool stackstomp; // add stack stomping code - bool useSwitchError; // check for switches without a default bool useUnitTests; // generate unittest code bool useInline; // inline expand functions bool useDIP25; // implement http://wiki.dlang.org/DIP25 @@ -138,7 +134,14 @@ struct Param CPU cpu; // CPU instruction set to target - BOUNDSCHECK useArrayBounds; // when to generate code for array bounds checks + CHECKENABLE useInvariants; // generate class invariant checks + CHECKENABLE useIn; // generate precondition checks + CHECKENABLE useOut; // generate postcondition checks + CHECKENABLE useArrayBounds; // when to generate code for array bounds checks + CHECKENABLE useAssert; // when to generate code for assert()'s + CHECKENABLE useSwitchError; // check for switches without a default + CHECKENABLE boundscheck; // state of -boundscheck switch + CHECKACTION checkAction; // action to take when bounds, asserts or switch defaults are violated const char *argv0; // program name diff --git a/gcc/d/dmd/statementsem.c b/gcc/d/dmd/statementsem.c index bfcb4b4db9c..cd48d9c03cf 100644 --- a/gcc/d/dmd/statementsem.c +++ b/gcc/d/dmd/statementsem.c @@ -2329,7 +2329,7 @@ public: needswitcherror = true; } - if (!sc->sw->sdefault && (!ss->isFinal || needswitcherror || global.params.useAssert)) + if (!sc->sw->sdefault && (!ss->isFinal || needswitcherror || global.params.useAssert == CHECKENABLEon)) { ss->hasNoDefault = 1; @@ -2341,7 +2341,7 @@ public: CompoundStatement *cs; Statement *s; - if (global.params.useSwitchError && + if (global.params.useSwitchError == CHECKENABLEon && global.params.checkAction != CHECKACTION_halt) { if (global.params.checkAction == CHECKACTION_C) diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 461124f704e..562e35a0f7c 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -1980,7 +1980,7 @@ public: tree assert_pass = void_node; tree assert_fail; - if (global.params.useAssert + if (global.params.useAssert == CHECKENABLEon && global.params.checkAction == CHECKACTION_D) { /* Generate: ((bool) e1 ? (void)0 : _d_assert (...)) @@ -1999,7 +1999,7 @@ public: /* Build a call to _d_assert(). */ assert_fail = d_assert_call (e->loc, libcall, tmsg); - if (global.params.useInvariants) + if (global.params.useInvariants == CHECKENABLEon) { /* If the condition is a D class or struct object with an invariant, call it if the condition result is true. */ @@ -2025,7 +2025,7 @@ public: } } } - else if (global.params.useAssert + else if (global.params.useAssert == CHECKENABLEon && global.params.checkAction == CHECKACTION_C) { /* Generate: __builtin_trap() */ -- 2.30.2