determine_lhs_ent(expr->va_starte.ap, lhs_ent);
return;
- EXPR_LITERAL_CASES
+ case EXPR_LITERAL_CASES:
case EXPR_ERROR:
case EXPR_STRING_LITERAL:
case EXPR_WIDE_STRING_LITERAL:
return result;
}
-/**
- * Checks if a given expression can be used as a constant initializer.
- */
-static bool is_initializer_constant(const expression_t *expression)
-{
- return is_constant_expression(expression) != EXPR_CLASS_VARIABLE ||
- is_linker_constant(expression) != EXPR_CLASS_VARIABLE;
-}
-
/**
* Parses an scalar initializer.
*
expression_t *expression = parse_assignment_expression();
mark_vars_read(expression, NULL);
- if (must_be_constant && !is_initializer_constant(expression)) {
+ if (must_be_constant && !is_linker_constant(expression)) {
errorf(&expression->base.source_position,
"initialisation expression '%E' is not constant",
expression);
expression_t *expression = parse_assignment_expression();
mark_vars_read(expression, NULL);
- if (env->must_be_constant && !is_initializer_constant(expression)) {
+ if (env->must_be_constant && !is_linker_constant(expression)) {
errorf(&expression->base.source_position,
"Initialisation expression '%E' is not constant",
expression);
switch (expr->kind) {
case EXPR_CALL: {
expression_t const *const func = expr->call.function;
- if (func->kind == EXPR_REFERENCE) {
- entity_t *entity = func->reference.entity;
- if (entity->kind == ENTITY_FUNCTION
- && entity->declaration.modifiers & DM_NORETURN)
+ type_t const *const type = skip_typeref(func->base.type);
+ if (type->kind == TYPE_POINTER) {
+ type_t const *const points_to
+ = skip_typeref(type->pointer.points_to);
+ if (points_to->kind == TYPE_FUNCTION
+ && points_to->function.modifiers & DM_NORETURN)
return false;
}
case EXPR_REFERENCE:
case EXPR_REFERENCE_ENUM_VALUE:
- EXPR_LITERAL_CASES
+ case EXPR_LITERAL_CASES:
case EXPR_STRING_LITERAL:
case EXPR_WIDE_STRING_LITERAL:
case EXPR_COMPOUND_LITERAL: // TODO descend into initialisers
case EXPR_VA_COPY:
return expression_returns(expr->va_copye.src);
- EXPR_UNARY_CASES_MANDATORY
+ case EXPR_UNARY_CASES_MANDATORY:
return expression_returns(expr->unary.value);
case EXPR_UNARY_THROW:
return false;
- EXPR_BINARY_CASES
+ case EXPR_BINARY_CASES:
// TODO handle constant lhs of && and ||
return
expression_returns(expr->binary.left) &&
}
}
+static bool is_main(entity_t *entity)
+{
+ static symbol_t *sym_main = NULL;
+ if (sym_main == NULL) {
+ sym_main = symbol_table_insert("main");
+ }
+
+ if (entity->base.symbol != sym_main)
+ return false;
+ /* must be in outermost scope */
+ if (entity->base.parent_scope != file_scope)
+ return false;
+
+ return true;
+}
+
static void parse_external_declaration(void)
{
/* function-definitions and declarations both start with declaration
}
}
+ if (is_main(entity) && enable_main_collect2_hack)
+ prepare_main_collect2(entity);
+
POP_PARENT();
assert(current_function == function);
assert(current_entity == entity);
token.kind != ';' ||
look_ahead(1)->kind != '}') {
errorf(pos, "'%N' has incomplete type '%T'", entity, orig_type);
+ } else if (compound->members.entities == NULL) {
+ errorf(pos, "flexible array member in otherwise empty struct");
}
}
}
eat(T_case);
- expression_t *const expression = parse_expression();
+ expression_t *expression = parse_expression();
+ type_t *expression_type = expression->base.type;
+ type_t *skipped = skip_typeref(expression_type);
+ if (!is_type_integer(skipped) && is_type_valid(skipped)) {
+ errorf(pos, "case expression '%E' must have integer type but has type '%T'",
+ expression, expression_type);
+ }
+
+ type_t *type = expression_type;
+ if (current_switch != NULL) {
+ type_t *switch_type = current_switch->expression->base.type;
+ if (is_type_valid(switch_type)) {
+ expression = create_implicit_cast(expression, switch_type);
+ }
+ }
+
statement->case_label.expression = expression;
expression_classification_t const expr_class = is_constant_expression(expression);
if (expr_class != EXPR_CLASS_CONSTANT) {
if (GNU_MODE) {
if (next_if(T_DOTDOTDOT)) {
- expression_t *const end_range = parse_expression();
+ expression_t *end_range = parse_expression();
+ expression_type = expression->base.type;
+ skipped = skip_typeref(expression_type);
+ if (!is_type_integer(skipped) && is_type_valid(skipped)) {
+ errorf(pos, "case expression '%E' must have integer type but has type '%T'",
+ expression, expression_type);
+ }
+
+ end_range = create_implicit_cast(end_range, type);
statement->case_label.end_range = end_range;
expression_classification_t const end_class = is_constant_expression(end_range);
if (end_class != EXPR_CLASS_CONSTANT) {
void prepare_main_collect2(entity_t *entity)
{
+ PUSH_SCOPE(&entity->function.statement->compound.scope);
+
// create call to __main
symbol_t *symbol = symbol_table_insert("__main");
entity_t *subsubmain_ent
expr_statement->base.next = compounds->statements;
compounds->statements = expr_statement;
+
+ POP_SCOPE();
}
void parse(void)