C ++ style cast priority

I. Why is aware of this issue

Before using the C-style cast time, a more annoying place is due priority switching operation, resulting in the type of conversion out of a need to use additional brackets hold up, look very bloated. Later, I noticed seemingly higher priority in C ++ style cast operators, although the input has increased, but when the input is relatively smooth, and therefore looks more processes.
@ Harry tsecer: CAT -n cpp.style.cast.cpp
. 1 struct S
2 {
. 3 int X;
. 4};
. 5
. 6 int foo (void * VP)
. 7 {
. 8 return static_cast <const * S> (VP) -> X
. 9 + (S *) (VP) -> X;
10}
tsecer Harry @: G ++ -C cpp.style.cast.cpp
cpp.style.cast.cpp: the function 'int foo (void *)' in which:
cpp.style.cast.cpp: 9: 14: error: 'void *' is not a pointing object type
+ (S *) (VP) -> X;
^
tsecer @ Harry:

Two, cast priority

In the C language, clearly defines the priority of the cast ,

priority Operators description Associativity
1 :: Scope resolution From left to right
2 a++   a-- Suffix increment and decrement
type()   type{} Functional style transformation
a() Function call
a[] Subscript
.   -> Member Access
3 ++a   --a Prefix increment and decrement From right to left
+a   -a One yuan addition and subtraction
!   ~ Logic NOT and bitwise NOT
(type) C-style transformation
*a Indirect (dereference)
&a Take site
sizeof Take size [Note 1]
co_await await expression  (C ++ 20)
new   new[] Dynamic memory allocation
delete   delete[] Dynamic memory allocation

 

Its priority and "prefix increment" (+) same, below the "Member access" (->) priority. But for C ++ style cast, that "notes" is the
table does not include const_cast, static_cast, dynamic_cast, reinterpret_cast, typeid, sizeof ..., noexcept and alignof, because they never have ambiguous.
But did not specify their priority. A post on Stack Overflow of the issues discussed .

Three, gcc processed in the syntax

You can see from the implementation of the function for C ++ style cast, as long as identify const_cast, static_cast, dynamic_cast, reinterpret_cast, keyword, behind the procedure is Yimapingchuan, then must be followed by a left angle bracket / less than sign (RT_LESS), type (typeid), the right angle bracket / greater than the number (RT_GREATER), a left parenthesis (RT_OPEN_PAREN), the expression (expression), there are brackets (RT_CLOSE_PAREN). The key is, after the completion of these analytic, direct calls build_dynamic_cast / build_static_cast / build_reinterpret_cast / build_const_cast to generate an expression, in this sense, C ++ style cast is more like an atomic operation, their entire grammatical structure constitutes a fundamental unit .
4.9.0-GCC \ GCC \ CP \ parser.c
/ * the Parse-A expression The postfix.

postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( expression-list [opt] )
simple-type-specifier ( expression-list [opt] )
typename :: [opt] nested-name-specifier identifier
( expression-list [opt] )
typename :: [opt] nested-name-specifier template [opt] template-id
( expression-list [opt] )
postfix-expression . template [opt] id-expression
postfix-expression -> template [opt] id-expression
postfix-expression . pseudo-destructor-name
postfix-expression -> pseudo-destructor-name
postfix-expression ++
postfix-expression --
dynamic_cast < type-id > ( expression )
static_cast < type-id > ( expression )
reinterpret_cast < type-id > ( expression )
const_cast < type-id > ( expression )
typeid ( expression )
typeid ( type-id )

GNU Extension:

postfix-expression:
( type-id ) { initializer-list , [opt] }

This extension is a GNU version of the C99 compound-literal
construct. (The C99 grammar uses `type-name' instead of `type-id',
but they are essentially the same concept.)

If ADDRESS_P is true, the postfix expression is the operand of the
`&' operator. CAST_P is true if this expression is the target of a
cast.

If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are
class member access expressions [expr.ref].

Returns a representation of the expression. */

static tree
cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
bool member_access_only_p, bool decltype_p,
cp_id_kind * pidk_return)
{
cp_token *token;
location_t loc;
enum rid keyword;
cp_id_kind idk = CP_ID_KIND_NONE;
tree postfix_expression = NULL_TREE;
bool is_member_access = false;
int saved_in_statement = -1;

/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
loc = token->location;
/* Some of the productions are determined by keywords. */
keyword = token->keyword;
switch (keyword)
{
case RID_DYNCAST:
case RID_STATCAST:
case RID_REINTCAST:
case RID_CONSTCAST:
{
tree type;
tree expression;
const char *saved_message;
bool saved_in_type_id_in_expr_p;

/* All of these can be handled in the same way from the point
of view of parsing. Begin by consuming the token
identifying the cast. */
cp_lexer_consume_token (parser->lexer);

/* New types cannot be defined in the cast. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
= G_("types may not be defined in casts");

/* Look for the opening `<'. */
cp_parser_require (parser, CPP_LESS, RT_LESS);
/* Parse the type to which we are casting. */
saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
parser->in_type_id_in_expr_p = true;
type = cp_parser_type_id (parser);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
/* Look for the closing `>'. */
cp_parser_require (parser, CPP_GREATER, RT_GREATER);
/* Restore the old message. */
parser->type_definition_forbidden_message = saved_message;

bool saved_greater_than_is_operator_p
= parser->greater_than_is_operator_p;
parser->greater_than_is_operator_p = true;

/* And the expression which is being cast. */
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
expression = cp_parser_expression (parser, /*cast_p=*/true, & idk);
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);

parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;

/* Only type conversions to integral or enumeration types
can be used in constant-expressions. */
if (!cast_valid_in_integral_constant_expression_p (type)
&& cp_parser_non_integral_constant_expression (parser, NIC_CAST))
return error_mark_node;

switch (keyword)
{
case RID_DYNCAST:
postfix_expression
= build_dynamic_cast (type, expression, tf_warning_or_error);
break;
case RID_STATCAST:
postfix_expression
= build_static_cast (type, expression, tf_warning_or_error);
break;
case RID_REINTCAST:
postfix_expression
= build_reinterpret_cast (type, expression,
tf_warning_or_error);
break;
case RID_CONSTCAST:
postfix_expression
= build_const_cast (type, expression, tf_warning_or_error);
break;
default:
gcc_unreachable ();
}
}
break;
……
}

Guess you like

Origin www.cnblogs.com/tsecer/p/12532736.html