Re: MSVC and GCC compilation warnings

96 views
Skip to first unread message

Jure Bagić

unread,
Apr 29, 2026, 11:35:44 AM (4 days ago) Apr 29
to lua-l
Seems like web email clients like gmail do not allow preview or download
of batch files for security reasons, so here is the gist:

https://gist.github.com/b-jure/549e80ec5db6ddfa20767497e5d989e4

--
Jure
signature.asc

Jure Bagić

unread,
Apr 29, 2026, 11:35:35 PM (3 days ago) Apr 29
to lua-l
On 26/04/29 03:51PM, Jure Bagić wrote:
> I recently setup a VM running Windows with a simple batch file to build Lua
> from source. Here is a complete list of warnings the Microsoft Vibe
> Coded Compiler emits.
>
> In lobject.c:
>
> lobject.c(167) : potentially uninitialized local variable 'n1' used
> lobject.c(167) : potentially uninitialized local variable 'n2' used
> lobject.c(179) : potentially uninitialized local variable 'n1' used
> lobject.c(179) : potentially uninitialized local variable 'n2' used
>
>
> The following are warnings for 'op_arithf_aux' macro in lvm.c:
>
> lvm.c(1445) : potentially uninitialized local variable 'n1' used
> lvm.c(1445) : potentially uninitialized local variable 'n2' used
> lvm.c(1449) : potentially uninitialized local variable 'n1' used
> lvm.c(1449) : potentially uninitialized local variable 'n2' used
> lvm.c(1453) : potentially uninitialized local variable 'n1' used
> lvm.c(1453) : potentially uninitialized local variable 'n2' used
> lvm.c(1458) : potentially uninitialized local variable 'n1' used
> lvm.c(1458) : potentially uninitialized local variable 'n2' used
> lvm.c(1462) : potentially uninitialized local variable 'n1' used
> lvm.c(1462) : potentially uninitialized local variable 'n2' used
> lvm.c(1466) : potentially uninitialized local variable 'n1' used
> lvm.c(1466) : potentially uninitialized local variable 'n2' used
> lvm.c(1471) : potentially uninitialized local variable 'n1' used
> lvm.c(1471) : potentially uninitialized local variable 'n2' used
> lvm.c(1507) : potentially uninitialized local variable 'n1' used
> lvm.c(1507) : potentially uninitialized local variable 'n2' used
> lvm.c(1511) : potentially uninitialized local variable 'n1' used
> lvm.c(1511) : potentially uninitialized local variable 'n2' used
> lvm.c(1515) : potentially uninitialized local variable 'n1' used
> lvm.c(1515) : potentially uninitialized local variable 'n2' used
> lvm.c(1520) : potentially uninitialized local variable 'n1' used
> lvm.c(1520) : potentially uninitialized local variable 'n2' used
> lvm.c(1524) : potentially uninitialized local variable 'n1' used
> lvm.c(1524) : potentially uninitialized local variable 'n2' used
> lvm.c(1528) : potentially uninitialized local variable 'n1' used
> lvm.c(1528) : potentially uninitialized local variable 'n2' used
> lvm.c(1533) : potentially uninitialized local variable 'n1' used
> lvm.c(1533) : potentially uninitialized local variable 'n2' used
>
> and the final one also in lvm.c:
>
> lvm.c(1595) : potentially uninitialized local variable 'nb' used
>
>
> Now, when the 'l_noret' is set as void, clang compiler emits no warnings.
> However, both gcc and msvc emit one warning each.
>
> gcc:
>
> ldo.c:121:9: warning: infinite recursion detected [-Winfinite-recursion]
> 121 | l_noret luaD_throw (lua_State *L, TStatus errcode) {
> ldo.c:132:7: note: recursive call
> 132 | luaD_throw(mainth, errcode); /* re-throw in main thread */
>
> msvc:
>
> lparser.c(1171) : potentially uninitialized local variable 'args' used
>
>
> It would be nice to have additional macro directive for debug builds in
> definition of 'l_noret':
>
> #if !defined(l_noret)
>
> #if defined(LUAI_ASSERT)
> #define l_noret void
> #elif defined(__GNUC__)
> #define l_noret void __attribute__((noreturn))
> #elif defined(_MSC_VER) && _MSC_VER >= 1200
> #define l_noret void __declspec(noreturn)
> #else
> #define l_noret void
> #endif
>
> #endif
>
>
> The build was done via the attached batch file on MSVC 19.44.35213 for x64.
> The script builds the standalone interpreter 'lua.exe' and the library files
> 'lua55.dll', 'lua55.exp' and 'lua55.lib'.
> It does not build the compiler ('luac.exe').
>
> --
> Jure


Does anyone see this initial email?
I think it somehow got discarded, well, there it is.

--
Jure
signature.asc

Scott Morgan

unread,
Apr 30, 2026, 6:16:48 AM (3 days ago) Apr 30
to lu...@googlegroups.com
On 30/04/2026 04:35, Jure Bagić wrote:
> Does anyone see this initial email?
> I think it somehow got discarded, well, there it is.

Didn't see that initial mail. Looks like there's something wrong with
your copy of the sources tonumberns macro.

Are you using a clean copy of the release tarball? Might be worth
re-downloading and re-extracting that.

Scott

Jure Bagić

unread,
Apr 30, 2026, 7:57:50 AM (3 days ago) Apr 30
to 'Scott Morgan' via lua-l

I am compiling from the latest commit on the mirror repository hosted on github.

I think this is just MSVC being ridiculous. I did browse a bit about this warning and stumbled upon this:
https://developercommunity.visualstudio.com/t/warning-c6001c4701-false-positive/1580097

The response the user got is that "it is too complex" to solve this.
Example provided by the user still fails 4 years later on the latest MSVC (https://godbolt.org/z/3bMb5Y5vT).

But then I can't possibly understand how it doesn't emit warning here for 'flim':

    ...
    lua_Number flim;  /* try to convert to float */
    if (!tonumber(lim, &flim)) /* cannot convert to float? */
      luaG_forerror(L, lim, "limit");
    /* else 'flim' is a float out of integer bounds */
    if (luai_numlt(0, flim)) {  /* if it is positive, it is too large */
      if (step < 0) return 1;  /* initial value must be less than it */
      *p = LUA_MAXINTEGER;  /* truncate */
    }
    ...

Anyways the only legit warning from MSVC here is I think for 'args' when 'l_noret' is void:

  ...
  expdesc args;
  int base, nparams;
  int line = ls->linenumber;
  switch (ls->t.token) {
    case '(': {  /* funcargs -> '(' [ explist ] ')' */
      luaX_next(ls);
      if (ls->t.token == ')')  /* arg list is empty? */
        args.k = VVOID;
      else {
        explist(ls, &args);
        if (hasmultret(args.k))
          luaK_setmultret(fs, &args);
      }
      check_match(ls, ')', '(', line);
      break;
    }
    case '{' /*}*/: {  /* funcargs -> constructor */
      constructor(ls, &args);
      break;
    }
    case TK_STRING: {  /* funcargs -> STRING */
      codestring(&args, ls->t.seminfo.ts);
      luaX_next(ls);  /* must use 'seminfo' before 'next' */
      break;
    }
    default: {
      luaX_syntaxerror(ls, "function arguments expected");
    }
  }
  lua_assert(f->k == VNONRELOC);
  base = f->u.info;  /* base register for call */
  if (hasmultret(args.k))
  ...

Roberto Ierusalimschy

unread,
Apr 30, 2026, 11:24:15 AM (3 days ago) Apr 30
to lu...@googlegroups.com
> > Now, when the 'l_noret' is set as void, clang compiler emits no warnings.
> > However, both gcc and msvc emit one warning each.
> >
> > gcc:
> >
> > ldo.c:121:9: warning: infinite recursion detected [-Winfinite-recursion]
> > 121 | l_noret luaD_throw (lua_State *L, TStatus errcode) {
> > ldo.c:132:7: note: recursive call
> > 132 | luaD_throw(mainth, errcode); /* re-throw in main thread */

Can anyone explain this warning? The recursive call is guarded by two
if's, and it calls the function with a different argument (L in the
original call, mainth in the recursive call). How can the compiler decide
that the recursion is infinite?

More exactly: the recursive call only happens if L->errorJmp is nil.
But then it is done with a new L (mainth) which errorJmp field is not
nil. So, it seems quite easy to prove that the recursive call happens at
most once. Or am I missing something?

-- Roberto

Gé Weijers

unread,
Apr 30, 2026, 12:34:35 PM (3 days ago) Apr 30
to lu...@googlegroups.com
On Thu, Apr 30, 2026 at 8:24 AM Roberto Ierusalimschy <rob...@inf.puc-rio.br> wrote:

Can anyone explain this warning? The recursive call is guarded by two
if's, and it calls the function with a different argument (L in the
original call, mainth in the recursive call). How can the compiler decide
that the recursion is infinite?

In my last job I used a commercial static analysis tool which was far more sophisticated than what you find in compilers, and it produced false positives by the truckload. The good thing about it was that it had a database in which you could permanently mark a warning as a false positive.

The compiler is just not 'smart' enough to figure out all cases (you'd need to solve the halting problem to do that), and if in doubt it gives a warning. There are ways to put pragmas in the code to suppress the warning, but they're compiler specific and not that useful for portable code like PUC Lua.


--

Francisco Olarte

unread,
Apr 30, 2026, 2:41:04 PM (3 days ago) Apr 30
to lu...@googlegroups.com
Roberto:

On Thu, 30 Apr 2026 at 17:24, Roberto Ierusalimschy <rob...@inf.puc-rio.br> wrote:
Can anyone explain this warning? The recursive call is guarded by two
if's, and it calls the function with a different argument (L in the
original call, mainth in the recursive call). How can the compiler decide
that the recursion is infinite?

More exactly: the recursive call only happens if L->errorJmp is nil.
But then it is done with a new L (mainth) which errorJmp field is not
nil. So, it seems quite easy to prove that the recursive call happens at
most once. Or am I missing something?

Does seem correct, but you may be hitting a compiler bug or the infinite recursion detector is not that smart.

What optimization settings are you using? I have found some cases of things detected differently when the compilers works harder analyzing the code.

Also, I do not know if it matters, but mainth is obtained from an external source, errorJmp is checked and then setobjs2s is called. setobjs2s could, via an external alias pointer, clear mainth->errorJmp before the recursion. I am not sure what definitions are visible to the compiler when it hits that spot. You could try to eliminate that bogus report by doing an unnecessary extra check of ->errorjmp guarding just the recursive call line and seeing if it clears the warn.

I think these "restrict" qualifiers young ones use those days help, but I fear they are not C89.

Francisco Olarte.

Jure Bagić

unread,
May 1, 2026, 1:33:07 AM (2 days ago) May 1
to lu...@googlegroups.com
> Can anyone explain this warning? The recursive call is guarded by two
> if's, and it calls the function with a different argument (L in the
> original call, mainth in the recursive call). How can the compiler decide
> that the recursion is infinite?
>
> More exactly: the recursive call only happens if L->errorJmp is nil.
> But then it is done with a new L (mainth) which errorJmp field is not
> nil. So, it seems quite easy to prove that the recursive call happens at
> most once. Or am I missing something?
>
> -- Roberto

A bug, no other way to explain it.
Clang compiles without producing that warning.

For anyone interested, the file responsible for this warning
(I think) in the gcc source is the 'gcc/gimple-warn-recursion.cc',
and in there the 'find_function_exit'.

Sorry for the private email Roberto, I meant to reply in this
list, I recently changed my email client and everything is broken.

--
Jure
signature.asc
Reply all
Reply to author
Forward
0 new messages