X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=18e428543a49a905b912f20786adb462cd27c0b2;hb=2f4d5b48891698c9c271382559f5e0380f5431b4;hp=a92c7e74b85ad8e68aeb53ae43f9e96a7483a776;hpb=26b0ae39a6c0f1b157b62ac9f228f3c3e0e2407c;p=cparser diff --git a/parser.c b/parser.c index a92c7e7..18e4285 100644 --- a/parser.c +++ b/parser.c @@ -30,6 +30,7 @@ struct declaration_specifiers_t { source_position_t source_position; unsigned char storage_class; bool is_inline; + decl_modifiers_t decl_modifiers; type_t *type; }; @@ -87,7 +88,8 @@ static void semantic_comparison(binary_expression_t *expression); case T_const: \ case T_restrict: \ case T_volatile: \ - case T_inline: + case T_inline: \ + case T_forceinline: #ifdef PROVIDE_COMPLEX #define COMPLEX_SPECIFIERS \ @@ -592,8 +594,11 @@ static declaration_t *stack_push(stack_entry_t **stack_ptr, print_type_quoted(previous_declaration->type); fputc('\n', stderr); } else { - unsigned old_storage_class = previous_declaration->storage_class; - unsigned new_storage_class = declaration->storage_class; + unsigned old_storage_class = previous_declaration->storage_class; + unsigned new_storage_class = declaration->storage_class; + type_t *type = previous_declaration->type; + type = skip_typeref(type); + if (current_function == NULL) { if (old_storage_class != STORAGE_CLASS_STATIC && new_storage_class == STORAGE_CLASS_STATIC) { @@ -609,7 +614,7 @@ static declaration_t *stack_push(stack_entry_t **stack_ptr, if (new_storage_class == STORAGE_CLASS_NONE) { previous_declaration->storage_class = STORAGE_CLASS_NONE; } - } else { + } else if(!is_type_function(type)) { parser_print_warning_prefix_pos(declaration->source_position); fprintf(stderr, "redundant declaration for '%s'\n", symbol->string); @@ -949,7 +954,16 @@ incompatible_assign_types: 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)) { + parser_print_error_prefix_pos(result->base.source_position); + fprintf(stderr, "expression '"); + print_expression(result); + fprintf(stderr, "' is not constant\n"); + } + + return result; } static expression_t *parse_assignment_expression(void) @@ -1735,6 +1749,10 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) 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; @@ -2016,7 +2034,7 @@ static declaration_t *parse_parameter(void) parse_declaration_specifiers(&specifiers); - declaration_t *declaration = parse_declarator(&specifiers, true); + declaration_t *declaration = parse_declarator(&specifiers, /*may_be_abstract=*/true); semantic_parameter(declaration); @@ -2352,10 +2370,11 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, 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); @@ -2562,7 +2581,7 @@ static void parse_declaration_rest(declaration_t *ndeclaration, break; eat(','); - ndeclaration = parse_declarator(specifiers, false); + ndeclaration = parse_declarator(specifiers, /*may_be_abstract=*/false); } expect_void(';'); } @@ -2585,7 +2604,7 @@ static void parse_declaration(parsed_declaration_func finished_declaration) 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); } } @@ -2593,7 +2612,8 @@ static void parse_declaration(parsed_declaration_func finished_declaration) static void parse_kr_declaration_list(declaration_t *declaration) { type_t *type = skip_typeref(declaration->type); - assert(is_type_function(type)); + if(!is_type_function(type)) + return; if(!type->function.kr_style_parameters) return; @@ -2683,7 +2703,7 @@ static void parse_external_declaration(void) } /* 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 == ';') { @@ -2778,7 +2798,7 @@ static void parse_struct_declarators(const declaration_specifiers_t *specifiers) 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 */ @@ -3193,7 +3213,7 @@ static expression_t *parse_function_keyword(void) expression->expression.type = EXPR_FUNCTION; expression->expression.datatype = type_string; - expression->value = "TODO: FUNCTION"; + expression->value = current_function->symbol->string; return (expression_t*) expression; } @@ -3203,12 +3223,16 @@ static expression_t *parse_pretty_function_keyword(void) eat(T___PRETTY_FUNCTION__); /* TODO */ + if (current_function == NULL) { + parse_error("'__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.datatype = type_string; - expression->value = "TODO: PRETTY FUNCTION"; + expression->value = current_function->symbol->string; return (expression_t*) expression; } @@ -3389,6 +3413,24 @@ static expression_t *parse_compare_builtin(void) 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_primary_expression(void) { switch(token.type) { @@ -3413,9 +3455,10 @@ static expression_t *parse_primary_expression(void) 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: @@ -4924,6 +4967,8 @@ static statement_t *parse_return(void) if(return_type == NULL) return (statement_t*) statement; + if(return_value != NULL && return_value->base.datatype == NULL) + return (statement_t*) statement; return_type = skip_typeref(return_type);