add an is_constant_expression, only try to fold expressions that are really constant...
[cparser] / parser.c
index a92c7e7..48ca810 100644 (file)
--- 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;
 }
@@ -4924,6 +4948,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);