*
* @param string the string constant
* @param border the border char
+ * @param skip number of chars to skip at the end
*/
-static void print_quoted_string(const string_t *const string, char border)
+static void print_quoted_string(const string_t *const string, char border, int skip)
{
fputc(border, out);
- const char *end = string->begin + string->size - 1;
+ const char *end = string->begin + string->size - skip;
for (const char *c = string->begin; c != end; ++c) {
if (*c == border) {
fputc('\\', out);
case '\t': fputs("\\t", out); break;
case '\v': fputs("\\v", out); break;
case '\?': fputs("\\?", out); break;
+ case 27:
+ if (c_mode & _GNUC) {
+ fputs("\\e", out); break;
+ }
+ /*fallthrough*/
default:
if(!isprint(*c)) {
fprintf(out, "\\%03o", *c);
/**
* Prints a wide string literal expression.
*
- * @param wstr the wide string literal expression
+ * @param wstr the wide string literal expression
+ * @param border the border char
+ * @param skip number of chars to skip at the end
*/
static void print_quoted_wide_string(const wide_string_t *const wstr,
- char border)
+ char border, int skip)
{
fputc('L', out);
fputc(border, out);
- for (const wchar_rep_t *c = wstr->begin, *end = wstr->begin + wstr->size-1;
- c != end; ++c) {
+ const wchar_rep_t *end = wstr->begin + wstr->size - skip;
+ for (const wchar_rep_t *c = wstr->begin; c != end; ++c) {
switch (*c) {
case L'\"': fputs("\\\"", out); break;
case L'\\': fputs("\\\\", out); break;
case L'\t': fputs("\\t", out); break;
case L'\v': fputs("\\v", out); break;
case L'\?': fputs("\\?", out); break;
+ case 27:
+ if (c_mode & _GNUC) {
+ fputs("\\e", out); break;
+ }
+ /*fallthrough*/
default: {
const unsigned tc = *c;
if (tc < 0x80U) {
*/
static void print_character_constant(const const_expression_t *cnst)
{
- print_quoted_string(&cnst->v.character, '\'');
+ print_quoted_string(&cnst->v.character, '\'', 0);
}
static void print_wide_character_constant(const const_expression_t *cnst)
{
- print_quoted_wide_string(&cnst->v.wide_character, '\'');
+ print_quoted_wide_string(&cnst->v.wide_character, '\'', 0);
}
/**
static void print_string_literal(
const string_literal_expression_t *string_literal)
{
- print_quoted_string(&string_literal->value, '"');
+ print_quoted_string(&string_literal->value, '"', 1);
}
/**
static void print_wide_string_literal(
const wide_string_literal_expression_t *const wstr)
{
- print_quoted_wide_string(&wstr->value, '"');
+ print_quoted_wide_string(&wstr->value, '"', 1);
}
static void print_compound_literal(
fputs("--", out);
return;
case EXPR_UNARY_CAST_IMPLICIT:
- if(!print_implicit_casts) {
- print_expression_prec(unexpr->value, prec);
- return;
- }
- /* fallthrough */
case EXPR_UNARY_CAST:
fputc('(', out);
print_type(unexpr->base.type);
if(!expression->flipped) {
print_expression_prec(expression->array_ref, prec);
fputc('[', out);
- print_expression_prec(expression->index, prec);
+ print_expression_prec(expression->index, PREC_BOTTOM);
fputc(']', out);
} else {
print_expression_prec(expression->index, prec);
fputc('[', out);
- print_expression_prec(expression->array_ref, prec);
+ print_expression_prec(expression->array_ref, PREC_BOTTOM);
fputc(']', out);
}
}
fputs("(", out);
print_expression_prec(expression->condition, prec);
fputs(" ? ", out);
- print_expression_prec(expression->true_expression, prec);
- fputs(" : ", out);
+ if (expression->true_expression != NULL) {
+ print_expression_prec(expression->true_expression, prec);
+ fputs(" : ", out);
+ } else {
+ fputs(": ", out);
+ }
print_expression_prec(expression->false_expression, 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);
for ( ; designator != NULL; designator = designator->next) {
if (designator->symbol == NULL) {
fputc('[', out);
- print_expression_prec(designator->array_index, PREC_ACCESS);
+ print_expression_prec(designator->array_index, PREC_BOTTOM);
fputc(']', out);
} else {
fputc('.', out);
*/
static void print_expression_prec(const expression_t *expression, unsigned top_prec)
{
+ if (expression->kind == EXPR_UNARY_CAST_IMPLICIT && !print_implicit_casts) {
+ expression = expression->unary.value;
+ }
unsigned prec = get_expression_precedence(expression->base.kind);
if (print_parenthesis && top_prec != PREC_BOTTOM)
top_prec = PREC_TOP;
}
/**
- * 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, '"', 1);
fputs(" (", out);
- print_expression(constraint->expression);
+ print_expression(argument->expression);
fputs(")", out);
}
}
if(clobber != clobbers)
fputs(", ", out);
- print_quoted_string(&clobber->clobber, '"');
+ print_quoted_string(&clobber->clobber, '"', 1);
}
}
fputs("volatile ", out);
}
fputs("(", out);
- print_quoted_string(&statement->asm_text, '"');
+ print_quoted_string(&statement->asm_text, '"', 1);
if(statement->inputs == NULL && statement->outputs == NULL
&& statement->clobbers == NULL)
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;
return;
}
case INITIALIZER_STRING:
- print_quoted_string(&initializer->string.string, '"');
+ print_quoted_string(&initializer->string.string, '"', 1);
return;
case INITIALIZER_WIDE_STRING:
- print_quoted_wide_string(&initializer->wide_string.string, '"');
+ print_quoted_wide_string(&initializer->wide_string.string, '"', 1);
return;
case INITIALIZER_DESIGNATOR:
print_designator(initializer->designator.designator);
if((c_mode & _MS) == 0)
return;
- decl_modifiers_t modifiers = declaration->decl_modifiers;
+ decl_modifiers_t modifiers = declaration->modifiers;
/* DM_FORCEINLINE handled outside. */
- if((modifiers & ~DM_FORCEINLINE) != 0 ||
- declaration->alignment != 0 || declaration->deprecated != 0 ||
- declaration->get_property_sym != NULL || declaration->put_property_sym != NULL) {
+ if ((modifiers & ~DM_FORCEINLINE) != 0 ||
+ declaration->alignment != 0 ||
+ declaration->get_property_sym != NULL ||
+ declaration->put_property_sym != NULL) {
char *next = "(";
fputs("__declspec", out);
if(modifiers & DM_NOINLINE) {
fputs(next, out); next = ", "; fputs("noinline", out);
}
- if(declaration->deprecated != 0) {
+ if (modifiers & DM_DEPRECATED) {
fputs(next, out); next = ", "; fputs("deprecated", out);
if(declaration->deprecated_string != NULL)
fprintf(out, "(\"%s\")", declaration->deprecated_string);
static void print_normal_declaration(const declaration_t *declaration)
{
print_storage_class((storage_class_tag_t) declaration->declared_storage_class);
- if(declaration->is_inline) {
- if(declaration->decl_modifiers & DM_FORCEINLINE)
+ if (declaration->is_inline) {
+ if (declaration->modifiers & DM_FORCEINLINE) {
fputs("__forceinline ", out);
- else {
- if(declaration->decl_modifiers & DM_MICROSOFT_INLINE)
- fputs("__inline ", out);
- else
- fputs("inline ", out);
+ } else if (declaration->modifiers & DM_MICROSOFT_INLINE) {
+ fputs("__inline ", out);
+ } else {
+ fputs("inline ", out);
}
}
print_ms_modifiers(declaration);
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:
return is_address_constant(expression->unary.value);
case EXPR_SELECT: {
- if(is_type_pointer(expression->select.compound->base.type)) {
+ type_t *base_type = skip_typeref(expression->select.compound->base.type);
+ if(is_type_pointer(base_type)) {
/* 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:
- return is_type_pointer(skip_typeref(expression->base.type))
- && (is_constant_expression(expression->unary.value)
+ case EXPR_UNARY_CAST: {
+ type_t *dest = skip_typeref(expression->base.type);
+ if (!is_type_pointer(dest) &&
+ ! (dest->kind == TYPE_ATOMIC
+ && (get_atomic_type_flags(dest->atomic.akind) & ATOMIC_TYPE_FLAG_INTEGER)
+ && (get_atomic_type_size(dest->atomic.akind) >= get_atomic_type_size(get_intptr_kind()))))
+ return false;
+
+ return (is_constant_expression(expression->unary.value)
|| is_address_constant(expression->unary.value));
+ }
case EXPR_BINARY_ADD:
case EXPR_BINARY_SUB: {
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_SELECT:
+ return is_constant_pointer(expression->select.compound);
+ 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_CHARACTER_CONSTANT:
case EXPR_STRING_LITERAL:
case EXPR_WIDE_STRING_LITERAL:
- case EXPR_SIZEOF:
case EXPR_CLASSIFY_TYPE:
case EXPR_FUNCNAME:
case EXPR_OFFSETOF:
case EXPR_BUILTIN_CONSTANT_P:
return true;
+ case EXPR_SIZEOF: {
+ type_t *type = expression->typeprop.type;
+ if (type == NULL)
+ type = expression->typeprop.tp_expression->base.type;
+
+ type = skip_typeref(type);
+ if (is_type_array(type) && type->array.is_vla)
+ return false;
+ return true;
+ }
+
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_PREFIX_INCREMENT:
case EXPR_UNARY_PREFIX_DECREMENT:
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: