[PATCH] Postpone __LINE__ evaluation to the end of #line directives

mtewoodbury@gmail.com mtewoodbury@gmail.com
Wed Nov 27 12:12:00 GMT 2013


From: Max TenEyck Woodbury <max+git@mtew.isa-geek.net>

Copyright 2013 assigned to the Free Software Foundation.
---
 gcc/testsuite/gcc.dg/cpp/line4.c | 19 +++++++++++++++----
 libcpp/directives.c              |  9 ++++++++-
 libcpp/internal.h                |  1 +
 libcpp/macro.c                   |  3 +++
 4 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/cpp/line4.c b/gcc/testsuite/gcc.dg/cpp/line4.c
index 84dbf96..0120a2b 100644
--- a/gcc/testsuite/gcc.dg/cpp/line4.c
+++ b/gcc/testsuite/gcc.dg/cpp/line4.c
@@ -13,7 +13,18 @@ enum { i = __LINE__ };
 enum { j = __LINE__ };
 
 #line 16  /* N.B. the _next_ line is line 16.  */
-
-char array1[i        == 44 ? 1 : -1];
-char array2[j        == 90 ? 1 : -1];
-char array3[__LINE__ == 19 ? 1 : -1];
+                                                     /* __LINE__ should be 16 */
+char array1[i        == 44 ? 1 : -1];                                   /* 17 */
+char array2[j        == 90 ? 1 : -1];                                   /* 18 */
+char array3[__LINE__ == 19 ? 1 : -1];                                   /* 19 */
+                                                                        /* 20 */
+# line __LINE__ /* N.B. the __LINE__ sequence should _not_ change here. */
+                                                                        /* 22 */
+char array4[__LINE__ == 23 ? 1: -1];                                    /* 23 */
+char array5[__LINE__ == 23 ? -1: 1];                                    /* 24 */
+                                                                        /* 25 */
+# line __LINE__ /* N.B. nor shoud a multi-line comment change the fact
+                   that the __LINE__ sequence should _not_ change here. */
+                                                                        /* 28 */
+char array6[__LINE__ == 29 ? 1: -1];                                    /* 29 */
+char array7[__LINE__ == 27 ? -1: 1];                                    /* 30 */
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 65b2034..adb04a5 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -900,7 +900,9 @@ do_line (cpp_reader *pfile)
   bool wrapped;
 
   /* #line commands expand macros.  */
+  ++pfile->state.in_directive;          /* Request special __LINE__ handling. */
   token = cpp_get_token (pfile);
+  --pfile->state.in_directive;                              /* Cancle request */
   if (token->type != CPP_NUMBER
       || strtolinenum (token->val.str.text, token->val.str.len,
 		       &new_lineno, &wrapped))
@@ -914,7 +916,9 @@ do_line (cpp_reader *pfile)
       return;
     }
 
-  if (CPP_PEDANTIC (pfile) && (new_lineno == 0 || new_lineno > cap || wrapped))
+  if (CPP_PEDANTIC (pfile) && (new_lineno == 0 ||
+      (new_lineno > cap && new_lineno != CUR__LINE__) ||
+      wrapped))
     cpp_error (pfile, CPP_DL_PEDWARN, "line number out of range");
   else if (wrapped)
     cpp_error (pfile, CPP_DL_WARNING, "line number out of range");
@@ -936,6 +940,9 @@ do_line (cpp_reader *pfile)
     }
 
   skip_rest_of_line (pfile);
+  if ( new_lineno == CUR__LINE__ )                  /* Postponed evaluation ? */
+    new_lineno = linemap_get_expansion_line (pfile->line_table,
+                                             pfile->line_table->highest_line);
   _cpp_do_file_change (pfile, LC_RENAME_VERBATIM, new_file, new_lineno,
 		       map_sysp);
 }
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 5321458..268de86 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -604,6 +604,7 @@ cpp_in_primary_file (cpp_reader *pfile)
 {
   return pfile->line_table->depth == 1;
 }
+#define CUR__LINE__ -1U
 
 /* In macro.c */
 extern void _cpp_free_definition (cpp_hashnode *);
diff --git a/libcpp/macro.c b/libcpp/macro.c
index e359d15..47e41b6 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -309,6 +309,9 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
       /* If __LINE__ is embedded in a macro, it must expand to the
 	 line of the macro's invocation, not its definition.
 	 Otherwise things like assert() will not work properly.  */
+      if ( pfile->state.in_directive > 1 )             /* In #line directive? */
+        number = CUR__LINE__;                  /* yes, postpone the lookup... */
+      else
       number = linemap_get_expansion_line (pfile->line_table,
 					   CPP_OPTION (pfile, traditional)
 					   ? pfile->line_table->highest_line
-- 
1.8.0.rc0.18.gf84667d



More information about the Gcc-patches mailing list