This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

adding support for column numbers


In the Java print-end, we keep track of column numbers,
for better error messages.  And cpplib will make it easier
to also keep track of column numbers for C and C++.
(It is difficult without an integrated cpplib, because
macro expansion can change column numbers.)  Some
debugging formats (at least dwarf2) can pass along
column numbers to a debugger.

So I think the time is right for adding at least a
framework for column numbers in Gcc.  The obvious
way is whereever we have a line number variable, field,
or parameter, we must also add a column number variable,
field, or parameter.  But this is a lot of work for the
amount of benefit.  It is also wasteful to add an
extra int column field to every decl node or every
linenote rtx.  Instead, we can combine the line and
column number into a single 32-bit value, counting
on that fact that we will never need either number
that large (though line numbers may reasonably exceed
2**16, so short is not enough).  If we also use a
trick where the column number is the *high-order*
bits of the combined line+column value, plus have the
interpretation that a column number of zero means
a missing/unknown column (or the entire line), then
we have "binary compatibility" between the new scheme
and the old scheme.

I suggest using a new typedef to indicate such a line+column
combination.  The typedef is mainly for documentation
purposes, to make it clear when a "line number" is a pure
line number and when a line+column combination.  I used the
name "linecol" for this typedef below.

The patch below is only for discussion.  I have not tested it.
While I do think the basic idea is good, the specifics
may be less so.  For example, the macro names are hardly
wonderful, nor is the "linecol" name itself.

	--Per Bothner
Cygnus Solutions     bothner@cygnus.com     http://www.cygnus.com/~bothner

Index: tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.59
diff -u -p -r1.59 tree.h
--- tree.h	1998/11/27 10:09:15	1.59
+++ tree.h	1999/01/13 22:38:44
@@ -147,6 +147,20 @@ enum built_in_function
 
 typedef union tree_node *tree;
 
+/* A linecol is a line number with an optional column number.	
+   The line number is the low order 22 bits of the linecol.
+   The column number is the high order 10 bits (or whatever) of the linecol.
+   A column number of 0 means "unknown" or "entire line".
+   Note that a linecol with a missing column number is the same as a line
+   number.  This provides portability with code that does not know about
+   column numbers.    */
+
+typedef int linecol;
+
+#define LINECOL_LINE(LC) ((LINECOL) & 0x3FFFFF)
+#define LINECOL_COLUMN(LC) ((LINECOL) >> 22)
+#define LINECOL_MAKE(LINE, COLUMN) ((LINE) << &0x2FFFFF) | ((COLUMN) << 22))
+
 /* Every kind of tree node starts with this structure,
    so all nodes have these fields.
 
@@ -699,11 +713,11 @@ struct tree_vec
 #define EXPR_WFL_NODE(NODE) TREE_OPERAND((NODE), 0)
 #define EXPR_WFL_FILENAME(NODE) (IDENTIFIER_POINTER ((NODE)->common.chain))
 #define EXPR_WFL_FILENAME_NODE(NODE) ((NODE)->common.chain)
-#define EXPR_WFL_LINENO(NODE) (EXPR_CHECK (NODE)->exp.complexity >> 12)
-#define EXPR_WFL_COLNO(NODE) (EXPR_CHECK (NODE)->exp.complexity & 0xfff)
+#define EXPR_WFL_LINENO(NODE) LINECOL_LINE ((EXPR_CHECK (NODE)->exp.complexity))
+#define EXPR_WFL_COLNO(NODE) LINECOL_COLUMN (EXPR_CHECK (NODE)->exp.complexity))
 #define EXPR_WFL_LINECOL(NODE) (EXPR_CHECK (NODE)->exp.complexity)
 #define EXPR_WFL_SET_LINECOL(NODE, LINE, COL) \
-  (EXPR_WFL_LINECOL(NODE) = ((LINE) << 12) | ((COL) & 0xfff))
+  (EXPR_WFL_LINECOL(NODE) = LINECOL_MAKE (LINE, COL))
 #define EXPR_WFL_EMIT_LINE_NOTE(NODE) ((NODE)->common.public_flag)
 
 struct tree_exp
@@ -1065,7 +1079,8 @@ struct tree_type
 #define DECL_QUALIFIER(NODE) (DECL_CHECK (NODE)->decl.initial)
 /* These two fields describe where in the source code the declaration was.  */
 #define DECL_SOURCE_FILE(NODE) (DECL_CHECK (NODE)->decl.filename)
