Fixed define warning and started warning levels master
authorRobert Pengelly <robertapengelly@hotmail.com>
Thu, 20 Aug 2026 12:38:04 +0000 (13:38 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Thu, 20 Aug 2026 12:38:04 +0000 (13:38 +0100)
amd64.c
cc.h
i386.c
int64.c
lib.c
macro.c
report.c

diff --git a/amd64.c b/amd64.c
index 884434331c598147d136ee16cf5a7d24e0fc5252..bc25c09762ad6f344a9129fab4b3cad30d754b8b 100644 (file)
--- a/amd64.c
+++ b/amd64.c
@@ -1158,7 +1158,9 @@ static void ensure_global_function_symbol (const char *name, const char *line_st
         return;
     }
     
-    report_line_at (get_filename (), lineno, REPORT_WARNING, line_start, name_caret, "implicit declaration of function '%s'", name);
+    if (state->warn & WARN_OLD_STYLE) {
+        report_line_at (get_filename (), lineno, REPORT_WARNING, line_start, name_caret, "implicit declaration of function '%s'", name);
+    }
     
     if (add_global_symbol (name, GLOBAL_SYMBOL_FUNCTION, 1, line_start, name_caret, lineno)) {
     
@@ -37158,9 +37160,17 @@ static void parse_statement (void) {
         }
         
         if (current_function_is_void && has_value) {
-            report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with a value in void function");
+        
+            if (state->warn & WARN_NO_RETURN) {
+                report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with a value in void function");
+            }
+        
         } else if (!current_function_is_void && !has_value) {
-            report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with no value in non-void function");
+        
+            if (state->warn & WARN_NO_RETURN) {
+                report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with no value in non-void function");
+            }
+        
         }
         
         if (state->ofp) {
@@ -37696,7 +37706,11 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     check_goto_labels ();
     
     if (!current_function_is_void && !current_function_has_return_statement) {
-        report_line_at (function_filename_copy ? function_filename_copy : get_filename (), function_line, REPORT_WARNING, function_start, function_caret, "control reaches end of non-void function");
+    
+        if (state->warn & WARN_NO_RETURN) {
+            report_line_at (function_filename_copy ? function_filename_copy : get_filename (), function_line, REPORT_WARNING, function_start, function_caret, "control reaches end of non-void function");
+        }
+    
     }
     
     pending_return_jump = 0;
diff --git a/cc.h b/cc.h
index 6aaf2091b9f9687c803a076c3f520bfcfd5a6fa3..997bbdacc9ecf7e169b92839366ef992ca2095a2 100755 (executable)
--- a/cc.h
+++ b/cc.h
 #include    "list.h"
 #include    "vector.h"
 
+#define     WARN_ERROR                  (1U << 0)
+#define     WARN_NO_RETURN              (1U << 1)
+#define     WARN_SIGNEDNESS             (1U << 2)
+#define     WARN_CONVERSION             (1U << 3)
+#define     WARN_DUP_DEFINE             (1U << 4)
+#define     WARN_UNUSED                 (1U << 5)
+#define     WARN_SHADOW                 (1U << 6)
+#define     WARN_UNREACHABLE            (1U << 7)
+#define     WARN_FALLTHROUGH            (1U << 8)
+#define     WARN_OLD_STYLE              (1U << 9)
+#define     WARN_INITIALIZER            (1U << 10)
+
+#define     WARN_DEFAULT                (WARN_DUP_DEFINE | WARN_UNREACHABLE)
+#define     WARN_ALL                    (WARN_DEFAULT | WARN_NO_RETURN | WARN_SIGNEDNESS | WARN_UNUSED | WARN_FALLTHROUGH | WARN_INITIALIZER)
+#define     WARN_EXTRA                  (WARN_ALL | WARN_CONVERSION | WARN_SHADOW | WARN_OLD_STYLE)
+
 struct cc_state {
     
     const char *ifile, *ofile;
@@ -28,6 +44,7 @@ struct cc_state {
     int bits, std;
     int long64;
     int syntax;
+    int warn;
     
     unsigned long max_errors;
     long version;
diff --git a/i386.c b/i386.c
index 04da1601c6586a789355f2950eb2213b9e52d301..dd41fe8d5fdc9ca2446d426be9832789c3c69824 100644 (file)
--- a/i386.c
+++ b/i386.c
@@ -972,7 +972,9 @@ static void ensure_global_function_symbol (const char *name, const char *line_st
         return;
     }
     
-    report_line_at (get_filename (), lineno, REPORT_WARNING, line_start, name_caret, "implicit declaration of function '%s'", name);
+    if (state->warn & WARN_OLD_STYLE) {
+        report_line_at (get_filename (), lineno, REPORT_WARNING, line_start, name_caret, "implicit declaration of function '%s'", name);
+    }
     
     if (add_global_symbol (name, GLOBAL_SYMBOL_FUNCTION, 1, line_start, name_caret, lineno)) {
     
@@ -34528,9 +34530,17 @@ static void parse_statement (void) {
         }
         
         if (current_function_is_void && has_value) {
-            report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with a value in void function");
+        
+            if (state->warn & WARN_NO_RETURN) {
+                report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with a value in void function");
+            }
+        
         } else if (!current_function_is_void && !has_value) {
-            report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with no value in non-void function");
+        
+            if (state->warn & WARN_NO_RETURN) {
+                report_line_at (get_filename (), ret_line, REPORT_WARNING, ret_start, ret_caret, "return with no value in non-void function");
+            }
+        
         }
         
         if (state->ofp) {
@@ -35055,7 +35065,11 @@ static void parse_function_body (const char *name, int storage_class, int is_inl
     check_goto_labels ();
     
     if (!current_function_is_void && !current_function_has_return_statement) {
-        report_line_at (function_filename_copy ? function_filename_copy : get_filename (), function_line, REPORT_WARNING, function_start, function_caret, "control reaches end of non-void function");
+    
+        if (state->warn & WARN_NO_RETURN) {
+            report_line_at (function_filename_copy ? function_filename_copy : get_filename (), function_line, REPORT_WARNING, function_start, function_caret, "control reaches end of non-void function");
+        }
+    
     }
     
     pending_return_jump = 0;
diff --git a/int64.c b/int64.c
index f9a46bde7375b937b3672003743a375d975f222d..eb3233e23d2d25d9967fe75078b92faa71f202fe 100644 (file)
--- a/int64.c
+++ b/int64.c
@@ -4,6 +4,7 @@
 #include    <ctype.h>
 #include    <string.h>
 
+#include    "cc.h"
 #include    "int64.h"
 #include    "report.h"
 
@@ -284,7 +285,7 @@ void mask64 (int64_s *a, int bits) {
     
     if (bits <= 0) {
     
-        if (a->high != 0 || a->low != 0) {
+        if ((state->warn & WARN_CONVERSION) && (a->high != 0 || a->low != 0)) {
             report_at (get_filename(), get_line_number(), REPORT_WARNING, "implicit truncation of 0x%08lX%08lX to 0x00000000", a->high, a->low);
         }
         
@@ -302,7 +303,7 @@ void mask64 (int64_s *a, int bits) {
         new_low = a->low & low_mask;
         new_high = 0;
         
-        if (a->high != 0 || (a->low & ~low_mask) != 0) {
+        if ((state->warn & WARN_CONVERSION) && (a->high != 0 || (a->low & ~low_mask) != 0)) {
             report_at (get_filename(), get_line_number(), REPORT_WARNING, "implicit truncation of 0x%08lX%08lX to 0x%08lX", a->high, a->low, new_low);
         }
     
@@ -312,7 +313,7 @@ void mask64 (int64_s *a, int bits) {
         new_low = a->low;
         new_high = 0;
         
-        if (a->high != 0) {
+        if ((state->warn & WARN_CONVERSION) && a->high != 0) {
             report_at (get_filename(), get_line_number(), REPORT_WARNING, "implicit truncation of 0x%08lX%08lX to 0x%08lX", a->high, a->low, new_low);
         }
     
@@ -323,7 +324,7 @@ void mask64 (int64_s *a, int bits) {
         new_low = a->low;
         new_high = a->high & high_mask;
         
-        if ((a->high & ~high_mask) != 0) {
+        if ((state->warn & WARN_CONVERSION) && (a->high & ~high_mask) != 0) {
             report_at (get_filename(), get_line_number(), REPORT_WARNING, "implicit truncation of 0x%08lX%08lX to 0x%08lX%08lX", a->high, a->low, new_high, new_low);
         }
     
diff --git a/lib.c b/lib.c
index 3d7c0517bcb8e3d9eaf7d1bb30d7b77a02643c2d..ad9ce7e05781862446be0f0bc32b497407f5ff13 100755 (executable)
--- a/lib.c
+++ b/lib.c
@@ -49,6 +49,7 @@ struct cc_option {
 #define     CC_OPTION_STD                                   17
 #define     CC_OPTION_TRANDITIONAL_LINEMARKERS              18
 #define     CC_OPTION_UNDEF                                 19
+#define     CC_OPTION_WARN                                  20
 
 static struct cc_option opts[] = {
 
@@ -67,6 +68,7 @@ static struct cc_option opts[] = {
     
     {   "-E",                               CC_OPTION_PREPOCESS,                    CC_OPTION_NO_ARG        },
     {   "-S",                               CC_OPTION_COMPILE,                      CC_OPTION_NO_ARG        },
+    {   "-W",                               CC_OPTION_WARN,                         CC_OPTION_HAS_ARG       },
     
     {   "-fno-leading-underscore",          CC_OPTION_NO_LEADING_UNDERSCORE,        CC_OPTION_NO_ARG        },
     {   "-fleading-underscore",             CC_OPTION_LEADING_UNDERSCORE,           CC_OPTION_NO_ARG        },
@@ -278,6 +280,7 @@ void parse_args (int argc, char **argv, int optind) {
     
     }
     
+    state->warn = WARN_DEFAULT;
     state->bits = 32;
     
     while (optind < argc) {
@@ -542,6 +545,34 @@ void parse_args (int argc, char **argv, int optind) {
             
             }
             
+            case CC_OPTION_WARN: {
+            
+                if (strcmp (optarg, "all") == 0) {
+                
+                    state->warn |= WARN_ALL;
+                    break;
+                
+                }
+                
+                if (strcmp (optarg, "extra") == 0) {
+                
+                    state->warn |= WARN_EXTRA;
+                    break;
+                
+                }
+                
+                if (strcmp (optarg, "error") == 0) {
+                
+                    state->warn |= WARN_ERROR;
+                    break;
+                
+                }
+                
+                report_at (program_name, 0, REPORT_ERROR, "unrecognised -W argument");
+                exit (EXIT_FAILURE);
+            
+            }
+            
             default: {
             
                 report_at (program_name, 0, REPORT_ERROR, "unsupported option '%s'", r);
diff --git a/macro.c b/macro.c
index 4aa45fafb2c9d8516a7072b7ba542047f4b2109b..ea2addf84c295a18f065927580de9495513d4cce 100755 (executable)
--- a/macro.c
+++ b/macro.c
@@ -34,7 +34,7 @@ struct macro *get_macro (struct hashtab_name *key) {
 
 void add_macro (char *start, char **pp, int report_line) {
 
-    char *sname, *caret = *pp, *arg;
+    char *sname, *caret = *pp, *arg, *old_value = 0;
     unsigned int len;
     
     struct hashtab_name *key;
@@ -90,14 +90,10 @@ void add_macro (char *start, char **pp, int report_line) {
     
     if ((key = find_macro (sname))) {
     
-        if (report_line) {
-            report_line_at (get_filename (), get_line_number (), REPORT_WARNING, start, caret, "\"%s\" redefined", sname);
-        } else {
-            report_at (get_filename (), get_line_number (), REPORT_WARNING, "\"%s\" redefined", sname);
-        }
-        
         if ((m = hashtab_get (&hashtab_macros, key))) {
         
+            old_value = xstrdup (m->value);
+            
             while ((arg = vec_pop (&m->args))) {
                 free (arg);
             }
@@ -238,15 +234,29 @@ void add_macro (char *start, char **pp, int report_line) {
     
     }
     
-    *pp = skip_whitespace (*pp);
-    
-    m->value = xstrdup (*pp);
+    m->value = xstrdup (*pp = skip_whitespace (*pp));
     len = strlen (m->value);
     
     if (is_end_of_line[(int) m->value[len - 1]]) {
         m->value[len - 1] = '\0';
     }
     
+    if (old_value) {
+        
+        if (strcmp (m->value, old_value) && state->warn & WARN_DUP_DEFINE) {
+        
+            if (report_line) {
+                report_line_at (get_filename (), get_line_number (), REPORT_WARNING, start, caret, "\"%s\" redefined", sname);
+            } else {
+                report_at (get_filename (), get_line_number (), REPORT_WARNING, "\"%s\" redefined", sname);
+            }
+        
+        }
+        
+        free (old_value);
+        
+    }
+    
     hashtab_put (&hashtab_macros, key, m);
     
     if (!m->is_variadic) {
index 72ca4d111682a89f0de5357b073fb48bb905f1d5..950a0616b37f222ef23abc4be0b633fd8d1bcb57 100755 (executable)
--- a/report.c
+++ b/report.c
@@ -64,6 +64,10 @@ extern void print_include_stack (void);
 
 static void output_message (const char *filename, unsigned long lineno, unsigned long idx, int type, const char *fmt, va_list ap) {
 
+    if (type == REPORT_WARNING && state && (state->warn & WARN_ERROR)) {
+        type = REPORT_ERROR;
+    }
+    
     if (has_include_stack ()) {
         print_include_stack ();
     }