Repair semantic of return-statements for C and implement them for C++.
authorChristoph Mallon <christoph.mallon@gmx.de>
Wed, 3 Dec 2008 21:00:43 +0000 (21:00 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Wed, 3 Dec 2008 21:00:43 +0000 (21:00 +0000)
[r24274]

parser.c

index dde9319..d23d7bf 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -10370,34 +10370,54 @@ static statement_t *parse_return(void)
        assert(is_type_function(func_type));
        type_t *const return_type = skip_typeref(func_type->function.return_type);
 
+       source_position_t const *const pos = &statement->base.source_position;
        if (return_value != NULL) {
                type_t *return_value_type = skip_typeref(return_value->base.type);
 
-               if (is_type_atomic(return_type,        ATOMIC_TYPE_VOID) &&
-                               !is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) {
-                       if (warning.other) {
-                               warningf(&statement->base.source_position,
-                                               "'return' with a value, in function returning void");
+               if (is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
+                       if (is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) {
+                               /* ISO/IEC 14882:1998(E) §6.6.3:2 */
+                               /* Only warn in C mode, because GCC does the same */
+                               if (c_mode & _CXX || strict_mode) {
+                                       errorf(pos,
+                                                       "'return' with a value, in function returning 'void'");
+                               } else if (warning.other) {
+                                       warningf(pos,
+                                                       "'return' with a value, in function returning 'void'");
+                               }
+                       } else if (!(c_mode & _CXX)) { /* ISO/IEC 14882:1998(E) §6.6.3:3 */
+                               /* Only warn in C mode, because GCC does the same */
+                               if (strict_mode) {
+                                       errorf(pos,
+                                                       "'return' with expression in function return 'void'");
+                               } else if (warning.other) {
+                                       warningf(pos,
+                                                       "'return' with expression in function return 'void'");
+                               }
                        }
-                       return_value = NULL;
                } else {
                        assign_error_t error = semantic_assign(return_type, return_value);
                        report_assign_error(error, return_type, return_value, "'return'",
-                                           &statement->base.source_position);
-                       return_value = create_implicit_cast(return_value, return_type);
+                                       pos);
                }
+               return_value = create_implicit_cast(return_value, return_type);
                /* check for returning address of a local var */
                if (warning.other && return_value != NULL
                                && return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) {
                        const expression_t *expression = return_value->unary.value;
                        if (expression_is_local_variable(expression)) {
-                               warningf(&statement->base.source_position,
-                                        "function returns address of local variable");
+                               warningf(pos, "function returns address of local variable");
                        }
                }
        } else if (warning.other && !is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
-               warningf(&statement->base.source_position,
-                               "'return' without value, in function returning non-void");
+               /* ISO/IEC 14882:1998(E) §6.6.3:3 */
+               if (c_mode & _CXX || strict_mode) {
+                       errorf(pos,
+                                       "'return' without value, in function returning non-void");
+               } else {
+                       warningf(pos,
+                                       "'return' without value, in function returning non-void");
+               }
        }
        statement->returns.value = return_value;