-#define DECL_SOURCE_LINE(NODE) (DECL_CHECK (NODE)->decl.linenum)
+#define DECL_SOURCE_LINENO(NODE) LINECOL_LINE ((DECL_CHECK (NODE)->decl.linenum))
+#define DECL_SOURCE_COLNO(NODE) LINECOL_COLUMN ((DECL_CHECK (NODE)->decl.linenum))
 /* Holds the size of the datum, as a tree expression.
    Need not be constant.  */
 #define DECL_SIZE(NODE) (DECL_CHECK (NODE)->decl.size)
@@ -1279,7 +1294,7 @@ struct tree_decl
 {
   char common[sizeof (struct tree_common)];
   char *filename;
-  int linenum;
+  linecol linenum;
   unsigned int uid;
   union tree_node *size;
 #ifdef ONLY_INT_FIELDS
@@ -1843,8 +1858,8 @@ extern tree char_type_node;
    being parsed originally came (before it went into cpp).  */
 extern char *input_filename;
 
-/* Current line number in input file.  */
-extern int lineno;
+/* Current line number (and optional column number) in input file.  */
+extern linecol lineno;
 
 /* Nonzero for -pedantic switch: warn about anything
    that standard C forbids.  */
Index: toplev.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/toplev.c,v
retrieving revision 1.134
diff -u -p -r1.134 toplev.c
--- toplev.c	1998/12/06 03:02:47	1.134
+++ toplev.c	1999/01/13 22:38:44
@@ -177,16 +177,18 @@ void sorry PVPROTO((char *s, ...));
 static void set_target_switch PROTO((char *));
 static char *decl_name PROTO((tree, int));
 static void vmessage PROTO((char *, char *, va_list));
-static void v_message_with_file_and_line PROTO((char *, int, char *,
+static void v_message_with_file_and_line PROTO((char *, linecol, char *,
 						char *, va_list));
 static void v_message_with_decl PROTO((tree, char *, char *, va_list));
 static void file_and_line_for_asm PROTO((rtx, char **, int *));
-static void v_error_with_file_and_line PROTO((char *, int, char *, va_list));
+static void v_error_with_file_and_line PROTO((char *, linecol,
+					      char *, va_list));
 static void v_error_with_decl PROTO((tree, char *, va_list));
 static void v_error_for_asm PROTO((rtx, char *, va_list));
 static void verror PROTO((char *, va_list));
 static void vfatal PROTO((char *, va_list)) ATTRIBUTE_NORETURN;
-static void v_warning_with_file_and_line PROTO ((char *, int, char *, va_list));
+static void v_warning_with_file_and_line PROTO ((char *, linecol,
+						 char *, va_list));
 static void v_warning_with_decl PROTO((tree, char *, va_list));
 static void v_warning_for_asm PROTO((rtx, char *, va_list));
 static void vwarning PROTO((char *, va_list));
@@ -238,9 +240,9 @@ char *input_filename;
 
 char *main_input_filename;
 
-/* Current line number in real source file.  */
+/* Current line number (and optional column number) in real source file.  */
 
-int lineno;
+linecol lineno;
 
 /* Nonzero if it is unsafe to create any new pseudo registers.  */
 int no_new_pseudos;
@@ -1509,7 +1511,7 @@ report_error_function (file)
       fprintf (stderr, "In file included");
       for (p = input_file_stack->next; p; p = p->next)
 	{
-	  fprintf (stderr, " from %s:%d", p->name, p->line);
+	  fprintf (stderr, " from %s:%d", p->name, LINECOL_LINE (p->line));
 	  if (p->next)
 	    fprintf (stderr, ",\n                ");
 	}
@@ -1532,18 +1534,29 @@ vmessage (prefix, s, ap)
   vfprintf (stderr, s, ap);
 }
 
+static void
+print_lineno (file, line)
+     char *file;
+     linecol line;
+{
+  int col = LINECOL_COLUMN (line);
+  fprintf (stderr, "%s:%d: ", file, LINECOL_LINE (line));
+  if (col != 0)
+    fprintf (stderr, ":%d", col);
+}
+
 /* Print a message relevant to line LINE of file FILE.  */
 
 static void
 v_message_with_file_and_line (file, line, prefix, s, ap)
      char *file;
-     int line;
+     linecol line;
      char *prefix;
      char *s;
      va_list ap;
 {
   if (file)
-    fprintf (stderr, "%s:%d: ", file, line);
+    print_lineno (file, line);
   else
     fprintf (stderr, "%s: ", progname);
 
@@ -1562,8 +1575,7 @@ v_message_with_decl (decl, prefix, s, ap
 {
   char *p;
 
-  fprintf (stderr, "%s:%d: ",
-	   DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
+  print_lineno (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
 
   if (prefix)
     fprintf (stderr, "%s: ", prefix);
@@ -1655,7 +1667,7 @@ file_and_line_for_asm (insn, pfile, plin
 static void
 v_error_with_file_and_line (file, line, s, ap)
      char *file;
-     int line;
+     linecol line;
      char *s;
      va_list ap;
 {
@@ -1822,7 +1834,7 @@ fatal VPROTO((char *s, ...))
 static void
 v_warning_with_file_and_line (file, line, s, ap)
      char *file;
-     int line;
+     linecol line;
      char *s;
      va_list ap;
 {
@@ -2079,7 +2091,7 @@ vsorry (s, ap)
 {
   sorrycount++;
   if (input_filename)
-    fprintf (stderr, "%s:%d: ", input_filename, lineno);
+    print_lineno (input_filename, lineno);
   else
     fprintf (stderr, "%s: ", progname);
   vmessage ("sorry, not implemented", s, ap);
@@ -2113,7 +2125,7 @@ v_really_sorry (s, ap)
 {
   sorrycount++;
   if (input_filename)
-    fprintf (stderr, "%s:%d: ", input_filename, lineno);
+    print_lineno (input_filename, lineno);
   else
     fprintf (stderr, "%s: ", progname);
   vmessage ("sorry, not implemented", s, ap);
@@ -3449,8 +3461,6 @@ rest_of_compilation (decl)
 
       /* If we can, defer compiling inlines until EOF.
 	 save_for_inline_copying can be extremely expensive.  */
-      if (inlinable && ! decl_function_context (decl))
-	DECL_DEFER_OUTPUT (decl) = 1;
 
       /* If function is inline, and we don't yet know whether to
 	 compile it by itself, defer decision till end of compilation.
Index: rtl.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/rtl.h,v
retrieving revision 1.70
diff -u -p -r1.70 rtl.h
--- rtl.h	1998/12/03 01:32:21	1.70
+++ rtl.h	1999/01/13 22:38:44
@@ -398,9 +398,11 @@ extern char *reg_note_name[];
    block node for a live range block.  */
 #define NOTE_BLOCK_LIVE_RANGE_BLOCK -1
 
-/* In a NOTE that is a line number, this is the line number.
+/* In a NOTE that is a line number, this is the line number (a linecol).
    Other kinds of NOTEs are identified by negative numbers here.  */
 #define NOTE_LINE_NUMBER(INSN) ((INSN)->fld[4].rtint)
+#define NOTE_LINENO(INSN) LINECOL_LINENO ((INSN)->fld[4].rtint)
+#define NOTE_COLNO(INSN) LINECOL_COLNO((INSN)->fld[4].rtint)
 
 /* Codes that appear in the NOTE_LINE_NUMBER field
    for kinds of notes that are not line numbers.
@@ -555,6 +557,8 @@ extern char *note_insn_name[];
 #define ASM_OPERANDS_INPUT_MODE(RTX, N) GET_MODE (XVECEXP ((RTX), 4, (N)))
 #define ASM_OPERANDS_SOURCE_FILE(RTX) XSTR ((RTX), 5)
 #define ASM_OPERANDS_SOURCE_LINE(RTX) XINT ((RTX), 6)
+#define ASM_OPERANDS_SOURCE_LINENO(RTX) LINECOL_LINENO (XINT ((RTX), 6))
+#define ASM_OPERANDS_SOURCE_COLNO(RTX) LINECOL_COLNO (XINT ((RTX), 6))
 
 /* For a MEM rtx, 1 if it's a volatile reference.
    Also in an ASM_OPERANDS rtx.  */
Index: dbxout.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/dbxout.c,v
retrieving revision 1.30
diff -u -p -r1.30 dbxout.c
--- dbxout.c	1998/11/09 20:33:37	1.30
+++ dbxout.c	1999/01/13 22:38:44
@@ -563,9 +563,10 @@ void
 dbxout_source_line (file, filename, lineno)
      FILE *file;
      char *filename;
-     int lineno;
+     linecol lineno;
 {
   dbxout_source_file (file, filename);
+  lineno = LINECOL_LINE (lineno);
 
 #ifdef ASM_OUTPUT_SOURCE_LINE
   ASM_OUTPUT_SOURCE_LINE (file, lineno);
@@ -2206,7 +2207,7 @@ dbxout_finish_symbol (sym)
 #else
   int line = 0;
   if (use_gnu_debug_info_extensions && sym != 0)
-    line = DECL_SOURCE_LINE (sym);
+    line = DECL_SOURCE_LINENO (sym);
 
   fprintf (asmfile, "\",%d,0,%d,", current_sym_code, line);
   if (current_sym_addr)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]