typedef struct {
declaration_t *old_declaration;
symbol_t *symbol;
- unsigned short namespace;
+ unsigned short namespc;
} stack_entry_t;
static token_t token;
return declaration->type == previous->type;
}
-static declaration_t *get_declaration(symbol_t *symbol, namespace_t namespace)
+static declaration_t *get_declaration(symbol_t *symbol, namespace_t namespc)
{
declaration_t *declaration = symbol->declaration;
for( ; declaration != NULL; declaration = declaration->symbol_next) {
- if(declaration->namespace == namespace)
+ if(declaration->namespc == namespc)
return declaration;
}
return NULL;
}
-static const char *get_namespace_prefix(namespace_t namespace)
+static const char *get_namespace_prefix(namespace_t namespc)
{
- switch(namespace) {
+ switch(namespc) {
case NAMESPACE_NORMAL:
return "";
case NAMESPACE_UNION:
context_t *parent_context)
{
symbol_t *symbol = declaration->symbol;
- namespace_t namespace = (namespace_t)declaration->namespace;
+ namespace_t namespc = (namespace_t)declaration->namespc;
/* a declaration should be only pushed once */
assert(declaration->parent_context == NULL);
declaration->parent_context = parent_context;
- declaration_t *previous_declaration = get_declaration(symbol, namespace);
+ declaration_t *previous_declaration = get_declaration(symbol, namespc);
assert(declaration != previous_declaration);
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(namespace), symbol->string);
+ get_namespace_prefix(namespc), symbol->string);
print_type_quoted(declaration->type);
fputc('\n', stderr);
parser_print_error_prefix_pos(
stack_entry_t entry;
entry.symbol = symbol;
entry.old_declaration = symbol->declaration;
- entry.namespace = namespace;
+ entry.namespc = namespc;
ARR_APP1(stack_entry_t, *stack_ptr, entry);
/* replace/add declaration into declaration list of the symbol */
declaration_t *iter = symbol->declaration;
for( ; iter != NULL; iter_last = iter, iter = iter->symbol_next) {
/* replace an entry? */
- if(iter->namespace == namespace) {
+ if(iter->namespc == namespc) {
if(iter_last == NULL) {
symbol->declaration = declaration;
} else {
declaration_t *old_declaration = entry->old_declaration;
symbol_t *symbol = entry->symbol;
- namespace_t namespace = (namespace_t)entry->namespace;
+ namespace_t namespc = (namespace_t)entry->namespc;
/* replace/remove declaration */
declaration_t *declaration = symbol->declaration;
assert(declaration != NULL);
- if(declaration->namespace == namespace) {
+ if(declaration->namespc == namespc) {
if(old_declaration == NULL) {
symbol->declaration = declaration->symbol_next;
} else {
declaration_t *iter = declaration->symbol_next;
for( ; iter != NULL; iter_last = iter, iter = iter->symbol_next) {
/* replace an entry? */
- if(iter->namespace == namespace) {
+ if(iter->namespc == namespc) {
assert(iter_last != NULL);
iter_last->symbol_next = old_declaration;
old_declaration->symbol_next = iter->symbol_next;
panic("casting of non-atomic types not implemented yet");
}
- type_error_incompatible("can't implicitely cast types",
+ type_error_incompatible("can't implicitly cast types",
expression->source_position,
source_type, dest_type);
return expression;
type_t *const type_left = skip_typeref(orig_type_left);
type_t *const type_right = skip_typeref(orig_type_right);
- if(type_left == type_right) {
- /* fine */
- } else if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) ||
- (type_left->type == TYPE_POINTER && is_null_expression(*right)) ||
- (type_left->type == TYPE_POINTER && type_right->type == TYPE_POINTER)) {
+ if (type_left == type_right) {
+ return;
+ }
+
+ if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) ||
+ (type_left->type == TYPE_POINTER && is_null_expression(*right)) ||
+ (type_left->type == TYPE_POINTER && type_right->type == TYPE_POINTER)) {
*right = create_implicit_cast(*right, type_left);
- } else {
- /* TODO: improve error message */
- parser_print_error_prefix();
- fprintf(stderr, "incompatible types in %s\n", context);
- parser_print_error_prefix();
- print_type_quoted(type_left);
- fputs(" <- ", stderr);
- print_type_quoted(type_right);
- fputs("\n", stderr);
+ return;
}
+ if (type_left->type == TYPE_POINTER) {
+ switch (type_right->type) {
+ case TYPE_FUNCTION: {
+ pointer_type_t *const ptr_type = (pointer_type_t*)type_left;
+ if (ptr_type->points_to == type_right) {
+ return;
+ }
+ break;
+ }
+
+ case TYPE_ARRAY: {
+ pointer_type_t *const ptr_type = (pointer_type_t*)type_left;
+ array_type_t *const arr_type = (array_type_t*)type_right;
+ if (ptr_type->points_to == arr_type->element_type) {
+ return;
+ }
+ break;
+ }
+
+ default: break;
+ }
+ }
+
+ /* TODO: improve error message */
+ parser_print_error_prefix();
+ fprintf(stderr, "incompatible types in %s\n", context);
+ parser_print_error_prefix();
+ print_type_quoted(type_left);
+ fputs(" <- ", stderr);
+ print_type_quoted(type_right);
+ fputs("\n", stderr);
}
static expression_t *parse_constant_expression(void)
symbol_t *symbol = NULL;
declaration_t *declaration = NULL;
+ if (token.type == T___attribute__) {
+ /* TODO */
+ parse_attributes();
+ }
+
if(token.type == T_IDENTIFIER) {
symbol = token.v.symbol;
next_token();
declaration = allocate_type_zero(sizeof(declaration[0]));
if(is_struct) {
- declaration->namespace = NAMESPACE_STRUCT;
+ declaration->namespc = NAMESPACE_STRUCT;
} else {
- declaration->namespace = NAMESPACE_UNION;
+ declaration->namespc = NAMESPACE_UNION;
}
declaration->source_position = token.source_position;
declaration->symbol = symbol;
if(declaration == NULL) {
declaration = allocate_type_zero(sizeof(declaration[0]));
- declaration->namespace = NAMESPACE_ENUM;
+ declaration->namespc = NAMESPACE_ENUM;
declaration->source_position = token.source_position;
declaration->symbol = symbol;
}
*/
static bool is_typedef_symbol(symbol_t *symbol)
{
- declaration_t *declaration = get_declaration(symbol, NAMESPACE_NORMAL);
- if(declaration == NULL
- || declaration->storage_class != STORAGE_CLASS_TYPEDEF)
- return false;
-
- return true;
+ const declaration_t *const declaration =
+ get_declaration(symbol, NAMESPACE_NORMAL);
+ return
+ declaration != NULL &&
+ declaration->storage_class == STORAGE_CLASS_TYPEDEF;
}
static type_t *parse_typeof(void)
parse_error("typedef not allowed in parameter list");
}
+ /* Array as last part of a paramter type is just syntactic sugar. Turn it
+ * into a pointer */
+ if (declaration->type->type == TYPE_ARRAY) {
+ const array_type_t *const arr_type =
+ (const array_type_t*)declaration->type;
+ declaration->type =
+ make_pointer_type(arr_type->element_type, TYPE_QUALIFIER_NONE);
+ }
+
return declaration;
}
if(declaration == NULL) {
#ifndef STRICT_C99
- /* an implicitely defined function */
+ /* an implicitly defined function */
if(token.type == '(') {
parser_print_prefix_pos(token.source_position);
fprintf(stderr, "warning: implicit declaration of function '%s'\n",
if(iter == NULL) {
parser_print_error_prefix();
print_type_quoted(type_left);
- fprintf(stderr, " has no memeber named '%s'\n", symbol->string);
+ fprintf(stderr, " has no member named '%s'\n", symbol->string);
return make_invalid_expression();
}
return parse_sub_expression(precedence);
}
+static expression_t *parse_builtin_classify_type(const unsigned precedence)
+{
+ eat(T___builtin_classify_type);
+
+ classify_type_expression_t *const classify_type_expr =
+ allocate_ast_zero(sizeof(classify_type_expr[0]));
+ classify_type_expr->expression.type = EXPR_CLASSIFY_TYPE;
+ classify_type_expr->expression.datatype = type_int;
+
+ expect('(');
+ expression_t *const expression = parse_sub_expression(precedence);
+ expect(')');
+ classify_type_expr->type_expression = expression;
+
+ return (expression_t*)classify_type_expr;
+}
+
static void semantic_incdec(unary_expression_t *expression)
{
type_t *orig_type = expression->value->datatype;
expression->expression.datatype = orig_type;
}
+static void semantic_unexpr_scalar(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if (!is_type_scalar(type)) {
+ parse_error("operand of ! must be of scalar type\n");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
+static void semantic_unexpr_integer(unary_expression_t *expression)
+{
+ type_t *orig_type = expression->value->datatype;
+ if(orig_type == NULL)
+ return;
+
+ type_t *type = skip_typeref(orig_type);
+ if (!is_type_integer(type)) {
+ parse_error("operand of ~ must be of integer type\n");
+ return;
+ }
+
+ expression->expression.datatype = orig_type;
+}
+
static void semantic_dereference(unary_expression_t *expression)
{
type_t *orig_type = expression->value->datatype;
CREATE_UNARY_EXPRESSION_PARSER('-', UNEXPR_NEGATE, semantic_unexpr_arithmetic)
CREATE_UNARY_EXPRESSION_PARSER('+', UNEXPR_PLUS, semantic_unexpr_arithmetic)
-CREATE_UNARY_EXPRESSION_PARSER('!', UNEXPR_NOT, semantic_unexpr_arithmetic)
+CREATE_UNARY_EXPRESSION_PARSER('!', UNEXPR_NOT, semantic_unexpr_scalar)
CREATE_UNARY_EXPRESSION_PARSER('*', UNEXPR_DEREFERENCE, semantic_dereference)
CREATE_UNARY_EXPRESSION_PARSER('&', UNEXPR_TAKE_ADDRESS, semantic_take_addr)
CREATE_UNARY_EXPRESSION_PARSER('~', UNEXPR_BITWISE_NEGATE,
- semantic_unexpr_arithmetic)
+ semantic_unexpr_integer)
CREATE_UNARY_EXPRESSION_PARSER(T_PLUSPLUS, UNEXPR_PREFIX_INCREMENT,
semantic_incdec)
CREATE_UNARY_EXPRESSION_PARSER(T_MINUSMINUS, UNEXPR_PREFIX_DECREMENT,
expression->expression.datatype = type_left;
} else if(type_right->type == TYPE_POINTER && is_type_integer(type_left)) {
expression->expression.datatype = type_right;
+ } else if (type_left->type == TYPE_ARRAY && is_type_integer(type_right)) {
+ const array_type_t *const arr_type = (const array_type_t*)type_left;
+ expression->expression.datatype =
+ make_pointer_type(arr_type->element_type, TYPE_QUALIFIER_NONE);
+ } else if (type_right->type == TYPE_ARRAY && is_type_integer(type_left)) {
+ const array_type_t *const arr_type = (const array_type_t*)type_right;
+ expression->expression.datatype =
+ make_pointer_type(arr_type->element_type, TYPE_QUALIFIER_NONE);
} else {
parser_print_error_prefix();
fprintf(stderr, "invalid operands to binary + (");
register_expression_parser(parse_UNEXPR_PREFIX_DECREMENT, T_MINUSMINUS, 25);
register_expression_parser(parse_sizeof, T_sizeof, 25);
register_expression_parser(parse_extension, T___extension__, 25);
+ register_expression_parser(parse_builtin_classify_type,
+ T___builtin_classify_type, 25);
}
/* otherwise we need to create a new one */
declaration_t *declaration = allocate_ast_zero(sizeof(declaration[0]));
- declaration->namespace = NAMESPACE_LABEL;
+ declaration->namespc = NAMESPACE_LABEL;
declaration->symbol = symbol;
label_push(declaration);