#include "entity_t.h"
#include "attribute_t.h"
#include "lang_features.h"
-#include "walk_statements.h"
+#include "walk.h"
#include "warning.h"
#include "printer.h"
#include "adt/bitfiddle.h"
static statement_t *current_loop = NULL;
static statement_t *current_parent = NULL;
static ms_try_statement_t *current_try = NULL;
-static linkage_kind_t current_linkage = LINKAGE_INVALID;
+static linkage_kind_t current_linkage;
static goto_statement_t *goto_first = NULL;
static goto_statement_t **goto_anchor = NULL;
static label_statement_t *label_first = NULL;
static size_t get_statement_struct_size(statement_kind_t kind)
{
static const size_t sizes[] = {
- [STATEMENT_INVALID] = sizeof(invalid_statement_t),
- [STATEMENT_EMPTY] = sizeof(empty_statement_t),
+ [STATEMENT_ERROR] = sizeof(statement_base_t),
+ [STATEMENT_EMPTY] = sizeof(statement_base_t),
[STATEMENT_COMPOUND] = sizeof(compound_statement_t),
[STATEMENT_RETURN] = sizeof(return_statement_t),
[STATEMENT_DECLARATION] = sizeof(declaration_statement_t),
static size_t get_expression_struct_size(expression_kind_t kind)
{
static const size_t sizes[] = {
- [EXPR_INVALID] = sizeof(expression_base_t),
+ [EXPR_ERROR] = sizeof(expression_base_t),
[EXPR_REFERENCE] = sizeof(reference_expression_t),
[EXPR_REFERENCE_ENUM_VALUE] = sizeof(reference_expression_t),
[EXPR_LITERAL_BOOLEAN] = sizeof(literal_expression_t),
* Creates a new invalid expression at the source position
* of the current token.
*/
-static expression_t *create_invalid_expression(void)
+static expression_t *create_error_expression(void)
{
- return allocate_expression_zero(EXPR_INVALID);
+ expression_t *expression = allocate_expression_zero(EXPR_ERROR);
+ expression->base.type = type_error_type;
+ return expression;
}
/**
* Creates a new invalid statement.
*/
-static statement_t *create_invalid_statement(void)
+static statement_t *create_error_statement(void)
{
- return allocate_statement_zero(STATEMENT_INVALID);
+ return allocate_statement_zero(STATEMENT_ERROR);
}
/**
static entity_t *get_entity(const symbol_t *const symbol,
namespace_tag_t namespc)
{
- assert(namespc != NAMESPACE_INVALID);
entity_t *entity = symbol->entity;
for (; entity != NULL; entity = entity->base.symbol_next) {
if ((namespace_tag_t)entity->base.namespc == namespc)
{
symbol_t *symbol = entity->base.symbol;
entity_namespace_t namespc = entity->base.namespc;
- assert(namespc != NAMESPACE_INVALID);
+ assert(namespc != 0);
/* replace/add entity into entity list of the symbol */
entity_t **anchor;
return;
EXPR_LITERAL_CASES
- case EXPR_UNKNOWN:
- case EXPR_INVALID:
+ case EXPR_ERROR:
case EXPR_STRING_LITERAL:
case EXPR_WIDE_STRING_LITERAL:
case EXPR_COMPOUND_LITERAL: // TODO init?
}
typedef enum construct_type_kind_t {
- CONSTRUCT_INVALID,
- CONSTRUCT_POINTER,
+ CONSTRUCT_POINTER = 1,
CONSTRUCT_REFERENCE,
CONSTRUCT_FUNCTION,
CONSTRUCT_ARRAY
for (; iter != NULL; iter = iter->base.next) {
source_position_t const* const pos = &iter->base.pos;
switch (iter->kind) {
- case CONSTRUCT_INVALID:
- break;
case CONSTRUCT_FUNCTION: {
construct_function_type_t *function = &iter->function;
type_t *function_type = function->function_type;
errorf(pos, "function returning array is not allowed");
} else {
if (skipped_return_type->base.qualifiers != 0) {
- warningf(WARN_OTHER, pos, "type qualifiers in return type of function type are meaningless");
+ warningf(WARN_IGNORED_QUALIFIERS, pos, "type qualifiers in return type of function type are meaningless");
}
}
case EXPR_BUILTIN_CONSTANT_P:
case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
case EXPR_OFFSETOF:
- case EXPR_INVALID:
+ case EXPR_ERROR:
return true;
case EXPR_STATEMENT: {
return
expression_returns(expr->binary.left) &&
expression_returns(expr->binary.right);
-
- case EXPR_UNKNOWN:
- break;
}
panic("unhandled expression");
statement_t *last = stmt;
statement_t *next;
switch (stmt->kind) {
- case STATEMENT_INVALID:
+ case STATEMENT_ERROR:
case STATEMENT_EMPTY:
case STATEMENT_ASM:
next = stmt->base.next;
}
switch (next->kind) {
- case STATEMENT_INVALID:
+ case STATEMENT_ERROR:
case STATEMENT_EMPTY:
case STATEMENT_DECLARATION:
case STATEMENT_EXPRESSION:
}
next_token();
- return create_invalid_expression();
+ return create_error_expression();
}
static type_t *get_string_type(void)
return cast;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
descend_into_subtype(&path);
if (!walk_designator(&path, designator, true)) {
- return create_invalid_expression();
+ return create_error_expression();
}
DEL_ARR_F(path.path);
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
}
expect(')', end_error);
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
expression->base.type = type_void;
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
eat(T_ANDAND);
if (token.kind != T_IDENTIFIER) {
parse_error_expected("while parsing label address", T_IDENTIFIER, NULL);
- return create_invalid_expression();
+ return create_error_expression();
}
label_t *const label = get_label();
parse_declaration_specifiers(&specifiers);
type_t const *const type = parse_abstract_declarator(specifiers.type);
errorf(&pos, "encountered type '%T' while parsing expression", type);
- return create_invalid_expression();
+ return create_error_expression();
}
}
errorf(HERE, "unexpected token %K, expected an expression", &token);
eat_until_anchor();
- return create_invalid_expression();
+ return create_error_expression();
}
static expression_t *parse_array_expression(expression_t *left)
if (token.kind != T_IDENTIFIER) {
parse_error_expected("while parsing select", T_IDENTIFIER, NULL);
- return create_invalid_expression();
+ return create_error_expression();
}
symbol_t *symbol = token.identifier.symbol;
next_token();
"request for member '%Y' in something not a struct or union, but '%T'",
symbol, type_left);
}
- return create_invalid_expression();
+ return create_error_expression();
}
compound_t *compound = type_left->compound.compound;
if (!compound->complete) {
errorf(&pos, "request for member '%Y' in incomplete type '%T'",
symbol, type_left);
- return create_invalid_expression();
+ return create_error_expression();
}
type_qualifiers_t qualifiers = type_left->base.qualifiers;
if (result == NULL) {
errorf(&pos, "'%T' has no member named '%Y'", orig_type, symbol);
- return create_invalid_expression();
+ return create_error_expression();
}
return result;
return result;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
{
switch (is_constant_expression(expr)) {
case EXPR_CLASS_ERROR: return false;
- case EXPR_CLASS_CONSTANT: return fold_constant_to_int(expr) < 0;
+ case EXPR_CLASS_CONSTANT: return constant_is_negative(expr);
default: return true;
}
}
static bool expression_has_effect(const expression_t *const expr)
{
switch (expr->kind) {
- case EXPR_UNKNOWN: break;
- case EXPR_INVALID: return true; /* do NOT warn */
+ case EXPR_ERROR: return true; /* do NOT warn */
case EXPR_REFERENCE: return false;
case EXPR_REFERENCE_ENUM_VALUE: return false;
case EXPR_LABEL_ADDRESS: return false;
left = parser->infix_parser(left);
assert(left != NULL);
- assert(left->kind != EXPR_UNKNOWN);
}
return left;
return statement;
end_error:
- return create_invalid_statement();
+ return create_error_statement();
}
static statement_t *parse_label_inner_statement(statement_t const *const label, char const *const label_kind)
switch (token.kind) {
case '}':
errorf(&label->base.source_position, "%s at end of compound statement", label_kind);
- inner_stmt = create_invalid_statement();
+ inner_stmt = create_error_statement();
break;
case ';':
statement->ifs.true_statement = true_stmt;
rem_anchor_token(T_else);
+ if (true_stmt->kind == STATEMENT_EMPTY) {
+ warningf(WARN_EMPTY_BODY, HERE,
+ "suggest braces around empty body in an ‘if’ statement");
+ }
+
if (next_if(T_else)) {
statement->ifs.false_statement = parse_inner_statement();
+
+ if (statement->ifs.false_statement->kind == STATEMENT_EMPTY) {
+ warningf(WARN_EMPTY_BODY, HERE,
+ "suggest braces around empty body in an ‘if’ statement");
+ }
} else if (true_stmt->kind == STATEMENT_IF &&
true_stmt->ifs.false_statement != NULL) {
source_position_t const *const pos = &true_stmt->base.source_position;
return statement;
end_error:
POP_PARENT();
- return create_invalid_statement();
+ return create_error_statement();
}
static statement_t *parse_loop_body(statement_t *const loop)
return statement;
end_error:
POP_PARENT();
- return create_invalid_statement();
+ return create_error_statement();
}
/**
return statement;
end_error:
POP_PARENT();
- return create_invalid_statement();
+ return create_error_statement();
}
/**
/* fallthrough */
end_error1:
- return create_invalid_statement();
+ return create_error_statement();
}
/**
else
parse_error_expected("while parsing goto", T_IDENTIFIER, NULL);
eat_until_anchor();
- return create_invalid_statement();
+ return create_error_statement();
}
/* remember the goto's in a list for later checking */
statement->ms_try.final_statement = parse_compound_statement(false);
} else {
parse_error_expected("while parsing __try statement", T___except, T___finally, NULL);
- return create_invalid_statement();
+ return create_error_statement();
}
return statement;
end_error:
- return create_invalid_statement();
+ return create_error_statement();
}
static statement_t *parse_empty_statement(void)
default:
errorf(HERE, "unexpected token %K while parsing statement", &token);
- statement = create_invalid_statement();
+ statement = create_error_statement();
if (!at_anchor())
next_token();
break;
break;
}
statement_t *sub_statement = intern_parse_statement();
- if (is_invalid_statement(sub_statement)) {
+ if (sub_statement->kind == STATEMENT_ERROR) {
/* an error occurred. if we are at an anchor, return */
if (at_anchor())
goto end_error;
new_linkage = LINKAGE_CXX;
} else {
errorf(&pos, "linkage string \"%s\" not recognized", linkage);
- new_linkage = LINKAGE_INVALID;
+ new_linkage = LINKAGE_C;
}
current_linkage = new_linkage;
case ';':
if (!strict_mode) {
- warningf(WARN_OTHER, HERE, "stray ';' outside of function");
+ warningf(WARN_STRAY_SEMICOLON, HERE, "stray ';' outside of function");
next_token();
return;
}