[EXPR_CLASSIFY_TYPE] = PREC_UNARY,
[EXPR_ALIGNOF] = PREC_UNARY,
- [EXPR_FUNCTION] = PREC_PRIM,
- [EXPR_PRETTY_FUNCTION] = PREC_PRIM,
+ [EXPR_FUNCNAME] = PREC_PRIM,
[EXPR_BUILTIN_SYMBOL] = PREC_PRIM,
[EXPR_BUILTIN_CONSTANT_P] = PREC_PRIM,
[EXPR_BUILTIN_PREFETCH] = PREC_PRIM,
[EXPR_UNARY_CAST] = PREC_UNARY,
[EXPR_UNARY_CAST_IMPLICIT] = PREC_UNARY,
[EXPR_UNARY_ASSUME] = PREC_PRIM,
- [EXPR_UNARY_BITFIELD_EXTRACT] = PREC_ACCESS,
[EXPR_BINARY_ADD] = PREC_PLUS,
[EXPR_BINARY_SUB] = PREC_PLUS,
print_quoted_string(&string_literal->value, '"');
}
+/**
+ * Prints a predefined symbol.
+ */
+static void print_funcname(
+ const funcname_expression_t *funcname)
+{
+ const char *s = "";
+ switch(funcname->kind) {
+ case FUNCNAME_FUNCTION: s = (c_mode & _C99) ? "__func__" : "__FUNCTION__"; break;
+ case FUNCNAME_PRETTY_FUNCTION: s = "__PRETTY_FUNCTION__"; break;
+ case FUNCNAME_FUNCSIG: s = "__FUNCSIG__"; break;
+ case FUNCNAME_FUNCDNAME: s = "__FUNCDNAME__"; break;
+ }
+ fputc('"', out);
+ fputs(s, out);
+ fputc('"', out);
+}
+
static void print_wide_string_literal(
const wide_string_literal_expression_t *const wstr)
{
case EXPR_UNARY_DEREFERENCE: fputs("*", out); break;
case EXPR_UNARY_TAKE_ADDRESS: fputs("&", out); break;
- case EXPR_UNARY_BITFIELD_EXTRACT:
- print_expression_prec(unexpr->value, prec);
- return;
-
case EXPR_UNARY_POSTFIX_INCREMENT:
print_expression_prec(unexpr->value, prec);
fputs("++", out);
{
unsigned prec = get_expression_precedence(expression->base.kind);
print_expression_prec(expression->compound, prec);
- if(is_type_pointer(expression->compound->base.type)) {
+ if(is_type_pointer(skip_typeref(expression->compound->base.type))) {
fputs("->", out);
} else {
fputc('.', out);
case EXPR_CONST:
print_const(&expression->conste);
break;
- case EXPR_FUNCTION:
- case EXPR_PRETTY_FUNCTION:
+ case EXPR_FUNCNAME:
+ print_funcname(&expression->funcname);
+ break;
case EXPR_STRING_LITERAL:
print_string_literal(&expression->string);
break;
}
/**
- * Print assembler constraints.
+ * Print assembler arguments.
*
- * @param constraints the constraints
+ * @param arguments the arguments
*/
-static void print_asm_constraints(asm_constraint_t *constraints)
+static void print_asm_arguments(asm_argument_t *arguments)
{
- asm_constraint_t *constraint = constraints;
- for( ; constraint != NULL; constraint = constraint->next) {
- if(constraint != constraints)
+ asm_argument_t *argument = arguments;
+ for( ; argument != NULL; argument = argument->next) {
+ if(argument != arguments)
fputs(", ", out);
- if(constraint->symbol) {
- fprintf(out, "[%s] ", constraint->symbol->string);
+ if(argument->symbol) {
+ fprintf(out, "[%s] ", argument->symbol->string);
}
- print_quoted_string(&constraint->constraints, '"');
+ print_quoted_string(&argument->constraints, '"');
fputs(" (", out);
- print_expression(constraint->expression);
+ print_expression(argument->expression);
fputs(")", out);
}
}
goto end_of_print_asm_statement;
fputs(" : ", out);
- print_asm_constraints(statement->inputs);
+ print_asm_arguments(statement->inputs);
if(statement->outputs == NULL && statement->clobbers == NULL)
goto end_of_print_asm_statement;
fputs(" : ", out);
- print_asm_constraints(statement->outputs);
+ print_asm_arguments(statement->outputs);
if(statement->clobbers == NULL)
goto end_of_print_asm_statement;
fputs(");\n", out);
}
+/**
+ * Print a microsoft __try statement.
+ *
+ * @param statement the statement
+ */
+static void print_ms_try_statement(const ms_try_statement_t *statement)
+{
+ fputs("__try ", out);
+ print_statement(statement->try_statement);
+ print_indent();
+ if(statement->except_expression != NULL) {
+ fputs("__except(", out);
+ print_expression(statement->except_expression);
+ fputs(") ", out);
+ } else {
+ fputs("__finally ", out);
+ }
+ print_statement(statement->final_statement);
+}
+
+/**
+ * Print a microsoft __leave statement.
+ *
+ * @param statement the statement
+ */
+static void print_leave_statement(const leave_statement_t *statement)
+{
+ (void) statement;
+ fputs("__leave;\n", out);
+}
+
/**
* Print a statement.
*
case STATEMENT_ASM:
print_asm_statement(&statement->asms);
break;
+ case STATEMENT_MS_TRY:
+ print_ms_try_statement(&statement->ms_try);
+ break;
+ case STATEMENT_LEAVE:
+ print_leave_statement(&statement->leave);
+ break;
case STATEMENT_INVALID:
fprintf(out, "$invalid statement$");
break;
panic("invalid initializer kind found");
}
-static bool is_object_with_constant_address(const expression_t *expression)
+static bool is_object_with_linker_constant_address(const expression_t *expression)
{
switch(expression->kind) {
case EXPR_UNARY_DEREFERENCE:
/* it's a -> */
return is_address_constant(expression->select.compound);
} else {
- return is_object_with_constant_address(expression->select.compound);
+ return is_object_with_linker_constant_address(expression->select.compound);
}
}
{
switch(expression->kind) {
case EXPR_UNARY_TAKE_ADDRESS:
- return is_object_with_constant_address(expression->unary.value);
+ return is_object_with_linker_constant_address(expression->unary.value);
case EXPR_UNARY_DEREFERENCE: {
- type_t *real_type = revert_automatic_type_conversion(expression->unary.value);
+ type_t *real_type
+ = revert_automatic_type_conversion(expression->unary.value);
/* dereferencing a function is a NOP */
if(is_type_function(real_type)) {
return is_address_constant(expression->unary.value);
}
+
+ /* fallthrough */
}
case EXPR_UNARY_CAST:
if(is_type_function(type))
return true;
if(is_type_array(type)) {
- return is_object_with_constant_address(expression);
+ return is_object_with_linker_constant_address(expression);
}
return false;
}
}
}
+static bool is_builtin_const_call(const expression_t *expression)
+{
+ expression_t *function = expression->call.function;
+ if (function->kind != EXPR_BUILTIN_SYMBOL) {
+ return false;
+ }
+
+ symbol_t *symbol = function->builtin_symbol.symbol;
+
+ switch (symbol->ID) {
+ case T___builtin_huge_val:
+ case T___builtin_nan:
+ case T___builtin_nanf:
+ case T___builtin_nand:
+ return true;
+ }
+
+ return false;
+}
+
+static bool is_constant_pointer(const expression_t *expression)
+{
+ if (is_constant_expression(expression))
+ return true;
+
+ switch (expression->kind) {
+ case EXPR_UNARY_CAST:
+ return is_constant_pointer(expression->unary.value);
+ default:
+ return false;
+ }
+}
+
+static bool is_object_with_constant_address(const expression_t *expression)
+{
+ switch(expression->kind) {
+ case EXPR_SELECT: {
+ expression_t *compound = expression->select.compound;
+ type_t *compound_type = compound->base.type;
+ compound_type = skip_typeref(compound_type);
+ if(is_type_pointer(compound_type)) {
+ return is_constant_pointer(compound);
+ } else {
+ return is_object_with_constant_address(compound);
+ }
+ }
+ case EXPR_ARRAY_ACCESS:
+ return is_constant_pointer(expression->array_access.array_ref)
+ && is_constant_expression(expression->array_access.index);
+ case EXPR_UNARY_DEREFERENCE:
+ return is_constant_pointer(expression->unary.value);
+ default:
+ return false;
+ }
+}
+
bool is_constant_expression(const expression_t *expression)
{
switch(expression->kind) {
case EXPR_WIDE_STRING_LITERAL:
case EXPR_SIZEOF:
case EXPR_CLASSIFY_TYPE:
- case EXPR_FUNCTION:
- case EXPR_PRETTY_FUNCTION:
+ case EXPR_FUNCNAME:
case EXPR_OFFSETOF:
case EXPR_ALIGNOF:
case EXPR_BUILTIN_CONSTANT_P:
case EXPR_BUILTIN_SYMBOL:
case EXPR_BUILTIN_PREFETCH:
- case EXPR_CALL:
case EXPR_SELECT:
case EXPR_VA_START:
case EXPR_VA_ARG:
case EXPR_UNARY_POSTFIX_DECREMENT:
case EXPR_UNARY_PREFIX_INCREMENT:
case EXPR_UNARY_PREFIX_DECREMENT:
- case EXPR_UNARY_BITFIELD_EXTRACT:
case EXPR_UNARY_ASSUME: /* has VOID type */
- case EXPR_UNARY_TAKE_ADDRESS:
case EXPR_UNARY_DEREFERENCE:
case EXPR_BINARY_ASSIGN:
case EXPR_BINARY_MUL_ASSIGN:
case EXPR_BINARY_COMMA:
return false;
+ case EXPR_UNARY_TAKE_ADDRESS:
+ return is_object_with_constant_address(expression->unary.value);
+
+ case EXPR_CALL:
+ return is_builtin_const_call(expression);
+
case EXPR_UNARY_NEGATE:
case EXPR_UNARY_PLUS:
case EXPR_UNARY_BITWISE_NEGATE: