2075 lines
55 KiB
C++
2075 lines
55 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
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);
|
|
}
|