Greetings,

I am slowly working on user defined literals for C++-0x.

This is my first foray into the C++ front end and I'm stuck.

Anyway, I managed to parse things like

  long double
  operator"" _foo(long double x) { return 2.0L * x; }

The result is a normal function that I can either call like
  operator "" _foo(1.2L);
or just
  _foo(1.2L);

The problem is when I parse something like

  u"string"w

I want to generate a call to something like

std::string operator"" w(const char16_t*, size_t);

i.e. I want to build a call:

w(u"string", 6);

I have a (not nearly ready for prime time) patch attached. My current problem is in parser.c cp_parser_primary_expression after the string types.

Thanks for any help you can give,

Ed


Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c      (revision 164355)
+++ gcc/cp/error.c      (working copy)
@@ -3033,7 +3033,12 @@
        pedwarn (input_location, OPT_pedantic,
                 "inline namespaces "
                 "only available with -std=c++0x or -std=gnu++0x");
-       break;  
+       break;
+      case CPP0X_USER_DEFINED_LITERALS:
+       pedwarn (input_location, 0,
+                "user-defined literals "
+                "only available with -std=c++0x or -std=gnu++0x");
+       break;
       default:
        gcc_unreachable();
       }
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c     (revision 164355)
+++ gcc/cp/parser.c     (working copy)
@@ -3579,13 +3579,50 @@
     case CPP_STRING32:
     case CPP_WSTRING:
     case CPP_UTF8STRING:
-      /* ??? Should wide strings be allowed when parser->translate_strings_p
-        is false (i.e. in attributes)?  If not, we can kill the third
-        argument to cp_parser_string_literal.  */
-      return cp_parser_string_literal (parser,
-                                      parser->translate_strings_p,
-                                      true);
+      {
+       tree strl;
+       cp_token *next_token;
 
+       /* ??? Should wide strings be allowed when parser->translate_strings_p
+          is false (i.e. in attributes)?  If not, we can kill the third
+          argument to cp_parser_string_literal.  */
+       strl = cp_parser_string_literal (parser,
+                                        parser->translate_strings_p,
+                                        true);
+
+       next_token = cp_lexer_peek_token (parser->lexer);
+       if (next_token->type == CPP_NAME)
+         {
+           tree identifier;
+           VEC(tree,gc) *vec;
+           int len = TREE_STRING_LENGTH (strl);
+
+           identifier = cp_parser_identifier(parser);
+           if (identifier == error_mark_node)
+             return error_mark_node;
+
+           /* Build up a call to the user-defined operator  */
+           vec = make_tree_vector ();
+           VEC_safe_push (tree, gc, vec, strl);
+           VEC_safe_push (tree, gc, vec, build_int_cst (size_type_node, len));
+           identifier = perform_koenig_lookup (identifier, vec,
+                                               /*include_std=*/false);
+           if (identifier == error_mark_node)
+             {
+               release_tree_vector (vec);
+               error ("unable to find user-defined operator");
+               return error_mark_node;
+             }
+           identifier = finish_call_expr (identifier, &vec, false, true,
+                                          tf_warning_or_error);
+           release_tree_vector (vec);
+
+           return identifier;
+         }
+       else
+         return strl;
+      }
+
     case CPP_OPEN_PAREN:
       {
        tree expr;
@@ -10927,6 +10964,31 @@
       cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
       return ansi_opname (ARRAY_REF);
 
+    case CPP_STRING:
+      {
+       if (cxx_dialect == cxx98)
+         maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS);
+       if (TREE_STRING_LENGTH (token->u.value) > 2)
+         {
+           error ("expected empty string after %<operator%> keyword");
+           return error_mark_node;
+         }
+       /* Consume the string.  */
+       cp_lexer_consume_token (parser->lexer);
+       /* Look for an identifier.  */
+       id = cp_parser_identifier (parser);
+
+       /* Look for a `('.  */
+       token = cp_lexer_peek_token (parser->lexer);
+       if (token->type != CPP_OPEN_PAREN)
+         {
+           error ("expected function declaration");
+           return error_mark_node;
+         }
+
+       return id;
+      }
+
     default:
       /* Anything else is an error.  */
       break;
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h    (revision 164355)
+++ gcc/cp/cp-tree.h    (working copy)
@@ -389,7 +389,9 @@
   /* defaulted and deleted functions */
   CPP0X_DEFAULTED_DELETED,
   /* inline namespaces */
-  CPP0X_INLINE_NAMESPACES
+  CPP0X_INLINE_NAMESPACES,
+  /* user defined literals */
+  CPP0X_USER_DEFINED_LITERALS
 } cpp0x_warn_str;
   
 /* The various kinds of operation used by composite_pointer_type. */
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h     (revision 164355)
+++ libcpp/include/cpplib.h     (working copy)
@@ -816,6 +816,8 @@
 #define CPP_N_FRACT    0x100000 /* Fract types.  */
 #define CPP_N_ACCUM    0x200000 /* Accum types.  */
 
