Allow __fastcall__ for C function. Contrary to the name, this is a size
optimization for C functions. The last parameter is not pushed onto the stack by the caller but in the function entry code, so there is no speed but a size gain. git-svn-id: svn://svn.cc65.org/cc65/trunk@645 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -648,6 +648,17 @@ int IsFastCallFunc (const type* T)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int IsEllipsisFunc (const type* T)
|
||||||
|
/* Return true if this is a function type with variable parameter list */
|
||||||
|
{
|
||||||
|
FuncDesc* F;
|
||||||
|
CHECK (IsTypeFunc (T));
|
||||||
|
F = DecodePtr (T+1);
|
||||||
|
return (F->Flags & FD_ELLIPSIS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int IsTypeFuncPtr (const type* T)
|
int IsTypeFuncPtr (const type* T)
|
||||||
/* Return true if this is a function pointer */
|
/* Return true if this is a function pointer */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -283,6 +283,9 @@ int IsQualVolatile (const type* T) attribute ((const));
|
|||||||
int IsFastCallFunc (const type* T) attribute ((const));
|
int IsFastCallFunc (const type* T) attribute ((const));
|
||||||
/* Return true if this is a function type with __fastcall__ calling conventions */
|
/* Return true if this is a function type with __fastcall__ calling conventions */
|
||||||
|
|
||||||
|
int IsEllipsisFunc (const type* T) attribute ((const));
|
||||||
|
/* Return true if this is a function type with variable parameter list */
|
||||||
|
|
||||||
int IsTypeFuncPtr (const type* T) attribute ((const));
|
int IsTypeFuncPtr (const type* T) attribute ((const));
|
||||||
/* Return true if this is a function pointer */
|
/* Return true if this is a function pointer */
|
||||||
|
|
||||||
|
|||||||
@@ -775,6 +775,8 @@ static void Decl (Declaration* D, unsigned Mode)
|
|||||||
/* Set the fastcall flag */
|
/* Set the fastcall flag */
|
||||||
if (!IsTypeFunc (T)) {
|
if (!IsTypeFunc (T)) {
|
||||||
Error ("__fastcall__ modifier applied to non function");
|
Error ("__fastcall__ modifier applied to non function");
|
||||||
|
} else if (IsEllipsisFunc (T)) {
|
||||||
|
Error ("Cannot apply __fastcall__ to functions with variable parameter list");
|
||||||
} else {
|
} else {
|
||||||
FuncDesc* F = DecodePtr (T+1);
|
FuncDesc* F = DecodePtr (T+1);
|
||||||
F->Flags |= FD_FASTCALL;
|
F->Flags |= FD_FASTCALL;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "check.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
@@ -115,6 +116,14 @@ const char* GetFuncName (const Function* F)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned GetParamCount (const Function* F)
|
||||||
|
/* Return the parameter count for the current function */
|
||||||
|
{
|
||||||
|
return F->Desc->ParamCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned GetParamSize (const Function* F)
|
unsigned GetParamSize (const Function* F)
|
||||||
/* Return the parameter size for the current function */
|
/* Return the parameter size for the current function */
|
||||||
{
|
{
|
||||||
@@ -213,11 +222,6 @@ void NewFunc (SymEntry* Func)
|
|||||||
/* Function body now defined */
|
/* Function body now defined */
|
||||||
Func->Flags |= SC_DEF;
|
Func->Flags |= SC_DEF;
|
||||||
|
|
||||||
/* C functions cannot currently have __fastcall__ calling conventions */
|
|
||||||
if (IsFastCallFunc (Func->Type)) {
|
|
||||||
Error ("__fastcall__ is not allowed for C functions");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Need a starting curly brace */
|
/* Need a starting curly brace */
|
||||||
if (curtok != TOK_LCURLY) {
|
if (curtok != TOK_LCURLY) {
|
||||||
Error ("`{' expected");
|
Error ("`{' expected");
|
||||||
@@ -230,7 +234,25 @@ void NewFunc (SymEntry* Func)
|
|||||||
g_usecode ();
|
g_usecode ();
|
||||||
g_defgloblabel (Func->Name);
|
g_defgloblabel (Func->Name);
|
||||||
|
|
||||||
/* If stack cehcking code is requested, emit a call to the helper routine */
|
/* If this is a fastcall function, push the last parameter onto the stack */
|
||||||
|
if (IsFastCallFunc (Func->Type) && D->ParamCount > 0 && (D->Flags & FD_ELLIPSIS) == 0) {
|
||||||
|
|
||||||
|
unsigned Flags;
|
||||||
|
|
||||||
|
/* Get a pointer to the last parameter entry */
|
||||||
|
SymEntry* LastParam = D->SymTab->SymTail;
|
||||||
|
|
||||||
|
/* Generate the push */
|
||||||
|
if (IsTypeFunc (LastParam->Type)) {
|
||||||
|
/* Pointer to function */
|
||||||
|
Flags = CF_PTR;
|
||||||
|
} else {
|
||||||
|
Flags = TypeOf (LastParam->Type) | CF_FORCECHAR;
|
||||||
|
}
|
||||||
|
g_push (Flags, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If stack checking code is requested, emit a call to the helper routine */
|
||||||
if (CheckStack) {
|
if (CheckStack) {
|
||||||
g_stackcheck ();
|
g_stackcheck ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ extern Function* CurrentFunc;
|
|||||||
const char* GetFuncName (const Function* F);
|
const char* GetFuncName (const Function* F);
|
||||||
/* Return the name of the current function */
|
/* Return the name of the current function */
|
||||||
|
|
||||||
|
unsigned GetParamCount (const Function* F);
|
||||||
|
/* Return the parameter count for the current function */
|
||||||
|
|
||||||
unsigned GetParamSize (const Function* F);
|
unsigned GetParamSize (const Function* F);
|
||||||
/* Return the parameter size for the current function */
|
/* Return the parameter size for the current function */
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000 Ullrich von Bassewitz */
|
/* (C) 2000-2001 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@musoftware.de */
|
||||||
@@ -164,7 +164,7 @@ ExprNode* DoAsm (void)
|
|||||||
if (CurTok.Tok != TOK_SCONST) {
|
if (CurTok.Tok != TOK_SCONST) {
|
||||||
|
|
||||||
/* Print an error */
|
/* Print an error */
|
||||||
Error (ERR_STRLIT_EXPECTED);
|
Error ("String literal expected");
|
||||||
|
|
||||||
/* To be on the safe side later, insert an empty asm string */
|
/* To be on the safe side later, insert an empty asm string */
|
||||||
AppendItem (N, xstrdup (""));
|
AppendItem (N, xstrdup (""));
|
||||||
@@ -238,7 +238,7 @@ static ExprNode* Primary (void)
|
|||||||
*/
|
*/
|
||||||
if (Preprocessing) {
|
if (Preprocessing) {
|
||||||
/* Illegal expression in PP mode */
|
/* Illegal expression in PP mode */
|
||||||
Error (ERR_CPP_EXPR_EXPECTED);
|
Error ("Preprocessor expression expected");
|
||||||
|
|
||||||
/* Skip the token for error recovery */
|
/* Skip the token for error recovery */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -266,11 +266,11 @@ static ExprNode* Primary (void)
|
|||||||
/* Check for illegal symbol types */
|
/* Check for illegal symbol types */
|
||||||
if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
|
if ((Sym->Flags & SC_LABEL) == SC_LABEL) {
|
||||||
/* Cannot use labels in expressions */
|
/* Cannot use labels in expressions */
|
||||||
Error (ERR_SYMBOL_KIND);
|
Error ("Cannot use a label in an expression");
|
||||||
return GetIntNode (0);
|
return GetIntNode (0);
|
||||||
} else if (Sym->Flags & SC_TYPE) {
|
} else if (Sym->Flags & SC_TYPE) {
|
||||||
/* Cannot use type symbols */
|
/* Cannot use type symbols */
|
||||||
Error (ERR_VAR_IDENT_EXPECTED);
|
Error ("Cannot use a type in an expression");
|
||||||
/* Assume an int type to make lval valid */
|
/* Assume an int type to make lval valid */
|
||||||
return GetIntNode (0);
|
return GetIntNode (0);
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ static ExprNode* Primary (void)
|
|||||||
if (CurTok.Tok == TOK_LPAREN) {
|
if (CurTok.Tok == TOK_LPAREN) {
|
||||||
|
|
||||||
/* Warn about the use of a function without prototype */
|
/* Warn about the use of a function without prototype */
|
||||||
Warning (WARN_FUNC_WITHOUT_PROTO);
|
Warning ("Function call without a prototype");
|
||||||
|
|
||||||
/* Declare a function returning int. For that purpose, prepare
|
/* Declare a function returning int. For that purpose, prepare
|
||||||
* a function signature for a function having an empty param
|
* a function signature for a function having an empty param
|
||||||
@@ -320,7 +320,7 @@ static ExprNode* Primary (void)
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Print an error about an undeclared variable */
|
/* Print an error about an undeclared variable */
|
||||||
Error (ERR_UNDEFINED_SYMBOL, Ident);
|
Error ("Undefined symbiol: `%s'", Ident);
|
||||||
|
|
||||||
/* Undeclared Variable */
|
/* Undeclared Variable */
|
||||||
Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
|
Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0);
|
||||||
@@ -370,7 +370,7 @@ static ExprNode* Primary (void)
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Illegal primary. */
|
/* Illegal primary. */
|
||||||
Error (ERR_EXPR_EXPECTED);
|
Error ("Expression expected");
|
||||||
N = GetIntNode (0);
|
N = GetIntNode (0);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -402,7 +402,7 @@ static ExprNode* DoArray (ExprNode* Left)
|
|||||||
/* Right side must be some sort of integer */
|
/* Right side must be some sort of integer */
|
||||||
if (!IsClassInt (Right->Type)) {
|
if (!IsClassInt (Right->Type)) {
|
||||||
/* Print an error */
|
/* Print an error */
|
||||||
Error (ERR_CANNOT_SUBSCRIPT);
|
Error ("Invalid subscript");
|
||||||
/* To avoid problems later, create a new, legal subscript
|
/* To avoid problems later, create a new, legal subscript
|
||||||
* expression
|
* expression
|
||||||
*/
|
*/
|
||||||
@@ -413,9 +413,9 @@ static ExprNode* DoArray (ExprNode* Left)
|
|||||||
ExprNode* Tmp;
|
ExprNode* Tmp;
|
||||||
|
|
||||||
/* Left side must be some sort of integer */
|
/* Left side must be some sort of integer */
|
||||||
if (!IsClassInt (Right->Type)) {
|
if (!IsClassInt (Left->Type)) {
|
||||||
/* Print an error */
|
/* Print an error */
|
||||||
Error (ERR_CANNOT_SUBSCRIPT);
|
Error ("Invalid subscript");
|
||||||
/* To avoid problems later, create a new, legal subscript
|
/* To avoid problems later, create a new, legal subscript
|
||||||
* expression
|
* expression
|
||||||
*/
|
*/
|
||||||
@@ -431,7 +431,7 @@ static ExprNode* DoArray (ExprNode* Left)
|
|||||||
/* Invalid array expression. Skip the closing bracket, then return
|
/* Invalid array expression. Skip the closing bracket, then return
|
||||||
* an integer instead of the array expression to be safe later.
|
* an integer instead of the array expression to be safe later.
|
||||||
*/
|
*/
|
||||||
Error (ERR_CANNOT_SUBSCRIPT);
|
Error ("Invalid subscript");
|
||||||
ConsumeRBrack ();
|
ConsumeRBrack ();
|
||||||
return GetIntNode (0);
|
return GetIntNode (0);
|
||||||
}
|
}
|
||||||
@@ -473,7 +473,7 @@ static ExprNode* DoStruct (ExprNode* Left)
|
|||||||
if (CurTok.Tok == TOK_PTR_REF) {
|
if (CurTok.Tok == TOK_PTR_REF) {
|
||||||
NT = NT_STRUCTPTR_ACCESS;
|
NT = NT_STRUCTPTR_ACCESS;
|
||||||
if (!IsTypePtr (StructType)) {
|
if (!IsTypePtr (StructType)) {
|
||||||
Error (ERR_STRUCT_PTR_EXPECTED);
|
Error ("Struct pointer expected");
|
||||||
return GetIntNode (0);
|
return GetIntNode (0);
|
||||||
}
|
}
|
||||||
StructType = Indirect (StructType);
|
StructType = Indirect (StructType);
|
||||||
@@ -481,7 +481,7 @@ static ExprNode* DoStruct (ExprNode* Left)
|
|||||||
NT = NT_STRUCT_ACCESS;
|
NT = NT_STRUCT_ACCESS;
|
||||||
}
|
}
|
||||||
if (!IsClassStruct (StructType)) {
|
if (!IsClassStruct (StructType)) {
|
||||||
Error (ERR_STRUCT_EXPECTED);
|
Error ("Struct expected");
|
||||||
return GetIntNode (0);
|
return GetIntNode (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,7 +489,7 @@ static ExprNode* DoStruct (ExprNode* Left)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
if (CurTok.Tok != TOK_IDENT) {
|
if (CurTok.Tok != TOK_IDENT) {
|
||||||
/* Print an error */
|
/* Print an error */
|
||||||
Error (ERR_IDENT_EXPECTED);
|
Error ("Identifier expected");
|
||||||
/* Return an integer expression instead */
|
/* Return an integer expression instead */
|
||||||
return GetIntNode (0);
|
return GetIntNode (0);
|
||||||
}
|
}
|
||||||
@@ -500,7 +500,7 @@ static ExprNode* DoStruct (ExprNode* Left)
|
|||||||
Field = FindStructField (StructType, Ident);
|
Field = FindStructField (StructType, Ident);
|
||||||
if (Field == 0) {
|
if (Field == 0) {
|
||||||
/* Struct field not found */
|
/* Struct field not found */
|
||||||
Error (ERR_STRUCT_FIELD_MISMATCH, Ident);
|
Error ("Struct/union has no field named `%s'", Ident);
|
||||||
/* Return an integer expression instead */
|
/* Return an integer expression instead */
|
||||||
return GetIntNode (0);
|
return GetIntNode (0);
|
||||||
}
|
}
|
||||||
@@ -539,7 +539,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
|
|||||||
if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
|
if (!IsTypeFunc (Left->Type) && !IsTypeFuncPtr (Left->Type)) {
|
||||||
|
|
||||||
/* Call to non function */
|
/* Call to non function */
|
||||||
Error (ERR_ILLEGAL_FUNC_CALL);
|
Error ("Illegal function call");
|
||||||
|
|
||||||
/* Free the old tree */
|
/* Free the old tree */
|
||||||
FreeExprTree (Left);
|
FreeExprTree (Left);
|
||||||
@@ -590,7 +590,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
|
|||||||
/* Too many arguments. Do we have an open param list? */
|
/* Too many arguments. Do we have an open param list? */
|
||||||
if ((Func->Flags & FD_ELLIPSIS) == 0) {
|
if ((Func->Flags & FD_ELLIPSIS) == 0) {
|
||||||
/* End of param list reached, no ellipsis */
|
/* End of param list reached, no ellipsis */
|
||||||
Error (ERR_TOO_MANY_FUNC_ARGS);
|
Error ("Too many function arguments");
|
||||||
}
|
}
|
||||||
/* Assume an ellipsis even in case of errors to avoid an error
|
/* Assume an ellipsis even in case of errors to avoid an error
|
||||||
* message for each other argument.
|
* message for each other argument.
|
||||||
@@ -615,7 +615,7 @@ static ExprNode* DoFunctionCall (ExprNode* Left)
|
|||||||
|
|
||||||
/* Check if we had enough parameters */
|
/* Check if we had enough parameters */
|
||||||
if (ParamCount < Func->ParamCount) {
|
if (ParamCount < Func->ParamCount) {
|
||||||
Error (ERR_TOO_FEW_FUNC_ARGS);
|
Error ("Too few function arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the function call node */
|
/* Return the function call node */
|
||||||
@@ -639,7 +639,7 @@ static ExprNode* DoPostIncDec (ExprNode* Left)
|
|||||||
if (Left->LValue == 0) {
|
if (Left->LValue == 0) {
|
||||||
|
|
||||||
/* Print a diagnostics */
|
/* Print a diagnostics */
|
||||||
Error (ERR_LVALUE_EXPECTED);
|
Error ("lvalue expected");
|
||||||
|
|
||||||
/* It is safe to return the operand expression and probably better
|
/* It is safe to return the operand expression and probably better
|
||||||
* than returning an int, since the operand expression already has
|
* than returning an int, since the operand expression already has
|
||||||
@@ -721,7 +721,7 @@ static ExprNode* DoPreIncDec (void)
|
|||||||
if (Op->LValue == 0) {
|
if (Op->LValue == 0) {
|
||||||
|
|
||||||
/* Print a diagnostics */
|
/* Print a diagnostics */
|
||||||
Error (ERR_LVALUE_EXPECTED);
|
Error ("lvalue expected");
|
||||||
|
|
||||||
/* It is safe to return the operand expression and probably better
|
/* It is safe to return the operand expression and probably better
|
||||||
* than returning an int, since the operand expression already has
|
* than returning an int, since the operand expression already has
|
||||||
@@ -758,7 +758,7 @@ static ExprNode* DoUnaryPlusMinus (void)
|
|||||||
if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
|
if (!IsClassInt (Op->Type) && !IsClassFloat (Op->Type)) {
|
||||||
|
|
||||||
/* Output diagnostic */
|
/* Output diagnostic */
|
||||||
Error (ERR_SYNTAX);
|
Error ("Syntax error");
|
||||||
|
|
||||||
/* Free the errorneous node */
|
/* Free the errorneous node */
|
||||||
FreeExprTree (Op);
|
FreeExprTree (Op);
|
||||||
@@ -817,7 +817,7 @@ static ExprNode* DoComplement (void)
|
|||||||
if (!IsClassInt (Op->Type)) {
|
if (!IsClassInt (Op->Type)) {
|
||||||
|
|
||||||
/* Display diagnostic */
|
/* Display diagnostic */
|
||||||
Error (ERR_OP_NOT_ALLOWED);
|
Error ("Operation not allowed on this type");
|
||||||
|
|
||||||
/* Free the errorneous node */
|
/* Free the errorneous node */
|
||||||
FreeExprTree (Op);
|
FreeExprTree (Op);
|
||||||
@@ -890,7 +890,7 @@ static ExprNode* DoAddress (void)
|
|||||||
ExprNode* Root;
|
ExprNode* Root;
|
||||||
|
|
||||||
/* Print diagnostics */
|
/* Print diagnostics */
|
||||||
Error (ERR_ILLEGAL_ADDRESS);
|
Error ("Cannot take address of rvalue");
|
||||||
|
|
||||||
/* Free the problematic tree */
|
/* Free the problematic tree */
|
||||||
FreeExprTree (Op);
|
FreeExprTree (Op);
|
||||||
@@ -924,7 +924,7 @@ static ExprNode* DoIndirect (void)
|
|||||||
if (!IsClassPtr (Op->Type)) {
|
if (!IsClassPtr (Op->Type)) {
|
||||||
|
|
||||||
/* Print diagnostics */
|
/* Print diagnostics */
|
||||||
Error (ERR_ILLEGAL_INDIRECT);
|
Error ("Illegal indirection");
|
||||||
|
|
||||||
/* Free the problematic tree */
|
/* Free the problematic tree */
|
||||||
FreeExprTree (Op);
|
FreeExprTree (Op);
|
||||||
@@ -1089,7 +1089,7 @@ static ExprNode* DoMul (ExprNode* Left)
|
|||||||
|
|
||||||
/* Check the type of the left operand */
|
/* Check the type of the left operand */
|
||||||
if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) {
|
if (!IsClassInt (Left->Type) && !IsClassFloat (Left->Type)) {
|
||||||
MError ("Invalid left operand to binary operator `*'");
|
Error ("Invalid left operand to binary operator `*'");
|
||||||
FreeExprTree (Left);
|
FreeExprTree (Left);
|
||||||
Left = GetIntNode (0);
|
Left = GetIntNode (0);
|
||||||
}
|
}
|
||||||
@@ -1102,7 +1102,7 @@ static ExprNode* DoMul (ExprNode* Left)
|
|||||||
|
|
||||||
/* Check the type of the right operand */
|
/* Check the type of the right operand */
|
||||||
if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) {
|
if (!IsClassInt (Right->Type) && !IsClassFloat (Right->Type)) {
|
||||||
MError ("Invalid right operand to binary operator `*'");
|
Error ("Invalid right operand to binary operator `*'");
|
||||||
FreeExprTree (Right);
|
FreeExprTree (Right);
|
||||||
Right = GetIntNode (0);
|
Right = GetIntNode (0);
|
||||||
}
|
}
|
||||||
@@ -1295,7 +1295,7 @@ static ExprNode* AndExpr (void)
|
|||||||
if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
|
if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
|
||||||
|
|
||||||
/* Print a diagnostic */
|
/* Print a diagnostic */
|
||||||
Error (ERR_OP_NOT_ALLOWED);
|
Error ("Operation not allowed for these types");
|
||||||
|
|
||||||
/* Remove the unneeded nodes */
|
/* Remove the unneeded nodes */
|
||||||
FreeExprTree (Right);
|
FreeExprTree (Right);
|
||||||
@@ -1358,7 +1358,7 @@ static ExprNode* XorExpr (void)
|
|||||||
if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
|
if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
|
||||||
|
|
||||||
/* Print a diagnostic */
|
/* Print a diagnostic */
|
||||||
Error (ERR_OP_NOT_ALLOWED);
|
Error ("Operation not allowed for these types");
|
||||||
|
|
||||||
/* Remove the unneeded nodes */
|
/* Remove the unneeded nodes */
|
||||||
FreeExprTree (Right);
|
FreeExprTree (Right);
|
||||||
@@ -1421,7 +1421,7 @@ static ExprNode* OrExpr (void)
|
|||||||
if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
|
if (!IsClassInt (Left->Type) || !IsClassInt (Right->Type)) {
|
||||||
|
|
||||||
/* Print a diagnostic */
|
/* Print a diagnostic */
|
||||||
Error (ERR_OP_NOT_ALLOWED);
|
Error ("Operation not allowed for these types");
|
||||||
|
|
||||||
/* Remove the unneeded nodes */
|
/* Remove the unneeded nodes */
|
||||||
FreeExprTree (Right);
|
FreeExprTree (Right);
|
||||||
|
|||||||
Reference in New Issue
Block a user