#include <stdarg.h>
#include <stdbool.h>
+#include "diagnostic.h"
+#include "format_check.h"
#include "parser.h"
#include "lexer.h"
#include "token_t.h"
+#include "types.h"
#include "type_t.h"
#include "type_hash.h"
#include "ast_t.h"
source_position_t source_position;
unsigned char storage_class;
bool is_inline;
+ decl_modifiers_t decl_modifiers;
type_t *type;
};
static declaration_t *last_declaration = NULL;
static declaration_t *current_function = NULL;
static struct obstack temp_obst;
-static bool found_error;
-
-static type_t *type_int = NULL;
-static type_t *type_long_double = NULL;
-static type_t *type_double = NULL;
-static type_t *type_float = NULL;
-static type_t *type_char = NULL;
-static type_t *type_string = NULL;
-static type_t *type_void = NULL;
-static type_t *type_void_ptr = NULL;
-static type_t *type_valist = NULL;
-
-type_t *type_size_t = NULL;
-type_t *type_ptrdiff_t = NULL;
-type_t *type_wchar_t = NULL;
-type_t *type_wchar_t_ptr = NULL;
+
+#define HERE token.source_position
+
+static type_t *type_valist;
static statement_t *parse_compound_statement(void);
static statement_t *parse_statement(void);
case T_const: \
case T_restrict: \
case T_volatile: \
- case T_inline:
+ case T_inline: \
+ case T_forceinline:
#ifdef PROVIDE_COMPLEX
#define COMPLEX_SPECIFIERS \
return res;
}
-static size_t get_statement_struct_size(statement_type_t type)
+static size_t get_statement_struct_size(statement_kind_t kind)
{
static const size_t sizes[] = {
[STATEMENT_COMPOUND] = sizeof(compound_statement_t),
[STATEMENT_FOR] = sizeof(for_statement_t),
[STATEMENT_ASM] = sizeof(asm_statement_t)
};
- assert(type <= sizeof(sizes) / sizeof(sizes[0]));
- assert(sizes[type] != 0);
- return sizes[type];
+ assert(kind <= sizeof(sizes) / sizeof(sizes[0]));
+ assert(sizes[kind] != 0);
+ return sizes[kind];
}
-static statement_t *allocate_statement_zero(statement_type_t type)
+static statement_t *allocate_statement_zero(statement_kind_t kind)
{
- size_t size = get_statement_struct_size(type);
+ size_t size = get_statement_struct_size(kind);
statement_t *res = allocate_ast_zero(size);
- res->base.type = type;
+ res->base.kind = kind;
return res;
}
-static size_t get_expression_struct_size(expression_type_t type)
+static size_t get_expression_struct_size(expression_kind_t type)
{
static const size_t sizes[] = {
[EXPR_INVALID] = sizeof(expression_base_t),
[EXPR_FUNCTION] = sizeof(string_literal_expression_t),
[EXPR_PRETTY_FUNCTION] = sizeof(string_literal_expression_t),
[EXPR_BUILTIN_SYMBOL] = sizeof(builtin_symbol_expression_t),
+ [EXPR_BUILTIN_CONSTANT_P] = sizeof(builtin_constant_expression_t),
+ [EXPR_BUILTIN_PREFETCH] = sizeof(builtin_prefetch_expression_t),
[EXPR_OFFSETOF] = sizeof(offsetof_expression_t),
[EXPR_VA_START] = sizeof(va_start_expression_t),
[EXPR_VA_ARG] = sizeof(va_arg_expression_t),
return sizes[type];
}
-static expression_t *allocate_expression_zero(expression_type_t type)
+static expression_t *allocate_expression_zero(expression_kind_t kind)
{
- size_t size = get_expression_struct_size(type);
+ size_t size = get_expression_struct_size(kind);
expression_t *res = allocate_ast_zero(size);
- res->base.type = type;
+ res->base.kind = kind;
return res;
}
-static size_t get_type_struct_size(type_type_t type)
+static size_t get_type_struct_size(type_kind_t kind)
{
static const size_t sizes[] = {
[TYPE_ATOMIC] = sizeof(atomic_type_t),
[TYPE_TYPEOF] = sizeof(typeof_type_t),
};
assert(sizeof(sizes) / sizeof(sizes[0]) == (int) TYPE_TYPEOF + 1);
- assert(type <= TYPE_TYPEOF);
- assert(sizes[type] != 0);
- return sizes[type];
+ assert(kind <= TYPE_TYPEOF);
+ assert(sizes[kind] != 0);
+ return sizes[kind];
}
-static type_t *allocate_type_zero(type_type_t type)
+static type_t *allocate_type_zero(type_kind_t kind)
{
- size_t size = get_type_struct_size(type);
+ size_t size = get_type_struct_size(kind);
type_t *res = obstack_alloc(type_obst, size);
memset(res, 0, size);
- res->base.type = type;
+ res->base.kind = kind;
return res;
}
-static size_t get_initializer_size(initializer_type_t type)
+static size_t get_initializer_size(initializer_kind_t kind)
{
static const size_t sizes[] = {
[INITIALIZER_VALUE] = sizeof(initializer_value_t),
[INITIALIZER_WIDE_STRING] = sizeof(initializer_wide_string_t),
[INITIALIZER_LIST] = sizeof(initializer_list_t)
};
- assert(type < sizeof(sizes) / sizeof(*sizes));
- assert(sizes[type] != 0);
- return sizes[type];
+ assert(kind < sizeof(sizes) / sizeof(*sizes));
+ assert(sizes[kind] != 0);
+ return sizes[kind];
}
-static initializer_t *allocate_initializer(initializer_type_t type)
+static initializer_t *allocate_initializer(initializer_kind_t kind)
{
- initializer_t *result = allocate_ast_zero(get_initializer_size(type));
- result->type = type;
+ initializer_t *result = allocate_ast_zero(get_initializer_size(kind));
+ result->kind = kind;
return result;
}
#define eat(token_type) do { assert(token.type == token_type); next_token(); } while(0)
-static void error(void)
-{
- found_error = true;
-#ifdef ABORT_ON_ERROR
- abort();
-#endif
-}
-
-static void parser_print_prefix_pos(const source_position_t source_position)
-{
- fputs(source_position.input_name, stderr);
- fputc(':', stderr);
- fprintf(stderr, "%u", source_position.linenr);
- fputs(": ", stderr);
-}
-
-static void parser_print_error_prefix_pos(
- const source_position_t source_position)
-{
- parser_print_prefix_pos(source_position);
- fputs("error: ", stderr);
- error();
-}
-
-static void parser_print_error_prefix(void)
-{
- parser_print_error_prefix_pos(token.source_position);
-}
-
-static void parse_error(const char *message)
-{
- parser_print_error_prefix();
- fprintf(stderr, "parse error: %s\n", message);
-}
-
-static void parser_print_warning_prefix_pos(
- const source_position_t source_position)
-{
- parser_print_prefix_pos(source_position);
- fputs("warning: ", stderr);
-}
-
-static void parser_print_warning_prefix(void)
-{
- parser_print_warning_prefix_pos(token.source_position);
-}
-
-static void parse_warning_pos(const source_position_t source_position,
- const char *const message)
-{
- parser_print_prefix_pos(source_position);
- fprintf(stderr, "warning: %s\n", message);
-}
-
-static void parse_warning(const char *message)
-{
- parse_warning_pos(token.source_position, message);
-}
-
static void parse_error_expected(const char *message, ...)
{
- va_list args;
- int first = 1;
-
if(message != NULL) {
- parser_print_error_prefix();
- fprintf(stderr, "%s\n", message);
- }
- parser_print_error_prefix();
- fputs("Parse error: got ", stderr);
- print_token(stderr, &token);
- fputs(", expected ", stderr);
-
- va_start(args, message);
- token_type_t token_type = va_arg(args, token_type_t);
- while(token_type != 0) {
- if(first == 1) {
- first = 0;
- } else {
- fprintf(stderr, ", ");
- }
- print_token_type(stderr, token_type);
- token_type = va_arg(args, token_type_t);
+ errorf(HERE, "%s", message);
}
- va_end(args);
- fprintf(stderr, "\n");
-}
-
-static void print_type_quoted(type_t *type)
-{
- fputc('\'', stderr);
- print_type(type);
- fputc('\'', stderr);
+ va_list ap;
+ va_start(ap, message);
+ errorf(HERE, "got '%K', expected %#k", &token, &ap, ", ");
+ va_end(ap);
}
static void type_error(const char *msg, const source_position_t source_position,
type_t *type)
{
- parser_print_error_prefix_pos(source_position);
- fprintf(stderr, "%s, but found type ", msg);
- print_type_quoted(type);
- fputc('\n', stderr);
+ errorf(source_position, "%s, but found type '%T'", msg, type);
}
static void type_error_incompatible(const char *msg,
const source_position_t source_position, type_t *type1, type_t *type2)
{
- parser_print_error_prefix_pos(source_position);
- fprintf(stderr, "%s, incompatible types: ", msg);
- print_type_quoted(type1);
- fprintf(stderr, " - ");
- print_type_quoted(type2);
- fprintf(stderr, ")\n");
+ errorf(source_position, "%s, incompatible types: '%T' - '%T'", msg, type1, type2);
}
static void eat_block(void)
if(previous_declaration != NULL
&& previous_declaration->parent_context == context) {
if(!is_compatible_declaration(declaration, previous_declaration)) {
- parser_print_error_prefix_pos(declaration->source_position);
- fprintf(stderr, "definition of symbol '%s%s' with type ",
- get_namespace_prefix(namespc), symbol->string);
- print_type_quoted(declaration->type);
- fputc('\n', stderr);
- parser_print_error_prefix_pos(
- previous_declaration->source_position);
- fprintf(stderr, "is incompatible with previous declaration "
- "of type ");
- print_type_quoted(previous_declaration->type);
- fputc('\n', stderr);
+ errorf(declaration->source_position, "definition of symbol '%s%s' with type '%T'", get_namespace_prefix(namespc), symbol->string, declaration->type);
+ errorf(previous_declaration->source_position, "is incompatible with previous declaration of type '%T'", previous_declaration->type);
} else {
unsigned old_storage_class = previous_declaration->storage_class;
unsigned new_storage_class = declaration->storage_class;
if (current_function == NULL) {
if (old_storage_class != STORAGE_CLASS_STATIC &&
new_storage_class == STORAGE_CLASS_STATIC) {
- parser_print_error_prefix_pos(declaration->source_position);
- fprintf(stderr,
- "static declaration of '%s' follows non-static declaration\n",
- symbol->string);
- parser_print_error_prefix_pos(previous_declaration->source_position);
- fprintf(stderr, "previous declaration of '%s' was here\n",
- symbol->string);
+ errorf(declaration->source_position, "static declaration of '%s' follows non-static declaration", symbol->string);
+ errorf(previous_declaration->source_position, "previous declaration of '%s' was here\n", symbol->string);
} else {
if (old_storage_class == STORAGE_CLASS_EXTERN) {
if (new_storage_class == STORAGE_CLASS_NONE) {
previous_declaration->storage_class = STORAGE_CLASS_NONE;
}
} else if(!is_type_function(type)) {
- parser_print_warning_prefix_pos(declaration->source_position);
- fprintf(stderr, "redundant declaration for '%s'\n",
- symbol->string);
- parser_print_warning_prefix_pos(previous_declaration->source_position);
- fprintf(stderr, "previous declaration of '%s' was here\n",
- symbol->string);
+ warningf(declaration->source_position, "redundant declaration for '%s'\n", symbol->string);
+ warningf(previous_declaration->source_position, "previous declaration of '%s' was here\n", symbol->string);
}
}
} else {
if (old_storage_class == STORAGE_CLASS_EXTERN &&
new_storage_class == STORAGE_CLASS_EXTERN) {
- parser_print_warning_prefix_pos(declaration->source_position);
- fprintf(stderr, "redundant extern declaration for '%s'\n",
- symbol->string);
- parser_print_warning_prefix_pos(previous_declaration->source_position);
- fprintf(stderr, "previous declaration of '%s' was here\n",
- symbol->string);
+ warningf(declaration->source_position, "redundant extern declaration for '%s'\n", symbol->string);
+ warningf(previous_declaration->source_position, "previous declaration of '%s' was here\n", symbol->string);
} else {
- parser_print_error_prefix_pos(declaration->source_position);
if (old_storage_class == new_storage_class) {
- fprintf(stderr, "redeclaration of '%s'\n", symbol->string);
+ errorf(declaration->source_position, "redeclaration of '%s'\n", symbol->string);
} else {
- fprintf(stderr, "redeclaration of '%s' with different linkage\n", symbol->string);
+ errorf(declaration->source_position, "redeclaration of '%s' with different linkage\n", symbol->string);
}
- parser_print_error_prefix_pos(previous_declaration->source_position);
- fprintf(stderr, "previous declaration of '%s' was here\n",
- symbol->string);
+ errorf(previous_declaration->source_position, "previous declaration of '%s' was here", symbol->string);
}
}
}
assert(!is_typeref(type));
/* The C-standard allows promoting to int or unsigned int (see § 7.2.2
* and esp. footnote 108). However we can't fold constants (yet), so we
- * can't decide wether unsigned int is possible, while int always works.
+ * can't decide whether unsigned int is possible, while int always works.
* (unsigned int would be preferable when possible... for stuff like
* struct { enum { ... } bla : 4; } ) */
- if(type->type == TYPE_ENUM)
+ if(type->kind == TYPE_ENUM)
return ATOMIC_TYPE_INT;
- assert(type->type == TYPE_ATOMIC);
+ assert(type->kind == TYPE_ATOMIC);
const atomic_type_t *atomic_type = &type->atomic;
atomic_type_type_t atype = atomic_type->atype;
return atype;
static bool is_null_pointer_constant(const expression_t *expression)
{
/* skip void* cast */
- if(expression->type == EXPR_UNARY_CAST
- || expression->type == EXPR_UNARY_CAST_IMPLICIT) {
+ if(expression->kind == EXPR_UNARY_CAST
+ || expression->kind == EXPR_UNARY_CAST_IMPLICIT) {
expression = expression->unary.value;
}
/* TODO: not correct yet, should be any constant integer expression
* which evaluates to 0 */
- if (expression->type != EXPR_CONST)
+ if (expression->kind != EXPR_CONST)
return false;
type_t *const type = skip_typeref(expression->base.datatype);
if(source_type == dest_type)
return expression;
- switch (dest_type->type) {
+ switch (dest_type->kind) {
case TYPE_ENUM:
/* TODO warning for implicitly converting to enum */
case TYPE_ATOMIC:
- if (source_type->type != TYPE_ATOMIC &&
- source_type->type != TYPE_ENUM) {
+ if (source_type->kind != TYPE_ATOMIC &&
+ source_type->kind != TYPE_ENUM) {
panic("casting of non-atomic types not implemented yet");
}
return create_cast_expression(expression, dest_type);
case TYPE_POINTER:
- switch (source_type->type) {
+ switch (source_type->kind) {
case TYPE_ATOMIC:
if (is_null_pointer_constant(expression)) {
return create_cast_expression(expression, dest_type);
unsigned missing_qualifiers
= points_to_right->base.qualifiers & ~points_to_left->base.qualifiers;
if(missing_qualifiers != 0) {
- parser_print_error_prefix();
- fprintf(stderr, "destination type ");
- print_type_quoted(type_left);
- fprintf(stderr, " in %s from type ", context);
- print_type_quoted(type_right);
- fprintf(stderr, " lacks qualifiers '");
- print_type_qualifiers(missing_qualifiers);
- fprintf(stderr, "' in pointed-to type\n");
+ errorf(HERE, "destination type '%T' in %s from type '%T' lacks qualifiers '%Q' in pointed-to type", type_left, context, type_right, missing_qualifiers);
return;
}
incompatible_assign_types:
/* TODO: improve error message */
- parser_print_error_prefix();
- fprintf(stderr, "incompatible types in %s\n", context);
- parser_print_error_prefix();
- print_type_quoted(orig_type_left);
- fputs(" <- ", stderr);
- print_type_quoted(orig_type_right);
- fputs("\n", stderr);
+ errorf(HERE, "incompatible types in %s", context);
+ errorf(HERE, "'%T' <- '%T'", orig_type_left, orig_type_right);
}
static expression_t *parse_constant_expression(void)
{
/* start parsing at precedence 7 (conditional expression) */
- return parse_sub_expression(7);
+ expression_t *result = parse_sub_expression(7);
+
+ if(!is_constant_expression(result)) {
+ errorf(result->base.source_position, "expression '%E' is not constant\n", result);
+ }
+
+ return result;
}
static expression_t *parse_assignment_expression(void)
static type_t *make_global_typedef(const char *name, type_t *type)
{
- symbol_t *symbol = symbol_table_insert(name);
+ symbol_t *const symbol = symbol_table_insert(name);
declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
declaration->namespc = NAMESPACE_NORMAL;
while(depth > 0) {
switch(token.type) {
case T_EOF:
- parse_error("EOF while parsing attribute");
+ errorf(HERE, "EOF while parsing attribute");
break;
case '(':
next_token();
/* § 6.7.8.14/15 char array may be initialized by string literals */
type_t *const expr_type = expression->base.datatype;
- if (is_type_array(type) && expr_type->type == TYPE_POINTER) {
+ if (is_type_array(type) && expr_type->kind == TYPE_POINTER) {
array_type_t *const array_type = &type->array;
type_t *const element_type = skip_typeref(array_type->element_type);
- if (element_type->type == TYPE_ATOMIC) {
- switch (expression->type) {
+ if (element_type->kind == TYPE_ATOMIC) {
+ switch (expression->kind) {
case EXPR_STRING_LITERAL:
if (element_type->atomic.atype == ATOMIC_TYPE_CHAR) {
return initializer_from_string(array_type,
if(token.type == '{') {
next_token();
if(!had_initializer_brace_warning) {
- parse_warning("braces around scalar initializer");
+ warningf(HERE, "braces around scalar initializer");
had_initializer_brace_warning = true;
}
initializer_t *result = parse_sub_initializer(type, NULL, NULL);
return initializer_from_expression(type, expression);
}
- /* does the expression match the currently looked at object to initalize */
+ /* does the expression match the currently looked at object to initialize */
if(expression != NULL) {
initializer_t *result = initializer_from_expression(type, expression);
if(result != NULL)
sub = parse_sub_initializer_elem(element_type);
if(sub == NULL) {
/* TODO error, do nicer cleanup */
- parse_error("member initializer didn't match");
+ errorf(HERE, "member initializer didn't match");
DEL_ARR_F(elems);
return NULL;
}
sub = parse_sub_initializer_elem(iter_type);
if(sub == NULL) {
- /* TODO error, do nicer cleanup*/
- parse_error("member initializer didn't match");
+ /* TODO error, do nicer cleanup */
+ errorf(HERE, "member initializer didn't match");
DEL_ARR_F(elems);
return NULL;
}
initializer_list_t *init = allocate_ast_zero(sizeof(init[0]) + elems_size);
- init->initializer.type = INITIALIZER_LIST;
+ init->initializer.kind = INITIALIZER_LIST;
init->len = len;
memcpy(init->initializers, elems, elems_size);
DEL_ARR_F(elems);
expression_t *expression = parse_assignment_expression();
initializer_t *initializer = initializer_from_expression(type, expression);
if(initializer == NULL) {
- parser_print_error_prefix();
- fprintf(stderr, "initializer expression '");
- print_expression(expression);
- fprintf(stderr, "', type ");
- print_type_quoted(expression->base.datatype);
- fprintf(stderr, " is incompatible with type ");
- print_type_quoted(type);
- fprintf(stderr, "\n");
+ errorf(HERE, "initializer expression '%E', type '%T' is incompatible with type '%T'", expression, expression->base.datatype, type);
}
return initializer;
}
if(token.type == '{') {
if(declaration->init.is_defined) {
assert(symbol != NULL);
- parser_print_error_prefix();
- fprintf(stderr, "multiple definition of %s %s\n",
- is_struct ? "struct" : "union", symbol->string);
+ errorf(HERE, "multiple definition of %s %s", is_struct ? "struct" : "union", symbol->string);
declaration->context.declarations = NULL;
}
declaration->init.is_defined = true;
if(token.type == '}') {
next_token();
- parse_error("empty enum not allowed");
+ errorf(HERE, "empty enum not allowed");
return;
}
if(token.type == '{') {
if(declaration->init.is_defined) {
- parser_print_error_prefix();
- fprintf(stderr, "multiple definitions of enum %s\n",
- symbol->string);
+ errorf(HERE, "multiple definitions of enum %s", symbol->string);
}
record_declaration(declaration);
declaration->init.is_defined = 1;
#define MATCH_STORAGE_CLASS(token, class) \
case token: \
if(specifiers->storage_class != STORAGE_CLASS_NONE) { \
- parse_error("multiple storage classes in declaration " \
- "specifiers"); \
+ errorf(HERE, "multiple storage classes in declaration specifiers"); \
} \
specifiers->storage_class = class; \
next_token(); \
break;
default:
- parse_error("multiple storage classes in declaration specifiers");
+ errorf(HERE, "multiple storage classes in declaration specifiers");
break;
}
next_token();
case token: \
next_token(); \
if(type_specifiers & specifier) { \
- parse_error("multiple " name " type specifiers given"); \
+ errorf(HERE, "multiple " name " type specifiers given"); \
} else { \
type_specifiers |= specifier; \
} \
MATCH_SPECIFIER(T__Complex, SPECIFIER_COMPLEX, "_Complex")
MATCH_SPECIFIER(T__Imaginary, SPECIFIER_IMAGINARY, "_Imaginary")
#endif
+ case T_forceinline:
+ /* only in microsoft mode */
+ specifiers->decl_modifiers |= DM_FORCEINLINE;
+
case T_inline:
next_token();
specifiers->is_inline = true;
case T_long:
next_token();
if(type_specifiers & SPECIFIER_LONG_LONG) {
- parse_error("multiple type specifiers given");
+ errorf(HERE, "multiple type specifiers given");
} else if(type_specifiers & SPECIFIER_LONG) {
type_specifiers |= SPECIFIER_LONG_LONG;
} else {
/* invalid specifier combination, give an error message */
if(type_specifiers == 0) {
#ifndef STRICT_C99
- parse_warning("no type specifiers in declaration, using int");
+ warningf(HERE, "no type specifiers in declaration, using int");
atomic_type = ATOMIC_TYPE_INT;
break;
#else
- parse_error("no type specifiers given in declaration");
+ errorf(HERE, "no type specifiers given in declaration");
#endif
} else if((type_specifiers & SPECIFIER_SIGNED) &&
(type_specifiers & SPECIFIER_UNSIGNED)) {
- parse_error("signed and unsigned specifiers gives");
+ errorf(HERE, "signed and unsigned specifiers gives");
} else if(type_specifiers & (SPECIFIER_SIGNED | SPECIFIER_UNSIGNED)) {
- parse_error("only integer types can be signed or unsigned");
+ errorf(HERE, "only integer types can be signed or unsigned");
} else {
- parse_error("multiple datatypes in declaration");
+ errorf(HERE, "multiple datatypes in declaration");
}
atomic_type = ATOMIC_TYPE_INVALID;
}
newtype = 1;
} else {
if(type_specifiers != 0) {
- parse_error("multiple datatypes in declaration");
+ errorf(HERE, "multiple datatypes in declaration");
}
}
/* TODO: improve error messages */
if(declaration->storage_class == STORAGE_CLASS_TYPEDEF) {
- parse_error("typedef not allowed in parameter list");
+ errorf(HERE, "typedef not allowed in parameter list");
} else if(declaration->storage_class != STORAGE_CLASS_NONE
&& declaration->storage_class != STORAGE_CLASS_REGISTER) {
- parse_error("parameter may only have none or register storage class");
+ errorf(HERE, "parameter may only have none or register storage class");
}
type_t *orig_type = declaration->type;
return;
type_t *type = skip_typeref(orig_type);
- /* Array as last part of a paramter type is just syntactic sugar. Turn it
+ /* Array as last part of a parameter type is just syntactic sugar. Turn it
* into a pointer. § 6.7.5.3 (7) */
if (is_type_array(type)) {
const array_type_t *arr_type = &type->array;
}
if(is_type_incomplete(type)) {
- parser_print_error_prefix();
- fprintf(stderr, "incomplete type (");
- print_type_quoted(orig_type);
- fprintf(stderr, ") not allowed for parameter '%s'\n",
- declaration->symbol->string);
+ errorf(HERE, "incomplete type ('%T') not allowed for parameter '%s'", orig_type, declaration->symbol->string);
}
}
parse_declaration_specifiers(&specifiers);
- declaration_t *declaration = parse_declarator(&specifiers, true);
+ declaration_t *declaration = parse_declarator(&specifiers, /*may_be_abstract=*/true);
semantic_parameter(declaration);
switch(token.type) {
case T_IDENTIFIER:
if(declaration == NULL) {
- parse_error("no identifier expected in typename");
+ errorf(HERE, "no identifier expected in typename");
} else {
declaration->symbol = token.v.symbol;
declaration->source_position = token.source_position;
static declaration_t *parse_declarator(
const declaration_specifiers_t *specifiers, bool may_be_abstract)
{
- type_t *type = specifiers->type;
- declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
- declaration->storage_class = specifiers->storage_class;
- declaration->is_inline = specifiers->is_inline;
+ type_t *type = specifiers->type;
+ declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
+ declaration->storage_class = specifiers->storage_class;
+ declaration->decl_modifiers = specifiers->decl_modifiers;
+ declaration->is_inline = specifiers->is_inline;
construct_type_t *construct_type
= parse_inner_declarator(declaration, may_be_abstract);
static void parser_error_multiple_definition(declaration_t *declaration,
const source_position_t source_position)
{
- parser_print_error_prefix_pos(source_position);
- fprintf(stderr, "multiple definition of symbol '%s'\n",
- declaration->symbol->string);
- parser_print_error_prefix_pos(declaration->source_position);
- fprintf(stderr, "this is the location of the previous definition.\n");
+ errorf(source_position, "multiple definition of symbol '%s'", declaration->symbol->string);
+ errorf(declaration->source_position, "this is the location of the previous definition.");
}
static bool is_declaration_specifier(const token_t *token,
initializer_t *initializer = parse_initializer(type);
- /* § 6.7.5 (22) array intializers for arrays with unknown size determine
+ /* § 6.7.5 (22) array initializers for arrays with unknown size determine
* the array type size */
if(type != NULL && is_type_array(type) && initializer != NULL) {
array_type_t *array_type = &type->array;
cnst->base.datatype = type_size_t;
- switch (initializer->type) {
+ switch (initializer->kind) {
case INITIALIZER_LIST: {
initializer_list_t *const list = &initializer->list;
cnst->conste.v.int_value = list->len;
}
if(type != NULL && is_type_function(type)) {
- parser_print_error_prefix_pos(declaration->source_position);
- fprintf(stderr, "initializers not allowed for function types at "
- "declator '%s' (type ", declaration->symbol->string);
- print_type_quoted(orig_type);
- fprintf(stderr, ")\n");
+ errorf(declaration->source_position, "initializers not allowed for function types at declator '%s' (type '%T')", declaration->symbol->string, orig_type);
} else {
declaration->init.initializer = initializer;
}
declaration->source_position = specifiers->source_position;
if (declaration->storage_class != STORAGE_CLASS_NONE) {
- parse_warning_pos(declaration->source_position,
- "useless storage class in empty declaration");
+ warningf(declaration->source_position, "useless storage class in empty declaration");
}
type_t *type = declaration->type;
- switch (type->type) {
+ switch (type->kind) {
case TYPE_COMPOUND_STRUCT:
case TYPE_COMPOUND_UNION: {
const compound_type_t *compound_type = &type->compound;
if (compound_type->declaration->symbol == NULL) {
- parse_warning_pos(declaration->source_position,
- "unnamed struct/union that defines no instances");
+ warningf(declaration->source_position, "unnamed struct/union that defines no instances");
}
break;
}
break;
default:
- parse_warning_pos(declaration->source_position,
- "empty declaration");
+ warningf(declaration->source_position, "empty declaration");
break;
}
type_t *orig_type = declaration->type;
type_t *type = skip_typeref(orig_type);
- if(type->type != TYPE_FUNCTION && declaration->is_inline) {
- parser_print_warning_prefix_pos(declaration->source_position);
- fprintf(stderr, "variable '%s' declared 'inline'\n",
- declaration->symbol->string);
+ if(type->kind != TYPE_FUNCTION && declaration->is_inline) {
+ warningf(declaration->source_position, "variable '%s' declared 'inline'\n", declaration->symbol->string);
}
if(token.type == '=') {
break;
eat(',');
- ndeclaration = parse_declarator(specifiers, false);
+ ndeclaration = parse_declarator(specifiers, /*may_be_abstract=*/false);
}
expect_void(';');
}
if(token.type == ';') {
parse_anonymous_declaration_rest(&specifiers, finished_declaration);
} else {
- declaration_t *declaration = parse_declarator(&specifiers, false);
+ declaration_t *declaration = parse_declarator(&specifiers, /*may_be_abstract=*/false);
parse_declaration_rest(declaration, &specifiers, finished_declaration);
}
}
type_t *parameter_type = parameter_declaration->type;
if(parameter_type == NULL) {
#ifdef STRICT_C99
- parser_print_error_prefix();
- fprintf(stderr, "no type specified for function parameter '%s'\n",
- parameter_declaration->symbol->string);
+ errorf(HERE, "no type specified for function parameter '%s'", parameter_declaration->symbol->string);
#else
- parser_print_warning_prefix();
- fprintf(stderr, "no type specified for function parameter '%s', "
- "using int\n", parameter_declaration->symbol->string);
+ warningf(HERE, "no type specified for function parameter '%s', using int", parameter_declaration->symbol->string);
parameter_type = type_int;
parameter_declaration->type = parameter_type;
#endif
}
/* declarator is common to both function-definitions and declarations */
- declaration_t *ndeclaration = parse_declarator(&specifiers, false);
+ declaration_t *ndeclaration = parse_declarator(&specifiers, /*may_be_abstract=*/false);
/* must be a declaration */
if(token.type == ',' || token.type == '=' || token.type == ';') {
/* note that we don't skip typerefs: the standard doesn't allow them here
* (so we can't use is_type_function here) */
- if(type->type != TYPE_FUNCTION) {
- parser_print_error_prefix();
- fprintf(stderr, "declarator '");
- print_type_ext(type, ndeclaration->symbol, NULL);
- fprintf(stderr, "' has a body but is not a function type.\n");
+ if(type->kind != TYPE_FUNCTION) {
+ errorf(HERE, "declarator '%#T' has a body but is not a function type", type, ndeclaration->symbol);
eat_block();
return;
}
parse_constant_expression();
/* TODO (bitfields) */
} else {
- declaration_t *declaration = parse_declarator(specifiers, true);
+ declaration_t *declaration = parse_declarator(specifiers, /*may_be_abstract=*/true);
/* TODO: check constraints for struct declarations */
/* TODO: check for doubled fields */
parse_struct_declarators(&specifiers);
}
if(token.type == T_EOF) {
- parse_error("EOF while parsing struct");
+ errorf(HERE, "EOF while parsing struct");
}
next_token();
}
/* TODO: improve error message, user does probably not know what a
* storage class is...
*/
- parse_error("typename may not have a storage class");
+ errorf(HERE, "typename may not have a storage class");
}
type_t *result = parse_abstract_declarator(specifiers.type);
static expression_t *expected_expression_error(void)
{
- parser_print_error_prefix();
- fprintf(stderr, "expected expression, got token ");
- print_token(stderr, &token);
- fprintf(stderr, "\n");
+ errorf(HERE, "expected expression, got token '%K'", &token);
next_token();
if(expression->base.datatype == NULL)
return NULL;
- switch(expression->type) {
+ switch(expression->kind) {
case EXPR_REFERENCE: {
const reference_expression_t *ref = &expression->reference;
return ref->declaration->type;
#ifndef STRICT_C99
/* an implicitly defined function */
if(token.type == '(') {
- parser_print_prefix_pos(token.source_position);
- fprintf(stderr, "warning: implicit declaration of function '%s'\n",
- ref->symbol->string);
+ warningf(HERE, "implicit declaration of function '%s'\n", ref->symbol->string);
declaration = create_implicit_function(ref->symbol,
source_position);
} else
#endif
{
- parser_print_error_prefix();
- fprintf(stderr, "unknown symbol '%s' found.\n", ref->symbol->string);
+ errorf(HERE, "unknown symbol '%s' found.\n", ref->symbol->string);
return expression;
}
}
return NULL;
}
- assert(statement->type == STATEMENT_COMPOUND);
+ assert(statement->kind == STATEMENT_COMPOUND);
compound_statement_t *compound_statement = &statement->compound;
/* find last statement and use it's type */
last_statement = iter;
}
- if(last_statement->type == STATEMENT_EXPRESSION) {
+ if(last_statement->kind == STATEMENT_EXPRESSION) {
const expression_statement_t *expression_statement
= &last_statement->expression;
expression->base.datatype
switch(token.type) {
case '{':
- /* gcc extension: a stement expression */
+ /* gcc extension: a statement expression */
return parse_statement_expression();
TYPE_QUALIFIERS
/* TODO */
if (current_function == NULL) {
- parse_error("'__func__' used outside of a function");
+ errorf(HERE, "'__func__' used outside of a function");
}
string_literal_expression_t *expression
= allocate_ast_zero(sizeof(expression[0]));
- expression->expression.type = EXPR_FUNCTION;
+ expression->expression.kind = EXPR_FUNCTION;
expression->expression.datatype = type_string;
- expression->value = "TODO: FUNCTION";
+ expression->value = current_function->symbol->string;
return (expression_t*) expression;
}
eat(T___PRETTY_FUNCTION__);
/* TODO */
+ if (current_function == NULL) {
+ errorf(HERE, "'__PRETTY_FUNCTION__' used outside of a function");
+ }
+
string_literal_expression_t *expression
= allocate_ast_zero(sizeof(expression[0]));
- expression->expression.type = EXPR_PRETTY_FUNCTION;
+ expression->expression.kind = EXPR_PRETTY_FUNCTION;
expression->expression.datatype = type_string;
- expression->value = "TODO: PRETTY FUNCTION";
+ expression->value = current_function->symbol->string;
return (expression_t*) expression;
}
expression->va_starte.ap = parse_assignment_expression();
expect(',');
expression_t *const expr = parse_assignment_expression();
- if (expr->type == EXPR_REFERENCE) {
+ if (expr->kind == EXPR_REFERENCE) {
declaration_t *const decl = expr->reference.declaration;
if (decl->parent_context == ¤t_function->context &&
decl->next == NULL) {
return expression;
}
}
- parser_print_error_prefix_pos(expr->base.source_position);
- fprintf(stderr, "second argument of 'va_start' must be last parameter "
- "of the current function\n");
+ errorf(expr->base.source_position, "second argument of 'va_start' must be last parameter of the current function");
return create_invalid_expression();
}
return expression;
}
+static expression_t *parse_builtin_constant(void)
+{
+ eat(T___builtin_constant_p);
+
+ expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_CONSTANT_P);
+
+ expect('(');
+ expression->builtin_constant.value = parse_assignment_expression();
+ expect(')');
+ expression->base.datatype = type_int;
+
+ return expression;
+}
+
+static expression_t *parse_builtin_prefetch(void)
+{
+ eat(T___builtin_prefetch);
+
+ expression_t *expression = allocate_expression_zero(EXPR_BUILTIN_PREFETCH);
+
+ expect('(');
+ expression->builtin_prefetch.adr = parse_assignment_expression();
+ if (token.type == ',') {
+ next_token();
+ expression->builtin_prefetch.rw = parse_assignment_expression();
+ }
+ if (token.type == ',') {
+ next_token();
+ expression->builtin_prefetch.locality = parse_assignment_expression();
+ }
+ expect(')');
+ expression->base.datatype = type_void;
+
+ return expression;
+}
+
static expression_t *parse_compare_builtin(void)
{
expression_t *expression;
return expression;
}
+static expression_t *parse_builtin_expect(void)
+{
+ eat(T___builtin_expect);
+
+ expression_t *expression
+ = allocate_expression_zero(EXPR_BINARY_BUILTIN_EXPECT);
+
+ expect('(');
+ expression->binary.left = parse_assignment_expression();
+ expect(',');
+ expression->binary.right = parse_constant_expression();
+ expect(')');
+
+ expression->base.datatype = expression->binary.left->base.datatype;
+
+ return expression;
+}
+
+static expression_t *parse_assume(void) {
+ eat(T_assume);
+
+ expression_t *expression
+ = allocate_expression_zero(EXPR_UNARY_ASSUME);
+
+ expect('(');
+ expression->unary.value = parse_assignment_expression();
+ expect(')');
+
+ expression->base.datatype = type_void;
+ return expression;
+}
+
+static expression_t *parse_alignof(void) {
+ eat(T___alignof__);
+
+ expression_t *expression
+ = allocate_expression_zero(EXPR_ALIGNOF);
+
+ expect('(');
+ expression->alignofe.type = parse_typename();
+ expect(')');
+
+ expression->base.datatype = type_size_t;
+ return expression;
+}
+
static expression_t *parse_primary_expression(void)
{
switch(token.type) {
return parse_va_start();
case T___builtin_va_arg:
return parse_va_arg();
+ case T___builtin_expect:
+ return parse_builtin_expect();
case T___builtin_nanf:
case T___builtin_alloca:
- case T___builtin_expect:
case T___builtin_va_end:
return parse_builtin_symbol();
case T___builtin_isgreater:
case T___builtin_islessgreater:
case T___builtin_isunordered:
return parse_compare_builtin();
+ case T___builtin_constant_p:
+ return parse_builtin_constant();
+ case T___builtin_prefetch:
+ return parse_builtin_prefetch();
+ case T___alignof__:
+ return parse_alignof();
+ case T_assume:
+ return parse_assume();
case '(':
return parse_brace_expression();
}
- parser_print_error_prefix();
- fprintf(stderr, "unexpected token ");
- print_token(stderr, &token);
- fprintf(stderr, "\n");
+ errorf(HERE, "unexpected token '%K'", &token);
eat_statement();
return create_invalid_expression();
array_access_expression_t *array_access
= allocate_ast_zero(sizeof(array_access[0]));
- array_access->expression.type = EXPR_ARRAY_ACCESS;
+ array_access->expression.kind = EXPR_ARRAY_ACCESS;
type_t *type_left = left->base.datatype;
type_t *type_inside = inside->base.datatype;
array_access->index = left;
array_access->flipped = true;
} else {
- parser_print_error_prefix();
- fprintf(stderr, "array access on object with non-pointer types ");
- print_type_quoted(type_left);
- fprintf(stderr, ", ");
- print_type_quoted(type_inside);
- fprintf(stderr, "\n");
+ errorf(HERE, "array access on object with non-pointer types '%T', '%T'", type_left, type_inside);
}
} else {
array_access->array_ref = left;
sizeof_expression_t *sizeof_expression
= allocate_ast_zero(sizeof(sizeof_expression[0]));
- sizeof_expression->expression.type = EXPR_SIZEOF;
+ sizeof_expression->expression.kind = EXPR_SIZEOF;
sizeof_expression->expression.datatype = type_size_t;
if(token.type == '(' && is_declaration_specifier(look_ahead(1), true)) {
type_t *type_left = type;
if(is_pointer) {
- if(type->type != TYPE_POINTER) {
- parser_print_error_prefix();
- fprintf(stderr, "left hand side of '->' is not a pointer, but ");
- print_type_quoted(orig_type);
- fputc('\n', stderr);
+ if(type->kind != TYPE_POINTER) {
+ errorf(HERE, "left hand side of '->' is not a pointer, but '%T'", orig_type);
return create_invalid_expression();
}
pointer_type_t *pointer_type = &type->pointer;
}
type_left = skip_typeref(type_left);
- if(type_left->type != TYPE_COMPOUND_STRUCT
- && type_left->type != TYPE_COMPOUND_UNION) {
- parser_print_error_prefix();
- fprintf(stderr, "request for member '%s' in something not a struct or "
- "union, but ", symbol->string);
- print_type_quoted(type_left);
- fputc('\n', stderr);
+ if(type_left->kind != TYPE_COMPOUND_STRUCT
+ && type_left->kind != TYPE_COMPOUND_UNION) {
+ errorf(HERE, "request for member '%s' in something not a struct or union, but '%T'", symbol->string, type_left);
return create_invalid_expression();
}
declaration_t *declaration = compound_type->declaration;
if(!declaration->init.is_defined) {
- parser_print_error_prefix();
- fprintf(stderr, "request for member '%s' of incomplete type ",
- symbol->string);
- print_type_quoted(type_left);
- fputc('\n', stderr);
+ errorf(HERE, "request for member '%s' of incomplete type '%T'", symbol->string, type_left);
return create_invalid_expression();
}
}
}
if(iter == NULL) {
- parser_print_error_prefix();
- print_type_quoted(type_left);
- fprintf(stderr, " has no member named '%s'\n", symbol->string);
+ errorf(HERE, "'%T' has no member names '%s'", type_left, symbol->string);
return create_invalid_expression();
}
}
}
if(function_type == NULL) {
- parser_print_error_prefix();
- fputs("called object '", stderr);
- print_expression(expression);
- fputs("' (type ", stderr);
- print_type_quoted(orig_type);
- fputs(") is not a pointer to a function\n", stderr);
+ errorf(HERE, "called object '%E' (type '%T') is not a pointer to a function", expression, orig_type);
function_type = NULL;
call->expression.datatype = NULL;
}
/* too few parameters */
if(parameter != NULL) {
- parser_print_error_prefix();
- fprintf(stderr, "too few arguments to function '");
- print_expression(expression);
- fprintf(stderr, "'\n");
+ errorf(HERE, "too few arguments to function '%E'", expression);
} else if(argument != NULL) {
/* too many parameters */
if(!function_type->variadic
&& !function_type->unspecified_parameters) {
- parser_print_error_prefix();
- fprintf(stderr, "too many arguments to function '");
- print_expression(expression);
- fprintf(stderr, "'\n");
+ errorf(HERE, "too many arguments to function '%E'", expression);
} else {
/* do default promotion */
for( ; argument != NULL; argument = argument->next) {
argument->expression
= create_implicit_cast(argument->expression, type);
}
+
+ check_format(&result->call);
}
+ } else {
+ check_format(&result->call);
}
}
{
if(!is_type_compound(type1))
return false;
- if(type1->type != type2->type)
+ if(type1->kind != type2->kind)
return false;
const compound_type_t *compound1 = &type1->compound;
return;
type_t *type = skip_typeref(orig_type);
- if(!is_type_arithmetic(type) && type->type != TYPE_POINTER) {
+ if(!is_type_arithmetic(type) && type->kind != TYPE_POINTER) {
/* TODO: improve error message */
- parser_print_error_prefix();
- fprintf(stderr, "operation needs an arithmetic or pointer type\n");
+ errorf(HERE, "operation needs an arithmetic or pointer type");
return;
}
type_t *type = skip_typeref(orig_type);
if(!is_type_arithmetic(type)) {
/* TODO: improve error message */
- parser_print_error_prefix();
- fprintf(stderr, "operation needs an arithmetic type\n");
+ errorf(HERE, "operation needs an arithmetic type");
return;
}
type_t *type = skip_typeref(orig_type);
if (!is_type_scalar(type)) {
- parse_error("operand of ! must be of scalar type\n");
+ errorf(HERE, "operand of ! must be of scalar type");
return;
}
type_t *type = skip_typeref(orig_type);
if (!is_type_integer(type)) {
- parse_error("operand of ~ must be of integer type\n");
+ errorf(HERE, "operand of ~ must be of integer type");
return;
}
type_t *type = skip_typeref(orig_type);
if(!is_type_pointer(type)) {
- parser_print_error_prefix();
- fputs("Unary '*' needs pointer or arrray type, but type ", stderr);
- print_type_quoted(orig_type);
- fputs(" given.\n", stderr);
+ errorf(HERE, "Unary '*' needs pointer or arrray type, but type '%T' given", orig_type);
return;
}
if(orig_type == NULL)
return;
- if(value->type == EXPR_REFERENCE) {
+ if(value->kind == EXPR_REFERENCE) {
reference_expression_t *reference = (reference_expression_t*) value;
declaration_t *declaration = reference->declaration;
if(declaration != NULL) {
if(!is_type_arithmetic(type_left) || !is_type_arithmetic(type_right)) {
/* TODO: improve error message */
- parser_print_error_prefix();
- fprintf(stderr, "operation needs arithmetic types\n");
+ errorf(HERE, "operation needs arithmetic types");
return;
}
if(!is_type_integer(type_left) || !is_type_integer(type_right)) {
/* TODO: improve error message */
- parser_print_error_prefix();
- fprintf(stderr, "operation needs integer types\n");
+ errorf(HERE, "operation needs integer types");
return;
}
} else if(is_type_pointer(type_right) && is_type_integer(type_left)) {
expression->expression.datatype = type_right;
} else {
- parser_print_error_prefix();
- fprintf(stderr, "invalid operands to binary + (");
- print_type_quoted(orig_type_left);
- fprintf(stderr, ", ");
- print_type_quoted(orig_type_right);
- fprintf(stderr, ")\n");
+ errorf(HERE, "invalid operands to binary + ('%T', '%T')", orig_type_left, orig_type_right);
}
}
expression->expression.datatype = type_left;
} else if(is_type_pointer(type_left) && is_type_pointer(type_right)) {
if(!pointers_compatible(type_left, type_right)) {
- parser_print_error_prefix();
- fprintf(stderr, "pointers to incompatible objects to binary - (");
- print_type_quoted(orig_type_left);
- fprintf(stderr, ", ");
- print_type_quoted(orig_type_right);
- fprintf(stderr, ")\n");
+ errorf(HERE, "pointers to incompatible objects to binary - ('%T', '%T')", orig_type_left, orig_type_right);
} else {
expression->expression.datatype = type_ptrdiff_t;
}
} else {
- parser_print_error_prefix();
- fprintf(stderr, "invalid operands to binary - (");
- print_type_quoted(orig_type_left);
- fprintf(stderr, ", ");
- print_type_quoted(orig_type_right);
- fprintf(stderr, ")\n");
+ errorf(HERE, "invalid operands to binary - ('%T', '%T')", orig_type_left, orig_type_right);
}
}
if(!is_type_arithmetic(type_left) || !is_type_arithmetic(type_right)) {
/* TODO: improve error message */
- parser_print_error_prefix();
- fprintf(stderr, "operation needs arithmetic types\n");
+ errorf(HERE, "operation needs arithmetic types");
return;
}
} else if (is_type_pointer(type_left) && is_type_integer(type_right)) {
expression->expression.datatype = type_left;
} else {
- parser_print_error_prefix();
- fputs("Incompatible types ", stderr);
- print_type_quoted(orig_type_left);
- fputs(" and ", stderr);
- print_type_quoted(orig_type_right);
- fputs(" in assignment\n", stderr);
+ errorf(HERE, "incompatible types '%T' and '%T' in assignment", orig_type_left, orig_type_right);
return;
}
}
if (!is_type_scalar(type_left) || !is_type_scalar(type_right)) {
/* TODO: improve error message */
- parser_print_error_prefix();
- fprintf(stderr, "operation needs scalar types\n");
+ errorf(HERE, "operation needs scalar types");
return;
}
/* must be a modifiable lvalue */
if (is_type_array(type_left)) {
- parser_print_error_prefix();
- fprintf(stderr, "Cannot assign to arrays ('");
- print_expression(left);
- fprintf(stderr, "')\n");
+ errorf(HERE, "cannot assign to arrays ('%E')", left);
return;
}
if(type_left->base.qualifiers & TYPE_QUALIFIER_CONST) {
- parser_print_error_prefix();
- fprintf(stderr, "assignment to readonly location '");
- print_expression(left);
- fprintf(stderr, "' (type ");
- print_type_quoted(orig_type_left);
- fprintf(stderr, ")\n");
+ errorf(HERE, "assignment to readonly location '%E' (type '%T')", left, orig_type_left);
return;
}
if(is_type_incomplete(type_left)) {
- parser_print_error_prefix();
- fprintf(stderr, "left-hand side of assignment '");
- print_expression(left);
- fprintf(stderr, "' has incomplete type ");
- print_type_quoted(orig_type_left);
- fprintf(stderr, "\n");
+ errorf(HERE, "left-hand side of assignment '%E' has incomplete type '%T'", left, orig_type_left);
return;
}
if(is_type_compound(type_left) && has_const_fields(type_left)) {
- parser_print_error_prefix();
- fprintf(stderr, "can't assign to '");
- print_expression(left);
- fprintf(stderr, "' because compound type ");
- print_type_quoted(orig_type_left);
- fprintf(stderr, " has readonly fields\n");
+ errorf(HERE, "cannot assign to '%E' because compound type '%T' has readonly fields", left, orig_type_left);
return;
}
left = parser->infix_parser(parser->infix_precedence, left);
assert(left != NULL);
- assert(left->type != EXPR_UNKNOWN);
+ assert(left->kind != EXPR_UNKNOWN);
left->base.source_position = source_position;
}
expression_parser_function_t *entry = &expression_parsers[token_type];
if(entry->parser != NULL) {
- fprintf(stderr, "for token ");
- print_token_type(stderr, (token_type_t) token_type);
- fprintf(stderr, "\n");
+ diagnosticf("for token '%k'\n", (token_type_t)token_type);
panic("trying to register multiple expression parsers for a token");
}
entry->parser = parser;
expression_parser_function_t *entry = &expression_parsers[token_type];
if(entry->infix_parser != NULL) {
- fprintf(stderr, "for token ");
- print_token_type(stderr, (token_type_t) token_type);
- fprintf(stderr, "\n");
+ diagnosticf("for token '%k'\n", (token_type_t)token_type);
panic("trying to register multiple infix expression parsers for a "
"token");
}
/* if source position is already set then the label is defined twice,
* otherwise it was just mentioned in a goto so far */
if(label->source_position.input_name != NULL) {
- parser_print_error_prefix();
- fprintf(stderr, "duplicate label '%s'\n", symbol->string);
- parser_print_error_prefix_pos(label->source_position);
- fprintf(stderr, "previous definition of '%s' was here\n",
- symbol->string);
+ errorf(HERE, "duplicate label '%s'\n", symbol->string);
+ errorf(label->source_position, "previous definition of '%s' was here\n", symbol->string);
} else {
label->source_position = token.source_position;
}
label_statement_t *label_statement = allocate_ast_zero(sizeof(label[0]));
- label_statement->statement.type = STATEMENT_LABEL;
+ label_statement->statement.kind = STATEMENT_LABEL;
label_statement->statement.source_position = token.source_position;
label_statement->label = label;
expect(':');
if(token.type == '}') {
- parse_error("label at end of compound statement");
+ /* TODO only warn? */
+ errorf(HERE, "label at end of compound statement");
return (statement_t*) label_statement;
} else {
label_statement->label_statement = parse_statement();
eat(T_if);
if_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->statement.type = STATEMENT_IF;
+ statement->statement.kind = STATEMENT_IF;
statement->statement.source_position = token.source_position;
expect('(');
eat(T_switch);
switch_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->statement.type = STATEMENT_SWITCH;
+ statement->statement.kind = STATEMENT_SWITCH;
statement->statement.source_position = token.source_position;
expect('(');
eat(T_while);
while_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->statement.type = STATEMENT_WHILE;
+ statement->statement.kind = STATEMENT_WHILE;
statement->statement.source_position = token.source_position;
expect('(');
eat(T_do);
do_while_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->statement.type = STATEMENT_DO_WHILE;
+ statement->statement.kind = STATEMENT_DO_WHILE;
statement->statement.source_position = token.source_position;
statement->body = parse_statement();
eat(T_for);
for_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->statement.type = STATEMENT_FOR;
+ statement->statement.kind = STATEMENT_FOR;
statement->statement.source_position = token.source_position;
expect('(');
goto_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->statement.type = STATEMENT_GOTO;
+ statement->statement.kind = STATEMENT_GOTO;
statement->statement.source_position = token.source_position;
statement->label = label;
expect(';');
statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->type = STATEMENT_CONTINUE;
+ statement->kind = STATEMENT_CONTINUE;
statement->base.source_position = token.source_position;
return statement;
expect(';');
statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->type = STATEMENT_BREAK;
+ statement->kind = STATEMENT_BREAK;
statement->base.source_position = token.source_position;
return statement;
return_statement_t *statement = allocate_ast_zero(sizeof(statement[0]));
- statement->statement.type = STATEMENT_RETURN;
+ statement->statement.kind = STATEMENT_RETURN;
statement->statement.source_position = token.source_position;
assert(is_type_function(current_function->type));
if(is_type_atomic(return_type, ATOMIC_TYPE_VOID)
&& !is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) {
- parse_warning("'return' with a value, in function returning void");
+ warningf(HERE, "'return' with a value, in function returning void");
return_value = NULL;
} else {
if(return_type != NULL) {
}
} else {
if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
- parse_warning("'return' without value, in function returning "
- "non-void");
+ warningf(HERE, "'return' without value, in function returning non-void");
}
}
statement->return_value = return_value;
{
compound_statement_t *compound_statement
= allocate_ast_zero(sizeof(compound_statement[0]));
- compound_statement->statement.type = STATEMENT_COMPOUND;
+ compound_statement->statement.kind = STATEMENT_COMPOUND;
compound_statement->statement.source_position = token.source_position;
eat('{');
}
if(token.type != '}') {
- parser_print_error_prefix_pos(
- compound_statement->statement.source_position);
- fprintf(stderr, "end of file while looking for closing '}'\n");
+ errorf(compound_statement->statement.source_position, "end of file while looking for closing '}'");
}
next_token();
static void initialize_builtins(void)
{
- type_wchar_t = make_global_typedef("__WCHAR_TYPE__", type_int);
- type_wchar_t_ptr = make_pointer_type(type_wchar_t, TYPE_QUALIFIER_NONE);
- type_size_t = make_global_typedef("__SIZE_TYPE__",
- make_atomic_type(ATOMIC_TYPE_ULONG, TYPE_QUALIFIER_NONE));
- type_ptrdiff_t = make_global_typedef("__PTRDIFF_TYPE__",
- make_atomic_type(ATOMIC_TYPE_LONG, TYPE_QUALIFIER_NONE));
+ type_intmax_t = make_global_typedef("__intmax_t__", type_long_long);
+ type_size_t = make_global_typedef("__SIZE_TYPE__", type_unsigned_long);
+ type_ssize_t = make_global_typedef("__SSIZE_TYPE__", type_long);
+ type_ptrdiff_t = make_global_typedef("__PTRDIFF_TYPE__", type_long);
+ type_uintmax_t = make_global_typedef("__uintmax_t__", type_unsigned_long_long);
+ type_uptrdiff_t = make_global_typedef("__UPTRDIFF_TYPE__", type_unsigned_long);
+ type_wchar_t = make_global_typedef("__WCHAR_TYPE__", type_int);
+ type_wint_t = make_global_typedef("__WINT_TYPE__", type_int);
+
+ type_intmax_t_ptr = make_pointer_type(type_intmax_t, TYPE_QUALIFIER_NONE);
+ type_ptrdiff_t_ptr = make_pointer_type(type_ptrdiff_t, TYPE_QUALIFIER_NONE);
+ type_ssize_t_ptr = make_pointer_type(type_ssize_t, TYPE_QUALIFIER_NONE);
+ type_wchar_t_ptr = make_pointer_type(type_wchar_t, TYPE_QUALIFIER_NONE);
}
static translation_unit_t *parse_translation_unit(void)
init_expression_parsers();
obstack_init(&temp_obst);
- type_int = make_atomic_type(ATOMIC_TYPE_INT, TYPE_QUALIFIER_NONE);
- type_long_double = make_atomic_type(ATOMIC_TYPE_LONG_DOUBLE,
- TYPE_QUALIFIER_NONE);
- type_double = make_atomic_type(ATOMIC_TYPE_DOUBLE,
- TYPE_QUALIFIER_NONE);
- type_float = make_atomic_type(ATOMIC_TYPE_FLOAT, TYPE_QUALIFIER_NONE);
- type_char = make_atomic_type(ATOMIC_TYPE_CHAR, TYPE_QUALIFIER_NONE);
- type_void = make_atomic_type(ATOMIC_TYPE_VOID, TYPE_QUALIFIER_NONE);
- type_void_ptr = make_pointer_type(type_void, TYPE_QUALIFIER_NONE);
- type_string = make_pointer_type(type_char, TYPE_QUALIFIER_NONE);
-
symbol_t *const va_list_sym = symbol_table_insert("__builtin_va_list");
type_valist = create_builtin_type(va_list_sym, type_void_ptr);
}