#include <stdbool.h>
#include "adt/strutil.h"
+#include "adt/util.h"
#include "parser.h"
#include "diagnostic.h"
#include "format_check.h"
#include "preprocessor.h"
#include "symbol_t.h"
+#include "symbol_table.h"
#include "token_t.h"
#include "types.h"
#include "type_t.h"
#include "type_hash.h"
#include "ast_t.h"
-#include "entity_t.h"
#include "attribute_t.h"
#include "lang_features.h"
#include "walk.h"
#include "warning.h"
#include "printer.h"
#include "ast2firm.h"
-#include "adt/bitfiddle.h"
#include "adt/error.h"
#include "adt/array.h"
struct declaration_specifiers_t {
position_t pos;
storage_class_t storage_class;
- unsigned char alignment; /**< Alignment, 0 if not set. */
bool is_inline : 1;
bool thread_local : 1;
attribute_t *attributes; /**< list of attributes */
/* skip void* cast */
if (expression->kind == EXPR_UNARY_CAST) {
type_t *const type = skip_typeref(expression->base.type);
- if (types_compatible(type, type_void_ptr))
+ if (type == type_void_ptr)
expression = expression->unary.value;
}
- type_t *const type = skip_typeref(expression->base.type);
- if (!is_type_integer(type))
- return false;
switch (is_constant_expression(expression)) {
- case EXPR_CLASS_ERROR: return true;
- case EXPR_CLASS_CONSTANT: return !fold_constant_to_bool(expression);
- default: return false;
+ case EXPR_CLASS_VARIABLE: return false;
+ case EXPR_CLASS_ERROR: return true;
+ case EXPR_CLASS_CONSTANT: return false;
+ case EXPR_CLASS_INTEGER_CONSTANT: return !fold_constant_to_bool(expression);
}
+ panic("invalid expression classification");
}
/**
}
} else {
expression_t *array_index = designator->array_index;
- if (is_constant_expression(array_index) != EXPR_CLASS_CONSTANT)
+ if (is_constant_expression(array_index) < EXPR_CLASS_CONSTANT)
return true;
if (!is_type_array(type)) {
type_t *first_type = first->type;
first_type = skip_typeref(first_type);
if (is_type_array(first_type)) {
- size_t index = first->v.index;
- if (index > path->max_index)
- path->max_index = index;
+ path->max_index = MAX(path->max_index, first->v.index);
}
/* append to initializers list */
if (size_expression != NULL) {
switch (is_constant_expression(size_expression)) {
- case EXPR_CLASS_CONSTANT: {
+ case EXPR_CLASS_INTEGER_CONSTANT: {
long const size = fold_constant_to_int(size_expression);
array_type->array.size = size;
array_type->array.size_constant = true;
break;
}
+ case EXPR_CLASS_CONSTANT:
case EXPR_CLASS_VARIABLE:
array_type->array.is_vla = true;
break;
errorf(pos, "redefinition of '%N' (declared %P)", entity, &entity->base.pos);
}
-static bool is_declaration_specifier(const token_t *token)
+static bool is_declaration_specifier(token_t const *const tk)
{
- switch (token->kind) {
+ switch (tk->kind) {
DECLARATION_START
return true;
case T_IDENTIFIER:
- return is_typedef_symbol(token->base.symbol);
+ return is_typedef_symbol(tk->base.symbol);
default:
return false;
static int determine_truth(expression_t const* const cond)
{
return
- is_constant_expression(cond) != EXPR_CLASS_CONSTANT ? 0 :
- fold_constant_to_bool(cond) ? 1 :
+ is_constant_expression(cond) < EXPR_CLASS_CONSTANT ? 0 :
+ fold_constant_to_bool(cond) ? 1 :
-1;
}
if (!expression_returns(expr))
return;
- if (is_constant_expression(expr) == EXPR_CLASS_CONSTANT) {
+ if (is_constant_expression(expr) >= EXPR_CLASS_CONSTANT) {
ir_tarval *const val = fold_constant_to_tarval(expr);
case_label_statement_t * defaults = NULL;
for (case_label_statement_t *i = switchs->first_case; i != NULL; i = i->next) {
return;
}
- assert(is_declaration(ndeclaration));
- type_t *const orig_type = ndeclaration->declaration.type;
- type_t * type = skip_typeref(orig_type);
+ {
+ assert(is_declaration(ndeclaration));
+ type_t *const orig_type = ndeclaration->declaration.type;
+ type_t *const type = skip_typeref(orig_type);
- if (!is_type_function(type)) {
- if (is_type_valid(type)) {
- errorf(HERE, "declarator '%#N' has a body but is not a function type", ndeclaration);
+ if (!is_type_function(type)) {
+ if (is_type_valid(type)) {
+ errorf(HERE, "declarator '%#N' has a body but is not a function type", ndeclaration);
+ }
+ eat_block();
+ return;
}
- eat_block();
- return;
- }
- position_t const *const pos = &ndeclaration->base.pos;
- if (is_typeref(orig_type)) {
- /* §6.9.1:2 */
- errorf(pos, "type of function definition '%#N' is a typedef", ndeclaration);
- }
-
- if (is_type_compound(skip_typeref(type->function.return_type))) {
- warningf(WARN_AGGREGATE_RETURN, pos, "'%N' returns an aggregate", ndeclaration);
- }
- if (type->function.unspecified_parameters) {
- warningf(WARN_OLD_STYLE_DEFINITION, pos, "old-style definition of '%N'", ndeclaration);
- } else {
- warningf(WARN_TRADITIONAL, pos, "traditional C rejects ISO C style definition of '%N'", ndeclaration);
- }
+ position_t const *const pos = &ndeclaration->base.pos;
+ if (is_typeref(orig_type)) {
+ /* §6.9.1:2 */
+ errorf(pos, "type of function definition '%#N' is a typedef", ndeclaration);
+ }
- /* §6.7.5.3:14 a function definition with () means no
- * parameters (and not unspecified parameters) */
- if (type->function.unspecified_parameters &&
- type->function.parameters == NULL) {
- type_t *copy = duplicate_type(type);
- copy->function.unspecified_parameters = false;
- type = identify_new_type(copy);
+ if (is_type_compound(skip_typeref(type->function.return_type))) {
+ warningf(WARN_AGGREGATE_RETURN, pos, "'%N' returns an aggregate", ndeclaration);
+ }
+ if (type->function.unspecified_parameters) {
+ warningf(WARN_OLD_STYLE_DEFINITION, pos, "old-style definition of '%N'", ndeclaration);
+ } else {
+ warningf(WARN_TRADITIONAL, pos, "traditional C rejects ISO C style definition of '%N'", ndeclaration);
+ }
- ndeclaration->declaration.type = type;
+ /* §6.7.5.3:14 a function definition with () means no
+ * parameters (and not unspecified parameters) */
+ if (type->function.unspecified_parameters &&
+ type->function.parameters == NULL) {
+ type_t *copy = duplicate_type(type);
+ copy->function.unspecified_parameters = false;
+ ndeclaration->declaration.type = identify_new_type(copy);
+ }
}
entity_t *const entity = record_entity(ndeclaration, true);
walk_statements(body, check_unreachable, NULL);
if (noreturn_candidate &&
!(function->base.modifiers & DM_NORETURN)) {
- position_t const *const pos = &body->base.pos;
- warningf(WARN_MISSING_NORETURN, pos, "function '%#N' is candidate for attribute 'noreturn'", entity);
+ warningf(WARN_MISSING_NORETURN, &body->base.pos, "function '%#N' is candidate for attribute 'noreturn'", entity);
}
}
check_deprecated(pos, entry);
expression_t *select = allocate_expression_zero(EXPR_SELECT);
+ select->base.pos = *pos;
select->select.compound = addr;
select->select.compound_entry = entry;
continue;
expression_t *sub_addr = create_select(pos, addr, qualifiers, iter);
- sub_addr->base.pos = *pos;
sub_addr->base.implicit = true;
return find_create_select(pos, sub_addr, qualifiers, sub_compound,
symbol);
type);
}
- if (is_constant_expression(size) != EXPR_CLASS_CONSTANT) {
+ if (is_constant_expression(size) < EXPR_CLASS_CONSTANT) {
/* error already reported by parse_constant_expression */
size_long = get_type_size(type) * 8;
} else {
add_anchor_token(';');
add_anchor_token(',');
do {
- entity_t *entity;
-
- if (token.kind == ':') {
- /* anonymous bitfield */
- type_t *type = specifiers->type;
- entity_t *const entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, NULL, HERE);
- entity->declaration.declared_storage_class = STORAGE_CLASS_NONE;
- entity->declaration.storage_class = STORAGE_CLASS_NONE;
- entity->declaration.type = type;
+ entity_t *const entity = parse_declarator(specifiers, DECL_MAY_BE_ABSTRACT | DECL_CREATE_COMPOUND_MEMBER);
+ position_t const *const pos = &entity->base.pos;
+ if (entity->kind == ENTITY_TYPEDEF) {
+ errorf(pos, "typedef not allowed as compound member");
+ continue;
+ }
- parse_bitfield_member(entity);
+ assert(entity->kind == ENTITY_COMPOUND_MEMBER);
- attribute_t *attributes = parse_attributes(NULL);
- attribute_t **anchor = &attributes;
- while (*anchor != NULL)
- anchor = &(*anchor)->next;
- *anchor = specifiers->attributes;
- if (attributes != NULL) {
- handle_entity_attributes(attributes, entity);
+ /* make sure we don't define a symbol multiple times */
+ symbol_t *symbol = entity->base.symbol;
+ if (symbol != NULL) {
+ entity_t *prev = find_compound_entry(compound, symbol);
+ if (prev != NULL) {
+ position_t const *const ppos = &prev->base.pos;
+ errorf(pos, "multiple declarations of '%N' (declared %P)", entity, ppos);
}
- entity->declaration.attributes = attributes;
-
- append_entity(&compound->members, entity);
- } else {
- entity = parse_declarator(specifiers,
- DECL_MAY_BE_ABSTRACT | DECL_CREATE_COMPOUND_MEMBER);
- position_t const *const pos = &entity->base.pos;
- if (entity->kind == ENTITY_TYPEDEF) {
- errorf(pos, "typedef not allowed as compound member");
- } else {
- assert(entity->kind == ENTITY_COMPOUND_MEMBER);
-
- /* make sure we don't define a symbol multiple times */
- symbol_t *symbol = entity->base.symbol;
- if (symbol != NULL) {
- entity_t *prev = find_compound_entry(compound, symbol);
- if (prev != NULL) {
- position_t const *const ppos = &prev->base.pos;
- errorf(pos, "multiple declarations of '%N' (declared %P)", entity, ppos);
- }
- }
+ }
- if (token.kind == ':') {
- parse_bitfield_member(entity);
+ if (token.kind == ':') {
+ parse_bitfield_member(entity);
- attribute_t *attributes = parse_attributes(NULL);
- handle_entity_attributes(attributes, entity);
- } else {
- type_t *orig_type = entity->declaration.type;
- type_t *type = skip_typeref(orig_type);
- if (is_type_function(type)) {
- errorf(pos, "'%N' must not have function type '%T'", entity, orig_type);
- } else if (is_type_incomplete(type)) {
- /* §6.7.2.1:16 flexible array member */
- if (!is_type_array(type) ||
- 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");
- }
- }
+ attribute_t *attributes = parse_attributes(NULL);
+ handle_entity_attributes(attributes, entity);
+ } else {
+ type_t *orig_type = entity->declaration.type;
+ type_t *type = skip_typeref(orig_type);
+ if (is_type_function(type)) {
+ errorf(pos, "'%N' must not have function type '%T'", entity, orig_type);
+ } else if (is_type_incomplete(type)) {
+ /* §6.7.2.1:16 flexible array member */
+ if (!is_type_array(type) ||
+ 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");
}
-
- append_entity(&compound->members, entity);
}
}
+
+ append_entity(&compound->members, entity);
} while (accept(','));
rem_anchor_token(',');
rem_anchor_token(';');
return literal;
}
-static void warn_traditional_suffix(char const *const suffix)
-{
- warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%s' suffix", suffix);
-}
-
-static void check_integer_suffix(expression_t *const expr, char const *const suffix)
+static void check_number_suffix(expression_t *const expr, char const *const suffix, bool const is_float)
{
- unsigned spec = SPECIFIER_NONE;
- char const *c = suffix;
- while (*c != '\0') {
+ unsigned spec = SPECIFIER_NONE;
+ for (char const *c = suffix; *c != '\0'; ++c) {
specifiers_t add;
switch (*c) {
- case 'L':
- case 'l':
+ case 'F': case 'f':
+ add = SPECIFIER_FLOAT;
+ break;
+
+ case 'L': case 'l':
add = SPECIFIER_LONG;
- if (*c == c[1]) {
+ if (*c == c[1] && !is_float) {
add |= SPECIFIER_LONG_LONG;
++c;
}
break;
- case 'u':
- case 'U':
+
+ case 'U': case 'u':
add = SPECIFIER_UNSIGNED;
break;
- case 'i':
- case 'I':
- case 'j':
- case 'J':
- if (!GNU_MODE)
- goto error;
+
+ case 'I': case 'i':
+ case 'J': case 'j':
add = SPECIFIER_COMPLEX;
break;
default:
goto error;
}
- ++c;
if (spec & add)
goto error;
spec |= add;
}
- if (*c == '\0') {
- type_t *type;
- switch (spec & ~SPECIFIER_COMPLEX) {
- case SPECIFIER_NONE: type = type_int; break;
- case SPECIFIER_LONG: type = type_long; break;
- case SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_long_long; break;
- case SPECIFIER_UNSIGNED: type = type_unsigned_int; break;
- case SPECIFIER_UNSIGNED | SPECIFIER_LONG: type = type_unsigned_long; break;
- case SPECIFIER_UNSIGNED | SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_unsigned_long_long; break;
- default: panic("inconsistent suffix");
- }
- if (spec != SPECIFIER_NONE && spec != SPECIFIER_LONG) {
- warn_traditional_suffix(suffix);
- }
- if (spec & SPECIFIER_COMPLEX) {
- assert(type->kind == TYPE_ATOMIC);
- type = make_complex_type(type->atomic.akind, TYPE_QUALIFIER_NONE);
- }
- expr->base.type = type;
- /* Integer type depends on the size of the number and the size
- * representable by the types. The backend/codegeneration has to
- * determine that. */
- determine_literal_type(&expr->literal);
- } else {
+ if (!(spec & SPECIFIER_FLOAT) && is_float)
+ spec |= SPECIFIER_DOUBLE;
+
+ if (!(spec & (SPECIFIER_FLOAT | SPECIFIER_DOUBLE)) == is_float)
+ goto error;
+
+ type_t *type;
+ switch (spec & ~SPECIFIER_COMPLEX) {
+ case SPECIFIER_NONE: type = type_int; break;
+ case SPECIFIER_LONG: type = type_long; break;
+ case SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_long_long; break;
+ case SPECIFIER_UNSIGNED: type = type_unsigned_int; break;
+ case SPECIFIER_UNSIGNED | SPECIFIER_LONG: type = type_unsigned_long; break;
+ case SPECIFIER_UNSIGNED | SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_unsigned_long_long; break;
+ case SPECIFIER_FLOAT: type = type_float; break;
+ case SPECIFIER_DOUBLE: type = type_double; break;
+ case SPECIFIER_DOUBLE | SPECIFIER_LONG: type = type_long_double; break;
+
+ default:
error:
- errorf(HERE, "invalid suffix '%s' on integer constant", suffix);
- }
-}
-
-static void check_floatingpoint_suffix(expression_t *const expr, char const *const suffix)
-{
- type_t *type;
- char const *c = suffix;
- bool is_complex = false;
-next:
- switch (*c) {
- case 'F':
- case 'f': type = type_float; ++c; break;
- case 'L':
- case 'l': type = type_long_double; ++c; break;
- case 'i':
- case 'I':
- case 'j':
- case 'J':
- if (!GNU_MODE)
- break;
- is_complex = true;
- ++c;
- goto next;
- default: type = type_double; break;
+ errorf(HERE, "invalid suffix '%s' on %s constant", suffix, is_float ? "floatingpoint" : "integer");
+ return;
}
- if (*c == '\0') {
- if (is_complex) {
- assert(type->kind == TYPE_ATOMIC);
- type = make_complex_type(type->atomic.akind, TYPE_QUALIFIER_NONE);
- }
+ if (spec != SPECIFIER_NONE && spec != SPECIFIER_LONG && spec != SPECIFIER_DOUBLE)
+ warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%s' suffix", suffix);
- expr->base.type = type;
- if (suffix[0] != '\0') {
- warn_traditional_suffix(suffix);
- }
- } else {
- errorf(HERE, "invalid suffix '%s' on floatingpoint constant", suffix);
+ if (spec & SPECIFIER_COMPLEX)
+ type = make_complex_type(get_arithmetic_akind(type), TYPE_QUALIFIER_NONE);
+
+ expr->base.type = type;
+ if (!is_float) {
+ /* Integer type depends on the size of the number and the size
+ * representable by the types. The backend/codegeneration has to
+ * determine that. */
+ determine_literal_type(&expr->literal);
}
}
errorf(HERE, "invalid digit in %K", &token);
} else {
expr->literal.suffix = i;
- if (is_float) {
- check_floatingpoint_suffix(expr, i);
- } else {
- check_integer_suffix(expr, i);
- }
+ check_number_suffix(expr, i, is_float);
}
}
expression_t const *const right = expression->right;
/* The type of the right operand can be different for /= */
if (is_type_integer(skip_typeref(right->base.type)) &&
- is_constant_expression(right) == EXPR_CLASS_CONSTANT &&
+ is_constant_expression(right) >= EXPR_CLASS_CONSTANT &&
!fold_constant_to_bool(right)) {
position_t const *const pos = &expression->base.pos;
warningf(WARN_DIV_BY_ZERO, pos, "division by zero");
type_left = promote_integer(type_left);
- if (is_constant_expression(right) == EXPR_CLASS_CONSTANT) {
+ if (is_constant_expression(right) >= EXPR_CLASS_CONSTANT) {
position_t const *const pos = &right->base.pos;
long const count = fold_constant_to_int(right);
if (count < 0) {
static bool maybe_negative(expression_t const *const expr)
{
switch (is_constant_expression(expr)) {
- case EXPR_CLASS_ERROR: return false;
- case EXPR_CLASS_CONSTANT: return constant_is_negative(expr);
- default: return true;
+ case EXPR_CLASS_VARIABLE: return true;
+ case EXPR_CLASS_ERROR: return false;
+ case EXPR_CLASS_CONSTANT:
+ case EXPR_CLASS_INTEGER_CONSTANT: return constant_is_negative(expr);
}
+ panic("invalid expression classification");
}
static void warn_comparison(position_t const *const pos, expression_t const *const expr, expression_t const *const other)
statement->case_label.expression = expression;
expression_classification_t const expr_class = is_constant_expression(expression);
- if (expr_class != EXPR_CLASS_CONSTANT) {
+ if (expr_class < EXPR_CLASS_CONSTANT) {
if (expr_class != EXPR_CLASS_ERROR) {
errorf(pos, "case label does not reduce to an integer constant");
}
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) {
+ if (end_class < EXPR_CLASS_CONSTANT) {
if (end_class != EXPR_CLASS_ERROR) {
errorf(pos, "case range does not reduce to an integer constant");
}