This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][libcpp] Macros for unique named functions / identifiers
- From: "Rahul Kharche" <rahul at IceraSemi dot com>
- To: "GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Cc: "sdkteam-gnu" <sdkteam-gnu at IceraSemi dot com>
- Date: Mon, 12 Apr 2010 17:51:38 +0100
- Subject: [PATCH][libcpp] Macros for unique named functions / identifiers
The following patch adds macros CANON_BASE_FILE and CANON_LINE.
CANON_BASE_FILE is analogous to BASE_FILE, but not a string constant
and only preserves characters valid as an identifiers. CANON_LINE
is analogous to the line number and occurance count in the
preprocessed output. Together they can be used to make unique named
identifiers and functions across files.
Because column numbers are not maintained in every case we
use an occurance count shifted into the lower OCCUR_NUM_BITS of
the flat line number to form CANON_LINE.
http://gcc.gnu.org/ml/gcc-patches/2010-04/msg00038.html
Together with the deferred pragma patch proposed earlier, they can be
used for late expansion of nested function definitions.
2010-04-12 Rahul Kharche <rahul@icerami.com>
* cpplib.h (BT_CANON_BASE_FILE, BT_CANON_SPECLINE): New enums.
* init.c (builtin_array): Add above to this array and register
new
macros __CANON_BASE_FILE__, __CANON_LINE__.
(cpp_create_reader): Initialize bt_canon_line_occur_count to 0.
* internal.h (bt_canon_line_occur_count): Addeded to cpp_reader.
* line-map.h (SOURCE_LINE_OCCURANCE, OCCUR_NUM_BITS): New
support
macros to splice a line number and occurance count.
* macro.c (make_identifier_name): New function.
(_cpp_builtin_macro_text): Add case for BT_CANON_SPECLINE and
expand
like __CANON_BASE_FILE__ using SOURCE_LINE_OCCURANCE. Add case
for
BT_CANON_BASE_FILE and call make_identifier_name.
* gcc.dg/cpp/canonmacros.c: New test for correct expansion of
__CANON_BASE_FILE__ and __CANON_LINE__.
Index: gcc/doc/cpp.texi
===================================================================
--- gcc/doc/cpp.texi (revision 158225)
+++ gcc/doc/cpp.texi (working copy)
@@ -2030,6 +2030,22 @@ This macro expands to the name of the ma
of a C string constant. This is the source file that was specified
on the command line of the preprocessor or C compiler.
+@item __CANON_BASE_FILE__
+This macro expands to the name of the main input file, like in the case
+of __BASE_FILE__, but not a string constant. Furthermore characters
that
+are invalid for function names (or identifiers) are stripped out
+from expansion. This is useful in creating named functions or
identifiers.
+
+@item __CANON_LINE__
+Similar to __LINE__ this macro expands to a decimal integer
corresponding
+to the line number. But, rather than referring to the line number in
the file
+that mentioned it, this macro expands to the final file it got included
in
+during preprocessing. It is analogous to the line number in the
preprocessed
+file. The line number is held in the higher bits. The lower 8 bits hold
an
+occurance count to make multiple occurances of this macro on a single
line
+unique. Together __CANON_BASE_FILE__ and __CANON_LINE__ can be used to
make a
+unique named function or identifier.
+
@item __INCLUDE_LEVEL__
This macro expands to a decimal integer constant that represents the
depth of nesting in include files. The value of this macro is
Index: gcc/testsuite/gcc.dg/cpp/canonmacros.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/canonmacros.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/canonmacros.c (revision 0)
@@ -0,0 +1,19 @@
+/* Verify that preprocessor expands __CANON_BASE_FILE__ and
__CANON_LINE__
+ macros correctly. This test is sensitive to line numbers, and will
need
+ updating if the test files are changed. */
+
+/* { dg-options --save-temps } */
+
+#include "canonmacros.h"
+
+
+int main ()
+{
+ GENERATE_IDENTIFIER (__LINE__);
+ return 0;
+}
+
+/* { dg-final { scan-file canonmacros.i "canonmacrosc_4864" } }
+ { dg-final { scan-file canonmacros.i "canonmacrosc_4865" } }
+ { dg-final { scan-file canonmacros.i "canonmacrosc_6658" } }
+ { dg-final { cleanup-saved-temps } } */
Index: gcc/testsuite/gcc.dg/cpp/canonmacros.h
===================================================================
--- gcc/testsuite/gcc.dg/cpp/canonmacros.h (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/canonmacros.h (revision 0)
@@ -0,0 +1,16 @@
+
+#define AUTO_IDENTIFIER_NAME_EXPAND(name, line) name##_##line
+
+#define AUTO_IDENTIFIER_NAME(name, line, arg) \
+ AUTO_IDENTIFIER_NAME_EXPAND(name, line) (arg)
+
+#define GENERATE_IDENTIFIER(arg) \
+ AUTO_IDENTIFIER_NAME(__CANON_BASE_FILE__, __CANON_LINE__, arg)
+
+int foo ()
+{
+
+ GENERATE_IDENTIFIER (__LINE__); GENERATE_IDENTIFIER (__LINE__);
+
+ return 0;
+}
Index: libcpp/macro.c
===================================================================
--- libcpp/macro.c (revision 158225)
+++ libcpp/macro.c (working copy)
@@ -71,6 +71,9 @@ static bool parse_params (cpp_reader *,
static void check_trad_stringification (cpp_reader *, const cpp_macro
*,
const cpp_string *);
+/* misc text processing functions */
+static void make_identifier_name (const char *, uchar *);
+
/* Emits a warning if NODE is a macro defined in the main file that
has not been used. */
int
@@ -187,6 +190,27 @@ _cpp_builtin_macro_text (cpp_reader *pfi
*buf = '\0';
}
break;
+
+ case BT_CANON_BASE_FILE:
+ {
+ unsigned int len;
+ const char *name;
+ uchar *buf;
+ map = linemap_lookup (pfile->line_table,
pfile->line_table->highest_line);
+
+ while (! MAIN_FILE_P (map))
+ map = INCLUDED_FROM (pfile->line_table, map);
+
+ name = map->to_file;
+ len = strlen (name);
+ /* Strip out any invalid characters from filename and make a
+ valid function name. */
+ buf = _cpp_unaligned_alloc (pfile, len * 2 + 1);
+ make_identifier_name (name, buf);
+ result = buf;
+ }
+ break;
+
case BT_INCLUDE_LEVEL:
/* The line map depth counts the primary source as level 1, but
@@ -206,6 +230,21 @@ _cpp_builtin_macro_text (cpp_reader *pfi
: pfile->cur_token[-1].src_loc);
break;
+ case BT_CANON_SPECLINE:
+ map = &pfile->line_table->maps[pfile->line_table->used-1];
+
+ while (! MAIN_FILE_P (map))
+ map = INCLUDED_FROM (pfile->line_table, map);
+
+ /* Splice in the occurance count with the line number to make
+ it unique. */
+ number = SOURCE_LINE_OCCURANCE (map,
pfile->cur_token[-1].src_loc,
+ pfile->bt_canon_line_occur_count);
+ /* Update the free running occurance count. The least significant
+ OCCUR_NUM_BITS will be used. The count will wrap on overflow.
*/
+ pfile->bt_canon_line_occur_count++;
+ break;
+
/* __STDC__ has the value 1 under normal circumstances.
However, if (a) we are in a system header, (b) the option
stdc_0_in_system_headers is true (set by target config), and
@@ -2108,3 +2147,17 @@ cpp_macro_definition (cpp_reader *pfile,
*buffer = '\0';
return pfile->macro_buffer;
}
+
+static void
+make_identifier_name (const char *name, uchar *buf)
+{
+ char *op = (char *)buf;
+ while (*name != '\0')
+ {
+ if (ISALNUM (*name) || *name == '_')
+ *op++ = *name;
+
+ name++;
+ }
+ *op = '\0';
+}
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h (revision 158225)
+++ libcpp/include/cpplib.h (working copy)
@@ -596,6 +596,8 @@ enum cpp_builtin_type
BT_DATE, /* `__DATE__' */
BT_FILE, /* `__FILE__' */
BT_BASE_FILE, /* `__BASE_FILE__' */
+ BT_CANON_BASE_FILE, /* `__CANON_BASE_FILE__' */
+ BT_CANON_SPECLINE, /* `__CANON_LINE__' */
BT_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
BT_TIME, /* `__TIME__' */
BT_STDC, /* `__STDC__' */
Index: libcpp/include/line-map.h
===================================================================
--- libcpp/include/line-map.h (revision 158225)
+++ libcpp/include/line-map.h (working copy)
@@ -155,6 +155,11 @@ extern const struct line_map *linemap_lo
#define SOURCE_COLUMN(MAP, LOC) \
(((LOC) - (MAP)->start_location) & ((1 << (MAP)->column_bits) - 1))
+#define OCCUR_NUM_BITS 8
+#define SOURCE_LINE_OCCURANCE(MAP, LOC, OCCUR) \
+ ((((LOC) >> (MAP)->column_bits) << OCCUR_NUM_BITS) \
+ + ((OCCUR) & ((1 << OCCUR_NUM_BITS) - 1)))
+
/* Returns the last source line within a map. This is the (last) line
of the #include, or other directive, that caused a map change. */
#define LAST_SOURCE_LINE(MAP) \
Index: libcpp/init.c
===================================================================
--- libcpp/init.c (revision 158225)
+++ libcpp/init.c (working copy)
@@ -218,6 +218,9 @@ cpp_create_reader (enum c_lang lang, has
/* Initialize table for push_macro/pop_macro. */
pfile->pushed_macros = 0;
+
+ /* Initialize occurance count for BT_CANON_SPECLINE macro. */
+ pfile->bt_canon_line_occur_count = 0;
/* The expression parser stack. */
_cpp_expand_op_stack (pfile);
@@ -340,18 +343,20 @@ struct builtin_macro
#define B(n, t, f) { DSC(n), t, f }
static const struct builtin_macro builtin_array[] =
{
- B("__TIMESTAMP__", BT_TIMESTAMP, false),
- B("__TIME__", BT_TIME, false),
- B("__DATE__", BT_DATE, false),
- B("__FILE__", BT_FILE, false),
- B("__BASE_FILE__", BT_BASE_FILE, false),
- B("__LINE__", BT_SPECLINE, true),
- B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL, true),
- B("__COUNTER__", BT_COUNTER, true),
+ B("__TIMESTAMP__", BT_TIMESTAMP, false),
+ B("__TIME__", BT_TIME, false),
+ B("__DATE__", BT_DATE, false),
+ B("__FILE__", BT_FILE, false),
+ B("__BASE_FILE__", BT_BASE_FILE, false),
+ B("__LINE__", BT_SPECLINE, true),
+ B("__CANON_LINE__", BT_CANON_SPECLINE, false),
+ B("__CANON_BASE_FILE__", BT_CANON_BASE_FILE, true),
+ B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL, true),
+ B("__COUNTER__", BT_COUNTER, true),
/* Keep builtins not used for -traditional-cpp at the end, and
update init_builtins() if any more are added. */
- B("_Pragma", BT_PRAGMA, true),
- B("__STDC__", BT_STDC, true),
+ B("_Pragma", BT_PRAGMA, true),
+ B("__STDC__", BT_STDC, true),
};
#undef B
Index: libcpp/internal.h
===================================================================
--- libcpp/internal.h (revision 158225)
+++ libcpp/internal.h (working copy)
@@ -489,6 +489,10 @@ struct cpp_reader
/* List of saved macros by push_macro. */
struct def_pragma_macro *pushed_macros;
+
+ /* Because the preprocessor does not maintain an accurate column
count
+ we need an occurance count to make BT_CANON_SPECLINE unique. */
+ unsigned int bt_canon_line_occur_count;
};
/* Character classes. Based on the more primitive macros in
safe-ctype.h.