|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989-1999 Microsoft Corporation
Module Name:
expr.cxx
Abstract:
expression evaluator routines implementation.
Notes:
History:
VibhasC Aug-05-1993 Created
----------------------------------------------------------------------------*/
#pragma warning ( disable : 4514 )
/****************************************************************************
* include files ***************************************************************************/ #include "nulldefs.h"
extern "C" { #include <stdio.h>
#include <string.h>
}
#include "expr.hxx"
#include "listhndl.hxx"
#include "nodeskl.hxx"
#include "semantic.hxx"
#include "symtable.hxx"
#include "cmdana.hxx"
#include <excpt.h>
#include <float.h>
/****************************************************************************
* extern definitions ***************************************************************************/ /****************************************************************************
* extern data ***************************************************************************/ extern SymTable * pBaseSymTbl; extern CMD_ARG * pCommand;
/****************************************************************************
* local definitions ***************************************************************************/ /****************************************************************************
* local data ***************************************************************************/ /***************************************************************************/
short expr_node::MakeListOfVars( ITERATOR & ) { return( 0 ); }
short expr_named_constant::MakeListOfVars( ITERATOR & ) { return( 0 ); }
short expr_variable::MakeListOfVars( ITERATOR & pList ) { pList.Insert( this ); return( 1 ); }
short expr_op_unary::MakeListOfVars( ITERATOR & pList ) { short VarCount = 0;
if ( GetLeft() ) VarCount = GetLeft()->MakeListOfVars( pList ); return( VarCount ); }
short expr_sizeof::MakeListOfVars( ITERATOR & ) /*++
expr_sizeof is a unary_op but it doesn't have a child! --*/ { return( 0 ); }
short expr_alignof::MakeListOfVars( ITERATOR & ) /*++
expr_alignof is a unary_op but it doesn't have a child! --*/ { return( 0 ); }
short expr_op_binary::MakeListOfVars( ITERATOR & pList ) { short VarCount;
VarCount = GetLeft()->MakeListOfVars( pList ); if ( GetRight() ) { VarCount = short( VarCount + GetRight()->MakeListOfVars( pList ) ); } return( VarCount ); }
short expr_ternary::MakeListOfVars( ITERATOR & pList ) { short VarCount;
VarCount = GetLeft()->MakeListOfVars( pList ); if ( GetRight() ) { VarCount = short( VarCount + GetRight()->MakeListOfVars( pList ) ); } if ( GetRelational() ) { VarCount = short( VarCount + GetRelational()->MakeListOfVars( pList ) ); } return( VarCount ); }
/***************************************************************************/ void expr_node::DecorateWithPrefix( char * pPrefix ) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
This routine decorates all the variable nodes in the expression with a prefix.
Arguments:
pPrefix - the prefix to be prepended to each variable
Return Value:
Notes:
----------------------------------------------------------------------------*/ { ITERATOR VarList; expr_variable * pVarNode = 0;
short VarCount = MakeListOfVars( VarList ); if ( VarCount ) { VarList.Init(); while ( ITERATOR_GETNEXT( VarList, pVarNode ) ) pVarNode->SetPrefix( pPrefix ); } return; }
expr_index::expr_index( expr_node * pL, expr_node * pR ) : expr_op_binary( OP_INDEX, pL, pR ) { SetType( pL->GetType() ); }
expr_param * expr_proc_call::SetParam( expr_param * pParam ) { expr_param * p = GetFirstParam();
IncrNoOfParams(); if( p ) { return p->SetLastPeerParam( pParam ); } else return SetFirstParam( pParam ); } expr_param * expr_proc_call::SetParam( expr_node * pExpr ) { return SetParam( new expr_param( pExpr )); }
expr_param * expr_param::SetLastPeerParam( expr_param * pParam ) { expr_param * p = GetNextParam();
if( p ) { return p->SetLastPeerParam( pParam ); } else { return SetNextParam( pParam ); } }
/**
** This routine attempts to recreate the string to be eaten by c compilers. ** If the user specified a string with a quote inside, substitute with an ** escape character. The new string with possible escapes will ALWAYS be ** smaller than the older one, so allocating the same amount of space is ** enough. **/
char * MakeNewStringWithProperQuoting( char * pSrc ) { char * pResult = new char [ strlen( pSrc ) + 1]; char ch; char * pDest = pResult;
while( ( ch = *pSrc++ ) != 0 ) {
*pDest = ch;
if( ch == '\\') { if( ( ch = *pSrc++ ) != 0 ) { if( (ch == '"') || ( ch == '\\') ) { *pDest = ch; } else { *pDest++ = '\\'; *pDest = ch; } } else break; } pDest++; } *pDest = '\0'; return pResult; }
// routines for expr_variable...
// constructor - see if the type is constant
expr_variable::expr_variable( PNAME p, node_skl * pT ) { SetName( p ); SetType( pT ); SetConstant( FALSE ); SetPrefix( NULL ); }
// resolve forwards on GetType
node_skl * expr_variable::GetType( void ) { if ( pType ) { if ( pType->NodeKind() == NODE_FORWARD ) { node_forward* pFwd = (node_forward *) pType; // (permanently) resolve the forward
pType = pFwd->ResolveFDecl(); // if it couldn't be resolved, put back the forward
if ( !pType ) { pType = pFwd; } } } return pType; }
// named constant routines...
// evaluate the variable if it is a constant
EXPR_VALUE expr_named_constant::GetValue() { node_skl * pT = GetType(); NODE_T Kind = ( pT ) ? (NODE_T) pT->NodeKind() : (NODE_T) NODE_ILLEGAL;
if ( !IsConstant() ) return 0;
// identifiers may be const... Forwards are assumed NOT const
if ( Kind == NODE_ID ) { node_id * pId = (node_id *) pT; node_skl * pType = pId->GetBasicType(); EXPR_VALUE Result = (pId->GetExpr()->GetValue() );
return (pType) ? pType->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result; } else if ( Kind == NODE_LABEL ) { return ( (node_label *) pT)->GetValue(); }
MIDL_ASSERT(FALSE); return 0; // for the compiler...
}
// evaluate the variable if it is a constant
expr_node * expr_named_constant::GetExpr() { node_skl * pT = GetType(); NODE_T Kind = ( pT ) ? (NODE_T) pT->NodeKind() : (NODE_T) NODE_ILLEGAL;
if ( !IsConstant() ) return 0;
// identifiers may be const... Forwards are assumed NOT const
if ( Kind == NODE_ID ) { node_id * pId = (node_id *) pT;
return pId->GetExpr(); } else if ( Kind == NODE_LABEL ) { return ( (node_label *) pT)->pExpr; }
MIDL_ASSERT(FALSE); return 0; // for the compiler...
}
/******************************************************************************
* expression list handler *****************************************************************************/ expr_list::expr_list() { SetConstant( TRUE ); }
STATUS_T expr_list::GetPeer( expr_node ** ppExpr ) { return (GetNext( (void **)ppExpr ) ); } STATUS_T expr_list::SetPeer( expr_node * pExpr ) { if ( pExpr && !pExpr->IsConstant() ) SetConstant( FALSE );
return Insert( (void *) pExpr ); }
EXPR_VALUE expr_u_arithmetic::GetValue() { EXPR_VALUE LeftValue = GetLeft()->GetValue(); EXPR_VALUE Result;
switch ( GetOperator() ) { case OP_UNARY_PLUS: { Result = LeftValue; break; } case OP_UNARY_MINUS: { if (IsStringConstant()) { char * szVal = (char *)LeftValue; char * szNewVal = new char[strlen(szVal)+2]; szNewVal[0] = '-'; strcpy(szNewVal + 1, szVal); Result = (EXPR_VALUE) szNewVal; } else { Result = -LeftValue; } break; } default: { Result = 0; break; } } return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result; }
EXPR_VALUE expr_u_not::GetValue() { EXPR_VALUE Result = !GetLeft()->GetValue();
return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result; }
EXPR_VALUE expr_u_complement::GetValue() { EXPR_VALUE Result = ~ GetLeft()->GetValue();
return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result; }
EXPR_VALUE expr_cast::GetValue() { return GetType()-> ConvertMyKindOfValueToEXPR_VALUE(GetLeft()->GetValue()); }
EXPR_VALUE expr_constant::GetValue() { return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Value.I64) : Value.I64; }
EXPR_VALUE expr_sizeof::GetValue() { return (pType) ? pType->GetSize() : 0; }
EXPR_VALUE expr_alignof::GetValue() { return (pType) ? pType->GetAlign() : 0; }
EXPR_VALUE expr_b_arithmetic::GetValue() { EXPR_VALUE LeftValue = GetLeft()->GetValue(); EXPR_VALUE RightValue = GetRight()->GetValue(); EXPR_VALUE Result;
switch ( GetOperator() ) { case OP_PLUS: { Result = LeftValue + RightValue; break; } case OP_MINUS: { Result = LeftValue - RightValue; break; } case OP_STAR: { Result = LeftValue * RightValue; break; } case OP_SLASH: { if (RightValue == 0) Result = 1; else Result = LeftValue / RightValue; break; } case OP_MOD: { if ( 0 == RightValue ) Result = 1; else Result = LeftValue % RightValue; break; } default: { Result = 0; break; } } return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result ; }
EXPR_VALUE expr_b_logical::GetValue() { EXPR_VALUE LeftValue = GetLeft()->GetValue(); EXPR_VALUE RightValue = GetRight()->GetValue(); EXPR_VALUE Result;
switch ( GetOperator() ) { case OP_LOGICAL_AND: { Result = LeftValue && RightValue; break; } case OP_LOGICAL_OR: { Result = LeftValue || RightValue; break; } default: { Result = 0; break; } } return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result ; }
EXPR_VALUE expr_relational::GetValue() { EXPR_VALUE LeftValue = GetLeft()->GetValue(); EXPR_VALUE RightValue = GetRight()->GetValue(); EXPR_VALUE Result;
switch ( GetOperator() ) { // gaj - we implicitly assume signed types
case OP_LESS: { Result = LeftValue < RightValue; break; } case OP_LESS_EQUAL: { Result = LeftValue <= RightValue; break; } case OP_GREATER_EQUAL: { Result = LeftValue >= RightValue; break; } case OP_GREATER: { Result = LeftValue > RightValue; break; } case OP_EQUAL: { Result = LeftValue == RightValue; break; } case OP_NOT_EQUAL: { Result = LeftValue != RightValue; break; } default: { Result = 0; break; } } return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result; }
EXPR_VALUE expr_shift::GetValue() { EXPR_VALUE LeftValue = GetLeft()->GetValue(); EXPR_VALUE RightValue = GetRight()->GetValue(); EXPR_VALUE Result;
switch ( GetOperator() ) { // gaj - we implicitly assume signed types
case OP_LEFT_SHIFT: { Result = LeftValue << RightValue; break; } case OP_RIGHT_SHIFT: { Result = LeftValue >> RightValue; break; } default: { Result = 0; break; } } return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result; }
EXPR_VALUE expr_bitwise::GetValue() { EXPR_VALUE LeftValue = GetLeft()->GetValue(); EXPR_VALUE RightValue = GetRight()->GetValue(); EXPR_VALUE Result;
switch ( GetOperator() ) { // gaj - we implicitly assume signed types
case OP_AND: { Result = LeftValue & RightValue; break; } case OP_OR: { Result = LeftValue | RightValue; break; } case OP_XOR: { Result = LeftValue ^ RightValue; break; } default: { Result = 0; break; } } return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result ; }
EXPR_VALUE expr_ternary::GetValue() { EXPR_VALUE RelValue = GetRelational()->GetValue(); EXPR_VALUE Result;
if ( RelValue ) Result = GetLeft()->GetValue(); else Result = GetRight()->GetValue();
return (GetType()) ? GetType()->ConvertMyKindOfValueToEXPR_VALUE(Result) : Result; }
////////////////////////////////////////////////////////////////////////
// analysis of expressions
//
void expr_node::ExprAnalyze( EXPR_CTXT * pExprCtxt ) { pExprCtxt->SetUpFlags( EX_VALUE_INVALID ); }
//
// determine the type of the expression
//
void expr_op_unary::DetermineType() { node_skl * pLeftType;
if ( !GetLeft() ) { return; }
pLeftType = GetLeft()->AlwaysGetType(); SetConstant( GetLeft()->IsConstant() );
switch ( GetOperator() ) { case OP_UNARY_PLUS: case OP_UNARY_COMPLEMENT: case OP_UNARY_MINUS: case OP_PRE_INCR: case OP_PRE_DECR: case OP_POST_INCR: case OP_POST_DECR: { // same type
SetType( pLeftType ); break; } case OP_UNARY_NOT: { node_skl * pTmpType;
GetBaseTypeNode( &pTmpType, SIGN_UNDEF, SIZE_UNDEF, TYPE_BOOLEAN );
SetType( pTmpType ); break; } case OP_UNARY_CAST: { SetType( GetType() ); break; } case OP_UNARY_SIZEOF: case OP_UNARY_ALIGNOF: { node_skl * pTmpType;
GetBaseTypeNode( &pTmpType, SIGN_SIGNED, SIZE_UNDEF, TYPE_INT );
SetType( pTmpType ); SetConstant( TRUE ); break; } case OP_UNARY_INDIRECTION: { node_skl * pNode = pLeftType;
if ( pNode->NodeKind() != NODE_POINTER ) { // probably the param or field; look down
pNode = pNode->GetBasicType(); }
// now get the pointee
pNode = pNode->GetBasicType();
SetType( pNode ); break; } case OP_UNARY_AND: { node_pointer * pPtr = new node_pointer;
pPtr->SetChild( pLeftType ); SetType( pPtr ); break; } default: { break; } } // end of switch
}
void expr_op_unary::ExprAnalyze( EXPR_CTXT * pExprCtxt ) { EXPR_CTXT LeftCtxt( pExprCtxt );
if ( GetLeft() ) { GetLeft()->ExprAnalyze( &LeftCtxt ); pExprCtxt->MergeUpFlags( &LeftCtxt ); SetConstant( GetLeft()->IsConstant() ); } else if ( GetOperator() != OP_UNARY_SIZEOF && GetOperator() != OP_UNARY_ALIGNOF) pExprCtxt->SetUpFlags( EX_VALUE_INVALID );
// do type compatibility stuff
switch ( GetOperator() ) { case OP_UNARY_PLUS: case OP_UNARY_COMPLEMENT: { // same type
pExprCtxt->pType = LeftCtxt.pType; pExprCtxt->TypeInfo = LeftCtxt.TypeInfo; pExprCtxt->fIntegral = LeftCtxt.fIntegral; SetType( pExprCtxt->pType ); break; } case OP_UNARY_MINUS: { node_skl * pTmp;
pExprCtxt->pType = LeftCtxt.pType; pExprCtxt->TypeInfo = LeftCtxt.TypeInfo; pExprCtxt->TypeInfo.TypeSign = SIGN_SIGNED; pExprCtxt->fIntegral = LeftCtxt.fIntegral; GetBaseTypeNode( &pTmp, pExprCtxt->TypeInfo ); if ( pTmp ) pExprCtxt->pType = pTmp;
SetType( pExprCtxt->pType ); break; } case OP_UNARY_NOT: { pExprCtxt->TypeInfo.TypeSize = SIZE_UNDEF; pExprCtxt->TypeInfo.BaseType = TYPE_BOOLEAN; pExprCtxt->TypeInfo.TypeSign = SIGN_UNDEF; GetBaseTypeNode( &(pExprCtxt->pType ), pExprCtxt->TypeInfo );
pExprCtxt->fIntegral = TRUE; SetType( pExprCtxt->pType ); break; } case OP_UNARY_CAST: { SetType( GetType() ); break; } case OP_UNARY_SIZEOF: case OP_UNARY_ALIGNOF: { pExprCtxt->TypeInfo.TypeSize = SIZE_UNDEF; pExprCtxt->TypeInfo.BaseType = TYPE_INT; pExprCtxt->TypeInfo.TypeSign = SIGN_SIGNED; GetBaseTypeNode( &(pExprCtxt->pType ), pExprCtxt->TypeInfo);
pExprCtxt->fIntegral = TRUE; SetType( pExprCtxt->pType ); break; } case OP_UNARY_INDIRECTION: { node_skl * pNode = GetLeft()->GetType(); node_skl * pOrigNode = pNode; node_ptr_attr * pPtrAttr; PTRTYPE PtrKind = PTR_UNKNOWN;
if ( pNode->FInSummary( ATTR_PTR_KIND ) ) { pPtrAttr = (node_ptr_attr *) ((named_node *)pNode)->GetAttribute( ATTR_PTR_KIND ); PtrKind = pPtrAttr->GetPtrKind(); }
if ( pNode->FInSummary( ATTR_IGNORE ) ) { SEM_ANALYSIS_CTXT * pCtxt = pExprCtxt->GetCtxt();
// Only complain about this on the actual type, not every
// single use of the type.
if ( !pCtxt->AnyAncestorBits( IN_PARAM_LIST ) ) { SemError( pNode, *pCtxt, CORRELATION_DERIVES_FROM_IGNORE_POINTER, NULL ); } }
if ( pNode->NodeKind() != NODE_POINTER ) { // probably the param or field; look down
pNode = pNode->GetBasicType(); }
if ( pNode->NodeKind() != NODE_POINTER ) { // error
pNode = NULL; } else { // check things about type of pointer
if ( PtrKind == PTR_UNKNOWN ) { node_interface * pIntf = pOrigNode->GetMyInterfaceNode();
if ( pOrigNode->NodeKind() == NODE_PARAM ) PtrKind = PTR_REF; else if ( pIntf->FInSummary( ATTR_PTR_KIND ) ) { pPtrAttr = (node_ptr_attr *) pIntf->GetAttribute( ATTR_PTR_KIND ); PtrKind = pPtrAttr->GetPtrKind(); } else { pIntf = pExprCtxt->GetCtxt()->GetInterfaceNode(); if ( pIntf->FInSummary( ATTR_PTR_KIND ) ) { pPtrAttr = (node_ptr_attr *) pIntf->GetAttribute( ATTR_PTR_KIND ); PtrKind = pPtrAttr->GetPtrKind(); } else { if (pCommand->IsSwitchDefined( SWITCH_MS_EXT ) ) { PtrKind = PTR_UNIQUE; } else { PtrKind = PTR_FULL; } } } }
if ( ( PtrKind == PTR_FULL ) || ( PtrKind == PTR_UNIQUE ) ) { SEM_ANALYSIS_CTXT * pCtxt = pExprCtxt->GetCtxt();
pExprCtxt->SetUpFlags( EX_PTR_FULL_UNIQUE ); SemError( pCtxt->GetParent(), *pCtxt, SIZE_LENGTH_SW_UNIQUE_OR_FULL, NULL ); }
pNode = pNode->GetBasicType(); }
SetType( pNode ); break; } case OP_UNARY_AND: { if ( GetType() ) break;
node_pointer * pPtr = new node_pointer;
pPtr->SetChild( GetLeft()->GetType() ); SetType( pPtr ); break; } case OP_PRE_INCR: case OP_PRE_DECR: case OP_POST_INCR: case OP_POST_DECR: { SetType( GetLeft()->GetType() ); break; } default: { break; } } // end of switch
pExprCtxt->pType = GetType();
// compute the value
if ( !pExprCtxt->AnyUpFlags( EX_VALUE_INVALID ) ) { // tbd - update value from LeftCtxt
EXPR_VALUE & LeftValue = LeftCtxt.Value(); EXPR_VALUE & Result = pExprCtxt->Value();
switch ( GetOperator() ) { case OP_UNARY_PLUS: { Result = LeftValue; break; } case OP_UNARY_MINUS: { Result = -LeftValue; break; } case OP_UNARY_NOT: { Result = !LeftValue; break; } case OP_UNARY_COMPLEMENT: { Result = ~LeftValue; break; } case OP_UNARY_CAST: { Result = LeftValue; break; } case OP_UNARY_SIZEOF: case OP_UNARY_ALIGNOF: { Result = GetValue(); break; } case OP_UNARY_INDIRECTION: case OP_UNARY_AND: case OP_PRE_INCR: case OP_PRE_DECR: case OP_POST_INCR: case OP_POST_DECR: { SetConstant( FALSE ); pExprCtxt->SetUpFlags( EX_VALUE_INVALID ); break; } default: { SetConstant( FALSE ); Result = 0; break; } } // end of case
} // end of if valid
}
//
// determine the type of the expression
//
void expr_op_binary::DetermineType() { node_skl * pLeftType = NULL; node_skl * pRightType = NULL;
if ( GetLeft() ) pLeftType = GetLeft()->AlwaysGetType(); if ( GetRight() ) pRightType = GetRight()->AlwaysGetType();
SetConstant( GetRight()->IsConstant() && GetLeft()->IsConstant() );
////////////////////////////////////////////////////////////////////////
// do type compatibility stuff
switch ( GetOperator() ) { case OP_PLUS: case OP_MINUS: case OP_STAR: case OP_MOD: // gaj - we implicitly assume signed types
case OP_LEFT_SHIFT: case OP_RIGHT_SHIFT: case OP_AND: case OP_OR: case OP_XOR: case OP_SLASH: { // tbd - for now, just grab one of the types
if ( !pRightType || (pLeftType && (pLeftType->GetSize() >= pRightType->GetSize() ) ) ) { SetType( pLeftType ); } else if ( pRightType ) { SetType( pRightType ); }
break; } case OP_LOGICAL_AND: case OP_LOGICAL_OR: // gaj - we implicitly assume signed types
case OP_LESS: case OP_LESS_EQUAL: case OP_GREATER_EQUAL: case OP_GREATER: case OP_EQUAL: case OP_NOT_EQUAL: { node_skl * pTmpType;
GetBaseTypeNode( &pTmpType, SIGN_UNDEF, SIZE_UNDEF, TYPE_BOOLEAN );
SetType( pTmpType ); break; } default: { break; } }
}
void expr_op_binary::ExprAnalyze( EXPR_CTXT * pExprCtxt ) { EXPR_CTXT LeftCtxt( pExprCtxt ); EXPR_CTXT RightCtxt( pExprCtxt );
if ( GetLeft() ) { GetLeft()->ExprAnalyze( &LeftCtxt ); pExprCtxt->MergeUpFlags( &LeftCtxt ); SetConstant( IsConstant() && GetLeft()->IsConstant() ); } else pExprCtxt->SetUpFlags( EX_VALUE_INVALID );
if ( GetRight() ) { GetRight()->ExprAnalyze( &RightCtxt ); pExprCtxt->MergeUpFlags( &RightCtxt ); SetConstant( IsConstant() && GetRight()->IsConstant() );
// check here for div by zero ( could be var / 0 )
if ( !RightCtxt.AnyUpFlags( EX_VALUE_INVALID ) && ( GetOperator() == OP_SLASH ) && ( RightCtxt.Value() == 0 ) ) { SemError( pExprCtxt->GetNode(), *(pExprCtxt->GetCtxt()), EXPR_DIV_BY_ZERO, NULL ); pExprCtxt->SetUpFlags( EX_VALUE_INVALID ); } } else pExprCtxt->SetUpFlags( EX_VALUE_INVALID );
////////////////////////////////////////////////////////////////////////
// do type compatibility stuff
switch ( GetOperator() ) { case OP_PLUS: case OP_MINUS: case OP_STAR: case OP_MOD: // gaj - we implicitly assume signed types
case OP_LEFT_SHIFT: case OP_RIGHT_SHIFT: case OP_AND: case OP_OR: case OP_XOR: case OP_SLASH: { // tbd - for now, just grab the bigger of the types
if ( !RightCtxt.pType || (LeftCtxt.pType && (LeftCtxt.pType->GetSize() >= RightCtxt.pType->GetSize() ) ) ) { pExprCtxt->pType = LeftCtxt.pType; pExprCtxt->TypeInfo = LeftCtxt.TypeInfo; pExprCtxt->fIntegral = LeftCtxt.fIntegral; SetType( pExprCtxt->pType ); } else if ( RightCtxt.pType ) { pExprCtxt->pType = RightCtxt.pType; pExprCtxt->TypeInfo = RightCtxt.TypeInfo; pExprCtxt->fIntegral = RightCtxt.fIntegral; SetType( pExprCtxt->pType ); }
break; } case OP_LOGICAL_AND: case OP_LOGICAL_OR: // gaj - we implicitly assume signed types
case OP_LESS: case OP_LESS_EQUAL: case OP_GREATER_EQUAL: case OP_GREATER: case OP_EQUAL: case OP_NOT_EQUAL: { pExprCtxt->TypeInfo.TypeSize = SIZE_UNDEF; pExprCtxt->TypeInfo.BaseType = TYPE_BOOLEAN; pExprCtxt->TypeInfo.TypeSign = SIGN_UNDEF; GetBaseTypeNode( &(pExprCtxt->pType ), pExprCtxt->TypeInfo );
pExprCtxt->fIntegral = TRUE; SetType( pExprCtxt->pType ); break; } default: { break; } }
////////////////////////////////////////////////////////////////////////
// compute the value
if ( !pExprCtxt->AnyUpFlags( EX_VALUE_INVALID ) ) { // update value directly from LeftCtxt and RightCtxt
EXPR_VALUE & LeftValue = LeftCtxt.Value(); EXPR_VALUE & RightValue = RightCtxt.Value(); EXPR_VALUE & Result = pExprCtxt->Value();
switch ( GetOperator() ) { case OP_PLUS: { Result = LeftValue + RightValue; break; } case OP_MINUS: { Result = LeftValue - RightValue; break; } case OP_STAR: { Result = LeftValue * RightValue; break; } case OP_SLASH: { if (RightValue == 0) Result = 0; else Result = LeftValue / RightValue; break; } case OP_MOD: { Result = LeftValue % RightValue; break; } case OP_LOGICAL_AND: { Result = LeftValue && RightValue; break; } case OP_LOGICAL_OR: { Result = LeftValue || RightValue; break; } // gaj - we implicitly assume signed types
case OP_LESS: { Result = LeftValue < RightValue; break; } case OP_LESS_EQUAL: { Result = LeftValue <= RightValue; break; } case OP_GREATER_EQUAL: { Result = LeftValue >= RightValue; break; } case OP_GREATER: { Result = LeftValue > RightValue; break; } case OP_EQUAL: { Result = LeftValue == RightValue; break; } case OP_NOT_EQUAL: { Result = LeftValue != RightValue; break; } // gaj - we implicitly assume signed types
case OP_LEFT_SHIFT: { Result = LeftValue << RightValue; break; } case OP_RIGHT_SHIFT: { Result = LeftValue >> RightValue; break; } case OP_AND: { Result = LeftValue & RightValue; break; } case OP_OR: { Result = LeftValue | RightValue; break; } case OP_XOR: { Result = LeftValue ^ RightValue; break; } default: { Result = 0; break; } }
}
}
//
// determine the type of the expression
//
void expr_ternary::DetermineType() { node_skl * pLeftType = NULL; node_skl * pRightType = NULL;
if ( GetLeft() ) pLeftType = GetLeft()->AlwaysGetType(); if ( GetRight() ) pRightType = GetRight()->AlwaysGetType();
SetConstant( GetRight()->IsConstant() && GetLeft()->IsConstant() );
if ( pLeftType ) SetType( pLeftType ); else if ( pRightType ) SetType( pRightType );
}
void expr_ternary::ExprAnalyze( EXPR_CTXT * pExprCtxt ) { EXPR_CTXT LeftCtxt( pExprCtxt ); EXPR_CTXT RightCtxt( pExprCtxt ); EXPR_CTXT RelCtxt( pExprCtxt );
if ( GetLeft() ) { GetLeft()->ExprAnalyze( &LeftCtxt ); pExprCtxt->MergeUpFlags( &LeftCtxt ); SetConstant( IsConstant() && GetLeft()->IsConstant() ); } else pExprCtxt->SetUpFlags( EX_VALUE_INVALID );
if ( GetRight() ) { GetRight()->ExprAnalyze( &RightCtxt ); pExprCtxt->MergeUpFlags( &RightCtxt ); SetConstant( IsConstant() && GetRight()->IsConstant() ); } else pExprCtxt->SetUpFlags( EX_VALUE_INVALID );
if ( GetRelational() ) { GetRelational()->ExprAnalyze( &RelCtxt ); pExprCtxt->MergeUpFlags( &RelCtxt ); SetConstant( IsConstant() && GetRelational()->IsConstant() ); } else pExprCtxt->SetUpFlags( EX_VALUE_INVALID );
// tbd - get the type from the left or right of the ':'
if ( LeftCtxt.pType ) { pExprCtxt->pType = LeftCtxt.pType; pExprCtxt->TypeInfo = LeftCtxt.TypeInfo; pExprCtxt->fIntegral = LeftCtxt.fIntegral; SetType( pExprCtxt->pType ); } else if ( RightCtxt.pType ) { pExprCtxt->pType = RightCtxt.pType; pExprCtxt->TypeInfo = RightCtxt.TypeInfo; pExprCtxt->fIntegral = RightCtxt.fIntegral; SetType( pExprCtxt->pType ); } else SetType( NULL );
////////////////////////////////////////////////////////////////////////
// compute the value
if ( !pExprCtxt->AnyUpFlags( EX_VALUE_INVALID ) ) { // update value directly from LeftCtxt and RightCtxt
EXPR_VALUE & LeftValue = LeftCtxt.Value(); EXPR_VALUE & RightValue = RightCtxt.Value(); EXPR_VALUE & RelValue = RelCtxt.Value(); EXPR_VALUE & Result = pExprCtxt->Value();
Result = (RelValue) ? LeftValue : RightValue;
}
}
//
// determine the type of the expression
//
void expr_variable::DetermineType() { if ( pType->NodeKind() == NODE_FORWARD ) { node_forward * pFwd = (node_forward *) pType; // (permanently) resolve the forward
pType = pFwd->ResolveFDecl();
// This appears to be a better fix for the problem of unresolved
// variables in async size expressions than the NULL type pointer check
// in Fixup[Begin|Finish]ProcExpr in front\copyto.cxx. However, at this
// time we don't fully understand the implications of this change while
// the other is localized to the async_uuid interfaces only.
// e.g. ([in] long size, [in, size_is(huh)] long *p)
// 03-May-99 MikeW
/*
// if it couldn't be resolved, put back the forward
if ( !pType ) { pType = pFwd; } */ } }
void expr_variable::ExprAnalyze( EXPR_CTXT * pExprCtxt ) { pExprCtxt->SetUpFlags( EX_VALUE_INVALID ); pExprCtxt->SetUpFlags( EX_NON_NUMERIC );
if ( !pType ) { pExprCtxt->SetUpFlags( EX_UNSAT_FWD ); return; }
if ( pType->NodeKind() == NODE_FORWARD ) { node_forward * pFwd = (node_forward *) pType; // (permanently) resolve the forward
pType = pFwd->ResolveFDecl(); // if it couldn't be resolved, put back the forward
if ( !pType ) { pExprCtxt->SetUpFlags( EX_UNSAT_FWD ); pExprCtxt->TypeInfo.TypeSize = SIZE_UNDEF; pExprCtxt->TypeInfo.BaseType = TYPE_INT; pExprCtxt->TypeInfo.TypeSign = SIGN_SIGNED; GetBaseTypeNode( &pType, pExprCtxt->TypeInfo); pExprCtxt->pType = pType; return; } }
// do type compatibility stuff
pExprCtxt->pType = pType; pExprCtxt->TypeInfo.TypeSize = SIZE_UNDEF; pExprCtxt->TypeInfo.BaseType = TYPE_UNDEF; pExprCtxt->TypeInfo.TypeSign = SIGN_UNDEF; pExprCtxt->fIntegral = FALSE; // for now...
if ( ( pType->NodeKind() == NODE_PARAM ) && pType->FInSummary( ATTR_OUT ) && !pType->FInSummary( ATTR_IN ) ) pExprCtxt->SetUpFlags( EX_OUT_ONLY_PARAM );
}
//
// determine the type of the expression
//
void expr_named_constant::DetermineType() { // do type compatibility stuff
if ( !GetType() ) { SetType( GetExpr()->AlwaysGetType() ); }
}
void expr_named_constant::ExprAnalyze( EXPR_CTXT * pExprCtxt ) { // named constants shouldn't be folded away
pExprCtxt->SetUpFlags( EX_NON_NUMERIC );
// update value
pExprCtxt->Value() = GetValue();
// do type compatibility stuff
if ( GetType() ) { pExprCtxt->pType = GetType(); pExprCtxt->TypeInfo.TypeSize = SIZE_UNDEF; pExprCtxt->TypeInfo.BaseType = TYPE_UNDEF; pExprCtxt->TypeInfo.TypeSign = SIGN_UNDEF; pExprCtxt->fIntegral = FALSE; // for now...
} else { EXPR_CTXT LeftCtxt( pExprCtxt ); expr_node * pExpr = GetExpr();
pExpr->ExprAnalyze( &LeftCtxt );
pExprCtxt->pType = LeftCtxt.pType; pExprCtxt->TypeInfo = LeftCtxt.TypeInfo; pExprCtxt->fIntegral = LeftCtxt.fIntegral; SetType( pExprCtxt->pType ); }
}
//
// determine the type of the expression
//
void expr_constant::DetermineType() { node_skl* pNewType = 0;
// do type compatibility stuff
if ( GetType() ) return;
// do type compatibility stuff
switch (Format) { case VALUE_TYPE_STRING: { node_skl * pBottomType; GetBaseTypeNode( &pBottomType, SIGN_SIGNED, SIZE_CHAR, TYPE_INT ); pNewType = new node_pointer; pNewType->SetChild( pBottomType ); break; } case VALUE_TYPE_WSTRING: { node_skl * pBottomType; SymKey SKey( "wchar_t", NAME_DEF );
pBottomType = pBaseSymTbl->SymSearch( SKey ); pNewType = new node_pointer; pNewType->SetChild( pBottomType ); break; } case VALUE_TYPE_CHAR: { GetBaseTypeNode( &pNewType, SIGN_SIGNED, SIZE_CHAR, TYPE_INT ); break; } case VALUE_TYPE_WCHAR: { SymKey SKey( "wchar_t", NAME_DEF );
pNewType = pBaseSymTbl->SymSearch( SKey ); break; } case VALUE_TYPE_NUMERIC: case VALUE_TYPE_HEX: case VALUE_TYPE_OCTAL: { GetBaseTypeNode( &pNewType, SIGN_SIGNED, SIZE_UNDEF, TYPE_INT ); break; } case VALUE_TYPE_NUMERIC_U: case VALUE_TYPE_HEX_U: case VALUE_TYPE_OCTAL_U: { GetBaseTypeNode( &pNewType, SIGN_UNSIGNED, SIZE_SHORT, TYPE_INT ); break; }
case VALUE_TYPE_NUMERIC_LONG: case VALUE_TYPE_HEX_LONG: case VALUE_TYPE_OCTAL_LONG: { GetBaseTypeNode( &pNewType, SIGN_SIGNED, SIZE_LONG, TYPE_INT ); break; }
case VALUE_TYPE_NUMERIC_ULONG: case VALUE_TYPE_HEX_ULONG: case VALUE_TYPE_OCTAL_ULONG: { GetBaseTypeNode( &pNewType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT ); break; }
case VALUE_TYPE_BOOL: { GetBaseTypeNode( &pNewType, SIGN_UNDEF, SIZE_UNDEF, TYPE_BOOLEAN ); break; }
case VALUE_TYPE_FLOAT: { GetBaseTypeNode( &pNewType, SIGN_UNDEF, SIZE_UNDEF, TYPE_FLOAT ); break; } case VALUE_TYPE_DOUBLE: { GetBaseTypeNode( &pNewType, SIGN_UNDEF, SIZE_UNDEF, TYPE_DOUBLE ); break; }
default: break; } SetType( pNewType ); }
void expr_constant::ExprAnalyze( EXPR_CTXT * pExprCtxt ) {
// update value
pExprCtxt->Value() = GetValue();
if ( GetType() ) { pExprCtxt->pType = GetType(); pExprCtxt->TypeInfo.TypeSize = SIZE_UNDEF; pExprCtxt->TypeInfo.BaseType = TYPE_UNDEF; pExprCtxt->TypeInfo.TypeSign = SIGN_UNDEF; pExprCtxt->fIntegral = FALSE; // for now...
return; }
// do type compatibility stuff
switch (Format) { case VALUE_TYPE_STRING: { node_skl * pBottomType; GetBaseTypeNode( &pBottomType, SIGN_SIGNED, SIZE_CHAR, TYPE_INT ); pExprCtxt->pType = new node_pointer; pExprCtxt->pType->SetChild( pBottomType ); break; } case VALUE_TYPE_WSTRING: { node_skl * pBottomType; SymKey SKey( "wchar_t", NAME_DEF );
pBottomType = pBaseSymTbl->SymSearch( SKey ); pExprCtxt->pType = new node_pointer; pExprCtxt->pType->SetChild( pBottomType ); break; } case VALUE_TYPE_CHAR: { GetBaseTypeNode( &pExprCtxt->pType, SIGN_SIGNED, SIZE_CHAR, TYPE_INT ); break; } case VALUE_TYPE_WCHAR: { SymKey SKey( "wchar_t", NAME_DEF );
pExprCtxt->pType = pBaseSymTbl->SymSearch( SKey ); break; } case VALUE_TYPE_NUMERIC: case VALUE_TYPE_HEX: case VALUE_TYPE_OCTAL: { short RealSize = SIZE_HYPER; __int64 val = GetValue();
if ( (val <= 127) && (val >= -128 ) ) RealSize = SIZE_CHAR; else if ( (val <= _I16_MAX) && (val >= _I16_MIN ) ) RealSize = SIZE_SHORT; else if ( (val <= _I32_MAX) && (val >= _I32_MIN ) ) RealSize = SIZE_LONG;
GetBaseTypeNode( &pExprCtxt->pType, SIGN_SIGNED, RealSize, TYPE_INT ); break; } case VALUE_TYPE_NUMERIC_U: case VALUE_TYPE_HEX_U: case VALUE_TYPE_OCTAL_U: { short RealSize = SIZE_LONG; unsigned long val = (unsigned long) GetValue();
if ( val <= 255 ) RealSize = SIZE_CHAR; else if ( val <= 65536 ) RealSize = SIZE_SHORT;
GetBaseTypeNode( &pExprCtxt->pType, SIGN_UNSIGNED, RealSize, TYPE_INT ); break; }
case VALUE_TYPE_NUMERIC_LONG: case VALUE_TYPE_HEX_LONG: case VALUE_TYPE_OCTAL_LONG: { GetBaseTypeNode( &pExprCtxt->pType, SIGN_SIGNED, SIZE_LONG, TYPE_INT ); break; }
case VALUE_TYPE_NUMERIC_ULONG: case VALUE_TYPE_HEX_ULONG: case VALUE_TYPE_OCTAL_ULONG: { GetBaseTypeNode( &pExprCtxt->pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT ); break; }
case VALUE_TYPE_BOOL: { GetBaseTypeNode( &pExprCtxt->pType, SIGN_UNDEF, SIZE_UNDEF, TYPE_BOOLEAN ); break; }
case VALUE_TYPE_FLOAT: { GetBaseTypeNode( &pExprCtxt->pType, SIGN_UNDEF, SIZE_UNDEF, TYPE_FLOAT ); break; } case VALUE_TYPE_DOUBLE: { GetBaseTypeNode( &pExprCtxt->pType, SIGN_UNDEF, SIZE_UNDEF, TYPE_DOUBLE ); break; }
default: break; } SetType( pExprCtxt->pType ); }
//
// determine the type of the expression
//
void expr_init_list::DetermineType() { SetType( pExpr->AlwaysGetType() ); }
void expr_init_list::ExprAnalyze( EXPR_CTXT * pExprCtxt ) {
// tbd - for now only process first element
pExpr->ExprAnalyze( pExprCtxt ); SetConstant( pExpr->IsConstant() ); SetType( pExpr->GetType() );
}
short expr_op_binary::MakeListOfDerefedVars( ITERATOR& List ) { if( GetLeft() ) GetLeft()->MakeListOfDerefedVars( List );
if( GetRight() ) GetRight()->MakeListOfDerefedVars( List ); return (short) ITERATOR_GETCOUNT( List ); }
short expr_u_deref::MakeListOfDerefedVars( ITERATOR& List ) { expr_node * pLeft = GetLeft();
if( !pLeft ) return 0;
if( pLeft->IsAVariable() ) ITERATOR_INSERT( List, pLeft ); else if( pLeft->GetOperator() == OP_UNARY_INDIRECTION ) pLeft->MakeListOfDerefedVars( List );
return ITERATOR_GETCOUNT( List ); }
BOOL expr_b_arithmetic::GetExprValue( SExprValue& v ) { SExprValue LeftValue = {VALUE_TYPE_UNDEFINED, 0}; SExprValue RightValue = {VALUE_TYPE_UNDEFINED, 0}; BOOL fSuccess;
fSuccess = GetLeft()->GetExprValue( LeftValue ) && GetRight()->GetExprValue( RightValue ) && (LeftValue.format == VALUE_TYPE_DOUBLE || LeftValue.format == VALUE_TYPE_DOUBLE) && (RightValue.format == VALUE_TYPE_DOUBLE || RightValue.format == VALUE_TYPE_DOUBLE);
if (fSuccess) { v.format = LeftValue.format == VALUE_TYPE_DOUBLE || RightValue.format == VALUE_TYPE_DOUBLE ? VALUE_TYPE_DOUBLE : VALUE_TYPE_FLOAT ; double l = LeftValue.format == VALUE_TYPE_DOUBLE ? LeftValue.d : LeftValue.f ; double r = RightValue.format == VALUE_TYPE_DOUBLE ? RightValue.d : RightValue.f ; switch ( GetOperator() ) { case OP_PLUS: l += r; break; case OP_MINUS: l -= r; break; case OP_STAR: l *= r; break; case OP_SLASH: __try { l /= r; } __except (EXCEPTION_EXECUTE_HANDLER) { fSuccess = FALSE; } break; } if (v.format == VALUE_TYPE_FLOAT) { v.f = (float) l; } else if (v.format == VALUE_TYPE_DOUBLE) { v.d = l; } } return fSuccess; }
BOOL expr_u_arithmetic::GetExprValue( SExprValue& v ) { SExprValue LeftValue = {VALUE_TYPE_UNDEFINED, 0}; BOOL fSuccess = GetLeft()->GetExprValue( LeftValue );
if (fSuccess) { v = LeftValue; if (GetOperator() == OP_UNARY_MINUS) { switch ( v.format ) { case VALUE_TYPE_FLOAT: v.f = -LeftValue.f; break; case VALUE_TYPE_DOUBLE: v.d = -LeftValue.d; break; default: fSuccess = FALSE; break; } } } return fSuccess; }
void expr_node::CopyTo( expr_node* lhs ) { DetermineType(); lhs->pType = pType; lhs->fFloatExpr = fFloatExpr; lhs->fConstant = fConstant; }
void expr_constant::CopyTo( expr_node* pExpr ) { expr_constant* lhs = (expr_constant*) pExpr; expr_node::CopyTo( lhs ); lhs->Format = Format; lhs->Value = Value; }
void expr_init_list::CopyTo( expr_node* pExpr ) { expr_init_list* lhs = (expr_init_list*) pExpr; expr_node::CopyTo( lhs ); lhs->pSibling = (expr_init_list*)pSibling->Clone(); pSibling->CopyTo(lhs->pSibling); lhs->pExpr = pExpr->Clone(); pExpr->CopyTo(lhs->pExpr); }
void expr_operator::CopyTo( expr_node* pExpr ) { expr_operator* lhs = (expr_operator*) pExpr; expr_node::CopyTo( lhs ); lhs->Operator = Operator; }
void expr_op_binary::CopyTo( expr_node* pExpr ) { expr_op_binary* lhs = (expr_op_binary*) pExpr; expr_operator::CopyTo( lhs ); lhs->pLeft = pLeft->Clone(); pLeft->CopyTo(lhs->pLeft); lhs->pRight = pRight->Clone(); pRight->CopyTo(lhs->pRight); }
void expr_param::CopyTo( expr_node* pExpr ) { expr_param* lhs = (expr_param*) pExpr; expr_op_binary::CopyTo( lhs ); _STRDUP( lhs->pName, pName ); }
void expr_op_unary::CopyTo( expr_node* pExpr ) { expr_op_unary* lhs = (expr_op_unary*) pExpr; expr_operator::CopyTo( lhs ); lhs->pLeft = pLeft->Clone(); pLeft->CopyTo(lhs->pLeft); }
void expr_cast::CopyTo( expr_node* pExpr ) { expr_cast* lhs = (expr_cast*) pExpr; expr_op_unary::CopyTo( lhs ); lhs->fEmitModifiers = fEmitModifiers; lhs->pCastType = pCastType; }
void expr_proc_call::CopyTo( expr_node* pExpr ) { expr_proc_call* lhs = (expr_proc_call*) pExpr; expr_op_unary::CopyTo( lhs ); _STRDUP( lhs->pName, pName ); lhs->NoOfParams = NoOfParams; }
void expr_sizeof::CopyTo( expr_node* pExpr ) { expr_sizeof* lhs = (expr_sizeof*) pExpr; expr_op_unary::CopyTo( lhs ); lhs->pType = pType; }
void expr_alignof::CopyTo( expr_node* pExpr ) { expr_alignof* lhs = (expr_alignof*) pExpr; expr_op_unary::CopyTo( lhs ); lhs->pType = pType; }
void expr_ternary::CopyTo( expr_node* pExpr ) { expr_ternary* lhs = (expr_ternary*) pExpr; expr_operator::CopyTo( lhs ); lhs->pLeft = pLeft->Clone(); pLeft->CopyTo(lhs->pLeft); lhs->pRight = pRight->Clone(); pRight->CopyTo(lhs->pRight); lhs->pRelational = pRelational->Clone(); pRelational->CopyTo(lhs->pRelational); }
void expr_variable::CopyTo( expr_node* pExpr ) { expr_variable* lhs = (expr_variable*) pExpr; expr_node::CopyTo( lhs ); _STRDUP( lhs->pIDName, pIDName ); _STRDUP( lhs->pPrefix, pPrefix ); }
expr_node* expr_ternary::Clone() { return new expr_ternary(OP_ILLEGAL,0,0,0); }
|