+#define CPP_N_USER_DEFINED 0x1000000 /* C++0x user-defned literal.  */
+
 /* Classify a CPP_NUMBER token.  The return value is a combination of
    the flags from the above sets.  */
 extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *);
Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c       (revision 164355)
+++ libcpp/expr.c       (working copy)
@@ -361,10 +361,18 @@
       result = interpret_float_suffix (str, limit - str);
       if (result == 0)
        {
-         cpp_error (pfile, CPP_DL_ERROR,
-                    "invalid suffix \"%.*s\" on floating constant",
-                    (int) (limit - str), str);
-         return CPP_N_INVALID;
+         if (CPP_OPTION (pfile, lang) == CLK_CXX0X
+          || CPP_OPTION (pfile, lang) == CLK_GNUCXX0X)
+           {
+             result |= CPP_N_USER_DEFINED;
+           }
+         else
+           {
+             cpp_error (pfile, CPP_DL_ERROR,
+                        "invalid suffix \"%.*s\" on floating constant",
+                        (int) (limit - str), str);
+             return CPP_N_INVALID;
+           }
        }
 
       /* Traditional C didn't accept any floating suffixes.  */
@@ -406,10 +414,18 @@
       result = interpret_int_suffix (str, limit - str);
       if (result == 0)
        {
-         cpp_error (pfile, CPP_DL_ERROR,
-                    "invalid suffix \"%.*s\" on integer constant",
-                    (int) (limit - str), str);
-         return CPP_N_INVALID;
+         if (CPP_OPTION (pfile, lang) == CLK_CXX0X
+          || CPP_OPTION (pfile, lang) == CLK_GNUCXX0X)
+           {
+             result |= CPP_N_USER_DEFINED;
+           }
+         else
+           {
+             cpp_error (pfile, CPP_DL_ERROR,
+                        "invalid suffix \"%.*s\" on integer constant",
+                        (int) (limit - str), str);
+             return CPP_N_INVALID;
+           }
        }
 
       /* Traditional C only accepted the 'L' suffix.
// ./bin_udlit/bin/g++ -std=c++0x -o user_defined_literal user_defined_literal.cpp

#include <iostream>
#include <string>
#include <complex>

long double operator"" v(long double);
std::string operator"" w(const char16_t*, size_t);
unsigned operator"" w(const char*);

std::complex<double>
operator"" _i(long double);

namespace Long
{
  long double operator"" L(long double);
}

long double loo(long double);

template<char...>
  int operator"" _abc();

//double operator"hi" _badword(long double);  //  user_defined_literal.cpp:23:8: error: expected empty string after 'operator' keyword  //  IMHO, this could be pedantic.

//double operator"" _baddecl;  //  user_defined_literal.cpp:25:19: error: expected function declaration

double operator"" _badargs(int, int);

int
main()
{
  std::cout << "Explicitly call operators..." << std::endl;
  std::cout << operator "" v(1.2L) << std::endl;
  std::cout << operator "" w(u"one", 3) << std::endl;
  std::cout << operator "" w("12") << std::endl;
  std::cout << operator "" _i(2.0) << std::endl;
  std::cout << Long::operator "" L(1.2) << std::endl;

  std::cout << "Explicitly call functions..." << std::endl;
  std::cout << v(1.2) << std::endl;
  std::cout << w(u"one", 3) << std::endl;
  std::cout << w("12") << std::endl;
  std::cout << _i(2.0) << std::endl;
  std::cout << Long::L(1.2) << std::endl;

  std::cout << "Literals..." << std::endl;
  std::cout << 1.2v << std::endl;  // calls operator "" w(1.2L)
  std::cout << u"one"w << std::endl;  // calls operator "" w(u"one", 3)
  std::cout << 12w << std::endl;  // calls operator "" w("12")
  std::cout << 2.0_i << std::endl;
  std::cout << loo(1.2) << std::endl;

  //std::cout << "two"w << std::endl;  // error: no applicable literal operator
}

long double operator"" v(long double x) { return x + 1.0L; }
std::string operator"" w(const char16_t*, size_t) { return std::string(); }
unsigned operator"" w(const char*) { return 0U; }

std::complex<double>
operator"" _i(long double y)
{ return std::complex<double>(0.0L, y); }

namespace Long
{
  long double
  operator"" L(long double x)
  { return x + 2.0L; }
}

long double
loo(long double x)
{
  using Long::L;
  return L(x);
}

template<char...>
  int operator"" _abc()
  { return 42; }

Reply via email to