Index: generic/tclBasic.c ================================================================== --- generic/tclBasic.c +++ generic/tclBasic.c @@ -4617,11 +4617,12 @@ TCL_DTRACE_CMD_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); } if (TCL_DTRACE_CMD_INFO_ENABLED() && iPtr->cmdFramePtr) { Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr); - const char *a[6]; Tcl_Size i[2]; + const char *a[6]; + Tcl_Size i[2]; TclDTraceInfo(info, a, i); TCL_DTRACE_CMD_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]); TclDecrRefCount(info); } @@ -6545,11 +6546,11 @@ if (Tcl_InitBignumFromDouble(interp, d, &big) != TCL_OK) { return TCL_ERROR; } resultPtr = Tcl_NewBignumObj(&big); } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case TCL_NUMBER_INT: case TCL_NUMBER_BIG: result = TclGetLongFromObj(interp, resultPtr, ptr); break; @@ -9611,11 +9612,11 @@ "wrong coro nargs; how did we get here? " "not implemented!", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL); return TCL_ERROR; } - /* fallthrough */ + TCL_FALLTHROUGH(); case COROUTINE_ARGUMENTS_ARBITRARY: if (objc > 1) { Tcl_SetObjResult(interp, Tcl_NewListObj(objc - 1, objv + 1)); } break; Index: generic/tclBinary.c ================================================================== --- generic/tclBinary.c +++ generic/tclBinary.c @@ -2500,10 +2500,12 @@ } switch (index) { case OPT_STRICT: strict = 1; break; + default: + TCL_UNREACHABLE(); } } TclNewObj(resultObj); data = Tcl_GetBytesFromObj(NULL, objv[objc - 1], &count); @@ -2644,10 +2646,12 @@ if (wrapchar == NULL) { purewrap = 0; wrapchar = TclGetStringFromObj(objv[i + 1], &wrapcharlen); } break; + default: + TCL_UNREACHABLE(); } } if (wrapcharlen == 0) { maxlen = 0; } @@ -2768,40 +2772,40 @@ lineLength = ((lineLength - 1) & -4) + 1; /* 5, 9, 13 ... */ break; case OPT_WRAPCHAR: wrapchar = (const unsigned char *)TclGetStringFromObj( objv[i + 1], &wrapcharlen); - { - const unsigned char *p = wrapchar; - Tcl_Size numBytes = wrapcharlen; - - while (numBytes) { - switch (*p) { - case '\t': - case '\v': - case '\f': - case '\r': - p++; numBytes--; - continue; - case '\n': - numBytes--; - break; - default: - badwrap: - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "invalid wrapchar; will defeat decoding", - -1)); - Tcl_SetErrorCode(interp, "TCL", "BINARY", - "ENCODE", "WRAPCHAR", (char *)NULL); - return TCL_ERROR; - } - } - if (numBytes) { + const unsigned char *p = wrapchar; + Tcl_Size numBytes = wrapcharlen; + + while (numBytes) { + switch (*p) { + case '\t': + case '\v': + case '\f': + case '\r': + p++; + numBytes--; + continue; + case '\n': + numBytes--; + break; + default: goto badwrap; } } + if (numBytes) { + badwrap: + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "invalid wrapchar; will defeat decoding", -1)); + Tcl_SetErrorCode(interp, "TCL", "BINARY", + "ENCODE", "WRAPCHAR", (char *)NULL); + return TCL_ERROR; + } break; + default: + TCL_UNREACHABLE(); } } /* * Allocate the buffer. This is a little bit too long, but is "good @@ -2904,10 +2908,12 @@ } switch (index) { case OPT_STRICT: strict = 1; break; + default: + TCL_UNREACHABLE(); } } TclNewObj(resultObj); data = Tcl_GetBytesFromObj(NULL, objv[objc - 1], &count); @@ -3079,10 +3085,12 @@ } switch (index) { case OPT_STRICT: strict = 1; break; + default: + TCL_UNREACHABLE(); } } TclNewObj(resultObj); data = Tcl_GetBytesFromObj(NULL, objv[objc - 1], &count); Index: generic/tclClock.c ================================================================== --- generic/tclClock.c +++ generic/tclClock.c @@ -1152,10 +1152,12 @@ if (Tcl_SetEnsembleFlags(interp, token, ensFlags) != TCL_OK) { return TCL_ERROR; } break; } + default: + TCL_UNREACHABLE(); } } return TCL_OK; } @@ -3157,10 +3159,12 @@ #endif break; case CLICKS_MICROS: clicks = TclpGetMicroseconds(); break; + default: + TCL_UNREACHABLE(); } Tcl_SetObjResult(interp, Tcl_NewWideIntObj(clicks)); return TCL_OK; } @@ -3369,10 +3373,12 @@ } else { opts->flags &= ~CLF_VALIDATE; } } break; + default: + TCL_UNREACHABLE(); } saw |= 1 << optionIndex; } /* @@ -3429,12 +3435,12 @@ if (TclHasInternalRep(baseObj, &tclBignumType)) { goto baseOverflow; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad seconds \"%s\": must be now or integer", - TclGetString(baseObj))); + "bad seconds \"%s\": must be now or integer", + TclGetString(baseObj))); i = baseIdx; goto badOption; } /* * Seconds could be an unsigned number that overflowed. Make sure @@ -3622,11 +3628,12 @@ if (ret != TCL_OK) { goto done; } /* seconds are in localSeconds (relative base date), so reset time here */ - yyHour = yyMinutes = yySeconds = yySecondOfDay = 0; yyMeridian = MER24; + yyHour = yyMinutes = yySeconds = yySecondOfDay = 0; + yyMeridian = MER24; /* If free scan */ if (opts.formatObj == NULL) { /* Use compiled version of FreeScan - */ @@ -4535,10 +4542,12 @@ yyRelSeconds += offs * 60; break; case CLC_ADD_SECONDS: yyRelSeconds += offs; break; + default: + TCL_UNREACHABLE(); } if (unitIndex < CLC_ADD_HOURS) { /* date units only */ info->flags |= CLF_RELCONV; } } Index: generic/tclClockFmt.c ================================================================== --- generic/tclClockFmt.c +++ generic/tclClockFmt.c @@ -1025,11 +1025,11 @@ static const char * FindTokenBegin( const char *p, const char *end, - ClockScanToken *tok, + const ClockScanToken *tok, int flags) { if (p < end) { char c; @@ -1038,35 +1038,45 @@ case CTOKT_INT: case CTOKT_WIDE: if (!(flags & CLF_STRICT)) { /* should match at least one digit or space */ while (!isdigit(UCHAR(*p)) && !isspace(UCHAR(*p)) && - (p = Tcl_UtfNext(p)) < end) {} + (p = Tcl_UtfNext(p)) < end) { + // Empty + } } else { /* should match at least one digit */ - while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {} + while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) { + // Empty + } } return p; case CTOKT_WORD: c = *(tok->tokWord.start); goto findChar; case CTOKT_SPACE: - while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {} + while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) { + // Empty + } return p; case CTOKT_CHAR: c = *((char *)tok->map->data); -findChar: + findChar: if (!(flags & CLF_STRICT)) { /* should match the char or space */ while (*p != c && !isspace(UCHAR(*p)) && - (p = Tcl_UtfNext(p)) < end) {} + (p = Tcl_UtfNext(p)) < end) { + // Empty + } } else { /* should match the char */ - while (*p != c && (p = Tcl_UtfNext(p)) < end) {} + while (*p != c && (p = Tcl_UtfNext(p)) < end) { + // Empty + } } return p; } } return p; @@ -1090,11 +1100,11 @@ static void DetermineGreedySearchLen( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok, + const ClockScanToken *tok, int *minLenPtr, int *maxLenPtr) { int minLen = tok->map->minSize; int maxLen; @@ -1142,11 +1152,11 @@ } /* try to get max length more precise for greedy match, * check the next ahead token available there */ if (minLen < maxLen && tok->lookAhTok) { - ClockScanToken *laTok = tok + tok->lookAhTok + 1; + const ClockScanToken *laTok = tok + tok->lookAhTok + 1; p = yyInput + maxLen; /* regards all possible spaces here (because they are optional) */ end = p + tok->lookAhMax + yySpaceCount + 1; if (end > info->dateEnd) { @@ -1156,11 +1166,11 @@ if (laTok->map && p < end) { /* try to find laTok between [lookAhMin, lookAhMax] */ while (minLen < maxLen) { const char *f = FindTokenBegin(p, end, laTok, - TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT); + TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT); /* if found (not below lookAhMax) */ if (f < end) { break; } /* try again with fewer length */ @@ -1492,11 +1502,11 @@ } #endif static inline const char * FindWordEnd( - ClockScanToken *tok, + const ClockScanToken *tok, const char *p, const char *end) { const char *x = tok->tokWord.start; const char *pfnd = p; @@ -1517,11 +1527,11 @@ static int ClockScnToken_Month_Proc( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok) + const ClockScanToken *tok) { #if 0 /* currently unused, test purposes only */ static const char * months[] = { /* full */ @@ -1567,11 +1577,11 @@ static int ClockScnToken_DayOfWeek_Proc( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok) + const ClockScanToken *tok) { static int dowKeys[] = {MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_FULL, 0}; int ret, val; int minLen, maxLen; @@ -1641,11 +1651,11 @@ static int ClockScnToken_amPmInd_Proc( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok) + const ClockScanToken *tok) { int ret, val; int minLen, maxLen; Tcl_Obj *amPmObj[2]; @@ -1674,11 +1684,11 @@ static int ClockScnToken_LocaleERA_Proc( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok) + const ClockScanToken *tok) { ClockClientData *dataPtr = opts->dataPtr; int ret, val; int minLen, maxLen; @@ -1713,11 +1723,11 @@ static int ClockScnToken_LocaleListMatcher_Proc( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok) + const ClockScanToken *tok) { int ret, val; int minLen, maxLen; TclStrIdxTree *idxTree; @@ -1744,11 +1754,11 @@ static int ClockScnToken_JDN_Proc( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok) + const ClockScanToken *tok) { int minLen, maxLen; const char *p = yyInput, *end, *s; Tcl_WideInt intJD; int fractJD = 0, fractJDDiv = 1; @@ -1815,11 +1825,11 @@ static int ClockScnToken_TimeZone_Proc( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok) + const ClockScanToken *tok) { int minLen, maxLen; int len = 0; const char *p = yyInput; Tcl_Obj *tzObjStor = NULL; @@ -1907,11 +1917,11 @@ static int ClockScnToken_StarDate_Proc( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok) + const ClockScanToken *tok) { int minLen, maxLen; const char *p = yyInput, *end, *s; int year, fractYear, fractDayDiv, fractDay; static const char *stardatePref = "stardate "; @@ -2301,36 +2311,35 @@ /* next token */ AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++; continue; } - word_tok: - { - /* try continue with previous word token */ - ClockScanToken *wordTok = tok - 1; - - if (wordTok < scnTok || wordTok->map != &ScnWordTokenMap) { - /* start with new word token */ - wordTok = tok; - wordTok->tokWord.start = p; - wordTok->map = &ScnWordTokenMap; - } - - do { - if (isspace(UCHAR(*p))) { - fss->scnSpaceCount++; - } - p = Tcl_UtfNext(p); - } while (p < e && *p != '%'); - wordTok->tokWord.end = p; - - if (wordTok == tok) { - AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); - tokCnt++; - } + word_tok: { + /* try continue with previous word token */ + ClockScanToken *wordTok = tok - 1; + + if (wordTok < scnTok || wordTok->map != &ScnWordTokenMap) { + /* start with new word token */ + wordTok = tok; + wordTok->tokWord.start = p; + wordTok->map = &ScnWordTokenMap; + } + + do { + if (isspace(UCHAR(*p))) { + fss->scnSpaceCount++; + } + p = Tcl_UtfNext(p); + } while (p < e && *p != '%'); + wordTok->tokWord.end = p; + + if (wordTok == tok) { + AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); + tokCnt++; } break; + } } } /* calculate end distance value for each tokens */ if (tok > scnTok) { @@ -2374,12 +2383,12 @@ DateInfo *info, /* Date fields used for parsing & converting */ Tcl_Obj *strObj, /* String containing the time to scan */ ClockFmtScnCmdArgs *opts) /* Command options */ { ClockClientData *dataPtr = opts->dataPtr; - ClockFmtScnStorage *fss; - ClockScanToken *tok; + const ClockFmtScnStorage *fss; + const ClockScanToken *tok; const ClockScanTokenMap *map; const char *p, *x, *end; unsigned short flags = 0; int ret = TCL_ERROR; @@ -2555,10 +2564,12 @@ if (isspace(UCHAR(*x))) { yySpaceCount--; } p++; break; + default: + TCL_UNREACHABLE(); } } /* check end was reached */ if (p < end) { /* in non-strict mode bypass spaces at end of input */ @@ -2603,11 +2614,11 @@ /* dd precedence below ddd */ switch (flags & (CLF_MONTH|CLF_DAYOFYEAR|CLF_DAYOFMONTH)) { case (CLF_DAYOFYEAR | CLF_DAYOFMONTH): /* miss month: ddd over dd (without month) */ flags &= ~CLF_DAYOFMONTH; - /* fallthrough */ + TCL_FALLTHROUGH(); case CLF_DAYOFYEAR: /* ddd over naked weekday */ if (!(flags & CLF_ISO8601YEAR)) { flags &= ~CLF_ISO8601WEEK; } Index: generic/tclCmdAH.c ================================================================== --- generic/tclCmdAH.c +++ generic/tclCmdAH.c @@ -481,10 +481,12 @@ } break; case FAILINDEX: failVarObj = objv[argIndex]; break; + default: + TCL_UNREACHABLE(); } } /* Get encoding after opts so no need to free it on option error */ if (Tcl_GetEncodingFromObj(interp, objv[objc - 2], &encoding) != TCL_OK) { return TCL_ERROR; @@ -2116,12 +2118,11 @@ break; case TCL_PATH_VOLUME_RELATIVE: TclNewLiteralStringObj(typeName, "volumerelative"); break; default: - /* Should be unreachable */ - return TCL_OK; + TCL_UNREACHABLE(); } Tcl_SetObjResult(interp, typeName); return TCL_OK; } @@ -2923,10 +2924,11 @@ case TCL_ERROR: Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%s\" body line %d)", (statePtr->resultList != NULL ? "lmap" : "foreach"), Tcl_GetErrorLine(interp))); + TCL_FALLTHROUGH(); default: goto done; } /* Index: generic/tclCmdIL.c ================================================================== --- generic/tclCmdIL.c +++ generic/tclCmdIL.c @@ -3350,10 +3350,12 @@ } sortInfo.indexv[j] = encoded; } break; } + default: + TCL_UNREACHABLE(); } } /* * Subindices only make sense if asked for with -index option set. @@ -4124,14 +4126,12 @@ step = numValues[3]; break; case LSEQ_BY: /* Error case */ goto syntax; - break; default: goto syntax; - break; } break; /* lseq n n 'by' n */ case 1121: @@ -4145,11 +4145,10 @@ case LSEQ_DOTS: case LSEQ_TO: case LSEQ_COUNT: default: goto syntax; - break; } break; /* lseq n 'to' n 'by' n */ /* lseq n 'count' n 'by' n */ @@ -4160,11 +4159,10 @@ case LSEQ_BY: step = numValues[4]; break; default: goto syntax; - break; } opmode = (SequenceOperators)values[1]; switch (opmode) { case LSEQ_DOTS: case LSEQ_TO: @@ -4175,20 +4173,18 @@ start = numValues[0]; elementCount = numValues[2]; break; default: goto syntax; - break; } break; /* All other argument errors */ default: syntax: Tcl_WrongNumArgs(interp, 1, objv, "n ??op? n ??by? n??"); goto done; - break; } /* Count needs to be integer, so try to convert if possible */ if (elementCount && TclHasInternalRep(elementCount, &tclDoubleType)) { double d = elementCount->internalRep.doubleValue; @@ -4530,10 +4526,12 @@ } groupSize = wide; group = 1; i++; break; + default: + TCL_UNREACHABLE(); } } if (nocase && (sortInfo.sortMode == SORTMODE_ASCII)) { sortInfo.sortMode = SORTMODE_ASCII_NC; } Index: generic/tclCmdMZ.c ================================================================== --- generic/tclCmdMZ.c +++ generic/tclCmdMZ.c @@ -209,10 +209,12 @@ break; } case REGEXP_LAST: i++; goto endOfForLoop; + default: + TCL_UNREACHABLE(); } } endOfForLoop: if ((objc - i) < (2 - about)) { @@ -564,10 +566,12 @@ break; } case REGSUB_LAST: idx++; goto endOfForLoop; + default: + TCL_UNREACHABLE(); } } endOfForLoop: if (objc < idx + 3 || objc > idx + 4) { @@ -1578,10 +1582,12 @@ "?-strict? ?-failindex var? str"); return TCL_ERROR; } failVarObj = objv[++i]; break; + default: + TCL_UNREACHABLE(); } } } /* @@ -1875,10 +1881,12 @@ chcomp = Tcl_UniCharIsWordChar; break; case STR_IS_XDIGIT: chcomp = UniCharIsHexDigit; break; + default: + TCL_UNREACHABLE(); } if (chcomp != NULL) { string1 = TclGetStringFromObj(objPtr, &length1); if (length1 == 0) { @@ -4184,10 +4192,12 @@ case TMRT_CALIBRATE: calibrate = objv[i]; break; case TMRT_LAST: break; + default: + TCL_UNREACHABLE(); } } if (i >= objc || i < objc - 3) { usage: @@ -4408,11 +4418,11 @@ /* * Force stop immediately. */ threshold = 1; maxcnt = 0; - /* FALLTHRU */ + TCL_FALLTHROUGH(); case TCL_CONTINUE: result = TCL_OK; break; default: goto done; @@ -4497,11 +4507,12 @@ lastIterTm = lastTm > avgIterTm ? lastTm : avgIterTm; } else { lastIterTm = avgIterTm; } estIterTm *= lastIterTm; - last = middle; lastCount = count; + last = middle; + lastCount = count; /* * Calculate next threshold to check. * Firstly check iteration time is not larger than remaining time, * considering last known iteration growth factor. @@ -4834,10 +4845,12 @@ Tcl_ListObjAppendElement(NULL, handlersObj, Tcl_NewListObj(5, info)); haveHandlers = 1; i += 3; break; + default: + TCL_UNREACHABLE(); } } if (bodyShared) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "last non-finally clause must not have a body of \"-\"", -1)); Index: generic/tclCompCmdsGR.c ================================================================== --- generic/tclCompCmdsGR.c +++ generic/tclCompCmdsGR.c @@ -2158,10 +2158,11 @@ /* * The pattern is "**"! I believe that should be impossible, * but we definitely can't handle that at all. */ } + TCL_FALLTHROUGH(); case '\0': case '?': case '[': case '\\': goto done; } bytes++; } Index: generic/tclCompCmdsSZ.c ================================================================== --- generic/tclCompCmdsSZ.c +++ generic/tclCompCmdsSZ.c @@ -2191,11 +2191,11 @@ } else { OP1( STR_MATCH, noCase); } break; default: - Tcl_Panic("unknown switch mode: %d", mode); + TCL_UNREACHABLE(); } /* * In a fall-through case, we will jump on _true_ to the place * where the body starts (generated later, with guarantee of this Index: generic/tclCompile.c ================================================================== --- generic/tclCompile.c +++ generic/tclCompile.c @@ -1492,16 +1492,22 @@ return 0; /* Runtime evals */ case INST_EVAL_STK: case INST_EXPR_STK: case INST_YIELD: + case INST_YIELD_TO_INVOKE: return 0; /* Upvars */ case INST_UPVAR: case INST_NSUPVAR: case INST_VARIABLE: return 0; + /* TclOO::next is NOT a problem: puts stack frame out of way. + * There's a way to do it, but it's beneath the threshold of + * likelihood. */ + case INST_TCLOO_NEXT: + case INST_TCLOO_NEXT_CLASS: default: size = tclInstructionTable[*pc].numBytes; assert (size > 0); break; } @@ -3775,11 +3781,12 @@ { size_t i = envPtr->exceptArrayNext; ExceptionRange *rangePtr = envPtr->exceptArrayPtr + i; while (i > 0) { - rangePtr--; i--; + rangePtr--; + i--; if (CurrentOffset(envPtr) >= rangePtr->codeOffset && (rangePtr->numCodeBytes == TCL_INDEX_NONE || CurrentOffset(envPtr) < rangePtr->codeOffset+rangePtr->numCodeBytes) && (returnCode != TCL_CONTINUE || Index: generic/tclConfig.c ================================================================== --- generic/tclConfig.c +++ generic/tclConfig.c @@ -297,12 +297,11 @@ Tcl_SetObjResult(interp, listPtr); return TCL_OK; default: - Tcl_Panic("QueryConfigObjCmd: Unknown subcommand to 'pkgconfig'. This can't happen"); - break; + TCL_UNREACHABLE(); } return TCL_ERROR; } /* Index: generic/tclDate.h ================================================================== --- generic/tclDate.h +++ generic/tclDate.h @@ -391,11 +391,11 @@ typedef struct ClockScanToken ClockScanToken; typedef int ClockScanTokenProc( ClockFmtScnCmdArgs *opts, DateInfo *info, - ClockScanToken *tok); + const ClockScanToken *tok); typedef enum _CLCKTOK_TYPE { CTOKT_INT = 1, CTOKT_WIDE, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR, CFMTT_PROC } CLCKTOK_TYPE; Index: generic/tclDictObj.c ================================================================== --- generic/tclDictObj.c +++ generic/tclDictObj.c @@ -3422,18 +3422,19 @@ * do. */ Tcl_ResetResult(interp); Tcl_DictObjDone(&search); - /* FALLTHRU */ + TCL_FALLTHROUGH(); case TCL_CONTINUE: result = TCL_OK; break; case TCL_ERROR: Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"dict filter\" script line %d)", Tcl_GetErrorLine(interp))); + TCL_FALLTHROUGH(); default: goto abnormalResult; } TclDecrRefCount(keyObj); @@ -3455,24 +3456,22 @@ Tcl_SetObjResult(interp, resultObj); } else { TclDecrRefCount(resultObj); } return result; - - abnormalResult: - Tcl_DictObjDone(&search); - TclDecrRefCount(keyObj); - TclDecrRefCount(valueObj); - TclDecrRefCount(keyVarObj); - TclDecrRefCount(valueVarObj); - TclDecrRefCount(scriptObj); - TclDecrRefCount(resultObj); - return result; - } - Tcl_Panic("unexpected fallthrough"); - /* Control never reaches this point. */ - return TCL_ERROR; + } + TCL_UNREACHABLE(); + + abnormalResult: + Tcl_DictObjDone(&search); + TclDecrRefCount(keyObj); + TclDecrRefCount(valueObj); + TclDecrRefCount(keyVarObj); + TclDecrRefCount(valueVarObj); + TclDecrRefCount(scriptObj); + TclDecrRefCount(resultObj); + return result; } /* *---------------------------------------------------------------------- * Index: generic/tclDisassemble.c ================================================================== --- generic/tclDisassemble.c +++ generic/tclDisassemble.c @@ -576,37 +576,43 @@ suffixBuffer[0] = '\0'; Tcl_AppendPrintfToObj(bufferObj, "(%u) %s ", pcOffset, instDesc->name); for (i = 0; i < instDesc->numOperands; i++) { switch (instDesc->opTypes[i]) { case OPERAND_INT1: - opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++; + opnd = TclGetInt1AtPtr(pc+numBytes); + numBytes++; Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_INT4: - opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4; + opnd = TclGetInt4AtPtr(pc+numBytes); + numBytes += 4; Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_UINT1: - opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; + opnd = TclGetUInt1AtPtr(pc+numBytes); + numBytes++; Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd); break; case OPERAND_UINT4: - opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; + opnd = TclGetUInt4AtPtr(pc+numBytes); + numBytes += 4; if (opCode == INST_START_CMD) { snprintf(suffixBuffer+strlen(suffixBuffer), sizeof(suffixBuffer) - strlen(suffixBuffer), ", %u cmds start here", opnd); } Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd); break; case OPERAND_OFFSET1: - opnd = TclGetInt1AtPtr(pc+numBytes); numBytes++; + opnd = TclGetInt1AtPtr(pc+numBytes); + numBytes++; snprintf(suffixBuffer, sizeof(suffixBuffer), "pc %u", pcOffset+opnd); Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_OFFSET4: - opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4; + opnd = TclGetInt4AtPtr(pc+numBytes); + numBytes += 4; if (opCode == INST_START_CMD) { snprintf(suffixBuffer, sizeof(suffixBuffer), "next cmd at pc %u", pcOffset+opnd); } else { snprintf(suffixBuffer, sizeof(suffixBuffer), @@ -613,26 +619,30 @@ "pc %u", pcOffset+opnd); } Tcl_AppendPrintfToObj(bufferObj, "%+d ", opnd); break; case OPERAND_LIT1: - opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; + opnd = TclGetUInt1AtPtr(pc+numBytes); + numBytes++; suffixObj = codePtr->objArrayPtr[opnd]; Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd); break; case OPERAND_LIT4: - opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; + opnd = TclGetUInt4AtPtr(pc+numBytes); + numBytes += 4; suffixObj = codePtr->objArrayPtr[opnd]; Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd); break; case OPERAND_AUX4: - opnd = TclGetUInt4AtPtr(pc+numBytes); numBytes += 4; + opnd = TclGetUInt4AtPtr(pc+numBytes); + numBytes += 4; Tcl_AppendPrintfToObj(bufferObj, "%u ", opnd); auxPtr = &codePtr->auxDataArrayPtr[opnd]; break; case OPERAND_IDX4: - opnd = TclGetInt4AtPtr(pc+numBytes); numBytes += 4; + opnd = TclGetInt4AtPtr(pc+numBytes); + numBytes += 4; if (opnd >= -1) { Tcl_AppendPrintfToObj(bufferObj, "%d ", opnd); } else if (opnd == -2) { Tcl_AppendPrintfToObj(bufferObj, "end "); } else { @@ -665,39 +675,43 @@ } } Tcl_AppendPrintfToObj(bufferObj, "%%v%u ", opnd); break; case OPERAND_SCLS1: - opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; + opnd = TclGetUInt1AtPtr(pc+numBytes); + numBytes++; Tcl_AppendPrintfToObj(bufferObj, "%s ", tclStringClassTable[opnd].name); break; case OPERAND_UNSF1: - opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; + opnd = TclGetUInt1AtPtr(pc+numBytes); + numBytes++; Tcl_AppendPrintfToObj(bufferObj, "silent=%s ", opnd?"no":"yes"); break; case OPERAND_CLK1: - opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; + opnd = TclGetUInt1AtPtr(pc+numBytes); + numBytes++; switch (opnd) { - case 0: + case CLOCK_READ_CLICKS: Tcl_AppendPrintfToObj(bufferObj, "clicks " ); break; - case 1: + case CLOCK_READ_MICROS: Tcl_AppendPrintfToObj(bufferObj, "micros " ); break; - case 2: + case CLOCK_READ_MILLIS: Tcl_AppendPrintfToObj(bufferObj, "millis " ); break; - case 3: + case CLOCK_READ_SECS: Tcl_AppendPrintfToObj(bufferObj, "secs " ); break; default: Tcl_Panic("unknown clock type"); } break; case OPERAND_LRPL1: - opnd = TclGetUInt1AtPtr(pc+numBytes); numBytes++; + opnd = TclGetUInt1AtPtr(pc+numBytes); + numBytes++; switch (opnd) { case 0: Tcl_AppendPrintfToObj(bufferObj, "0 "); break; case TCL_LREPLACE4_END_IS_LAST: @@ -1552,14 +1566,14 @@ oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]); if (oPtr == NULL) { return TCL_ERROR; } + ooWhat = objv[3]; if (oPtr->methodsPtr == NULL) { goto unknownMethod; } - ooWhat = objv[3]; hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, ooWhat); /* * Compile (if necessary) and disassemble a method body. */ @@ -1603,11 +1617,11 @@ } } codeObjPtr = procPtr->bodyPtr; break; default: - CLANG_ASSERT(0); + TCL_UNREACHABLE(); } /* * Do the actual disassembly. */ Index: generic/tclEncoding.c ================================================================== --- generic/tclEncoding.c +++ generic/tclEncoding.c @@ -2580,11 +2580,12 @@ ch = UNICODE_REPLACE_CHAR; ++src; } else { /* TCL_ENCODING_PROFILE_TCL8 */ char chbuf[2]; - chbuf[0] = UCHAR(*src++); chbuf[1] = 0; + chbuf[0] = UCHAR(*src++); + chbuf[1] = 0; TclUtfToUniChar(chbuf, &ch); } dst += Tcl_UniCharToUtf(ch, dst); } else { /* Have a complete character */ @@ -3506,11 +3507,12 @@ } if (PROFILE_REPLACE(flags)) { ch = UNICODE_REPLACE_CHAR; } else { char chbuf[2]; - chbuf[0] = byte; chbuf[1] = 0; + chbuf[0] = byte; + chbuf[1] = 0; TclUtfToUniChar(chbuf, &ch); } } /* Index: generic/tclEnsemble.c ================================================================== --- generic/tclEnsemble.c +++ generic/tclEnsemble.c @@ -228,13 +228,12 @@ } else { return SetEnsembleConfigOptions(interp, token, objc - 3, objv + 3); } default: - Tcl_Panic("unexpected ensemble command"); + TCL_UNREACHABLE(); } - return TCL_OK; } /* *---------------------------------------------------------------------- * @@ -385,10 +384,12 @@ if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { goto error; } unknownObj = (len > 0 ? objv[1] : NULL); continue; + default: + TCL_UNREACHABLE(); } } TclGetNamespaceForQualName(interp, name, cxtPtr, TCL_CREATE_NS_IF_UNKNOWN, &foundNsPtr, &altFoundNsPtr, @@ -483,10 +484,12 @@ Tcl_GetEnsembleUnknownHandler(NULL, token, &resultObj); if (resultObj != NULL) { Tcl_SetObjResult(interp, resultObj); } break; + default: + TCL_UNREACHABLE(); } return TCL_OK; } /* *---------------------------------------------------------------------- @@ -713,10 +716,12 @@ if (TclListObjLength(interp, objv[1], &len) != TCL_OK) { goto freeMapAndError; } unknownObj = (len > 0 ? objv[1] : NULL); continue; + default: + TCL_UNREACHABLE(); } } /* * Update the namespace now that we've finished the parsing stage. Index: generic/tclEvent.c ================================================================== --- generic/tclEvent.c +++ generic/tclEvent.c @@ -1648,10 +1648,12 @@ vwaitItems[numItems].sequence = -1; vwaitItems[numItems].mask = TCL_WRITABLE; vwaitItems[numItems].sourceObj = objv[i]; numItems++; break; + default: + TCL_UNREACHABLE(); } } endOfOptionLoop: if ((mask & (TCL_FILE_EVENTS | TCL_IDLE_EVENTS | @@ -1965,11 +1967,11 @@ switch (optionIndex) { case OPT_IDLETASKS: flags = TCL_IDLE_EVENTS|TCL_DONT_WAIT; break; default: - Tcl_Panic("Tcl_UpdateObjCmd: bad option index to UpdateOptions"); + TCL_UNREACHABLE(); } } else { Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?"); return TCL_ERROR; } Index: generic/tclExecute.c ================================================================== --- generic/tclExecute.c +++ generic/tclExecute.c @@ -24,10 +24,16 @@ #include "tclOOInt.h" #include "tclTomMath.h" #include #include +#if defined(__GNUC__) && (__GNUC__ > 4) && defined(_WIN32) && defined(TCL_COMPILE_DEBUG) +// These are FAR too noisy when we're using the MSVC runtime. +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wformat-extra-args" +#endif + /* * Hack to determine whether we may expect IEEE floating point. The hack is * formally incorrect in that non-IEEE platforms might have the same precision * and range, but VAX, IBM, and Cray do not; are there any other floating * point units that we might care about? @@ -116,10 +122,13 @@ ByteCode *codePtr; /* Constant until the BC returns */ /* -----------------------------------------*/ Tcl_Obj **catchTop; /* These fields are used on return TO this */ Tcl_Obj *auxObjList; /* level: they record the state when a new */ CmdFrame cmdFrame; /* codePtr was received for NR execution. */ +#ifdef TCL_COMPILE_DEBUG + char cmdNameBuf[21]; /* Space to store the command name across an invoke. */ +#endif Tcl_Obj *stack[1]; /* Start of the actual combined catch and obj * stacks; the struct will be expanded as * necessary */ } TEBCdata; @@ -197,11 +206,11 @@ /*checkStack*/ !(starting || auxObjList)); \ starting = 0; \ } while (0) #else #define CHECK_STACK() -#endif +#endif // TCL_COMPILE_DEBUG #define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \ do { \ TCL_CT_ASSERT((nCleanup >= 0) && (nCleanup <= 2)); \ CHECK_STACK(); \ @@ -221,18 +230,18 @@ } \ pc += (pcAdjustment); \ switch (nCleanup) { \ case 1: goto cleanup1_pushObjResultPtr; \ case 2: goto cleanup2_pushObjResultPtr; \ - case 0: break; \ + default: TCL_UNREACHABLE(); \ } \ } else { \ pc += (pcAdjustment); \ switch (nCleanup) { \ case 1: goto cleanup1; \ case 2: goto cleanup2; \ - case 0: break; \ + default: TCL_UNREACHABLE(); \ } \ } \ } while (0) /* Cut down version of NEXT_INST_F() for resultHandling==0 case. */ @@ -243,11 +252,11 @@ pc += (pcAdjustment); \ switch (nCleanup) { \ case 0: goto cleanup0; \ case 1: goto cleanup1; \ case 2: goto cleanup2; \ - default: Tcl_Panic("should be unreachable"); \ + default: TCL_UNREACHABLE(); \ } \ } while (0) #define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \ CHECK_STACK(); \ @@ -260,10 +269,11 @@ } \ goto cleanupV_pushObjResultPtr; \ } else { \ goto cleanupV; \ } \ + TCL_UNREACHABLE(); \ } while (0) #ifndef TCL_COMPILE_DEBUG #ifndef REMOVE_DEPRECATED_OPCODES #define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \ @@ -270,118 +280,108 @@ do { \ pc += (pcAdjustment); \ switch (*pc) { \ case INST_JUMP_FALSE1: \ NEXT_INST_F0(((condition)? 2 : TclGetInt1AtPtr(pc + 1)), (cleanup)); \ - break; \ case INST_JUMP_TRUE1: \ NEXT_INST_F0(((condition)? TclGetInt1AtPtr(pc + 1) : 2), (cleanup)); \ - break; \ case INST_JUMP_FALSE: \ NEXT_INST_F0(((condition)? 5 : TclGetInt4AtPtr(pc + 1)), (cleanup)); \ - break; \ case INST_JUMP_TRUE: \ NEXT_INST_F0(((condition)? TclGetInt4AtPtr(pc + 1) : 5), (cleanup)); \ - break; \ default: \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_F(0, (cleanup), 1); \ - break; \ } \ + TCL_UNREACHABLE(); \ } while (0) #define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \ do { \ pc += (pcAdjustment); \ switch (*pc) { \ case INST_JUMP_FALSE1: \ NEXT_INST_V(((condition)? 2 : TclGetInt1AtPtr(pc + 1)), (cleanup), 0); \ - break; \ case INST_JUMP_TRUE1: \ NEXT_INST_V(((condition)? TclGetInt1AtPtr(pc + 1) : 2), (cleanup), 0); \ - break; \ case INST_JUMP_FALSE: \ NEXT_INST_V(((condition)? 5 : TclGetInt4AtPtr(pc + 1)), (cleanup), 0); \ - break; \ case INST_JUMP_TRUE: \ NEXT_INST_V(((condition)? TclGetInt4AtPtr(pc + 1) : 5), (cleanup), 0); \ - break; \ default: \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_V(0, (cleanup), 1); \ - break; \ } \ + TCL_UNREACHABLE(); \ } while (0) -#else +#else // REMOVE_DEPRECATED_OPCODES #define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \ do { \ pc += (pcAdjustment); \ switch (*pc) { \ case INST_JUMP_FALSE: \ NEXT_INST_F0(((condition)? 5 : TclGetInt4AtPtr(pc + 1)), (cleanup)); \ - break; \ case INST_JUMP_TRUE: \ NEXT_INST_F0(((condition)? TclGetInt4AtPtr(pc + 1) : 5), (cleanup)); \ - break; \ default: \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_F(0, (cleanup), 1); \ - break; \ } \ + TCL_UNREACHABLE(); \ } while (0) #define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \ do { \ pc += (pcAdjustment); \ switch (*pc) { \ case INST_JUMP_FALSE: \ NEXT_INST_V(((condition)? 5 : TclGetInt4AtPtr(pc + 1)), (cleanup), 0); \ - break; \ case INST_JUMP_TRUE: \ NEXT_INST_V(((condition)? TclGetInt4AtPtr(pc + 1) : 5), (cleanup), 0); \ - break; \ default: \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_V(0, (cleanup), 1); \ - break; \ } \ + TCL_UNREACHABLE(); \ } while (0) -#endif -#else /* TCL_COMPILE_DEBUG */ +#endif // REMOVE_DEPRECATED_OPCODES +#else // TCL_COMPILE_DEBUG #define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \ do{ \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_F((pcAdjustment), (cleanup), 1); \ + TCL_UNREACHABLE(); \ } while (0) #define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \ do{ \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_V((pcAdjustment), (cleanup), 1); \ + TCL_UNREACHABLE(); \ } while (0) -#endif +#endif // TCL_COMPILE_DEBUG /* * Macros used to cache often-referenced Tcl evaluation stack information * in local variables. Note that a DECACHE_STACK_INFO()-CACHE_STACK_INFO() * pair must surround any call inside TclNRExecuteByteCode (and a few other @@ -470,28 +470,28 @@ (objPtr ? TclGetString(objPtr) : "") # define TRACE_APPEND_OBJ(objPtr) \ TRACE_APPEND(("\"%.30s\"\n", O2S(objPtr))) # define TRACE_APPEND_NUM_OBJ(objPtr) \ TRACE_APPEND(("%.30s\n", O2S(objPtr))) -#else /* !TCL_COMPILE_DEBUG */ +#else // !TCL_COMPILE_DEBUG # define TRACE(a) # define TRACE_APPEND(a) # define TRACE_ERROR(interp) # define TRACE_WITH_OBJ(a, objPtr) # define O2S(objPtr) # define TRACE_APPEND_OBJ(objPtr) # define TRACE_APPEND_NUM_OBJ(objPtr) -#endif /* TCL_COMPILE_DEBUG */ +#endif // TCL_COMPILE_DEBUG #ifndef REMOVE_DEPRECATED_OPCODES #ifdef PANIC_ON_DEPRECATED_OPCODES #define DEPRECATED_OPCODE_MARK(opcode) \ Tcl_Panic("%s deprecated for removal", #name) #else #define DEPRECATED_OPCODE_MARK(opcode) /* Do nothing. */ #endif -#endif +#endif // REMOVE_DEPRECATED_OPCODES /* * DTrace instruction probe macros. */ @@ -563,11 +563,11 @@ #ifndef ACCEPT_NAN #define IsErroringNaNType(type) ((type) == TCL_NUMBER_NAN) #else #define IsErroringNaNType(type) 0 -#endif +#endif // ACCEPT_NAN /* * Auxiliary tables used to compute powers of small integers. */ @@ -775,27 +775,23 @@ static void ReleaseDictIterator( Tcl_Obj *objPtr) { - Tcl_DictSearch *searchPtr; - Tcl_Obj *dictPtr; - const Tcl_ObjInternalRep *irPtr; - - irPtr = TclFetchInternalRep(objPtr, &dictIteratorType); + const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &dictIteratorType); assert(irPtr != NULL); /* * First kill the search, and then release the reference to the dictionary * that we were holding. */ - searchPtr = (Tcl_DictSearch *)irPtr->twoPtrValue.ptr1; + Tcl_DictSearch *searchPtr = (Tcl_DictSearch *)irPtr->twoPtrValue.ptr1; Tcl_DictObjDone(searchPtr); Tcl_Free(searchPtr); - dictPtr = (Tcl_Obj *)irPtr->twoPtrValue.ptr2; + Tcl_Obj *dictPtr = (Tcl_Obj *)irPtr->twoPtrValue.ptr2; TclDecrRefCount(dictPtr); } /* *---------------------------------------------------------------------- @@ -942,11 +938,11 @@ TclDeleteExecEnv( ExecEnv *eePtr) /* Execution environment to free. */ { ExecStack *esPtr = eePtr->execStackPtr, *tmpPtr; - cachedInExit = TclInExit(); + cachedInExit = TclInExit(); /* * Delete all stacks in this exec env. */ @@ -1069,12 +1065,12 @@ Tcl_Panic("STACK: Reallocating with no previous alloc"); } if (needed <= 0) { return MEMSTART(markerPtr); } - } else { #ifndef PURIFY + } else { Tcl_Obj **tmpMarkerPtr = esPtr->tosPtr + 1; int offset = wordSkip(tmpMarkerPtr); if (needed + offset < 0) { /* @@ -1087,11 +1083,11 @@ memStart = tmpMarkerPtr + offset; esPtr->tosPtr = memStart - 1; *esPtr->markerPtr = (Tcl_Obj *) markerPtr; return memStart; } -#endif +#endif // !PURIFY } /* * Reset move to hold the number of words to be moved to new stack (if * any) and growth to hold the complete stack requirements: add one for @@ -1236,14 +1232,10 @@ TclStackFree( Tcl_Interp *interp, void *freePtr) { Interp *iPtr = (Interp *) interp; - ExecEnv *eePtr; - ExecStack *esPtr; - Tcl_Obj **markerPtr, *marker; - if (iPtr == NULL || iPtr->execEnvPtr == NULL) { Tcl_Free(freePtr); return; } @@ -1251,14 +1243,14 @@ * Rewind the stack to the previous marker position. The current marker, * as set in the last call to GrowEvaluationStack, contains a pointer to * the previous marker. */ - eePtr = iPtr->execEnvPtr; - esPtr = eePtr->execStackPtr; - markerPtr = esPtr->markerPtr; - marker = *markerPtr; + ExecEnv *eePtr = iPtr->execEnvPtr; + ExecStack *esPtr = eePtr->execStackPtr; + Tcl_Obj **markerPtr = esPtr->markerPtr; + Tcl_Obj *marker = *markerPtr; if ((freePtr != NULL) && (MEMSTART(markerPtr) != (Tcl_Obj **)freePtr)) { Tcl_Panic("TclStackFree: incorrect freePtr (%p != %p). Call out of sequence?", freePtr, MEMSTART(markerPtr)); } @@ -1290,11 +1282,11 @@ if (esPtr->prevPtr) { eePtr->execStackPtr = esPtr->prevPtr; #ifdef PURIFY eePtr->execStackPtr->nextPtr = NULL; DeleteExecStack(esPtr); -#endif +#endif // PURIFY } else { eePtr->execStackPtr = esPtr; } } @@ -1302,16 +1294,15 @@ TclStackAlloc( Tcl_Interp *interp, size_t numBytes) { Interp *iPtr = (Interp *) interp; - size_t numWords; if (iPtr == NULL || iPtr->execEnvPtr == NULL) { return Tcl_Alloc(numBytes); } - numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *); + size_t numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *); return StackAllocWords(interp, numWords); } void * TclStackRealloc( @@ -1318,28 +1309,24 @@ Tcl_Interp *interp, void *ptr, size_t numBytes) { Interp *iPtr = (Interp *) interp; - ExecEnv *eePtr; - ExecStack *esPtr; - Tcl_Obj **markerPtr; - size_t numWords; if (iPtr == NULL || iPtr->execEnvPtr == NULL) { return Tcl_Realloc(ptr, numBytes); } - eePtr = iPtr->execEnvPtr; - esPtr = eePtr->execStackPtr; - markerPtr = esPtr->markerPtr; + ExecEnv *eePtr = iPtr->execEnvPtr; + ExecStack *esPtr = eePtr->execStackPtr; + Tcl_Obj **markerPtr = esPtr->markerPtr; if (MEMSTART(markerPtr) != (Tcl_Obj **)ptr) { Tcl_Panic("TclStackRealloc: incorrect ptr. Call out of sequence?"); } - numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *); + size_t numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *); return (void *) StackReallocWords(interp, numWords); } /* *-------------------------------------------------------------- @@ -1428,16 +1415,14 @@ Tcl_NRExprObj( Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj *resultPtr) { - ByteCode *codePtr; Tcl_InterpState state = Tcl_SaveInterpState(interp, TCL_OK); Tcl_ResetResult(interp); - codePtr = CompileExprObj(interp, objPtr); - + ByteCode *codePtr = CompileExprObj(interp, objPtr); Tcl_NRAddCallback(interp, ExprObjCallback, state, resultPtr, NULL, NULL); return TclNRExecuteByteCode(interp, codePtr); } @@ -1680,11 +1665,11 @@ * environment! If not, recompile. */ if (!(codePtr->flags & TCL_BYTECODE_PRECOMPILED) && (codePtr->procPtr == NULL) && - (codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)){ + (codePtr->localCachePtr != iPtr->varFramePtr->localCachePtr)) { goto recompileObj; } /* * #280. @@ -1716,23 +1701,18 @@ */ if (invoker == NULL) { return codePtr; } else { - Tcl_HashEntry *hePtr = - Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr); - ExtCmdLoc *eclPtr; - CmdFrame *ctxCopyPtr; - int redo; - + Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr); if (!hePtr) { return codePtr; } - - eclPtr = (ExtCmdLoc *)Tcl_GetHashValue(hePtr); - redo = 0; - ctxCopyPtr = (CmdFrame *)TclStackAlloc(interp, sizeof(CmdFrame)); + ExtCmdLoc *eclPtr = (ExtCmdLoc *)Tcl_GetHashValue(hePtr); + int redo = 0; + CmdFrame *ctxCopyPtr = (CmdFrame *) + TclStackAlloc(interp, sizeof(CmdFrame)); *ctxCopyPtr = *invoker; if (invoker->type == TCL_LOCATION_BC) { /* * Note: Type BC => ctx.data.eval.path is not used. @@ -1824,11 +1804,10 @@ Tcl_Obj *incrPtr) { void *ptr1, *ptr2; int type1, type2; mp_int value, incr; - mp_err err; if (Tcl_IsShared(valuePtr)) { Tcl_Panic("%s called with shared object", "TclIncrObj"); } @@ -1865,15 +1844,13 @@ Tcl_AddErrorInfo(interp, "\n (reading increment)"); return TCL_ERROR; } if ((type1 == TCL_NUMBER_INT) && (type2 == TCL_NUMBER_INT)) { - Tcl_WideInt w1, w2, sum; - - w1 = *((const Tcl_WideInt *)ptr1); - w2 = *((const Tcl_WideInt *)ptr2); - sum = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2); + Tcl_WideInt w1 = *((const Tcl_WideInt *)ptr1); + Tcl_WideInt w2 = *((const Tcl_WideInt *)ptr2); + Tcl_WideInt sum = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2); /* * Check for overflow. */ @@ -1883,11 +1860,11 @@ } } Tcl_TakeBignumFromObj(interp, valuePtr, &value); Tcl_GetBignumFromObj(interp, incrPtr, &incr); - err = mp_add(&value, &incr, &value); + mp_err err = mp_add(&value, &incr, &value); mp_clear(&incr); if (err != MP_OKAY) { return TCL_ERROR; } Tcl_SetBignumObj(valuePtr, &value); @@ -1930,10 +1907,42 @@ } /* *---------------------------------------------------------------------- * + * PrintArgumentWords -- + * + * A helper for TEBC. Prints a sequence of words. + * + * Results: + * None + * + * Side effects: + * May register information about the bytecode in the command frame. + * + *---------------------------------------------------------------------- + */ + +#ifdef TCL_COMPILE_DEBUG +static inline void +PrintArgumentWords( + Tcl_Size objc, + Tcl_Obj *const *objv) +{ + Tcl_Size i; + for (i = 0; i < objc; i++) { + TclPrintObject(stdout, objv[i], 15); + if (i < objc - 1) { + fprintf(stdout, " "); + } + } +} +#endif // TCL_COMPILE_DEBUG + +/* + *---------------------------------------------------------------------- + * * TclNRExecuteByteCode -- * * This procedure executes the instructions of a ByteCode structure. It * returns when a "done" instruction is executed or an error occurs. * @@ -1956,11 +1965,10 @@ TclNRExecuteByteCode( Tcl_Interp *interp, /* Token for command interpreter. */ ByteCode *codePtr) /* The bytecode sequence to interpret. */ { Interp *iPtr = (Interp *) interp; - TEBCdata *TD; size_t size = sizeof(TEBCdata) - 1 + (codePtr->maxStackDepth + codePtr->maxExceptDepth) * sizeof(void *); size_t numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *); @@ -1976,16 +1984,19 @@ * catch commands that could ever be executing at the same time (this will * be no more than the exception range array's depth). Make sure the * execution stack is large enough to execute this ByteCode. */ - TD = (TEBCdata *) GrowEvaluationStack(iPtr->execEnvPtr, numWords, 0); + TEBCdata *TD = (TEBCdata *) GrowEvaluationStack(iPtr->execEnvPtr, numWords, 0); esPtr->tosPtr = initTosPtr; TD->codePtr = codePtr; TD->catchTop = initCatchTop; TD->auxObjList = NULL; +#ifdef TCL_COMPILE_DEBUG + TD->cmdNameBuf[0] = 0; +#endif /* * TIP #280: Initialize the frame. Do not push it yet: it will be pushed * every time that we call out from this TD, popped when we return to it. */ @@ -2045,13 +2056,13 @@ /* * Check just the read-traced/write-traced bit of a variable. */ -#define ReadTraced(varPtr) ((varPtr)->flags & VAR_TRACED_READ) -#define WriteTraced(varPtr) ((varPtr)->flags & VAR_TRACED_WRITE) -#define UnsetTraced(varPtr) ((varPtr)->flags & VAR_TRACED_UNSET) +#define ReadTraced(varPtr) ((varPtr)->flags & VAR_TRACED_READ) +#define WriteTraced(varPtr) ((varPtr)->flags & VAR_TRACED_WRITE) +#define UnsetTraced(varPtr) ((varPtr)->flags & VAR_TRACED_UNSET) /* * Bottom of allocated stack holds the NR data */ @@ -2088,10 +2099,11 @@ TEBCdata *TD = (TEBCdata *)data[0]; #define auxObjList (TD->auxObjList) #define catchTop (TD->catchTop) #define codePtr (TD->codePtr) #define curEvalFlags PTR2INT(data[3]) /* calling iPtr->evalFlags */ +#define cmdNameBuf (TD->cmdNameBuf) /* * Globals: variables that store state, must remain valid at all times. */ @@ -2119,15 +2131,12 @@ Tcl_Obj *objPtr, *valuePtr, *value2Ptr, *part1Ptr, *part2Ptr, *tmpPtr; Tcl_Obj **objv = NULL; Tcl_Size length, objc = 0, varIdx, numArgs; unsigned tblIdx; - int pcAdjustment, encIndex; + int pcAdjustment; Var *varPtr, *arrayPtr; -#ifdef TCL_COMPILE_DEBUG - char cmdNameBuf[21]; -#endif #ifdef TCL_COMPILE_DEBUG int starting = 1; traceInstructions = (tclTraceExec >= TCL_TRACE_BYTECODE_EXEC_INSTRUCTIONS); #endif @@ -2241,16 +2250,16 @@ cleanup -= 2; while (cleanup--) { objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 2: cleanup2_pushObjResultPtr: objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 1: cleanup1_pushObjResultPtr: objPtr = OBJ_AT_TOS; TclDecrRefCount(objPtr); } @@ -2263,21 +2272,21 @@ cleanup -= 2; while (cleanup--) { objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 2: cleanup2: objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 1: cleanup1: objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 0: /* * We really want to do nothing now, but this is needed for some * compilers (SunPro CC). */ @@ -2640,45 +2649,38 @@ case INST_PUSH1: DEPRECATED_OPCODE_MARK(INST_PUSH1); objResultPtr = codePtr->objArrayPtr[TclGetUInt1AtPtr(pc + 1)]; TRACE_WITH_OBJ(("%u => ", TclGetUInt1AtPtr(pc + 1)), objResultPtr); NEXT_INST_F(2, 0, 1); - break; #endif case INST_PUSH: objResultPtr = codePtr->objArrayPtr[TclGetUInt4AtPtr(pc + 1)]; TRACE_WITH_OBJ(("%u => ", TclGetUInt4AtPtr(pc + 1)), objResultPtr); NEXT_INST_F(5, 0, 1); - break; case INST_POP: TRACE_WITH_OBJ(("=> discarding "), OBJ_AT_TOS); objPtr = POP_OBJECT(); TclDecrRefCount(objPtr); NEXT_INST_F0(1, 0); - break; case INST_DUP: objResultPtr = OBJ_AT_TOS; TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); - break; case INST_OVER: numArgs = TclGetUInt4AtPtr(pc + 1); objResultPtr = OBJ_AT_DEPTH(numArgs); TRACE_WITH_OBJ(("%u => ", (unsigned) numArgs), objResultPtr); NEXT_INST_F(5, 0, 1); - break; case INST_REVERSE: { - Tcl_Obj **a, **b; - numArgs = TclGetUInt4AtPtr(pc + 1); - a = tosPtr - (numArgs - 1); - b = tosPtr; + Tcl_Obj **a = tosPtr - (numArgs - 1); + Tcl_Obj **b = tosPtr; while (a < b) { tmpPtr = *a; *a = *b; *b = tmpPtr; a++; @@ -2685,38 +2687,30 @@ b--; } TRACE(("%u => OK\n", (unsigned) numArgs)); NEXT_INST_F0(5, 0); } - break; - case INST_SWAP: { - Tcl_Obj *a, *b; - - a = OBJ_AT_TOS; - b = OBJ_UNDER_TOS; - OBJ_UNDER_TOS = a; - OBJ_AT_TOS = b; + case INST_SWAP: + tmpPtr = OBJ_UNDER_TOS; + OBJ_UNDER_TOS = OBJ_AT_TOS; + OBJ_AT_TOS = tmpPtr; TRACE(("=> OK\n")); NEXT_INST_F0(1, 0); - } - break; case INST_STR_CONCAT1: numArgs = TclGetUInt1AtPtr(pc + 1); DECACHE_STACK_INFO(); objResultPtr = TclStringCat(interp, numArgs, &OBJ_AT_DEPTH(numArgs - 1), TCL_STRING_IN_PLACE); + CACHE_STACK_INFO(); if (objResultPtr == NULL) { - CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } - CACHE_STACK_INFO(); TRACE_WITH_OBJ(("%u => ", (unsigned)numArgs), objResultPtr); NEXT_INST_V(2, numArgs, 1); - break; case INST_CONCAT_STK: /* * Pop the numArgs (objc) top stack elements, run through Tcl_ConcatObj, * and then decrement their ref counts. @@ -2724,11 +2718,10 @@ numArgs = TclGetUInt4AtPtr(pc + 1); objResultPtr = Tcl_ConcatObj(numArgs, &OBJ_AT_DEPTH(numArgs - 1)); TRACE_WITH_OBJ(("%u => ", (unsigned) numArgs), objResultPtr); NEXT_INST_V(5, numArgs, 1); - break; case INST_EXPAND_START: /* * Push an element to the auxObjList. This records the current * stack depth - i.e., the point in the stack where the expanded @@ -2746,11 +2739,10 @@ objPtr->internalRep.twoPtrValue.ptr2 = INT2PTR(CURR_DEPTH); objPtr->length = 0; PUSH_TAUX_OBJ(objPtr); TRACE(("=> mark depth as %" SIZEd "\n", CURR_DEPTH)); NEXT_INST_F0(1, 0); - break; case INST_EXPAND_DROP: /* * Drops an element of the auxObjList, popping stack elements to * restore the stack to the state before the point where the aux @@ -2765,15 +2757,11 @@ starting = 1; #endif TRACE(("=> drop %" SIZEd " items\n", objc)); NEXT_INST_V(1, objc, 0); - case INST_EXPAND_STKTOP: { - Tcl_Size i; - TEBCdata *newTD; - Tcl_Size oldCatchTopOff, oldTosPtrOff; - + case INST_EXPAND_STKTOP: /* * Make sure that the element at stackTop is a list; if not, just * leave with an error. Note that the element from the expand list * will be removed at checkForCatch. */ @@ -2793,17 +2781,17 @@ * stack depth, as seen by the compiler. */ auxObjList->length += objc - 1; if ((objc > 1) && (auxObjList->length > 0)) { - length = auxObjList->length /* Total expansion room we need */ - + codePtr->maxStackDepth /* Beyond the original max */ - - CURR_DEPTH; /* Relative to where we are */ + length = auxObjList->length // Total expansion room we need + + codePtr->maxStackDepth // Beyond the original max + - CURR_DEPTH; // Relative to where we are DECACHE_STACK_INFO(); - oldCatchTopOff = catchTop - initCatchTop; - oldTosPtrOff = tosPtr - initTosPtr; - newTD = (TEBCdata *) + Tcl_Size oldCatchTopOff = catchTop - initCatchTop; + Tcl_Size oldTosPtrOff = tosPtr - initTosPtr; + TEBCdata *newTD = (TEBCdata *) GrowEvaluationStack(iPtr->execEnvPtr, length, 1); if (newTD != TD) { /* * Change the global data to point to the new stack: move the * TEBCdataPtr TD, recompute the position of every other @@ -2820,27 +2808,26 @@ /* * Expand the list at stacktop onto the stack; free the list. Knowing * that it has a freeIntRepProc we use Tcl_DecrRefCount(). */ - for (i = 0; i < objc; i++) { - PUSH_OBJECT(objv[i]); + { + Tcl_Size i; + for (i = 0; i < objc; i++) { + PUSH_OBJECT(objv[i]); + } } TRACE_APPEND(("OK\n")); Tcl_DecrRefCount(objPtr); NEXT_INST_F0(5, 0); - } - break; case INST_EXPR_STK: { - ByteCode *newCodePtr; - bcFramePtr->data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; DECACHE_STACK_INFO(); - newCodePtr = CompileExprObj(interp, OBJ_AT_TOS); + ByteCode *newCodePtr = CompileExprObj(interp, OBJ_AT_TOS); CACHE_STACK_INFO(); cleanup = 1; pc++; TEBC_YIELD(); return TclNRExecuteByteCode(interp, newCodePtr); @@ -2876,11 +2863,10 @@ * Nothing was expanded, return {}. */ TclNewObj(objResultPtr); NEXT_INST_F(1, 0, 1); - break; case INST_INVOKE_STK: objc = TclGetUInt4AtPtr(pc + 1); pcAdjustment = 5; #ifndef REMOVE_DEPRECATED_OPCODES @@ -2897,23 +2883,18 @@ objv = &OBJ_AT_DEPTH(objc - 1); cleanup = objc; #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= TCL_TRACE_BYTECODE_EXEC_COMMANDS) { - Tcl_Size i; - if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); TRACE(("%" SIZEd " => call ", objc)); } else { fprintf(stdout, "%" SIZEd ": (%" SIZEd ") invoking ", iPtr->numLevels, PC_REL); } - for (i = 0; i < objc; i++) { - TclPrintObject(stdout, objv[i], 15); - fprintf(stdout, " "); - } + PrintArgumentWords(objc, objv); fprintf(stdout, "\n"); fflush(stdout); } #endif /*TCL_COMPILE_DEBUG*/ @@ -2937,11 +2918,11 @@ TEBC_YIELD(); if (objc > INT_MAX) { return TclCommandWordLimitError(interp, objc); } else { return TclNREvalObjv(interp, objc, objv, - TCL_EVAL_NOERR | TCL_EVAL_SOURCE_IN_FRAME, NULL); + TCL_EVAL_NOERR | TCL_EVAL_SOURCE_IN_FRAME, NULL); } case INST_INVOKE_REPLACE: objc = TclGetUInt4AtPtr(pc + 1); numArgs = TclGetUInt1AtPtr(pc + 5); @@ -2948,20 +2929,19 @@ objPtr = POP_OBJECT(); objv = &OBJ_AT_DEPTH(objc - 1); cleanup = objc; #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= TCL_TRACE_BYTECODE_EXEC_COMMANDS) { - Tcl_Size i; - if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); TRACE(("%" SIZEd " => call (implementation %s) ", objc, O2S(objPtr))); } else { fprintf(stdout, "%" SIZEd ": (%" SIZEd ") invoking (using implementation %s) ", iPtr->numLevels, PC_REL, O2S(objPtr)); } + Tcl_Size i; for (i = 0; i < objc; i++) { if (i < numArgs) { fprintf(stdout, "<"); TclPrintObject(stdout, objv[i], 15); fprintf(stdout, ">"); @@ -3662,10 +3642,11 @@ goto doIncrScalar; case INST_INCR_ARRAY: goto doIncrArray; default: Tcl_Panic("unknown instruction"); + TCL_UNREACHABLE(); } case INST_INCR_ARRAY_STK_IMM: case INST_INCR_SCALAR_STK_IMM: case INST_INCR_STK_IMM: @@ -4109,11 +4090,10 @@ errorInUnset: CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } - break; /* * End of INST_UNSET instructions. * ----------------------------------------------------------------- * Start of INST_CONST instructions. @@ -4160,15 +4140,13 @@ } if (TclIsVarDirectModifyable(varPtr)) { varPtr->value.objPtr = objPtr; Tcl_IncrRefCount(objPtr); } else { - Tcl_Obj *resPtr; - DECACHE_STACK_INFO(); - resPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr, NULL, - objPtr, TCL_LEAVE_ERR_MSG, varIdx); + Tcl_Obj *resPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, + part1Ptr, NULL, objPtr, TCL_LEAVE_ERR_MSG, varIdx); CACHE_STACK_INFO(); if (resPtr == NULL) { TRACE_ERROR(interp); goto gotError; } @@ -4177,11 +4155,13 @@ TRACE_APPEND(("\n")); NEXT_INST_V(pcAdjustment, cleanup, 0); constError: TclObjVarErrMsg(interp, part1Ptr, NULL, "make constant", msgPart, varIdx); + DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONST", (char *)NULL); + CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } /* @@ -4398,11 +4378,10 @@ */ TRACE_APPEND(("link made\n")); NEXT_INST_F0(5, 1); } - break; /* * End of variable linking instructions. * ----------------------------------------------------------------- */ @@ -4489,67 +4468,55 @@ } } #endif NEXT_INST_F0(jmpOffset[b], 1); } - break; - case INST_JUMP_TABLE: { + { Tcl_HashEntry *hPtr; - JumptableInfo *jtPtr; - + /* * Jump to location looked up in a hashtable; fall through to next * instr if lookup fails. Lookup by string. */ - + + case INST_JUMP_TABLE: tblIdx = TclGetInt4AtPtr(pc + 1); - jtPtr = (JumptableInfo *) codePtr->auxDataArrayPtr[tblIdx].clientData; + JumptableInfo *jtPtr = (JumptableInfo *) + codePtr->auxDataArrayPtr[tblIdx].clientData; TRACE(("%u \"%.20s\" => ", tblIdx, O2S(OBJ_AT_TOS))); hPtr = Tcl_FindHashEntry(&jtPtr->hashTable, TclGetString(OBJ_AT_TOS)); + goto processJumpTableEntry; + + /* + * Jump to location looked up in a hashtable; fall through to next + * instr if lookup fails or key is non-integer. Lookup by integer. + */ + + case INST_JUMP_TABLE_NUM: + tblIdx = TclGetInt4AtPtr(pc + 1); + JumptableNumInfo *jtnPtr = (JumptableNumInfo *) + codePtr->auxDataArrayPtr[tblIdx].clientData; + TRACE(("%u \"%.20s\" => ", tblIdx, O2S(OBJ_AT_TOS))); + Tcl_WideInt key; + if (Tcl_GetWideIntFromObj(NULL, OBJ_AT_TOS, &key) != TCL_OK) { + goto jumpTableNumFallthrough; + } + hPtr = Tcl_FindHashEntry(&jtnPtr->hashTable, (void *)key); + + processJumpTableEntry: if (hPtr != NULL) { Tcl_Size jumpOffset = PTR2INT(Tcl_GetHashValue(hPtr)); TRACE_APPEND(("found in table, new pc %" SIZEu "\n", PC_REL + jumpOffset)); NEXT_INST_F0(jumpOffset, 1); - } else { - TRACE_APPEND(("not found in table\n")); - NEXT_INST_F0(5, 1); - } - } - break; - case INST_JUMP_TABLE_NUM: { - Tcl_HashEntry *hPtr; - JumptableNumInfo *jtnPtr; - Tcl_WideInt key; - - /* - * Jump to location looked up in a hashtable; fall through to next - * instr if lookup fails. Lookup by integer. - */ - - tblIdx = TclGetInt4AtPtr(pc + 1); - jtnPtr = (JumptableNumInfo *) codePtr->auxDataArrayPtr[tblIdx].clientData; - TRACE(("%u \"%.20s\" => ", tblIdx, O2S(OBJ_AT_TOS))); - if (Tcl_GetWideIntFromObj(NULL, OBJ_AT_TOS, &key) != TCL_OK) { - goto jumpTableNumFallthrough; - } - hPtr = Tcl_FindHashEntry(&jtnPtr->hashTable, (void *)key); - if (hPtr != NULL) { - Tcl_Size jumpOffset = PTR2INT(Tcl_GetHashValue(hPtr)); - - TRACE_APPEND(("found in table, new pc %" SIZEu "\n", - PC_REL + jumpOffset)); - NEXT_INST_F0(jumpOffset, 1); - } else { - jumpTableNumFallthrough: - TRACE_APPEND(("not found in table\n")); - NEXT_INST_F0(5, 1); - } - } - break; + } + jumpTableNumFallthrough: + TRACE_APPEND(("not found in table\n")); + NEXT_INST_F0(5, 1); + } /* * ----------------------------------------------------------------- * Start of general introspector instructions. */ @@ -4556,11 +4523,10 @@ case INST_NS_CURRENT: objResultPtr = TclNewNamespaceObj(TclGetCurrentNamespace(interp)); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); - break; case INST_COROUTINE_NAME: { CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; TclNewObj(objResultPtr); if (corPtr && !(corPtr->cmdPtr->flags & CMD_DYING)) { @@ -4568,16 +4534,14 @@ objResultPtr); } TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); } - break; case INST_INFO_LEVEL_NUM: TclNewIntObj(objResultPtr, (int)iPtr->varFramePtr->level); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); - break; case INST_INFO_LEVEL_ARGS: { Tcl_WideInt level; CallFrame *framePtr = iPtr->varFramePtr; CallFrame *rootFramePtr = iPtr->rootFramePtr; @@ -4807,22 +4771,17 @@ } doInvokeNext: #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= TCL_TRACE_BYTECODE_EXEC_COMMANDS) { - Tcl_Size i; - if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); } else { fprintf(stdout, "%" SIZEd ": (%" SIZEd ") invoking ", iPtr->numLevels, PC_REL); } - for (i = 0; i < numArgs; i++) { - TclPrintObject(stdout, objv[i], 15); - fprintf(stdout, " "); - } + PrintArgumentWords(numArgs, objv); fprintf(stdout, "\n"); fflush(stdout); } #endif /*TCL_COMPILE_DEBUG*/ bcFramePtr->data.tebc.pc = (char *) pc; @@ -4857,18 +4816,20 @@ } else { oPtr->flags &= ~FILTER_HANDLING; } { - Method *const mPtr = - contextPtr->callPtr->chain[newDepth].mPtr; + const Method *mPtr = contextPtr->callPtr->chain[newDepth].mPtr; if (mPtr->typePtr->version < TCL_OO_METHOD_VERSION_2) { return mPtr->typePtr->callProc(mPtr->clientData, interp, - (Tcl_ObjectContext) contextPtr, numArgs, objv); + (Tcl_ObjectContext) contextPtr, (int)numArgs, objv); } - return ((Tcl_MethodCallProc2 *)(void *)(mPtr->typePtr->callProc))(mPtr->clientData, interp, + // Ugly indirect cast + Tcl_MethodCallProc2 *call2Proc = (Tcl_MethodCallProc2 *) + (void *)mPtr->typePtr->callProc; + return call2Proc(mPtr->clientData, interp, (Tcl_ObjectContext) contextPtr, numArgs, objv); } case INST_TCLOO_IS_OBJECT: DECACHE_STACK_INFO(); @@ -4895,10 +4856,12 @@ objResultPtr = TclNewNamespaceObj(oPtr->namespacePtr); break; case INST_TCLOO_ID: objResultPtr = Tcl_NewWideIntObj(oPtr->creationEpoch); break; + default: + TCL_UNREACHABLE(); } TRACE_WITH_OBJ(("%.30s => ", O2S(OBJ_AT_TOS)), objResultPtr); NEXT_INST_F(1, 1, 1); } @@ -4907,11 +4870,11 @@ * ----------------------------------------------------------------- * Start of INST_LIST and related instructions. */ { - int nocase, match, cflags, fromIdxEnc, toIdxEnc; + int nocase, match, fromIdxEnc, toIdxEnc; Tcl_Size slength, length2, fromIdx, toIdx, index, s1len, s2len, numIndices; const char *s1, *s2; case INST_LIST: /* @@ -4970,19 +4933,17 @@ && (!TclHasInternalRep(value2Ptr, &tclListType) || (Tcl_ListObjLength(interp, value2Ptr, &value2Length), value2Length == 1 ? (indexListPtr = TclListObjGetElement(value2Ptr, 0), 1) : 0))) { - int code; - /* increment the refCount of value2Ptr because TclListObjGetElement may * have just extracted it from a list in the condition for this block. */ Tcl_IncrRefCount(indexListPtr); DECACHE_STACK_INFO(); - code = TclGetIntForIndexM(interp, indexListPtr, objc - 1, &index); + int code = TclGetIntForIndexM(interp, indexListPtr, objc - 1, &index); TclDecrRefCount(indexListPtr); CACHE_STACK_INFO(); if (code == TCL_OK) { Tcl_DecrRefCount(value2Ptr); tosPtr--; @@ -5008,19 +4969,19 @@ */ TRACE_APPEND_OBJ(objResultPtr); NEXT_INST_F(1, 2, -1); /* Already has the correct refCount */ - case INST_LIST_INDEX_IMM: /* lindex with objc==3 and index in bytecode + case INST_LIST_INDEX_IMM: { /* lindex with objc==3 and index in bytecode * stream */ /* * Pop the list and get the index. */ valuePtr = OBJ_AT_TOS; - encIndex = TclGetInt4AtPtr(pc + 1); + int encIndex = TclGetInt4AtPtr(pc + 1); TRACE(("\"%.30s\" %d => ", O2S(valuePtr), encIndex)); /* * Get the contents of the list, making sure that it really is a list * in the process. @@ -5034,16 +4995,16 @@ index = TclIndexDecode(encIndex, length - 1); if (index >= 0 && index < length) { /* Compute value @ index */ DECACHE_STACK_INFO(); - if (TclObjTypeIndex(interp, valuePtr, index, &objResultPtr)!=TCL_OK) { - CACHE_STACK_INFO(); + int code = TclObjTypeIndex(interp, valuePtr, index, &objResultPtr); + CACHE_STACK_INFO(); + if (code != TCL_OK) { TRACE_ERROR(interp); goto gotError; } - CACHE_STACK_INFO(); } else { TclNewObj(objResultPtr); } pcAdjustment = 5; @@ -5069,10 +5030,11 @@ } lindexFastPath2: TRACE_APPEND_OBJ(objResultPtr); NEXT_INST_F(pcAdjustment, 1, 1); + } case INST_LIST_INDEX_MULTI: /* 'lindex' with multiple index args */ /* * Determine the count of index args. */ @@ -5129,20 +5091,19 @@ &OBJ_AT_DEPTH(numIndices), OBJ_AT_TOS); } else { objResultPtr = TclLsetFlat(interp, valuePtr, numIndices, &OBJ_AT_DEPTH(numIndices), OBJ_AT_TOS); } + CACHE_STACK_INFO(); if (!objResultPtr) { - CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } /* * Set result. */ - CACHE_STACK_INFO(); TRACE_APPEND_OBJ(objResultPtr); NEXT_INST_V(5, numIndices + 1, -1); case INST_LSET_LIST: /* 'lset' with 4 args */ /* @@ -5250,19 +5211,17 @@ } fromIdx = TclIndexDecode(fromIdxEnc, objc - 1); DECACHE_STACK_INFO(); - if (Tcl_ListObjRange(interp, valuePtr, fromIdx, toIdx, &objResultPtr) != - TCL_OK) { + if (Tcl_ListObjRange(interp, valuePtr, fromIdx, toIdx, + &objResultPtr) != TCL_OK) { objResultPtr = NULL; - CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } - CACHE_STACK_INFO(); TRACE_APPEND_OBJ(objResultPtr); NEXT_INST_F(9, 1, 1); case INST_LIST_IN: case INST_LIST_NOT_IN: /* Basic list containment operators. */ @@ -5284,26 +5243,26 @@ goto gotError; } match = 0; if (length > 0) { Tcl_Size i = 0; - Tcl_Obj *o; int isAbstractList = TclObjTypeHasProc(value2Ptr, indexProc) != NULL; /* * An empty list doesn't match anything. */ do { + Tcl_Obj *o; if (isAbstractList) { DECACHE_STACK_INFO(); - if (TclObjTypeIndex(interp, value2Ptr, i, &o) != TCL_OK) { - CACHE_STACK_INFO(); + int status = TclObjTypeIndex(interp, value2Ptr, i, &o); + CACHE_STACK_INFO(); + if (status != TCL_OK) { TRACE_ERROR(interp); goto gotError; } - CACHE_STACK_INFO(); } else { Tcl_ListObjIndex(NULL, value2Ptr, i, &o); } if (o != NULL) { s2 = TclGetStringFromObj(o, &s2len); @@ -5350,45 +5309,40 @@ goto gotError; } TRACE_APPEND_OBJ(objResultPtr); NEXT_INST_F(1, 2, 1); } else { - if (Tcl_ListObjAppendList(interp, valuePtr, value2Ptr) != TCL_OK){ + if (Tcl_ListObjAppendList(interp, valuePtr, value2Ptr) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } TRACE_APPEND_OBJ(valuePtr); NEXT_INST_F0(1, 1); } case INST_LREPLACE: { - size_t numToDelete, numNewElems; - int end_indicator; - int haveSecondIndex, flags; - Tcl_Obj *fromIdxObj, *toIdxObj; numArgs = TclGetUInt4AtPtr(pc + 1); - flags = TclGetInt1AtPtr(pc + 5); + int flags = TclGetInt1AtPtr(pc + 5); /* Stack: ... listobj index1 ?index2? new1 ... newN */ valuePtr = OBJ_AT_DEPTH(numArgs - 1); /* haveSecondIndex==0 => pure insert */ - haveSecondIndex = (flags & TCL_LREPLACE4_SINGLE_INDEX) == 0; - numNewElems = numArgs - 2 - haveSecondIndex; + int haveSecondIndex = (flags & TCL_LREPLACE4_SINGLE_INDEX) == 0; + size_t numNewElems = numArgs - 2 - haveSecondIndex; /* end_indicator==1 => "end" is last element's index, 0=>index beyond */ - end_indicator = (flags & TCL_LREPLACE4_END_IS_LAST) != 0; - fromIdxObj = OBJ_AT_DEPTH(numArgs - 2); - toIdxObj = haveSecondIndex ? OBJ_AT_DEPTH(numArgs - 3) : NULL; + int endIndicator = (flags & TCL_LREPLACE4_END_IS_LAST) != 0; + Tcl_Obj *fromIdxObj = OBJ_AT_DEPTH(numArgs - 2); + Tcl_Obj *toIdxObj = haveSecondIndex ? OBJ_AT_DEPTH(numArgs - 3) : NULL; if (Tcl_ListObjLength(interp, valuePtr, &length) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } DECACHE_STACK_INFO(); - - if (TclGetIntForIndexM(interp, fromIdxObj, length - end_indicator, + if (TclGetIntForIndexM(interp, fromIdxObj, length - endIndicator, &fromIdx) != TCL_OK) { CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } @@ -5395,13 +5349,13 @@ if (fromIdx == TCL_INDEX_NONE) { fromIdx = 0; } else if (fromIdx > length) { fromIdx = length; } - numToDelete = 0; + size_t numToDelete = 0; if (toIdxObj) { - if (TclGetIntForIndexM(interp, toIdxObj, length - end_indicator, + if (TclGetIntForIndexM(interp, toIdxObj, length - endIndicator, &toIdx) != TCL_OK) { CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } @@ -5434,11 +5388,11 @@ goto gotError; } TRACE_APPEND_OBJ(valuePtr); NEXT_INST_V(6, numArgs - 1, 0); } - } + } /* * End of INST_LIST and related instructions. * ----------------------------------------------------------------- * Start of string-related instructions. @@ -5508,61 +5462,40 @@ slength = Tcl_GetCharLength(valuePtr); TclNewIntObj(objResultPtr, slength); TRACE(("\"%.30s\" => %" SIZEu "\n", O2S(valuePtr), slength)); NEXT_INST_F(1, 1, 1); - case INST_STR_UPPER: - valuePtr = OBJ_AT_TOS; - TRACE(("\"%.30s\" => ", O2S(valuePtr))); - if (Tcl_IsShared(valuePtr)) { - s1 = TclGetStringFromObj(valuePtr, &slength); - TclNewStringObj(objResultPtr, s1, slength); - slength = Tcl_UtfToUpper(TclGetString(objResultPtr)); - Tcl_SetObjLength(objResultPtr, slength); - TRACE_APPEND_OBJ(objResultPtr); - NEXT_INST_F(1, 1, 1); - } else { - slength = Tcl_UtfToUpper(TclGetString(valuePtr)); - Tcl_SetObjLength(valuePtr, slength); - TclFreeInternalRep(valuePtr); - TRACE_APPEND_OBJ(valuePtr); - NEXT_INST_F0(1, 0); - } - case INST_STR_LOWER: - valuePtr = OBJ_AT_TOS; - TRACE(("\"%.30s\" => ", O2S(valuePtr))); - if (Tcl_IsShared(valuePtr)) { - s1 = TclGetStringFromObj(valuePtr, &slength); - TclNewStringObj(objResultPtr, s1, slength); - slength = Tcl_UtfToLower(TclGetString(objResultPtr)); - Tcl_SetObjLength(objResultPtr, slength); - TRACE_APPEND_OBJ(objResultPtr); - NEXT_INST_F(1, 1, 1); - } else { - slength = Tcl_UtfToLower(TclGetString(valuePtr)); - Tcl_SetObjLength(valuePtr, slength); - TclFreeInternalRep(valuePtr); - TRACE_APPEND_OBJ(valuePtr); - NEXT_INST_F0(1, 0); - } - case INST_STR_TITLE: - valuePtr = OBJ_AT_TOS; - TRACE(("\"%.30s\" => ", O2S(valuePtr))); - if (Tcl_IsShared(valuePtr)) { - s1 = TclGetStringFromObj(valuePtr, &slength); - TclNewStringObj(objResultPtr, s1, slength); - slength = Tcl_UtfToTitle(TclGetString(objResultPtr)); - Tcl_SetObjLength(objResultPtr, slength); - TRACE_APPEND_OBJ(objResultPtr); - NEXT_INST_F(1, 1, 1); - } else { - slength = Tcl_UtfToTitle(TclGetString(valuePtr)); - Tcl_SetObjLength(valuePtr, slength); - TclFreeInternalRep(valuePtr); - TRACE_APPEND_OBJ(valuePtr); - NEXT_INST_F0(1, 0); - } + { + Tcl_Size (*transform)(char *); + + case INST_STR_UPPER: + transform = Tcl_UtfToUpper; + goto applyStringTransform; + case INST_STR_LOWER: + transform = Tcl_UtfToLower; + goto applyStringTransform; + case INST_STR_TITLE: + transform = Tcl_UtfToTitle; + applyStringTransform: + valuePtr = OBJ_AT_TOS; + TRACE(("\"%.30s\" => ", O2S(valuePtr))); + if (Tcl_IsShared(valuePtr)) { + // Make copy of UTF-8 representation ONLY; we're about to modify it + s1 = TclGetStringFromObj(valuePtr, &slength); + TclNewStringObj(objResultPtr, s1, slength); + slength = transform(TclGetString(objResultPtr)); + Tcl_SetObjLength(objResultPtr, slength); + TRACE_APPEND_OBJ(objResultPtr); + NEXT_INST_F(1, 1, 1); + } else { + slength = transform(TclGetString(valuePtr)); + Tcl_SetObjLength(valuePtr, slength); + TclFreeInternalRep(valuePtr); + TRACE_APPEND_OBJ(valuePtr); + NEXT_INST_F0(1, 0); + } + } case INST_STR_INDEX: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; TRACE(("\"%.30s\" %.20s => ", O2S(valuePtr), O2S(value2Ptr))); @@ -5570,17 +5503,19 @@ /* * Get char length to calculate what 'end' means. */ slength = Tcl_GetCharLength(valuePtr); - DECACHE_STACK_INFO(); - if (TclGetIntForIndexM(interp, value2Ptr, slength - 1, &index)!=TCL_OK) { + { + DECACHE_STACK_INFO(); + int code = TclGetIntForIndexM(interp, value2Ptr, slength - 1, &index); CACHE_STACK_INFO(); - TRACE_ERROR(interp); - goto gotError; + if (code != TCL_OK) { + TRACE_ERROR(interp); + goto gotError; + } } - CACHE_STACK_INFO(); if (index < 0 || index >= slength) { TclNewObj(objResultPtr); } else if (TclIsPureByteArray(valuePtr)) { objResultPtr = Tcl_NewByteArrayObj( @@ -5612,16 +5547,12 @@ TRACE(("\"%.20s\" %.20s %.20s =>", O2S(OBJ_AT_DEPTH(2)), O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS))); slength = Tcl_GetCharLength(OBJ_AT_DEPTH(2)) - 1; DECACHE_STACK_INFO(); - if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, slength, &fromIdx) != TCL_OK) { - CACHE_STACK_INFO(); - TRACE_ERROR(interp); - goto gotError; - } - if (TclGetIntForIndexM(interp, OBJ_AT_TOS, slength, &toIdx) != TCL_OK) { + if (TclGetIntForIndexM(interp, OBJ_UNDER_TOS, slength, &fromIdx) != TCL_OK || + TclGetIntForIndexM(interp, OBJ_AT_TOS, slength, &toIdx) != TCL_OK) { CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } CACHE_STACK_INFO(); @@ -5801,14 +5732,13 @@ TRACE(("%s \"%.30s\" => ", tclStringClassTable[tblIdx].name, O2S(valuePtr))); ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &slength); match = 1; if (slength > 0) { - int ch; end = ustring1 + slength; for (p=ustring1 ; p ", O2S(valuePtr), O2S(value2Ptr))); /* * Compile and match the regular expression. */ - { - Tcl_RegExp regExpr = - Tcl_GetRegExpFromObj(interp, value2Ptr, cflags); - - if (regExpr == NULL) { - TRACE_ERROR(interp); - goto gotError; - } - match = Tcl_RegExpExecObj(interp, regExpr, valuePtr, 0, 0, 0); - if (match < 0) { - TRACE_ERROR(interp); - goto gotError; - } - } - - TRACE_APPEND(("%d\n", match)); + DECACHE_STACK_INFO(); + Tcl_RegExp regExpr = Tcl_GetRegExpFromObj(interp, value2Ptr, cflags); + if (regExpr == NULL) { + CACHE_STACK_INFO(); + TRACE_ERROR(interp); + goto gotError; + } + match = Tcl_RegExpExecObj(interp, regExpr, valuePtr, 0, 0, 0); + CACHE_STACK_INFO(); + if (match < 0) { + TRACE_ERROR(interp); + goto gotError; + } /* * Peep-hole optimisation: if you're about to jump, do jump from here. * Adjustment is 2 due to the nocase byte. */ + TRACE_APPEND(("%d\n", match)); JUMP_PEEPHOLE_F(match, 2, 2); } - break; + } case INST_IS_EMPTY: { int empty = Tcl_IsEmpty(OBJ_AT_TOS); TRACE(("\"%.30s\" => %d", O2S(OBJ_AT_TOS), empty)); JUMP_PEEPHOLE_F(empty, 1, 1); } - break; /* * End of string-related instructions. * ----------------------------------------------------------------- * Start of numeric operator instructions. @@ -6141,11 +6064,10 @@ } wResult = (Tcl_WideInt)((Tcl_WideUInt)w1 - (Tcl_WideUInt)w2*(Tcl_WideUInt)wResult); goto wideResultOfArithmetic; } - break; case INST_RSHIFT: if (w2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); @@ -6190,11 +6112,10 @@ */ wResult = w1 >> ((int) w2); goto wideResultOfArithmetic; } - break; case INST_LSHIFT: if (w2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); @@ -6380,11 +6301,10 @@ NEXT_INST_F(1, 2, 1); } TclSetIntObj(valuePtr, wResult); TRACE(("%s\n", O2S(valuePtr))); NEXT_INST_F0(1, 1); - break; case INST_DIV: if (w2 == 0) { TRACE(("%s %s => DIVIDE BY ZERO\n", O2S(valuePtr), O2S(value2Ptr))); @@ -6450,16 +6370,15 @@ TRACE_APPEND_NUM_OBJ(objResultPtr); NEXT_INST_F(1, 2, 1); } case INST_LNOT: { - int b; - valuePtr = OBJ_AT_TOS; /* TODO - check claim that taking address of b harms performance */ /* TODO - consider optimization search for constants */ + int b; if (TclGetBooleanFromObj(NULL, valuePtr, &b) != TCL_OK) { TRACE(("\"%.20s\" => ERROR: illegal type %s\n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); DECACHE_STACK_INFO(); IllegalExprOperandType(interp, "", pc, valuePtr); @@ -6523,11 +6442,10 @@ switch (type1) { case TCL_NUMBER_NAN: /* -NaN => NaN */ TRACE_APPEND_NUM_OBJ(valuePtr); NEXT_INST_F0(1, 0); - break; case TCL_NUMBER_INT: w1 = *((const Tcl_WideInt *) ptr1); if (w1 != WIDE_MIN) { if (Tcl_IsShared(valuePtr)) { TclNewIntObj(objResultPtr, -w1); @@ -6536,11 +6454,13 @@ } TclSetIntObj(valuePtr, -w1); TRACE_APPEND_NUM_OBJ(valuePtr); NEXT_INST_F0(1, 0); } - /* FALLTHROUGH */ + TCL_FALLTHROUGH(); + default: + break; } objResultPtr = ExecuteExtendedUnaryMathOp(*pc, valuePtr); if (objResultPtr != NULL) { TRACE_APPEND_NUM_OBJ(objResultPtr); NEXT_INST_F(1, 1, 1); @@ -6632,11 +6552,10 @@ } TclInvalidateStringRep(valuePtr); TRACE_APPEND(("numeric, same Tcl_Obj\n")); NEXT_INST_F0(1, 0); } - break; /* * End of numeric operator instructions. * ----------------------------------------------------------------- */ @@ -6649,11 +6568,10 @@ int res = (TclSetBooleanFromAny(NULL, valuePtr) == TCL_OK); objResultPtr = TCONST(res); } TRACE_WITH_OBJ(("\"%.30s\" => ", O2S(valuePtr)), objResultPtr); NEXT_INST_F(1, 0, 1); - break; case INST_BREAK: /* DECACHE_STACK_INFO(); Tcl_ResetResult(interp); @@ -6750,10 +6668,11 @@ * Jump directly to the INST_FOREACH_STEP instruction; the C code just * falls through. */ pc += 5 - infoPtr->loopCtTemp; + TCL_FALLTHROUGH(); case INST_FOREACH_STEP: /* TODO: address abstract list indexing here! */ /* * "Step" a foreach loop (i.e., begin its next iteration) by assigning * the next value list element to each loop var. @@ -6843,11 +6762,11 @@ Tcl_IncrRefCount(valuePtr); } } else { DECACHE_STACK_INFO(); if (TclPtrSetVarIdx(interp, varPtr, NULL, NULL, NULL, - valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){ + valuePtr, TCL_LEAVE_ERR_MSG, varIndex) == NULL) { CACHE_STACK_INFO(); TRACE_APPEND(("ERROR init. index temp %" SIZEd ": %s\n", varIndex, O2S(Tcl_GetObjResult(interp)))); goto gotError; } @@ -6864,14 +6783,12 @@ TRACE_APPEND(("loop has no more iterations\n")); #ifdef TCL_COMPILE_DEBUG NEXT_INST_F0(1, 0); #else - /* - * FALL THROUGH - */ pc++; + TCL_FALLTHROUGH(); #endif case INST_FOREACH_END: /* THIS INSTRUCTION IS ONLY CALLED AS A BREAK TARGET */ tmpPtr = OBJ_AT_TOS; infoPtr = (ForeachInfo *)tmpPtr->internalRep.twoPtrValue.ptr1; @@ -6897,11 +6814,10 @@ objPtr = OBJ_AT_DEPTH(3 + numLists); Tcl_ListObjAppendElement(NULL, objPtr, OBJ_AT_TOS); NEXT_INST_F0(1, 1); } - break; case INST_BEGIN_CATCH: /* * Record start of the catch command with exception range index equal * to the operand. Push the current stack depth onto the special catch @@ -6911,21 +6827,19 @@ *(++catchTop) = (Tcl_Obj *)INT2PTR(CURR_DEPTH); TRACE(("%u => catchTop=%" SIZEd ", stackTop=%" SIZEd "\n", TclGetUInt4AtPtr(pc + 1), (Tcl_Size)(catchTop - initCatchTop - 1), CURR_DEPTH)); NEXT_INST_F0(5, 0); - break; case INST_END_CATCH: catchTop--; DECACHE_STACK_INFO(); Tcl_ResetResult(interp); CACHE_STACK_INFO(); result = TCL_OK; TRACE(("=> catchTop=%" SIZEd "\n", (Tcl_Size)(catchTop - initCatchTop - 1))); NEXT_INST_F0(1, 0); - break; case INST_PUSH_RESULT: objResultPtr = Tcl_GetObjResult(interp); TRACE_WITH_OBJ(("=> "), objResultPtr); @@ -6935,25 +6849,22 @@ TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); iPtr->objResultPtr = objPtr; NEXT_INST_F(1, 0, -1); - break; case INST_PUSH_RETURN_CODE: TclNewIntObj(objResultPtr, result); TRACE(("=> %u\n", result)); NEXT_INST_F(1, 0, 1); - break; case INST_PUSH_RETURN_OPTIONS: DECACHE_STACK_INFO(); objResultPtr = Tcl_GetReturnOptions(interp, result); CACHE_STACK_INFO(); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); - break; #ifndef REMOVE_DEPRECATED_OPCODES case INST_RETURN_CODE_BRANCH: { int code; @@ -7011,11 +6922,10 @@ } } TRACE_APPEND(("%d\n", match ? 1 : 0)); JUMP_PEEPHOLE_F(match ? 1 : 0, 5, 2); } - break; /* * ----------------------------------------------------------------- * Start of dictionary-related instructions. */ @@ -7038,11 +6948,10 @@ goto gotError; } TRACE_APPEND(("OK\n")); NEXT_INST_F0(1, 1); } - break; case INST_DICT_EXISTS: { int found; numArgs = TclGetUInt4AtPtr(pc + 1); @@ -7240,12 +7149,11 @@ cleanup = numArgs; result = Tcl_DictObjRemoveKeyList(interp, dictPtr, numArgs, &OBJ_AT_DEPTH(numArgs - 1)); break; default: - cleanup = 0; /* stop compiler warning */ - Tcl_Panic("Should not happen!"); + TCL_UNREACHABLE(); } if (result != TCL_OK) { if (allocateDict) { TclDecrRefCount(dictPtr); @@ -7352,11 +7260,10 @@ */ if (valuePtr == NULL) { Tcl_DictObjPut(NULL, dictPtr, OBJ_UNDER_TOS, Tcl_NewListObj(1, &OBJ_AT_TOS)); - break; } else if (Tcl_IsShared(valuePtr)) { valuePtr = Tcl_DuplicateObj(valuePtr); if (Tcl_ListObjAppendElement(interp, valuePtr, OBJ_AT_TOS) != TCL_OK) { TclDecrRefCount(valuePtr); @@ -7383,11 +7290,11 @@ TclInvalidateStringRep(dictPtr); } break; default: - Tcl_Panic("Should not happen!"); + TCL_UNREACHABLE(); } if (TclIsVarDirectWritable(varPtr)) { if (allocateDict) { value2Ptr = varPtr->value.objPtr; @@ -7445,10 +7352,11 @@ } varPtr = LOCAL(varIdx); if (varPtr->value.objPtr) { if (TclHasInternalRep(varPtr->value.objPtr, &dictIteratorType)) { Tcl_Panic("mis-issued dictFirst!"); + TCL_UNREACHABLE(); } TclDecrRefCount(varPtr->value.objPtr); } varPtr->value.objPtr = statePtr; Tcl_IncrRefCount(statePtr); @@ -7465,10 +7373,11 @@ (irPtr = TclFetchInternalRep(statePtr, &dictIteratorType))) { searchPtr = (Tcl_DictSearch *)irPtr->twoPtrValue.ptr1; Tcl_DictObjNext(searchPtr, &keyPtr, &valuePtr, &done); } else { Tcl_Panic("mis-issued dictNext!"); + TCL_UNREACHABLE(); } } pushDictIteratorResult: if (done) { TclNewObj(emptyPtr); @@ -7517,10 +7426,11 @@ TRACE_ERROR(interp); goto gotError; } if (length != duiPtr->length) { Tcl_Panic("dictUpdateStart argument length mismatch"); + TCL_UNREACHABLE(); } for (i=0 ; i "), objResultPtr); NEXT_INST_F(2, 0, 1); } - break; default: Tcl_Panic("TclNRExecuteByteCode: unrecognized opCode %u", *pc); } /* end of switch on opCode */ @@ -7761,18 +7669,23 @@ */ processExceptionReturn: #ifdef TCL_COMPILE_DEBUG switch (*pc) { +#ifndef REMOVE_DEPRECATED_OPCODES case INST_INVOKE_STK1: numArgs = TclGetUInt1AtPtr(pc + 1); TRACE(("%u => ... after \"%.20s\": ", (unsigned)numArgs, cmdNameBuf)); break; +#endif // REMOVE_DEPRECATED_OPCODES case INST_INVOKE_STK: numArgs = TclGetUInt4AtPtr(pc + 1); TRACE(("%u => ... after \"%.20s\": ", (unsigned)numArgs, cmdNameBuf)); break; + case INST_INVOKE_EXPANDED: + TRACE((" => ... after \"%.20s\": ", cmdNameBuf)); + break; case INST_EVAL_STK: /* * Note that the object at stacktop has to be used before doing * the cleanup. */ @@ -8041,48 +7954,41 @@ return result; /* * INST_START_CMD failure case removed where it doesn't bother that much * - * Remark that if the interpreter is marked for deletion its - * compileEpoch is modified, so that the epoch check also verifies - * that the interp is not deleted. If no outside call has been made - * since the last check, it is safe to omit the check. + * Remark that if the interpreter is marked for deletion its compileEpoch + * is modified, so that the epoch check also verifies that the interp is + * not deleted. If no outside call has been made since the last check, it + * is safe to omit the check. * case INST_START_CMD: */ - instStartCmdFailed: - { - const char *bytes; - Tcl_Size xxx1length; - unsigned offset; - - xxx1length = 0; - - if (TclInterpReady(interp) == TCL_ERROR) { - goto gotError; - } - - /* - * We used to switch to direct eval; for NRE-awareness we now - * compile and eval the command so that this evaluation does not - * add a new TEBC instance. Bug [2910748], bug [fa6bf38d07] - * - * TODO: recompile, search this command and eval a code starting from, - * so that this evaluation does not add a new TEBC instance without - * NRE-trampoline. - */ - - codePtr->flags |= TCL_BYTECODE_RECOMPILE; - bytes = GetSrcInfoForPc(pc, codePtr, &xxx1length, NULL, NULL); - offset = TclGetUInt4AtPtr(pc + 1); - pc += (offset - 1); - assert(bytes); - PUSH_OBJECT(Tcl_NewStringObj(bytes, xxx1length)); - goto instEvalStk; - } + instStartCmdFailed: + if (TclInterpReady(interp) == TCL_ERROR) { + goto gotError; + } + + /* + * We used to switch to direct eval; for NRE-awareness we now compile and + * eval the command so that this evaluation does not add a new TEBC + * instance. Bug [2910748], bug [fa6bf38d07] + * + * TODO: recompile, search this command and eval a code starting from, + * so that this evaluation does not add a new TEBC instance without + * NRE-trampoline. + */ + + codePtr->flags |= TCL_BYTECODE_RECOMPILE; + Tcl_Size xxx1length = 0; + const char *bytes = GetSrcInfoForPc(pc, codePtr, &xxx1length, NULL, NULL); + unsigned offset = TclGetUInt4AtPtr(pc + 1); + pc += offset - 1; + assert(bytes); + PUSH_OBJECT(Tcl_NewStringObj(bytes, xxx1length)); + goto instEvalStk; } #undef codePtr #undef iPtr #undef bcFramePtr @@ -8416,12 +8322,11 @@ Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); invalid = mp_isneg(&big2); mp_clear(&big2); break; default: - /* Unused, here to silence compiler warning */ - invalid = 0; + TCL_UNREACHABLE(); } if (invalid) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); return GENERAL_ARITHMETIC_ERROR; @@ -8494,12 +8399,11 @@ Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); zero = !mp_isneg(&big1); mp_clear(&big1); break; default: - /* Unused, here to silence compiler warning. */ - zero = 0; + TCL_UNREACHABLE(); } if (zero) { return constants[0]; } WIDE_RESULT(-1); @@ -8551,18 +8455,18 @@ if (err == MP_OKAY) { switch (opcode) { case INST_BITAND: err = mp_and(&big1, &big2, &bigResult); break; - case INST_BITOR: err = mp_or(&big1, &big2, &bigResult); break; - case INST_BITXOR: err = mp_xor(&big1, &big2, &bigResult); break; + default: + TCL_UNREACHABLE(); } } if (err != MP_OKAY) { return OUT_OF_MEMORY; } @@ -8584,12 +8488,11 @@ break; case INST_BITXOR: wResult = w1 ^ w2; break; default: - /* Unused, here to silence compiler warning. */ - wResult = 0; + TCL_UNREACHABLE(); } WIDE_RESULT(wResult); case INST_EXPON: { int oddExponent = 0, negativeExponent = 0; @@ -8645,11 +8548,11 @@ return EXPONENT_OF_ZERO; case -1: if (oddExponent) { WIDE_RESULT(-1); } - /* fallthrough */ + TCL_FALLTHROUGH(); case 1: /* * 1 to any power is 1. */ @@ -8656,11 +8559,10 @@ return constants[1]; } } } if (negativeExponent) { - /* * Integers with magnitude greater than 1 raise to a negative * power yield the answer zero (see TIP 123). */ return constants[0]; @@ -8669,27 +8571,27 @@ if (type1 != TCL_NUMBER_INT) { goto overflowExpon; } switch (w1) { - case 0: - /* - * Zero to a positive power is zero. - */ - - return constants[0]; - case 1: - /* - * 1 to any power is 1. - */ - - return constants[1]; - case -1: - if (!oddExponent) { - return constants[1]; - } - WIDE_RESULT(-1); + case 0: + /* + * Zero to a positive power is zero. + */ + + return constants[0]; + case 1: + /* + * 1 to any power is 1. + */ + + return constants[1]; + case -1: + if (!oddExponent) { + return constants[1]; + } + WIDE_RESULT(-1); } /* * We refuse to accept exponent arguments that exceed one mp_digit * which means the max exponent value is 2**28-1 = 0x0FFFFFFF = @@ -8833,12 +8735,11 @@ */ dResult = d1 / d2; break; default: - /* Unused, here to silence compiler warning. */ - dResult = 0; + TCL_UNREACHABLE(); } doubleResult: #ifndef ACCEPT_NAN /* @@ -8922,15 +8823,11 @@ wResult -= 1; } break; default: - /* - * Unused, here to silence compiler warning. - */ - - wResult = 0; + TCL_UNREACHABLE(); } WIDE_RESULT(wResult); } @@ -8977,14 +8874,14 @@ } } mp_clear(&big1); mp_clear(&big2); BIG_RESULT(&bigResult); + default: + Tcl_Panic("unexpected opcode"); + TCL_UNREACHABLE(); } - - Tcl_Panic("unexpected opcode"); - return NULL; } static Tcl_Obj * ExecuteExtendedUnaryMathOp( int opcode, /* What operation to perform. */ @@ -9035,14 +8932,14 @@ err = mp_neg(&big, &big); if (err != MP_OKAY) { return OUT_OF_MEMORY; } BIG_RESULT(&big); + default: + Tcl_Panic("unexpected opcode"); + TCL_UNREACHABLE(); } - - Tcl_Panic("unexpected opcode"); - return NULL; } #undef WIDE_RESULT #undef BIG_RESULT #undef DOUBLE_RESULT @@ -9128,12 +9025,13 @@ } else { compare = MP_LT; } mp_clear(&big2); return compare; + default: + TCL_UNREACHABLE(); } - break; case TCL_NUMBER_DOUBLE: d1 = *((const double *)ptr1); switch (type2) { case TCL_NUMBER_DOUBLE: @@ -9175,12 +9073,13 @@ mp_clear(&big2); goto doubleCompare; } Tcl_InitBignumFromDouble(NULL, d1, &big1); goto bigCompare; + default: + TCL_UNREACHABLE(); } - break; case TCL_NUMBER_BIG: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); switch (type2) { case TCL_NUMBER_INT: @@ -9212,14 +9111,16 @@ bigCompare: compare = mp_cmp(&big1, &big2); mp_clear(&big1); mp_clear(&big2); return compare; + default: + TCL_UNREACHABLE(); } - break; default: Tcl_Panic("unexpected number type"); + TCL_UNREACHABLE(); } return TCL_ERROR; } #ifdef TCL_COMPILE_DEBUG @@ -9748,11 +9649,12 @@ return rangePtr; } if (searchMode == TCL_BREAK) { return rangePtr; } - if (searchMode == TCL_CONTINUE && rangePtr->continueOffset != TCL_INDEX_NONE){ + if (searchMode == TCL_CONTINUE + && rangePtr->continueOffset != TCL_INDEX_NONE) { return rangePtr; } } } return NULL; Index: generic/tclFileName.c ================================================================== --- generic/tclFileName.c +++ generic/tclFileName.c @@ -1231,10 +1231,12 @@ i++; break; case GLOB_LAST: /* -- */ i++; goto endOfForLoop; + default: + TCL_UNREACHABLE(); } } endOfForLoop: if ((globFlags & TCL_GLOBMODE_TAILS) && (pathOrDir == NULL)) { Index: generic/tclIOCmd.c ================================================================== --- generic/tclIOCmd.c +++ generic/tclIOCmd.c @@ -133,11 +133,11 @@ if (strcmp(TclGetString(objv[1]), "-nonewline") == 0) { chanObjPtr = objv[2]; string = objv[3]; break; } - /* Fall through */ + TCL_FALLTHROUGH(); default: /* [puts] or * [puts some bad number of arguments...] */ Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? ?channel? string"); return TCL_ERROR; } @@ -1603,11 +1603,11 @@ if (Tcl_GetIntFromObj(interp, objv[a], &backlog) != TCL_OK) { return TCL_ERROR; } break; default: - Tcl_Panic("Tcl_SocketObjCmd: bad option index to SocketOptions"); + TCL_UNREACHABLE(); } } if (server) { host = myaddr; /* NULL implies INADDR_ANY */ if (myport != 0) { @@ -1808,10 +1808,12 @@ } break; case FcopyCommand: cmdPtr = objv[i+1]; break; + default: + TCL_UNREACHABLE(); } } return TclCopyChannel(interp, inChan, outChan, toRead, cmdPtr); } @@ -1874,10 +1876,12 @@ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-1)); } else { Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_OutputBuffered(chan))); } break; + default: + TCL_UNREACHABLE(); } return TCL_OK; } /* Index: generic/tclIORChan.c ================================================================== --- generic/tclIORChan.c +++ generic/tclIORChan.c @@ -2107,10 +2107,12 @@ events |= TCL_READABLE; break; case EVENT_WRITE: events |= TCL_WRITABLE; break; + default: + TCL_UNREACHABLE(); } listc --; } *mask = events; Index: generic/tclIcu.c ================================================================== --- generic/tclIcu.c +++ generic/tclIcu.c @@ -759,11 +759,11 @@ dstLen = ucnv_fromUChars(ucnvPtr, Tcl_DStringValue(dsOutPtr), (int)dstLen, utf16, (int)utf16len, &status); if (U_SUCCESS(status)) { break; } - /* FALLTHRU */ + TCL_FALLTHROUGH(); default: Tcl_DStringFree(dsOutPtr); ucnv_close(ucnvPtr); return IcuError(interp, "ICU error while encoding", status); } @@ -839,11 +839,11 @@ dstLen = ucnv_toUChars(ucnvPtr, (UCharx *)Tcl_DStringValue(dsOutPtr), dstCapacity, (const char *)bytes, (int)nbytes, &status); if (U_SUCCESS(status)) { break; } - /* FALLTHRU */ + TCL_FALLTHROUGH(); default: Tcl_DStringFree(dsOutPtr); ucnv_close(ucnvPtr); return IcuError(interp, "ICU error while decoding", status); } @@ -935,11 +935,11 @@ normLen = unorm2_normalize( normalizer, utf16, (int)utf16len, normPtr, normLen, &status); if (U_SUCCESS(status)) { break; } - /* FALLTHRU */ + TCL_FALLTHROUGH(); default: Tcl_DStringFree(dsOutPtr); return IcuError(interp, "String normalization failed", status); } } @@ -998,10 +998,12 @@ case OPT_FAILINDEX: /* TBD */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "Option -failindex not implemented.", TCL_INDEX_NONE)); return TCL_ERROR; + default: + TCL_UNREACHABLE(); } } *strictPtr = strict; *failindexVarPtr = NULL; return TCL_OK; @@ -1167,10 +1169,12 @@ if (Tcl_GetIndexFromObj(interp, objv[i], normalizationForms, "normalization mode", 0, &mode) != TCL_OK) { return TCL_ERROR; } break; + default: + TCL_UNREACHABLE(); } } Tcl_DString dsIn; Tcl_DString dsNorm; @@ -1321,11 +1325,12 @@ }; /* Going back down to ICU version 60 */ while ((icu_fns.libs[0] == NULL) && (icuversion[1] >= '6')) { if (--icuversion[2] < '0') { - icuversion[1]--; icuversion[2] = '9'; + icuversion[1]--; + icuversion[2] = '9'; } #if defined(__CYGWIN__) i = 2; #else i = 0; Index: generic/tclInt.h ================================================================== --- generic/tclInt.h +++ generic/tclInt.h @@ -138,10 +138,36 @@ # undef Tcl_ConditionWait # define Tcl_ConditionWait(condPtr, mutexPtr, timePtr) # undef Tcl_ConditionFinalize # define Tcl_ConditionFinalize(condPtr) #endif + +// A way to mark a code path as unreachable. +#ifndef TCL_UNREACHABLE +#if defined(__STDC__) && __STDC__ >= 202311L +#include +#define TCL_UNREACHABLE() unreachable() +#elif defined(__GNUC__) +#define TCL_UNREACHABLE() __builtin_unreachable() +#elif defined(_MSC_VER) +#include +#define TCL_UNREACHABLE() __assume(false) +#else +#define TCL_UNREACHABLE() ((void) 0) +#endif +#endif // TCL_UNREACHABLE + +#ifndef TCL_FALLTHROUGH +#if defined(__STDC__) && __STDC__ >= 202311L +#define TCL_FALLTHROUGH() [[fallthrough]] +#elif defined(__GNUC__) +#define TCL_FALLTHROUGH() __attribute__((fallthrough)) +#else +// Nothing documented as an alternative to the standard [[fallthrough]]. +#define TCL_FALLTHROUGH() ((void) 0) +#endif +#endif // TCL_FALLTHROUGH /* * The following procedures allow namespaces to be customized to support * special name resolution rules for commands/variables. */ Index: generic/tclInterp.c ================================================================== --- generic/tclInterp.c +++ generic/tclInterp.c @@ -754,10 +754,12 @@ flags |= TCL_CANCEL_UNWIND; break; case OPT_LAST: i++; goto endOfForLoop; + default: + TCL_UNREACHABLE(); } } endOfForLoop: if (i < objc - 2) { @@ -1020,12 +1022,11 @@ case LIMIT_TYPE_COMMANDS: return ChildCommandLimitCmd(interp, childInterp, 4, objc,objv); case LIMIT_TYPE_TIME: return ChildTimeLimitCmd(interp, childInterp, 4, objc, objv); default: - Tcl_Panic("unreachable"); - return TCL_ERROR; + TCL_UNREACHABLE(); } } case OPT_MARKTRUSTED: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "path"); @@ -1145,12 +1146,11 @@ return TCL_ERROR; } return TCL_OK; } default: - Tcl_Panic("unreachable"); - return TCL_ERROR; + TCL_UNREACHABLE(); } } /* *--------------------------------------------------------------------------- @@ -2675,13 +2675,14 @@ switch (limitType) { case LIMIT_TYPE_COMMANDS: return ChildCommandLimitCmd(interp, childInterp, 3, objc,objv); case LIMIT_TYPE_TIME: return ChildTimeLimitCmd(interp, childInterp, 3, objc, objv); + default: + TCL_UNREACHABLE(); } } - break; case OPT_MARKTRUSTED: if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } @@ -2690,10 +2691,12 @@ if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "?newlimit?"); return TCL_ERROR; } return ChildRecursionLimit(interp, childInterp, objc - 2, objv + 2); + default: + TCL_UNREACHABLE(); } return TCL_ERROR; } @@ -4527,10 +4530,12 @@ if (Tcl_LimitTypeEnabled(childInterp, TCL_LIMIT_COMMANDS)) { Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_LimitGetCommands(childInterp))); } break; + default: + TCL_UNREACHABLE(); } return TCL_OK; } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) { Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?"); return TCL_ERROR; @@ -4577,10 +4582,12 @@ Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP", "BADVALUE", (char *)NULL); return TCL_ERROR; } break; + default: + TCL_UNREACHABLE(); } } if (scriptObj != NULL) { SetScriptLimitCallback(interp, TCL_LIMIT_COMMANDS, childInterp, (scriptLen > 0 ? scriptObj : NULL)); @@ -4727,10 +4734,12 @@ Tcl_LimitGetTime(childInterp, &limitMoment); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(limitMoment.sec)); } break; + default: + TCL_UNREACHABLE(); } return TCL_OK; } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) { Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?"); return TCL_ERROR; @@ -4800,10 +4809,12 @@ "BADVALUE", (char *)NULL); return TCL_ERROR; } limitMoment.sec = (long long) tmp; break; + default: + TCL_UNREACHABLE(); } } if (milliObj != NULL || secObj != NULL) { if (milliObj != NULL) { /* Index: generic/tclLink.c ================================================================== --- generic/tclLink.c +++ generic/tclLink.c @@ -1314,11 +1314,11 @@ } linkPtr->lastValue.uw = LinkedVar(Tcl_WideUInt); Tcl_Obj *uwObj; TclNewUIntObj(uwObj, linkPtr->lastValue.uw); return uwObj; - } + } case TCL_LINK_STRING: p = LinkedVar(char *); if (p == NULL) { TclNewLiteralStringObj(resultObj, "NULL"); Index: generic/tclLoad.c ================================================================== --- generic/tclLoad.c +++ generic/tclLoad.c @@ -155,17 +155,18 @@ } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } - ++objv; --objc; + ++objv; + --objc; if (LOAD_GLOBAL == index) { flags |= TCL_LOAD_GLOBAL; } else if (LOAD_LAZY == index) { flags |= TCL_LOAD_LAZY; } else { - break; + break; } } if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, savedobjv, "?-global? ?-lazy? ?--? fileName ?prefix? ?interp?"); @@ -597,10 +598,12 @@ keepLibrary = 1; break; case UNLOAD_LAST: /* -- */ i++; goto endOfForLoop; + default: + TCL_UNREACHABLE(); } } endOfForLoop: if ((objc-i < 1) || (objc-i > 3)) { Tcl_WrongNumArgs(interp, 1, objv, Index: generic/tclNamesp.c ================================================================== --- generic/tclNamesp.c +++ generic/tclNamesp.c @@ -4767,27 +4767,27 @@ } } TclNewObj(resultPtr); switch (lookupType) { - case 0: { /* -command */ + case 0:; /* -command */ Tcl_Command cmd = Tcl_GetCommandFromObj(interp, objv[objc-1]); if (cmd != NULL) { Tcl_GetCommandFullName(interp, cmd, resultPtr); } break; - } - case 1: { /* -variable */ + case 1:; /* -variable */ Tcl_Var var = Tcl_FindNamespaceVar(interp, TclGetString(objv[objc-1]), NULL, /*flags*/ 0); if (var != NULL) { Tcl_GetVariableFullName(interp, var, resultPtr); } break; - } + default: + TCL_UNREACHABLE(); } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } Index: generic/tclOOBasic.c ================================================================== --- generic/tclOOBasic.c +++ generic/tclOOBasic.c @@ -1187,17 +1187,11 @@ if (mPtr->declaringClassPtr != NULL) { declarerPtr = mPtr->declaringClassPtr->thisPtr; } else if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; } else { - /* - * This should be unreachable code. - */ - - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "method without declarer!", TCL_AUTO_LENGTH)); - return TCL_ERROR; + TCL_UNREACHABLE(); } result[0] = TclOOObjectName(interp, declarerPtr); result[1] = TclOOObjectName(interp, callerPtr->oPtr); if (callerPtr->callPtr->flags & CONSTRUCTOR) { @@ -1219,17 +1213,11 @@ if (mPtr->declaringClassPtr != NULL) { declarerPtr = mPtr->declaringClassPtr->thisPtr; } else if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; } else { - /* - * This should be unreachable code. - */ - - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "method without declarer!", TCL_AUTO_LENGTH)); - return TCL_ERROR; + TCL_UNREACHABLE(); } result[0] = TclOOObjectName(interp, declarerPtr); if (contextPtr->callPtr->flags & CONSTRUCTOR) { result[1] = declarerPtr->fPtr->constructorName; @@ -1264,17 +1252,11 @@ if (mPtr->declaringClassPtr != NULL) { declarerPtr = mPtr->declaringClassPtr->thisPtr; } else if (mPtr->declaringObjectPtr != NULL) { declarerPtr = mPtr->declaringObjectPtr; } else { - /* - * This should be unreachable code. - */ - - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "method without declarer!", TCL_AUTO_LENGTH)); - return TCL_ERROR; + TCL_UNREACHABLE(); } result[0] = TclOOObjectName(interp, declarerPtr); result[1] = mPtr->namePtr; Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); return TCL_OK; @@ -1282,12 +1264,13 @@ case SELF_CALL: result[0] = TclOORenderCallChain(interp, contextPtr->callPtr); TclNewIndexObj(result[1], contextPtr->index); Tcl_SetObjResult(interp, Tcl_NewListObj(2, result)); return TCL_OK; + default: + TCL_UNREACHABLE(); } - return TCL_ERROR; } /* * ---------------------------------------------------------------------- * Index: generic/tclOOCall.c ================================================================== --- generic/tclOOCall.c +++ generic/tclOOCall.c @@ -1665,10 +1665,11 @@ default: FOREACH(superPtr, clsPtr->superclasses) { AddClassFiltersToCallContext(oPtr, superPtr, cbPtr, doneFilters, flags); } + TCL_FALLTHROUGH(); case 0: return; } } @@ -1752,11 +1753,11 @@ if (AddPrivatesFromClassChainToCallContext(superPtr, contextCls, methodName, cbPtr, doneFilters, flags, filterDecl)) { return 1; } } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 0: return 0; } } @@ -1847,11 +1848,11 @@ default: FOREACH(superPtr, classPtr->superclasses) { privateDanger |= AddSimpleClassChainToCallContext(superPtr, methodNameObj, cbPtr, doneFilters, flags, filterDecl); } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 0: return privateDanger; } } @@ -2085,10 +2086,11 @@ goto tailRecurse; default: FOREACH(superPtr, classPtr->superclasses) { AddSimpleClassDefineNamespaces(superPtr, definePtr, flags); } + TCL_FALLTHROUGH(); case 0: return; } } Index: generic/tclOODefineCmds.c ================================================================== --- generic/tclOODefineCmds.c +++ generic/tclOODefineCmds.c @@ -1736,13 +1736,13 @@ /* * Update the correct field of the class definition. */ - if (kind) { + if (kind) { // -instance storagePtr = &clsPtr->objDefinitionNs; - } else { + } else { // -class storagePtr = &clsPtr->clsDefinitionNs; } if (*storagePtr != NULL) { Tcl_DecrRefCount(*storagePtr); } @@ -2095,10 +2095,12 @@ isPublic = TRUE_PRIVATE_METHOD; break; case MODE_UNEXPORT: isPublic = 0; break; + default: + TCL_UNREACHABLE(); } } else { if (IsPrivateDefine(interp)) { isPublic = TRUE_PRIVATE_METHOD; } else { Index: generic/tclOOInfo.c ================================================================== --- generic/tclOOInfo.c +++ generic/tclOOInfo.c @@ -486,10 +486,12 @@ if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "objName className"); return TCL_ERROR; } break; + default: + TCL_UNREACHABLE(); } /* * Perform the check. Note that we can guarantee that we will not fail * from here on; "failures" result in a false-TCL_OK result. @@ -539,10 +541,12 @@ } if (o2Ptr->classPtr != NULL) { result = TclOOIsReachable(o2Ptr->classPtr, oPtr->selfCls); } break; + default: + TCL_UNREACHABLE(); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; failPrecondition: @@ -629,10 +633,12 @@ if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0, &scope) != TCL_OK) { return TCL_ERROR; } break; + default: + TCL_UNREACHABLE(); } } } if (scope != SCOPE_DEFAULT) { recurse = 0; @@ -1118,13 +1124,13 @@ if (objc == 3 && Tcl_GetIndexFromObj(interp, objv[2], kindList, "kind", 0, &kind) != TCL_OK) { return TCL_ERROR; } - if (kind) { + if (kind) { // -instance nsNamePtr = clsPtr->objDefinitionNs; - } else { + } else { // -class nsNamePtr = clsPtr->clsDefinitionNs; } if (nsNamePtr) { Tcl_SetObjResult(interp, nsNamePtr); } @@ -1385,10 +1391,12 @@ if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0, &scope) != TCL_OK) { return TCL_ERROR; } break; + default: + TCL_UNREACHABLE(); } } } if (scope != SCOPE_DEFAULT) { recurse = 0; @@ -1400,10 +1408,12 @@ flag = PUBLIC_METHOD; break; case SCOPE_UNEXPORTED: flag = 0; break; + default: + TCL_UNREACHABLE(); } } TclNewObj(resultObj); if (recurse) { Index: generic/tclOOProp.c ================================================================== --- generic/tclOOProp.c +++ generic/tclOOProp.c @@ -1097,10 +1097,12 @@ if (Tcl_GetIndexFromObj(interp, argObj, kinds, "kind", 0, &kind) != TCL_OK) { return TCL_ERROR; } break; + default: + TCL_UNREACHABLE(); } } /* * Install the property. Note that TclOOInstallStdPropertyImpls @@ -1219,10 +1221,12 @@ writable = 0; break; case PROP_WRITABLE: writable = 1; break; + default: + TCL_UNREACHABLE(); } } /* * Get the properties. @@ -1277,10 +1281,12 @@ writable = 0; break; case PROP_WRITABLE: writable = 1; break; + default: + TCL_UNREACHABLE(); } } /* * Get the properties. Index: generic/tclParse.c ================================================================== --- generic/tclParse.c +++ generic/tclParse.c @@ -1379,22 +1379,27 @@ * underscore: in this case, there is no variable name and the token is * just "$". */ if (*src == '{') { - char ch; int braceCount = 0; + char ch; + int braceCount = 0; src++; numBytes--; tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->start = src; tokenPtr->numComponents = 0; ch = *src; while (numBytes && (braceCount>0 || ch != '}')) { switch (ch) { - case '{': braceCount++; break; - case '}': braceCount--; break; + case '{': + braceCount++; + break; + case '}': + braceCount--; + break; case '\\': /* if 2 or more left, consume 2, else consume * just the \ and let it run into the end */ if (numBytes > 1) { src++; Index: generic/tclPathObj.c ================================================================== --- generic/tclPathObj.c +++ generic/tclPathObj.c @@ -678,14 +678,11 @@ Tcl_IncrRefCount(resultPtr); return resultPtr; } } default: - /* We should never get here */ - Tcl_Panic("Bad portion to TclPathPart"); - /* For less clever compilers */ - return NULL; + TCL_UNREACHABLE(); } } else if (fsPathPtr->cwdPtr != NULL) { /* Relative path */ goto standardPath; } else { Index: generic/tclPkg.c ================================================================== --- generic/tclPkg.c +++ generic/tclPkg.c @@ -1097,17 +1097,16 @@ &optionIndex) != TCL_OK) { return TCL_ERROR; } switch (optionIndex) { case PKG_FILES: { - PkgFiles *pkgFiles; - if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "package"); return TCL_ERROR; } - pkgFiles = (PkgFiles *) Tcl_GetAssocData(interp, "tclPkgFiles", NULL); + PkgFiles *pkgFiles = (PkgFiles *) + Tcl_GetAssocData(interp, "tclPkgFiles", NULL); if (pkgFiles) { Tcl_HashEntry *entry = Tcl_FindHashEntry(&pkgFiles->table, TclGetString(objv[2])); if (entry) { @@ -1115,16 +1114,15 @@ } } break; } case PKG_FORGET: { - const char *keyString; PkgFiles *pkgFiles = (PkgFiles *) Tcl_GetAssocData(interp, "tclPkgFiles", NULL); for (i = 2; i < objc; i++) { - keyString = TclGetString(objv[i]); + const char *keyString = TclGetString(objv[i]); if (pkgFiles) { hPtr = Tcl_FindHashEntry(&pkgFiles->table, keyString); if (hPtr) { Tcl_Obj *obj = (Tcl_Obj *)Tcl_GetHashValue(hPtr); Tcl_DeleteHashEntry(hPtr); @@ -1156,12 +1154,11 @@ } break; } case PKG_IFNEEDED: { Tcl_Size length; - int res; - char *argv3i, *avi; + char *argv3i; if ((objc != 4) && (objc != 5)) { Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?"); return TCL_ERROR; } @@ -1182,17 +1179,18 @@ } argv3 = TclGetStringFromObj(objv[3], &length); for (availPtr = pkgPtr->availPtr, prevPtr = NULL; availPtr != NULL; prevPtr = availPtr, availPtr = availPtr->nextPtr) { + char *avi; if (CheckVersionAndConvert(interp, availPtr->version, &avi, NULL) != TCL_OK) { Tcl_Free(argv3i); return TCL_ERROR; } - res = CompareVersions(avi, argv3i, NULL); + int res = CompareVersions(avi, argv3i, NULL); Tcl_Free(avi); if (res == 0) { if (objc == 4) { Tcl_Free(argv3i); @@ -1393,22 +1391,21 @@ PkgRequireCore, (void *) argv2, INT2PTR(newobjc), newObjvPtr, NULL); return TCL_OK; } break; - case PKG_UNKNOWN: { - Tcl_Size length; - + case PKG_UNKNOWN: if (objc == 2) { if (iPtr->packageUnknown != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(iPtr->packageUnknown, -1)); } } else if (objc == 3) { if (iPtr->packageUnknown != NULL) { Tcl_Free(iPtr->packageUnknown); } + Tcl_Size length; argv2 = TclGetStringFromObj(objv[2], &length); if (argv2[0] == 0) { iPtr->packageUnknown = NULL; } else { DupBlock(iPtr->packageUnknown, argv2, length+1); @@ -1416,11 +1413,10 @@ } else { Tcl_WrongNumArgs(interp, 2, objv, "?command?"); return TCL_ERROR; } break; - } case PKG_PREFER: { static const char *const pkgPreferOptions[] = { "latest", "stable", NULL }; @@ -1527,11 +1523,11 @@ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(satisfies)); break; } default: - Tcl_Panic("Tcl_PackageObjCmd: bad option index to pkgOptions"); + TCL_UNREACHABLE(); } return TCL_OK; } static int Index: generic/tclProc.c ================================================================== --- generic/tclProc.c +++ generic/tclProc.c @@ -1760,11 +1760,12 @@ TCL_DTRACE_PROC_ARGS(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); } if (TCL_DTRACE_PROC_INFO_ENABLED() && iPtr->cmdFramePtr) { Tcl_Obj *info = TclInfoFrame(interp, iPtr->cmdFramePtr); - const char *a[6]; Tcl_Size i[2]; + const char *a[6]; + Tcl_Size i[2]; TclDTraceInfo(info, a, i); TCL_DTRACE_PROC_INFO(a[0], a[1], a[2], a[3], i[0], i[1], a[4], a[5]); TclDecrRefCount(info); } @@ -1873,12 +1874,11 @@ Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invoked \"%s\" outside of a loop", ((result == TCL_BREAK) ? "break" : "continue"))); Tcl_SetErrorCode(interp, "TCL", "RESULT", "UNEXPECTED", (char *)NULL); result = TCL_ERROR; - - /* FALLTHRU */ + TCL_FALLTHROUGH(); case TCL_ERROR: /* * Now it _must_ be an error, so we need to log it as such. This means * filling out the error trace. Luckily, we just hand this off to the Index: generic/tclProcess.c ================================================================== --- generic/tclProcess.c +++ generic/tclProcess.c @@ -497,11 +497,12 @@ } if (Tcl_GetIndexFromObj(interp, objv[1], switches, "switches", 0, &index) != TCL_OK) { return TCL_ERROR; } - ++objv; --objc; + ++objv; + --objc; if (STATUS_WAIT == index) { options = 0; } else { break; } Index: generic/tclScan.c ================================================================== --- generic/tclScan.c +++ generic/tclScan.c @@ -394,15 +394,15 @@ flags |= SCAN_BIG; format += 1; format += TclUtfToUniChar(format, &ch); break; } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 'j': case 'q': flags |= SCAN_LONGER; - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 'h': format += TclUtfToUniChar(format, &ch); } if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) { @@ -420,11 +420,11 @@ "field width may not be specified in %c conversion", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADWIDTH", (char *)NULL); goto error; } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 'n': case 's': if (flags & (SCAN_LONGER|SCAN_BIG)) { invalidFieldSize: buf[Tcl_UniCharToUtf(ch, buf)] = '\0'; @@ -434,13 +434,11 @@ Tcl_AppendToObj(errorMsg, " conversion", -1); Tcl_SetObjResult(interp, errorMsg); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADSIZE", (char *)NULL); goto error; } - /* - * Fall through! - */ + TCL_FALLTHROUGH(); case 'd': case 'e': case 'E': case 'f': case 'g': @@ -747,15 +745,15 @@ flags |= SCAN_BIG; format += 1; format += TclUtfToUniChar(format, &ch); break; } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 'j': case 'q': flags |= SCAN_LONGER; - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 'h': format += TclUtfToUniChar(format, &ch); } /* Index: generic/tclStrIdxTree.c ================================================================== --- generic/tclStrIdxTree.c +++ generic/tclStrIdxTree.c @@ -522,16 +522,16 @@ Tcl_SetObjResult(interp, Tcl_NewIntObj(ret - cs)); break; case O_INDEX: case O_PUTS_INDEX: { - Tcl_Obj **lstv; - Tcl_Size i, lstc; TclStrIdxTree idxTree = {NULL, NULL}; - i = 1; + Tcl_Size i = 1; while (++i < objc) { + Tcl_Obj **lstv; + Tcl_Size lstc; if (TclListObjGetElements(interp, objv[i], &lstc, &lstv) != TCL_OK) { return TCL_ERROR; } TclStrIdxTreeBuildFromList(&idxTree, lstc, lstv, NULL); @@ -540,10 +540,12 @@ TclStrIdxTreePrint(interp, idxTree.firstPtr, 0); } TclStrIdxTreeFree(idxTree.firstPtr); break; } + default: + TCL_UNREACHABLE(); } return TCL_OK; } #endif Index: generic/tclStrToD.c ================================================================== --- generic/tclStrToD.c +++ generic/tclStrToD.c @@ -670,11 +670,11 @@ } else if (c == '-') { signum = 1; state = SIGNUM; break; } - /* FALLTHROUGH */ + TCL_FALLTHROUGH(); case SIGNUM: /* * Scanned a leading + or -. Acceptable characters are digits, * period, I, and N. @@ -766,11 +766,11 @@ */ acceptState = state; acceptPoint = p; acceptLen = len; - /* FALLTHROUGH */ + TCL_FALLTHROUGH(); case ZERO_O: zeroo: if (c == '0') { numTrailZeros++; state = OCTAL; @@ -845,11 +845,11 @@ case HEXADECIMAL: acceptState = state; acceptPoint = p; acceptLen = len; - /* FALLTHROUGH */ + TCL_FALLTHROUGH(); case ZERO_X: zerox: if (c == '0') { numTrailZeros++; @@ -909,11 +909,11 @@ case BINARY: acceptState = state; acceptPoint = p; acceptLen = len; - /* FALLTHRU */ + TCL_FALLTHROUGH(); case ZERO_B: zerob: if (c == '0') { numTrailZeros++; state = BINARY; @@ -970,11 +970,11 @@ } else if ( ! isdigit(UCHAR(c))) { goto endgame; } state = DECIMAL; flags |= TCL_PARSE_INTEGER_ONLY; - /* FALLTHROUGH */ + TCL_FALLTHROUGH(); case DECIMAL: /* * Scanned an optional + or - followed by a string of decimal * digits. @@ -1022,11 +1022,11 @@ acceptLen = len; if (c == 'E' || c=='e') { state = EXPONENT_START; break; } - /* FALLTHROUGH */ + TCL_FALLTHROUGH(); case LEADING_RADIX_POINT: if (c == '0') { numDigitsAfterDp++; numTrailZeros++; @@ -1064,11 +1064,11 @@ } else if (c == '-') { exponentSignum = 1; state = EXPONENT_SIGNUM; break; } - /* FALLTHROUGH */ + TCL_FALLTHROUGH(); case EXPONENT_SIGNUM: /* * Found the E at the start of the exponent, followed by a sign * character. @@ -1184,11 +1184,11 @@ case sNANHEX: if (c == ')') { state = sNANFINISH; break; } - /* FALLTHROUGH */ + TCL_FALLTHROUGH(); case sNANPAREN: if (TclIsSpaceProcM(c)) { break; } if (numSigDigs < 13) { @@ -1513,11 +1513,11 @@ objPtr->typePtr = &tclDoubleType; break; #endif case INITIAL: /* This case only to silence compiler warning. */ - Tcl_Panic("TclParseNumber: state INITIAL can't happen here"); + TCL_UNREACHABLE(); } } /* * Format an error message when an invalid number is encountered. @@ -2310,26 +2310,32 @@ { int rv = 0; Tcl_WideUInt w = *wPtr; if (!(w & (Tcl_WideUInt) 0xFFFFFFFF)) { - w >>= 32; rv += 32; + w >>= 32; + rv += 32; } if (!(w & (Tcl_WideUInt) 0xFFFF)) { - w >>= 16; rv += 16; + w >>= 16; + rv += 16; } if (!(w & (Tcl_WideUInt) 0xFF)) { - w >>= 8; rv += 8; + w >>= 8; + rv += 8; } if (!(w & (Tcl_WideUInt) 0xF)) { - w >>= 4; rv += 4; + w >>= 4; + rv += 4; } if (!(w & 0x3)) { - w >>= 2; rv += 2; + w >>= 2; + rv += 2; } if (!(w & 0x1)) { - w >>= 1; ++rv; + w >>= 1; + ++rv; } *wPtr = w; return rv; } @@ -3173,11 +3179,13 @@ * Adjust if the logarithm was guessed wrong. */ if (b < S) { b = 10 * b; - ++m2plus; ++m2minus; ++m5; + ++m2plus; + ++m2minus; + ++m5; ilim = ilim1; --k; } /* @@ -3552,11 +3560,13 @@ * Adjust if the logarithm was guessed wrong. */ if ((err == MP_OKAY) && (b.used <= sd)) { err = mp_mul_d(&b, 10, &b); - ++m2plus; ++m2minus; ++m5; + ++m2plus; + ++m2minus; + ++m5; ilim = ilim1; --k; } /* @@ -3592,11 +3602,12 @@ } else { digit = b.dp[sd]; if (b.used > sd+1 || digit >= 10) { Tcl_Panic("wrong digit!"); } - --b.used; mp_clamp(&b); + --b.used; + mp_clamp(&b); } /* * Does the current digit put us on the low side of the exact value * but within roundoff of being exact? @@ -4568,13 +4579,15 @@ /* * Reduce numerator and denominator to lowest terms. */ if (b2 >= s2 && s2 > 0) { - b2 -= s2; s2 = 0; + b2 -= s2; + s2 = 0; } else if (s2 >= b2 && b2 > 0) { - s2 -= b2; b2 = 0; + s2 -= b2; + b2 = 0; } if (s5+1 < N_LOG2POW5 && s2+1 + log2pow5[s5+1] < 64) { /* * If 10*2**s2*5**s5 == 2**(s2+1)+5**(s5+1) fits in a 64-bit word, Index: generic/tclStringObj.c ================================================================== --- generic/tclStringObj.c +++ generic/tclStringObj.c @@ -2166,11 +2166,10 @@ allocSegment = 1; break; } case 'u': - /* FALLTHRU */ case 'd': case 'o': case 'p': case 'x': case 'X': @@ -2774,11 +2773,11 @@ } case 'p': if (sizeof(size_t) == sizeof(Tcl_WideInt)) { size = 2; } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case 'c': case 'i': case 'u': case 'd': case 'o': @@ -2869,11 +2868,11 @@ size = 3; p++; break; case 'h': size = -1; - /* FALLTHRU */ + TCL_FALLTHROUGH(); default: p++; } } while (seekingConversion); } @@ -3273,11 +3272,12 @@ } } } while (--oc); } else { /* Result will be concat of string reps. Pre-size it. */ - ov = objv; oc = objc; + ov = objv; + oc = objc; do { Tcl_Obj *pendingPtr = NULL; /* * Loop until a possibly non-empty value is reached. @@ -3357,11 +3357,12 @@ /* Only one non-empty value or zero length; return first */ /* NOTE: (length == 0) implies (last <= first) */ return objv[first]; } - objv += first; objc = (last - first + 1); + objv += first; + objc = (last - first + 1); inPlace = (flags & TCL_STRING_IN_PLACE) && !Tcl_IsShared(*objv); if (binary) { /* Efficiently produce a pure byte array result */ unsigned char *dst; @@ -3372,11 +3373,12 @@ */ if (inPlace) { Tcl_Size start = 0; - objResultPtr = *objv++; objc--; + objResultPtr = *objv++; + objc--; (void)Tcl_GetBytesFromObj(NULL, objResultPtr, &start); dst = Tcl_SetByteArrayLength(objResultPtr, length) + start; } else { objResultPtr = Tcl_NewByteArrayObj(NULL, length); dst = Tcl_SetByteArrayLength(objResultPtr, length); @@ -3402,11 +3404,12 @@ Tcl_UniChar *dst; if (inPlace) { Tcl_Size start; - objResultPtr = *objv++; objc--; + objResultPtr = *objv++; + objc--; /* Ugly interface! Force resize of the unicode array. */ (void)Tcl_GetUnicodeFromObj(objResultPtr, &start); Tcl_InvalidateStringRep(objResultPtr); if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) { @@ -3453,11 +3456,12 @@ char *dst; if (inPlace) { Tcl_Size start; - objResultPtr = *objv++; objc--; + objResultPtr = *objv++; + objc--; (void)TclGetStringFromObj(objResultPtr, &start); if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) { if (interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( Index: generic/tclTest.c ================================================================== --- generic/tclTest.c +++ generic/tclTest.c @@ -8774,11 +8774,11 @@ /* Avoid the loop below if lengths differ */ if (nL1 != nL2) { Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); break; } - /* FALLTHRU */ + TCL_FALLTHROUGH(); case LUTIL_DIFFINDEX: nCmp = nL1 <= nL2 ? nL1 : nL2; for (i = 0; i < nCmp; ++i) { if (strcmp(Tcl_GetString(l1Elems[i]), Tcl_GetString(l2Elems[i]))) { break; Index: generic/tclTimer.c ================================================================== --- generic/tclTimer.c +++ generic/tclTimer.c @@ -977,11 +977,11 @@ (afterPtr->token == NULL) ? "idle" : "timer", -1)); Tcl_SetObjResult(interp, resultListPtr); } break; default: - Tcl_Panic("Tcl_AfterObjCmd: bad subcommand index to afterSubCmds"); + TCL_UNREACHABLE(); } return TCL_OK; } /* Index: generic/tclTrace.c ================================================================== --- generic/tclTrace.c +++ generic/tclTrace.c @@ -248,13 +248,13 @@ if (Tcl_GetIndexFromObj(interp, objv[2], traceTypeOptions, "option", 0, &typeIndex) != TCL_OK) { return TCL_ERROR; } return traceSubCmds[typeIndex](interp, optionIndex, objc, objv); - break; } - + default: + TCL_UNREACHABLE(); } return TCL_OK; } /* @@ -342,10 +342,12 @@ flags |= TCL_TRACE_ENTER_DURING_EXEC; break; case TRACE_EXEC_LEAVE_STEP: flags |= TCL_TRACE_LEAVE_DURING_EXEC; break; + default: + TCL_UNREACHABLE(); } } command = TclGetStringFromObj(objv[5], &length); if (optionIndex == TRACE_ADD) { TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)Tcl_Alloc( @@ -498,10 +500,12 @@ Tcl_ListObjAppendElement(interp, resultListPtr, eachTraceObjPtr); } Tcl_SetObjResult(interp, resultListPtr); break; } + default: + TCL_UNREACHABLE(); } return TCL_OK; } /* @@ -578,10 +582,12 @@ flags |= TCL_TRACE_RENAME; break; case TRACE_CMD_DELETE: flags |= TCL_TRACE_DELETE; break; + default: + TCL_UNREACHABLE(); } } command = TclGetStringFromObj(objv[5], &length); if (optionIndex == TRACE_ADD) { @@ -692,10 +698,12 @@ Tcl_ListObjAppendElement(interp, resultListPtr, eachTraceObjPtr); } Tcl_SetObjResult(interp, resultListPtr); break; } + default: + TCL_UNREACHABLE(); } return TCL_OK; } /* @@ -783,10 +791,12 @@ flags |= TCL_TRACE_UNSETS; break; case TRACE_VAR_WRITE: flags |= TCL_TRACE_WRITES; break; + default: + TCL_UNREACHABLE(); } } command = TclGetStringFromObj(objv[5], &length); if (optionIndex == TRACE_ADD) { CombinedTraceVarInfo *ctvarPtr = (CombinedTraceVarInfo *)Tcl_Alloc( @@ -876,10 +886,12 @@ eachTraceObjPtr); } Tcl_SetObjResult(interp, resultListPtr); break; } + default: + TCL_UNREACHABLE(); } return TCL_OK; } /* Index: generic/tclUtil.c ================================================================== --- generic/tclUtil.c +++ generic/tclUtil.c @@ -1131,11 +1131,11 @@ forbidNone = 1; extra++; /* Escapes all just prepend a backslash */ preferEscape = 1; break; #else - /* FLOW THROUGH */ + TCL_FALLTHROUGH(); #endif /* COMPAT */ case '[': /* TYPE_SUBS */ case '$': /* TYPE_SUBS */ case ';': /* TYPE_COMMAND_END */ forbidNone = 1; @@ -4447,11 +4447,11 @@ for (p = reStr + 4; p < strEnd; p++) { switch (*p) { case '\\': case '*': case '[': case ']': case '?': /* Only add \ where necessary for glob */ *dsStr++ = '\\'; - /* fall through */ + TCL_FALLTHROUGH(); default: *dsStr++ = *p; break; } } @@ -4528,11 +4528,11 @@ break; case '*': case '[': case ']': case '?': /* Only add \ where necessary for glob */ *dsStr++ = '\\'; anchorLeft = 0; /* prevent exact match */ - /* fall through */ + TCL_FALLTHROUGH(); case '{': case '}': case '(': case ')': case '+': case '.': case '|': case '^': case '$': *dsStr++ = *p; break; default: Index: generic/tclVar.c ================================================================== --- generic/tclVar.c +++ generic/tclVar.c @@ -3943,10 +3943,12 @@ if (matched < 0) { TclDecrRefCount(resultObj); return TCL_ERROR; } break; + default: + TCL_UNREACHABLE(); } if (matched == 0) { continue; } } @@ -6978,14 +6980,14 @@ return NotArrayError(interp, arrayNameObj); } SetArrayDefault(varPtr, NULL); } return TCL_OK; - } - /* Unreached */ - return TCL_ERROR; + default: + TCL_UNREACHABLE(); + } } /* * Initialize array variable. */ Index: generic/tclZipfs.c ================================================================== --- generic/tclZipfs.c +++ generic/tclZipfs.c @@ -4254,10 +4254,12 @@ regexp = Tcl_RegExpCompile(interp, TclGetString(objv[2])); if (!regexp) { return TCL_ERROR; } break; + default: + TCL_UNREACHABLE(); } } else if (objc == 2) { pattern = TclGetString(objv[1]); } Index: generic/tclZlib.c ================================================================== --- generic/tclZlib.c +++ generic/tclZlib.c @@ -393,13 +393,11 @@ * Catch-all. Should be unreachable because all cases are already * listed above. */ default: - TclNewLiteralStringObj(objv[2], "UNKNOWN"); - TclNewIntObj(objv[3], code); - return Tcl_NewListObj(4, objv); + TCL_UNREACHABLE(); } } /* *---------------------------------------------------------------------- @@ -2103,23 +2101,25 @@ if (Tcl_GetIndexFromObj(interp, objv[i], gzipopts, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } switch (option) { - case 0: + case 0: // -header headerDictObj = objv[i + 1]; break; - case 1: + case 1: // -level if (Tcl_GetIntFromObj(interp, objv[i + 1], &level) != TCL_OK) { return TCL_ERROR; } if (level < 0 || level > 9) { extraInfoStr = "\n (in -level option)"; goto badLevel; } break; + default: + TCL_UNREACHABLE(); } } return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_GZIP, objv[2], level, headerDictObj); case CMD_INFLATE: /* inflate rawcomprdata ?bufferSize? @@ -2177,11 +2177,11 @@ if (Tcl_GetIndexFromObj(interp, objv[i], gunzipopts, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } switch (option) { - case 0: + case 0: // -buffersize if (TclGetWideIntFromObj(interp, objv[i + 1], &wideLen) != TCL_OK) { return TCL_ERROR; } if (wideLen < MIN_NONSTREAM_BUFFER_SIZE @@ -2188,14 +2188,16 @@ || wideLen > MAX_BUFFER_SIZE) { goto badBuffer; } buffersize = wideLen; break; - case 1: + case 1: // -headerVar headerVarObj = objv[i + 1]; TclNewObj(headerDictObj); break; + default: + TCL_UNREACHABLE(); } } if (Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_GZIP, objv[2], buffersize, headerDictObj) != TCL_OK) { if (headerDictObj) { @@ -2213,14 +2215,15 @@ * -> handleCmd */ return ZlibStreamSubcmd(interp, objc, objv); case CMD_PUSH: /* push mode channel options... * -> channel */ return ZlibPushSubcmd(interp, objc, objv); + + default: // Should be no other options + TCL_UNREACHABLE(); } - return TCL_ERROR; - badLevel: Tcl_SetObjResult(interp, Tcl_NewStringObj( "level must be 0 to 9", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", (char *)NULL); if (extraInfoStr) { @@ -2338,11 +2341,11 @@ desc = gunzipOpts; mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_GZIP; break; default: - Tcl_Panic("should be unreachable"); + TCL_UNREACHABLE(); } /* * Parse the options. */ @@ -2470,11 +2473,11 @@ case FMT_GUNZIP: mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_GZIP; break; default: - Tcl_Panic("should be unreachable"); + TCL_UNREACHABLE(); } if (TclGetChannelFromObj(interp, objv[3], &chan, &chanMode, 0) != TCL_OK) { return TCL_ERROR; } @@ -2553,10 +2556,12 @@ Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOPT", (char *)NULL); goto genericOptionError; } compDictObj = objv[i]; break; + default: + TCL_UNREACHABLE(); } } if (compDictObj && (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL))) { @@ -2706,13 +2711,13 @@ if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } return Tcl_ZlibStreamReset(zstream); + default: + TCL_UNREACHABLE(); } - - return TCL_OK; } static int ZlibStreamAddCmd( void *clientData, @@ -2785,10 +2790,12 @@ Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL); return TCL_ERROR; } compDictObj = objv[++i]; break; + default: + TCL_UNREACHABLE(); } if (flush == -2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-flush\", \"-fullflush\" and \"-finalize\" options" @@ -2893,10 +2900,12 @@ Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL); return TCL_ERROR; } compDictObj = objv[++i]; break; + default: + TCL_UNREACHABLE(); } if (flush == -2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-flush\", \"-fullflush\" and \"-finalize\" options" " are mutually exclusive", TCL_AUTO_LENGTH)); Index: unix/tclUnixChan.c ================================================================== --- unix/tclUnixChan.c +++ unix/tclUnixChan.c @@ -1507,19 +1507,19 @@ baud = TtyGetBaud(cfgetospeed(&iostate)); parity = 'n'; #ifdef PAREXT switch ((int) (iostate.c_cflag & (PARENB | PARODD | PAREXT))) { - case PARENB : parity = 'e'; break; - case PARENB | PARODD : parity = 'o'; break; - case PARENB | PAREXT : parity = 's'; break; - case PARENB | PARODD | PAREXT : parity = 'm'; break; + case PARENB : parity = 'e'; break; + case PARENB | PARODD : parity = 'o'; break; + case PARENB | PAREXT : parity = 's'; break; + case PARENB | PARODD | PAREXT : parity = 'm'; break; } #else /* !PAREXT */ switch ((int) (iostate.c_cflag & (PARENB | PARODD))) { - case PARENB : parity = 'e'; break; - case PARENB | PARODD : parity = 'o'; break; + case PARENB : parity = 'e'; break; + case PARENB | PARODD : parity = 'o'; break; } #endif /* PAREXT */ data = iostate.c_cflag & CSIZE; data = (data == CS5) ? 5 : (data == CS6) ? 6 : (data == CS7) ? 7 : 8; Index: win/tclWinPipe.c ================================================================== --- win/tclWinPipe.c +++ win/tclWinPipe.c @@ -3457,11 +3457,11 @@ * Thread was idle/waiting, notify it goes teardown */ SetEvent(evControl); *pipeTIPtr = NULL; - /* FALLTHRU */ + TCL_FALLTHROUGH(); case PTI_STATE_DOWN: return 1; default: /*