diff --git a/libtcc.c b/libtcc.c
index 65ceef05..f8547a81 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -544,7 +544,7 @@ static void error1(int mode, const char *fmt, va_list ap)
     if (mode == ERROR_WARN) {
         if (s1->warn_none)
             return;
-        if (s1->warn_error)
+        if (s1->warn_mask & (WARN_ERROR << WARN_ERROR_SHIFT))
             mode = ERROR_ERROR;
     }
 
@@ -1288,7 +1288,7 @@ ST_FUNC int set_W_flag(TCCState *s, const char *optarg)
         char const *name;
     } const opts[] = {
         {WARN_ALL, 0, "all"},
-        {WARN_ERROR, 0, "error"},
+        {WARN_ERROR | (WARN_ERROR << WARN_ERROR_SHIFT), 0, "error"},
         {WARN_UNSUPPORTED, WD_ERROR, "unsupported"},
         {WARN_GCC_COMPAT, WD_ERROR, "gcc-compat"},
         {WARN_WRITE_STRINGS, WD_ERROR | WD_ALL, "write-strings"},
diff --git a/tcc.h b/tcc.h
index 6db8e2d1..cacd1381 100644
--- a/tcc.h
+++ b/tcc.h
@@ -744,7 +744,7 @@ enum warn_option {
     WARN_GCC_COMPAT = 1u<<1,
     WARN_WRITE_STRINGS = 1u<<2,
     WARN_IMPLICIT_FUNCTION_DECLARATION = 1u<<3,
-    WARN_ERROR = 1u<<4,
+    WARN_ERROR = 1u<<4, /* Not really as such in warn area, here only "MAX" */
     WARN_ALL = WARN_ERROR - 1
 };
 enum {WARN_ERROR_SHIFT = 16u};
@@ -780,14 +780,13 @@ struct TCCState {
     unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */
 
     unsigned char warn_none;
-    unsigned char warn_error;
     /* NEED_WARNING(SELF,X) used to drive W[[no-]error]=X */
     uint32_t warn_mask;
 #define NEED_WARNING(SELF,SWITCH) \
     (((SELF)->warn_mask & \
             (WARN_ ## SWITCH | (WARN_ ## SWITCH << WARN_ERROR_SHIFT))) \
      ? (((SELF)->warn_mask & (WARN_ ## SWITCH << WARN_ERROR_SHIFT)) \
-        ? (SELF)->warn_error = 1 : 1) : 0)
+        ? (SELF)->warn_mask |= (WARN_ERROR << WARN_ERROR_SHIFT), 1 : 1) : 0)
 
     /* compile with debug symbol (and use them if error during execution) */
     unsigned char do_debug;