X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fstmt.c;h=1f5a61ea4b785a00c424ff647accdb2debf0bfd7;hb=ed2767e65f05b853eda1b071938062126de6f517;hp=67742113cdda5532c7e9540d6d3a48042118702f;hpb=9df7321d90332eeb24b3d72639577f801f30a010;p=cc65 diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index 67742113c..1f5a61ea4 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2004 Ullrich von Bassewitz */ -/* Römerstraße 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2009, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -57,9 +57,9 @@ #include "pragma.h" #include "scanner.h" #include "stackptr.h" +#include "stmt.h" #include "swstmt.h" #include "symtab.h" -#include "stmt.h" #include "testexpr.h" #include "typeconv.h" @@ -71,6 +71,19 @@ +static void CheckLabelWithoutStatement (void) +/* Called from Statement() after a label definition. Will check for a + * following closing curly brace. This means that a label is not followed + * by a statement which is required by the standard. Output an error if so. + */ +{ + if (CurTok.Tok == TOK_RCURLY) { + Error ("Label at end of compound statement"); + } +} + + + static void CheckTok (token_t Tok, const char* Msg, int* PendingToken) /* Helper function for Statement. Will check for Tok and print Msg if not * found. If PendingToken is NULL, it will the skip the token, otherwise @@ -78,7 +91,7 @@ static void CheckTok (token_t Tok, const char* Msg, int* PendingToken) */ { if (CurTok.Tok != Tok) { - Error (Msg); + Error ("%s", Msg); } else if (PendingToken) { *PendingToken = 1; } else { @@ -279,17 +292,16 @@ static void ReturnStatement (void) NextToken (); if (CurTok.Tok != TOK_SEMI) { - /* Check if the function has a return value declared */ - if (F_HasVoidReturn (CurrentFunc)) { - Error ("Returning a value in function with return type void"); - } - /* Evaluate the return expression */ hie0 (&Expr); - /* Ignore the return expression if the function returns void */ - if (!F_HasVoidReturn (CurrentFunc)) { - + /* If we return something in a void function, print an error and + * ignore the value. Otherwise convert the value to the type of the + * return. + */ + if (F_HasVoidReturn (CurrentFunc)) { + Error ("Returning a value in function with return type void"); + } else { /* Convert the return value to the type of the function result */ TypeConversion (&Expr, F_GetReturnType (CurrentFunc)); @@ -301,6 +313,9 @@ static void ReturnStatement (void) Error ("Function `%s' must return a value", F_GetFuncName (CurrentFunc)); } + /* Mark the function as having a return statement */ + F_ReturnFound (CurrentFunc); + /* Cleanup the stack in case we're inside a block with locals */ g_space (StackPtr - F_GetTopLevelSP (CurrentFunc)); @@ -529,90 +544,100 @@ int Statement (int* PendingToken) *PendingToken = 0; } - /* Check for a label */ - if (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) { - - /* Special handling for a label */ + /* Check for a label. A label is always part of a statement, it does not + * replace one. + */ + while (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) { + /* Handle the label */ DoLabel (); + CheckLabelWithoutStatement (); + } - } else { + switch (CurTok.Tok) { - switch (CurTok.Tok) { - - case TOK_LCURLY: - NextToken (); - GotBreak = CompoundStatement (); - CheckTok (TOK_RCURLY, "`{' expected", PendingToken); - return GotBreak; - - case TOK_IF: - return IfStatement (); - - case TOK_WHILE: - WhileStatement (); - break; - - case TOK_DO: - DoStatement (); - break; - - case TOK_SWITCH: - SwitchStatement (); - break; - - case TOK_RETURN: - ReturnStatement (); - CheckSemi (PendingToken); - return 1; - - case TOK_BREAK: - BreakStatement (); - CheckSemi (PendingToken); - return 1; - - case TOK_CONTINUE: - ContinueStatement (); - CheckSemi (PendingToken); - return 1; - - case TOK_FOR: - ForStatement (); - break; - - case TOK_GOTO: - GotoStatement (); - CheckSemi (PendingToken); - return 1; - - case TOK_SEMI: - /* Ignore it */ - CheckSemi (PendingToken); - break; - - case TOK_PRAGMA: - DoPragma (); - break; - - default: - /* Remember the current code position */ - GetCodePos (&Start); - /* Actual statement */ - ExprWithCheck (hie0, &Expr); - /* Load the result only if it is an lvalue and the type is - * marked as volatile. Otherwise the load is useless. - */ - if (ED_IsLVal (&Expr) && IsQualVolatile (Expr.Type)) { - LoadExpr (CF_NONE, &Expr); - } - /* If the statement didn't generate code, and is not of type - * void, emit a warning. - */ - GetCodePos (&End); - if (CodeRangeIsEmpty (&Start, &End) && !IsTypeVoid (Expr.Type)) { - Warning ("Statement has no effect"); - } - CheckSemi (PendingToken); - } + case TOK_LCURLY: + NextToken (); + GotBreak = CompoundStatement (); + CheckTok (TOK_RCURLY, "`{' expected", PendingToken); + return GotBreak; + + case TOK_IF: + return IfStatement (); + + case TOK_WHILE: + WhileStatement (); + break; + + case TOK_DO: + DoStatement (); + break; + + case TOK_SWITCH: + SwitchStatement (); + break; + + case TOK_RETURN: + ReturnStatement (); + CheckSemi (PendingToken); + return 1; + + case TOK_BREAK: + BreakStatement (); + CheckSemi (PendingToken); + return 1; + + case TOK_CONTINUE: + ContinueStatement (); + CheckSemi (PendingToken); + return 1; + + case TOK_FOR: + ForStatement (); + break; + + case TOK_GOTO: + GotoStatement (); + CheckSemi (PendingToken); + return 1; + + case TOK_SEMI: + /* Ignore it */ + CheckSemi (PendingToken); + break; + + case TOK_PRAGMA: + DoPragma (); + break; + + case TOK_CASE: + CaseLabel (); + CheckLabelWithoutStatement (); + break; + + case TOK_DEFAULT: + DefaultLabel (); + CheckLabelWithoutStatement (); + break; + + default: + /* Remember the current code position */ + GetCodePos (&Start); + /* Actual statement */ + ExprWithCheck (hie0, &Expr); + /* Load the result only if it is an lvalue and the type is + * marked as volatile. Otherwise the load is useless. + */ + if (ED_IsLVal (&Expr) && IsQualVolatile (Expr.Type)) { + LoadExpr (CF_NONE, &Expr); + } + /* If the statement didn't generate code, and is not of type + * void, emit a warning. + */ + GetCodePos (&End); + if (CodeRangeIsEmpty (&Start, &End) && !IsTypeVoid (Expr.Type)) { + Warning ("Statement has no effect"); + } + CheckSemi (PendingToken); } return 0; }