parse line-directive flags to detect system headers
authorMatthias Braun <matze@braunis.de>
Mon, 5 Sep 2011 17:53:22 +0000 (19:53 +0200)
committerMatthias Braun <matze@braunis.de>
Mon, 5 Sep 2011 17:57:59 +0000 (19:57 +0200)
In system headers we disable the redundant decl warning and the
redefinition error for typedefs

diagnostic.c
lexer.c
parser.c
token.c
token_t.h

index 447ed7d..a0b40e6 100644 (file)
@@ -47,7 +47,7 @@ static void print_source_position(FILE *out, const source_position_t *pos)
 {
        fprintf(out, "at line %u", pos->lineno);
        if (show_column)
-               fprintf(out, ":%u", pos->colno);
+               fprintf(out, ":%u", (unsigned)pos->colno);
        if (curr_pos == NULL || curr_pos->input_name != pos->input_name)
                fprintf(out, " of \"%s\"", pos->input_name);
 }
@@ -216,7 +216,7 @@ static void diagnosticposvf(source_position_t const *const pos, char const *cons
        FILE *const out = stderr;
        fprintf(out, "%s:%u:", pos->input_name, pos->lineno);
        if (show_column)
-               fprintf(out, "%u:", pos->colno);
+               fprintf(out, "%u:", (unsigned)pos->colno);
        fprintf(out, " %s: ", kind);
        curr_pos = pos;
        diagnosticvf(fmt, ap);
diff --git a/lexer.c b/lexer.c
index 88cb446..3a2a748 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -897,7 +897,24 @@ static void parse_line_directive(void)
        }
        if (pp_token.kind == T_STRING_LITERAL) {
                lexer_pos.input_name = pp_token.string.string.begin;
+               lexer_pos.is_system_header = false;
                next_pp_token();
+
+               /* attempt to parse numeric flags as outputted by gcc preprocessor */
+               while (pp_token.kind == T_INTEGER) {
+                       /* flags:
+                        * 1 - indicates start of a new file
+                        * 2 - indicates return from a file
+                        * 3 - indicates system header
+                        * 4 - indicates implicit extern "C" in C++ mode
+                        *
+                        * currently we're only interested in "3"
+                        */
+                       if (strcmp(pp_token.number.number.begin, "3") == 0) {
+                               lexer_pos.is_system_header = true;
+                       }
+                       next_pp_token();
+               }
        }
 
        eat_until_newline();
@@ -1306,6 +1323,6 @@ static __attribute__((unused))
 void dbg_pos(const source_position_t source_position)
 {
        fprintf(stdout, "%s:%u:%u\n", source_position.input_name,
-               source_position.lineno, source_position.colno);
+               source_position.lineno, (unsigned)source_position.colno);
        fflush(stdout);
 }
index 463a444..37190b0 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -4104,8 +4104,15 @@ entity_t *record_entity(entity_t *entity, const bool is_definition)
                                goto finish;
                        }
                        if (previous_entity->kind == ENTITY_TYPEDEF) {
-                               /* TODO: C++ allows this for exactly the same type */
-                               errorf(pos, "redefinition of '%N' (declared %P)", entity, ppos);
+                               type_t *const type      = skip_typeref(entity->typedefe.type);
+                               type_t *const prev_type
+                                       = skip_typeref(previous_entity->typedefe.type);
+                               /* gcc extension redef in system headers is allowed */
+                               if ((!(c_mode & _CXX) && !pos->is_system_header)
+                                       || !types_compatible(type, prev_type)) {
+                                       errorf(pos, "redefinition of '%N' (declared %P)",
+                                              entity, ppos);
+                               }
                                goto finish;
                        }
 
@@ -4185,7 +4192,7 @@ warn_redundant_declaration: ;
                                                merge_in_attributes(decl, prev_decl->attributes);
                                        } else if (!is_definition        &&
                                                        is_type_valid(prev_type) &&
-                                                       strcmp(ppos->input_name, "<builtin>") != 0) {
+                                                       !pos->is_system_header) {
                                                warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%Y' (declared %P)", symbol, ppos);
                                        }
                                } else if (current_function == NULL) {
diff --git a/token.c b/token.c
index 183a0ca..ddadc54 100644 (file)
--- a/token.c
+++ b/token.c
@@ -32,7 +32,7 @@
 static symbol_t *token_symbols[T_LAST_TOKEN];
 static symbol_t *pp_token_symbols[TP_LAST_TOKEN];
 
-const source_position_t builtin_source_position = { "<built-in>", 0, 0 };
+const source_position_t builtin_source_position = { "<built-in>", 0, 0, true };
 
 static int last_id;
 
index 2f2918d..e0adbab 100644 (file)
--- a/token_t.h
+++ b/token_t.h
@@ -54,7 +54,8 @@ typedef struct source_position_t source_position_t;
 struct source_position_t {
        const char *input_name;
        unsigned    lineno;
-       unsigned    colno;
+       unsigned    colno            : 31;
+       unsigned    is_system_header : 1;
 };
 
 /* position used for "builtin" declarations/types */