summaryrefslogtreecommitdiff
path: root/gcc/c-family
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-26 19:30:59 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-26 19:30:59 +0000
commit244db24d8ddff5d5788dc1f10c971d815c9b4388 (patch)
tree1d0c22775480b21a84a6024b85f12710e67dd587 /gcc/c-family
parenta60a96f62b663b8dc609fa90feb808ca74956a03 (diff)
downloadgcc-244db24d8ddff5d5788dc1f10c971d815c9b4388.tar.gz
Implement C++11 user-defined literals.
libcpp/ * expr.c: (cpp_interpret_float_suffix, cpp_interpret_int_suffix, cpp_userdef_string_remove_type, cpp_userdef_string_add_type, cpp_userdef_char_remove_type, cpp_userdef_char_add_type, cpp_userdef_string_p, cpp_userdef_char_p, cpp_get_userdef_suffix): New. (cpp_classify_number): Classify unrecognized tokens as user-defined literals. * include/cpplib.h: Add new tokens for user-defined literals. * init.c: Add new preprocessor flag (cxx11). * lex.c: (lex_string, lex_raw_string): Handle user-defined literals including concatenation and promotion with suffixes. c-family/ * c-common.c (build_userdef_literal): New. * c-common.def: New tree code. * c-common.h (tree_userdef_literal): New tree struct and accessors. * c-lex.c (interpret_float): Add suffix parm. (c_lex_with_flags): Build literal tokens. cp/ * cp-objcp-common.c: (cp_tree_size) Return size of USERDEF_LITERAL tree. * cp-tree.h: (UDLIT_OP_*, UDLIT_OPER_P): Literal operator name tools. New tree code for user-defined literals. * cxx-pretty-print.h: (pp_cxx_userdef_literal) New. * cxx-pretty-print.c: (pp_cxx_userdef_literal) New. (pp_cxx_primary_expression, pp_cxx_expression): Use it. * decl.c: (cp_tree_node_structure): Return new tree code. (duplicate_decls): Check for raw vs. template operator conflicts. (grokfndecl, grokdeclarator): New checks for literal operators. * error.c: (dump_expr): Warn about user-defined literals in C++98 mode. (dump_function_name): Pretty printing. * mangle.c: (write_literal_operator_name): New. (write_unqualified_id, write_unqualified_name): Use it. * parser.c: (cp_parser_operator): Handle operator"". (cp_parser_userdef_char_literal, cp_parser_userdef_numeric_literal, cp_parser_userdef_string_literal): New. (cp_parser_primary_expression): Handle new user-defined literal tokens with new functions. * semantics.c: (potential_constant_expression_1): Add user-defined literals. * typeck.c (check_raw_literal_operator, check_literal_operator_args): New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180536 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-family')
-rw-r--r--gcc/c-family/ChangeLog9
-rw-r--r--gcc/c-family/c-common.c13
-rw-r--r--gcc/c-family/c-common.def6
-rw-r--r--gcc/c-family/c-common.h23
-rw-r--r--gcc/c-family/c-lex.c63
5 files changed, 108 insertions, 6 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index d1c2c49ac85..b49e827866b 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,12 @@
+2011-10-26 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++11 user-defined literals.
+ * c-common.c (build_userdef_literal): New.
+ * c-common.def: New tree code.
+ * c-common.h (tree_userdef_literal): New tree struct and accessors.
+ * c-lex.c (interpret_float): Add suffix parm.
+ (c_lex_with_flags): Build literal tokens.
+
2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/50841
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index ae18de3929c..2eefe03f390 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -9912,4 +9912,17 @@ c_common_init_ts (void)
MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
}
+/* Build a user-defined numeric literal out of an integer constant type VALUE
+ with identifier SUFFIX. */
+
+tree
+build_userdef_literal (tree suffix_id, tree value, tree num_string)
+{
+ tree literal = make_node (USERDEF_LITERAL);
+ USERDEF_LITERAL_SUFFIX_ID (literal) = suffix_id;
+ USERDEF_LITERAL_VALUE (literal) = value;
+ USERDEF_LITERAL_NUM_STRING (literal) = num_string;
+ return literal;
+}
+
#include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.def b/gcc/c-family/c-common.def
index c7e01b693ca..2a7df882d0a 100644
--- a/gcc/c-family/c-common.def
+++ b/gcc/c-family/c-common.def
@@ -47,6 +47,12 @@ DEFTREECODE (C_MAYBE_CONST_EXPR, "c_maybe_const_expr", tcc_expression, 2)
evaluated. */
DEFTREECODE (EXCESS_PRECISION_EXPR, "excess_precision_expr", tcc_expression, 1)
+/* Used to represent a user-defined literal.
+ The operands are an IDENTIFIER for the suffix, the VALUE of the literal,
+ and for numeric literals the original string representation of the
+ number. */
+DEFTREECODE (USERDEF_LITERAL, "userdef_literal", tcc_exceptional, 3)
+
/*
Local variables:
mode:c
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 9818c9ca682..be9d7295b2a 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1067,4 +1067,27 @@ c_tree_chain_next (tree t)
return NULL;
}
+/* A suffix-identifier value doublet that represents user-defined literals
+ for C++-0x. */
+struct GTY(()) tree_userdef_literal {
+ struct tree_base base;
+ tree suffix_id;
+ tree value;
+ tree num_string;
+};
+
+#define USERDEF_LITERAL_SUFFIX_ID(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->suffix_id)
+
+#define USERDEF_LITERAL_VALUE(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value)
+
+#define USERDEF_LITERAL_NUM_STRING(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string)
+
+#define USERDEF_LITERAL_TYPE(NODE) \
+ (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE)))
+
+extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string);
+
#endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index b151564000c..baee8eb9799 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -45,7 +45,7 @@ int pending_lang_change; /* If we need to switch languages - C++ only */
int c_header_level; /* depth in C headers - C++ only */
static tree interpret_integer (const cpp_token *, unsigned int);
-static tree interpret_float (const cpp_token *, unsigned int);
+static tree interpret_float (const cpp_token *, unsigned int, const char *);
static tree interpret_fixed (const cpp_token *, unsigned int);
static enum integer_type_kind narrowest_unsigned_type
(unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned int);
@@ -314,7 +314,8 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
case CPP_NUMBER:
{
- unsigned int flags = cpp_classify_number (parse_in, tok);
+ const char *suffix = NULL;
+ unsigned int flags = cpp_classify_number (parse_in, tok, &suffix);
switch (flags & CPP_N_CATEGORY)
{
@@ -332,12 +333,27 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
break;
case CPP_N_FLOATING:
- *value = interpret_float (tok, flags);
+ *value = interpret_float (tok, flags, suffix);
break;
default:
gcc_unreachable ();
}
+
+ if (flags & CPP_N_USERDEF)
+ {
+ tree suffix_id = get_identifier (suffix);
+ int len = tok->val.str.len - strlen (suffix);
+ tree num_string = build_string (len + 1,
+ (const char *) tok->val.str.text);
+ TREE_TYPE (num_string) = char_array_type_node;
+ num_string = fix_string_type (num_string);
+ char *str = CONST_CAST (char *, TREE_STRING_POINTER (num_string));
+ str[len] = '\0';
+ tree literal = build_userdef_literal (suffix_id, *value,
+ num_string);
+ *value = literal;
+ }
}
break;
@@ -415,6 +431,22 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
}
goto retry;
+ case CPP_CHAR_USERDEF:
+ case CPP_WCHAR_USERDEF:
+ case CPP_CHAR16_USERDEF:
+ case CPP_CHAR32_USERDEF:
+ {
+ tree literal;
+ cpp_token temp_tok = *tok;
+ const char *suffix = cpp_get_userdef_suffix (tok);
+ temp_tok.val.str.len -= strlen (suffix);
+ temp_tok.type = cpp_userdef_char_remove_type (type);
+ literal = build_userdef_literal (get_identifier (suffix),
+ lex_charconst (&temp_tok), NULL_TREE);
+ *value = literal;
+ }
+ break;
+
case CPP_CHAR:
case CPP_WCHAR:
case CPP_CHAR16:
@@ -422,6 +454,22 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
*value = lex_charconst (tok);
break;
+ case CPP_STRING_USERDEF:
+ case CPP_WSTRING_USERDEF:
+ case CPP_STRING16_USERDEF:
+ case CPP_STRING32_USERDEF:
+ case CPP_UTF8STRING_USERDEF:
+ {
+ tree literal, string;
+ const char *suffix = cpp_get_userdef_suffix (tok);
+ string = build_string (tok->val.str.len - strlen (suffix),
+ (const char *) tok->val.str.text);
+ literal = build_userdef_literal (get_identifier (suffix),
+ string, NULL_TREE);
+ *value = literal;
+ }
+ break;
+
case CPP_STRING:
case CPP_WSTRING:
case CPP_STRING16:
@@ -621,9 +669,10 @@ interpret_integer (const cpp_token *token, unsigned int flags)
}
/* Interpret TOKEN, a floating point number with FLAGS as classified
- by cpplib. */
+ by cpplib. For C++0X SUFFIX may contain a user-defined literal suffix. */
static tree
-interpret_float (const cpp_token *token, unsigned int flags)
+interpret_float (const cpp_token *token, unsigned int flags,
+ const char *suffix)
{
tree type;
tree const_type;
@@ -702,7 +751,9 @@ interpret_float (const cpp_token *token, unsigned int flags)
has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF
can't handle them. */
copylen = token->val.str.len;
- if (flags & CPP_N_DFLOAT)
+ if (flags & CPP_N_USERDEF)
+ copylen -= strlen (suffix);
+ else if (flags & CPP_N_DFLOAT)
copylen -= 2;
else
{