Commit c865f923 by Ed Smith-Rowland Committed by Edward Smith-Rowland

lex.c (lex_raw_string(), [...]): Constrain suffixes treated as concatenated…

lex.c (lex_raw_string(), [...]): Constrain suffixes treated as concatenated literal and macro to just the...

libcpp:

2013-06-28  Ed Smith-Rowland  <3dw4rd@verizon.net>

	* lex.c (lex_raw_string(), lex_string()): Constrain suffixes treated
	as concatenated literal and macro to just the patterns found in
	inttypes.h; (is_macro()): New.


gcc/cp:

2013-06-28  Ed Smith-Rowland  <3dw4rd@verizon.net>

	* cp-tree.h (UDLIT_OP_ANSI_PREFIX): Remove space.
	* parser.c (cp_parser_operator()): Parse user-defined string
	literal as literal operator.


gcc/testsuite:

2013-06-28  Ed Smith-Rowland  <3dw4rd@verizon.net>

	* g++.dg/cpp0x/udlit-nospace-neg.C: Adjust.
	* g++.dg/cpp1y/udlit-enc-prefix-neg.C: New.
	* g++.dg/cpp1y/udlit-userdef-string.C: New.
	* g++.dg/cpp1y/complex_literals.h: New.

From-SVN: r200563
parent efc58ac5
2013-06-28 Ed Smith-Rowland <3dw4rd@verizon.net>
* cp-tree.h (UDLIT_OP_ANSI_PREFIX): Remove space.
* parser.c (cp_parser_operator()): Parse user-defined string
literal as literal operator.
2013-06-28 Paolo Carlini <paolo.carlini@oracle.com> 2013-06-28 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/57645 PR c++/57645
......
...@@ -4404,7 +4404,7 @@ extern GTY(()) vec<tree, va_gc> *local_classes; ...@@ -4404,7 +4404,7 @@ extern GTY(()) vec<tree, va_gc> *local_classes;
#define LAMBDANAME_PREFIX "__lambda" #define LAMBDANAME_PREFIX "__lambda"
#define LAMBDANAME_FORMAT LAMBDANAME_PREFIX "%d" #define LAMBDANAME_FORMAT LAMBDANAME_PREFIX "%d"
#define UDLIT_OP_ANSI_PREFIX "operator\"\" " #define UDLIT_OP_ANSI_PREFIX "operator\"\""
#define UDLIT_OP_ANSI_FORMAT UDLIT_OP_ANSI_PREFIX "%s" #define UDLIT_OP_ANSI_FORMAT UDLIT_OP_ANSI_PREFIX "%s"
#define UDLIT_OP_MANGLED_PREFIX "li" #define UDLIT_OP_MANGLED_PREFIX "li"
#define UDLIT_OP_MANGLED_FORMAT UDLIT_OP_MANGLED_PREFIX "%s" #define UDLIT_OP_MANGLED_FORMAT UDLIT_OP_MANGLED_PREFIX "%s"
......
...@@ -12244,6 +12244,8 @@ cp_parser_operator (cp_parser* parser) ...@@ -12244,6 +12244,8 @@ cp_parser_operator (cp_parser* parser)
{ {
tree id = NULL_TREE; tree id = NULL_TREE;
cp_token *token; cp_token *token;
bool bad_encoding_prefix = false;
int string_len = 2;
/* Peek at the next token. */ /* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer); token = cp_lexer_peek_token (parser->lexer);
...@@ -12443,10 +12445,20 @@ cp_parser_operator (cp_parser* parser) ...@@ -12443,10 +12445,20 @@ cp_parser_operator (cp_parser* parser)
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
return ansi_opname (ARRAY_REF); return ansi_opname (ARRAY_REF);
case CPP_WSTRING:
string_len = 3;
case CPP_STRING16:
case CPP_STRING32:
string_len = 5;
case CPP_UTF8STRING:
string_len = 4;
bad_encoding_prefix = true;
case CPP_STRING: case CPP_STRING:
if (cxx_dialect == cxx98) if (cxx_dialect == cxx98)
maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS); maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS);
if (TREE_STRING_LENGTH (token->u.value) > 2) if (bad_encoding_prefix)
error ("invalid encoding prefix in literal operator");
if (TREE_STRING_LENGTH (token->u.value) > string_len)
{ {
error ("expected empty string after %<operator%> keyword"); error ("expected empty string after %<operator%> keyword");
return error_mark_node; return error_mark_node;
...@@ -12464,15 +12476,49 @@ cp_parser_operator (cp_parser* parser) ...@@ -12464,15 +12476,49 @@ cp_parser_operator (cp_parser* parser)
return cp_literal_operator_id (name); return cp_literal_operator_id (name);
} }
} }
else if (token->type == CPP_KEYWORD)
{
error ("unexpected keyword;"
" remove space between quotes and suffix identifier");
return error_mark_node;
}
else else
{ {
error ("expected suffix identifier"); error ("expected suffix identifier");
return error_mark_node; return error_mark_node;
} }
case CPP_WSTRING_USERDEF:
string_len = 3;
case CPP_STRING16_USERDEF:
case CPP_STRING32_USERDEF:
string_len = 5;
case CPP_UTF8STRING_USERDEF:
string_len = 4;
bad_encoding_prefix = true;
case CPP_STRING_USERDEF: case CPP_STRING_USERDEF:
error ("missing space between %<\"\"%> and suffix identifier"); if (cxx_dialect == cxx98)
return error_mark_node; maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS);
if (bad_encoding_prefix)
error ("invalid encoding prefix in literal operator");
{
tree string_tree = USERDEF_LITERAL_VALUE (token->u.value);
if (TREE_STRING_LENGTH (string_tree) > string_len)
{
error ("expected empty string after %<operator%> keyword");
return error_mark_node;
}
id = USERDEF_LITERAL_SUFFIX_ID (token->u.value);
/* Consume the user-defined string literal. */
cp_lexer_consume_token (parser->lexer);
if (id != error_mark_node)
{
const char *name = IDENTIFIER_POINTER (id);
return cp_literal_operator_id (name);
}
else
return error_mark_node;
}
default: default:
/* Anything else is an error. */ /* Anything else is an error. */
......
2013-06-28 Ed Smith-Rowland <3dw4rd@verizon.net>
* g++.dg/cpp0x/udlit-nospace-neg.C: Adjust.
* g++.dg/cpp1y/udlit-enc-prefix-neg.C: New.
* g++.dg/cpp1y/udlit-userdef-string.C: New.
* g++.dg/cpp1y/complex_literals.h: New.
2013-06-28 Paolo Carlini <paolo.carlini@oracle.com> 2013-06-28 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/57645 PR c++/57645
......
// { dg-options "-std=c++0x" } // { dg-options "-std=c++0x" }
float operator ""_abc(const char*); // { dg-error "missing space between|and suffix identifier" } float operator ""_abc(const char*);
int operator""_def(long double);
#include <complex>
#pragma GCC system_header
std::complex<float>
operator""if(long double ximag)
{ return std::complex<float>(0.0F, static_cast<float>(ximag)); }
std::complex<float>
operator""if(unsigned long long nimag)
{ return std::complex<float>(0.0F, static_cast<float>(nimag)); }
// { dg-options -std=c++1y }
int
operator L""_Ls(unsigned long long) // { dg-error "invalid encoding prefix in literal operator" }
{ return 0; }
int
operator u""_s16(unsigned long long) // { dg-error "invalid encoding prefix in literal operator" }
{ return 0; }
int
operator U""_s32(unsigned long long) // { dg-error "invalid encoding prefix in literal operator" }
{ return 0; }
int
operator u8""_u8s(unsigned long long) // { dg-error "invalid encoding prefix in literal operator" }
{ return 0; }
// { dg-options -std=c++1y }
#include "complex_literals.h"
auto cx = 1.1if;
auto cn = 123if;
2013-06-28 Ed Smith-Rowland <3dw4rd@verizon.net>
* lex.c (lex_raw_string(), lex_string()): Constrain suffixes treated
as concatenated literal and macro to just the patterns found in
inttypes.h; (is_macro()): New.
2013-06-24 Dehao Chen <dehao@google.com> 2013-06-24 Dehao Chen <dehao@google.com>
* files.c (_cpp_stack_include): Fix the highest_location when header * files.c (_cpp_stack_include): Fix the highest_location when header
......
...@@ -1334,6 +1334,33 @@ bufring_append (cpp_reader *pfile, const uchar *base, size_t len, ...@@ -1334,6 +1334,33 @@ bufring_append (cpp_reader *pfile, const uchar *base, size_t len,
*last_buff_p = last_buff; *last_buff_p = last_buff;
} }
/* Returns true if a macro has been defined.
This might not work if compile with -save-temps,
or preprocess separately from compilation. */
static bool
is_macro(cpp_reader *pfile, const uchar *base)
{
const uchar *cur = base;
if (! ISIDST (*cur))
return false;
unsigned int hash = HT_HASHSTEP (0, *cur);
++cur;
while (ISIDNUM (*cur))
{
hash = HT_HASHSTEP (hash, *cur);
++cur;
}
hash = HT_HASHFINISH (hash, cur - base);
cpp_hashnode *result = CPP_HASHNODE (ht_lookup_with_hash (pfile->hash_table,
base, cur - base, hash, HT_NO_INSERT));
return !result ? false : (result->type == NT_MACRO);
}
/* Lexes a raw string. The stored string contains the spelling, including /* Lexes a raw string. The stored string contains the spelling, including
double quotes, delimiter string, '(' and ')', any leading double quotes, delimiter string, '(' and ')', any leading
'L', 'u', 'U' or 'u8' and 'R' modifier. It returns the type of the 'L', 'u', 'U' or 'u8' and 'R' modifier. It returns the type of the
...@@ -1556,22 +1583,18 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base, ...@@ -1556,22 +1583,18 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
if (CPP_OPTION (pfile, user_literals)) if (CPP_OPTION (pfile, user_literals))
{ {
/* According to C++11 [lex.ext]p10, a ud-suffix not starting with an /* If a string format macro, say from inttypes.h, is placed touching
underscore is ill-formed. Since this breaks programs using macros a string literal it could be parsed as a C++11 user-defined string
from inttypes.h, we generate a warning and treat the ud-suffix as a literal thus breaking the program.
separate preprocessing token. This approach is under discussion by Try to identify macros with is_macro. A warning is issued. */
the standards committee, and has been adopted as a conforming if (is_macro (pfile, cur))
extension by other front ends such as clang.
A special exception is made for the suffix 's' which will be
standardized as a user-defined literal suffix for strings. */
if (ISALPHA (*cur) && *cur != 's')
{ {
/* Raise a warning, but do not consume subsequent tokens. */ /* Raise a warning, but do not consume subsequent tokens. */
if (CPP_OPTION (pfile, warn_literal_suffix)) if (CPP_OPTION (pfile, warn_literal_suffix))
cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX, cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX,
token->src_loc, 0, token->src_loc, 0,
"invalid suffix on literal; C++11 requires " "invalid suffix on literal; C++11 requires "
"a space between literal and identifier"); "a space between literal and string macro");
} }
/* Grab user defined literal suffix. */ /* Grab user defined literal suffix. */
else if (ISIDST (*cur)) else if (ISIDST (*cur))
...@@ -1689,22 +1712,18 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) ...@@ -1689,22 +1712,18 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
if (CPP_OPTION (pfile, user_literals)) if (CPP_OPTION (pfile, user_literals))
{ {
/* According to C++11 [lex.ext]p10, a ud-suffix not starting with an /* If a string format macro, say from inttypes.h, is placed touching
underscore is ill-formed. Since this breaks programs using macros a string literal it could be parsed as a C++11 user-defined string
from inttypes.h, we generate a warning and treat the ud-suffix as a literal thus breaking the program.
separate preprocessing token. This approach is under discussion by Try to identify macros with is_macro. A warning is issued. */
the standards committee, and has been adopted as a conforming if (is_macro (pfile, cur))
extension by other front ends such as clang.
A special exception is made for the suffix 's' which will be
standardized as a user-defined literal suffix for strings. */
if (ISALPHA (*cur) && *cur != 's')
{ {
/* Raise a warning, but do not consume subsequent tokens. */ /* Raise a warning, but do not consume subsequent tokens. */
if (CPP_OPTION (pfile, warn_literal_suffix)) if (CPP_OPTION (pfile, warn_literal_suffix))
cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX, cpp_warning_with_line (pfile, CPP_W_LITERAL_SUFFIX,
token->src_loc, 0, token->src_loc, 0,
"invalid suffix on literal; C++11 requires " "invalid suffix on literal; C++11 requires "
"a space between literal and identifier"); "a space between literal and string macro");
} }
/* Grab user defined literal suffix. */ /* Grab user defined literal suffix. */
else if (ISIDST (*cur)) else if (ISIDST (*cur))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment