windows-nt/Source/XPSP1/NT/com/rpc/midl/front/fldattr.cxx

911 lines
22 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989-1999 Microsoft Corporation
Module Name:
fldattr.cxx
Abstract:
field attribute handling routines
Notes:
Author:
GregJen Oct-27-1993 Created.
Notes:
----------------------------------------------------------------------------*/
#pragma warning ( disable : 4514 )
/****************************************************************************
* include files
***************************************************************************/
#include "allnodes.hxx"
#include "fldattr.hxx"
#include "semantic.hxx"
/****************************************************************************
* local data
***************************************************************************/
expr_constant * pZero = NULL;
expr_constant * pOne = NULL;
node_skl * pInt = NULL;
/****************************************************************************
* externs
***************************************************************************/
/****************************************************************************
* definitions
***************************************************************************/
/////////////////
// helper routines for Normalize functions;
//Don't add or subtract 0.
expr_node *
CreateSimpleBinaryArithExpression(
OPERATOR Op,
expr_node * pL,
expr_node * pR
)
{
MIDL_ASSERT( (Op==OP_PLUS) || (Op==OP_MINUS) );
MIDL_ASSERT( pL );
MIDL_ASSERT( pR );
if ( pR->IsConstant() && (pR->GetValue() == 0) )
return pL;
if ( pL->IsConstant() && (pL->GetValue() == 0) )
return pR;
expr_node * pRet = new expr_b_arithmetic( Op, pL, pR );
if ( pL->GetType() )
pRet->SetType( pL->GetType() );
else if ( pR->GetType() )
pRet->SetType( pR->GetType() );
else
MIDL_ASSERT( !"no type for expression" );
return pRet;
}
// return the constant 0 over and over
expr_constant *
GetConstant0()
{
if ( pZero ) return pZero;
pZero = new expr_constant( 0L, VALUE_TYPE_NUMERIC );
if ( !pInt )
GetBaseTypeNode( &pInt, SIGN_SIGNED, SIZE_UNDEF, TYPE_INT );
pZero->SetType( pInt );
return pZero;
}
// return the constant 1 over and over
expr_constant *
GetConstant1()
{
if ( pOne ) return pOne;
pOne = new expr_constant( 1L, VALUE_TYPE_NUMERIC );
if ( !pInt )
GetBaseTypeNode( &pInt, SIGN_SIGNED, SIZE_UNDEF, TYPE_INT );
pOne->SetType( pInt );
return pOne;
}
BOOL
IsInValidOutOnly( SEM_ANALYSIS_CTXT * pCtxt )
{
// an out-only size is valid only on out-only non-top-level things
// in, in/out things not allowed
if ( pCtxt->AnyAncestorBits( UNDER_IN_PARAM ) )
return TRUE;
// look up the stack for a pointer (or array) that is unique
SEM_ANALYSIS_CTXT * pCurCtxt = pCtxt;
NODE_T Kind;
node_skl * pNode;
while ( pCurCtxt )
{
pNode = pCurCtxt->GetParent();
Kind = pNode->NodeKind();
switch ( Kind )
{
case NODE_DEF:
case NODE_ARRAY:
break;
case NODE_POINTER:
if ( pCtxt->AnyAncestorBits( IN_NON_REF_PTR ) )
return FALSE;
break;
case NODE_PARAM:
case NODE_PROC:
default:
return TRUE;
}
pCurCtxt = ( SEM_ANALYSIS_CTXT * ) pCurCtxt->GetParentContext();
}
return TRUE;
}
BOOL Xxx_Is_Type_OK( node_skl * pType)
{
if ( !pType )
return FALSE;
for (;;)
{
switch ( pType->NodeKind() )
{
case NODE_PARAM:
case NODE_FIELD:
if ( !pType->GetChild() )
return FALSE;
break;
// make sure that there is no transmit_as or represent_as
case NODE_DEF:
if ( pType->FInSummary( ATTR_TRANSMIT ) ||
pType->FInSummary( ATTR_REPRESENT_AS ) ||
pType->FInSummary( ATTR_USER_MARSHAL ) ||
pType->FInSummary( ATTR_WIRE_MARSHAL ) )
return FALSE;
break;
// for an ID, make sure it is a const decl, then use its type
case NODE_ID:
{
node_id * pID = (node_id *) pType;
if ( !pID->pInit )
return FALSE;
break;
}
case NODE_ENUM:
case NODE_LONG:
case NODE_SHORT:
case NODE_INT:
case NODE_INT32:
case NODE_SMALL:
case NODE_CHAR:
case NODE_BOOLEAN:
case NODE_BYTE:
return TRUE;
// 64b expr support
case NODE_INT3264:
case NODE_INT64:
case NODE_HYPER:
return FALSE;
// no 128b expr support
case NODE_INT128:
case NODE_FLOAT80:
case NODE_FLOAT128:
return FALSE;
default:
return FALSE;
}
pType = pType->GetChild();
}
}
BOOL IID_Is_Type_OK( node_skl * pType )
{
if ( !pType )
return FALSE;
for (;;)
{
switch ( pType->NodeKind() )
{
case NODE_PARAM:
case NODE_FIELD:
if ( !pType->GetChild() )
return FALSE;
break;
case NODE_DEF:
if ( pType->FInSummary( ATTR_TRANSMIT ) ||
pType->FInSummary( ATTR_REPRESENT_AS ) ||
pType->FInSummary( ATTR_USER_MARSHAL ) ||
pType->FInSummary( ATTR_WIRE_MARSHAL ) )
return FALSE;
break;
case NODE_POINTER:
if ( pType->GetChild() )
return ( 16 == pType->GetChild()->GetSize() );
default:
return FALSE;
}
pType = pType->GetChild();
}
}
// validate the bunch of attributes for pointers: check combinations, ranges,
// and expressions
void
FIELD_ATTR_INFO::Validate( SEM_ANALYSIS_CTXT * pCtxt )
{
if ( Kind == FA_NONE )
return;
node_skl * pParent = pCtxt->GetParent();
// things to check:
// expression types (must be integral types)
if ( pMaxIsExpr )
{
EXPR_CTXT MaxCtxt( pCtxt );
pMaxIsExpr->ExprAnalyze( &MaxCtxt );
if ( MaxCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( MaxCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) && IsInValidOutOnly( pCtxt ) )
RpcSemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
if ( !MaxCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pMaxIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
RpcSemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pMinIsExpr )
{
EXPR_CTXT MinCtxt( pCtxt );
pMinIsExpr->ExprAnalyze( &MinCtxt );
if ( MinCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
RpcSemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( MinCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) && IsInValidOutOnly( pCtxt ) )
SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
if ( !MinCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pMinIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pSizeIsExpr )
{
EXPR_CTXT SizeCtxt( pCtxt );
pSizeIsExpr->ExprAnalyze( &SizeCtxt );
if ( SizeCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( SizeCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) && IsInValidOutOnly( pCtxt ) )
SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
if ( !SizeCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pSizeIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pFirstIsExpr )
{
EXPR_CTXT FirstCtxt( pCtxt );
pFirstIsExpr->ExprAnalyze( &FirstCtxt );
if ( FirstCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( !FirstCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pFirstIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pLastIsExpr )
{
EXPR_CTXT LastCtxt( pCtxt );
pLastIsExpr->ExprAnalyze( &LastCtxt );
if ( LastCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( !LastCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pLastIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pLengthIsExpr )
{
EXPR_CTXT LengthCtxt( pCtxt );
pLengthIsExpr->ExprAnalyze( &LengthCtxt );
if ( LengthCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( !LengthCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pLengthIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pIIDIsExpr )
{
EXPR_CTXT IIDCtxt( pCtxt );
pIIDIsExpr->ExprAnalyze( &IIDCtxt );
if ( IIDCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( !IIDCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !IID_Is_Type_OK( pIIDIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, IID_IS_EXPR_NON_POINTER, NULL );
}
// min_is == 0 ( for now )
// constant min_is <= constant max_is
// size_is not with max_is
if ( pMaxIsExpr && pSizeIsExpr )
SemError( pParent, *pCtxt, MAX_AND_SIZE, NULL );
// min_is not alone
// constant first_is <= constant last_is + 1
// length_is not with last_is
if ( pLengthIsExpr && pLastIsExpr )
SemError( pParent, *pCtxt, LAST_AND_LENGTH, NULL );
// constant first_is, last_is both within min<->max range
// length_is <= size_is
// string attrs not with varying attrs
// string and bstring not together
// conformant strings may leave out size_is if [in] or [in,out]
// accept the NULL value ( turn expression back null, clear kind bits )
// make sure variables come from the correct context
// lengthed, unsized pointer
if ( ( pLengthIsExpr || pFirstIsExpr || pLastIsExpr || pMinIsExpr) &&
!( pSizeIsExpr || pMaxIsExpr ) )
SemError( pParent, *pCtxt, UNSIZED_ARRAY, NULL );
}
void
FIELD_ATTR_INFO::Validate( SEM_ANALYSIS_CTXT * pCtxt,
expr_node * pLower,
expr_node * pUpper )
{
node_skl * pParent = pCtxt->GetParent();
if ( pUpper == (expr_node *) -1 )
{
pUpper = NULL;
Kind |= FA_CONFORMANT;
}
else if ( pUpper )
{
if ( pUpper->GetValue() <= 0 )
{
SemError( pParent, *pCtxt, ILLEGAL_ARRAY_BOUNDS, NULL );
}
}
if ( pLower &&
( pLower != (expr_node *) -1 ) &&
( pLower->GetValue() != 0 ) )
{
SemError( pParent, *pCtxt, ARRAY_BOUNDS_CONSTRUCT_BAD, NULL );
}
if ( pUpper && ( pMaxIsExpr || pSizeIsExpr ) )
{
SemError( pParent, *pCtxt, SIZING_ON_FIXED_ARRAYS, NULL );
}
// things to check:
// expression types (must be integral types)
if ( pMaxIsExpr )
{
EXPR_CTXT MaxCtxt( pCtxt );
pMaxIsExpr->ExprAnalyze( &MaxCtxt );
if ( MaxCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( MaxCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) )
SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
if ( !MaxCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pMaxIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pMinIsExpr )
{
EXPR_CTXT MinCtxt( pCtxt );
pMinIsExpr->ExprAnalyze( &MinCtxt );
if ( MinCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( MinCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) )
SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
if ( !MinCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pMinIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pSizeIsExpr )
{
EXPR_CTXT SizeCtxt( pCtxt );
pSizeIsExpr->ExprAnalyze( &SizeCtxt );
if ( SizeCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( SizeCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) )
SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
if ( !SizeCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pSizeIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pFirstIsExpr )
{
EXPR_CTXT FirstCtxt( pCtxt );
pFirstIsExpr->ExprAnalyze( &FirstCtxt );
if ( FirstCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( !FirstCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pFirstIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pLastIsExpr )
{
EXPR_CTXT LastCtxt( pCtxt );
pLastIsExpr->ExprAnalyze( &LastCtxt );
if ( LastCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( !LastCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pLastIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pLengthIsExpr )
{
EXPR_CTXT LengthCtxt( pCtxt );
pLengthIsExpr->ExprAnalyze( &LengthCtxt );
if ( LengthCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
if ( !LengthCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
if ( !Xxx_Is_Type_OK( pLengthIsExpr->GetType() ) &&
pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
}
if ( pIIDIsExpr )
{
SemError( pParent, *pCtxt, IID_IS_NON_POINTER, NULL );
}
// min_is == 0 ( for now )
// constant min_is <= constant max_is
// size_is not with max_is
if ( pMaxIsExpr && pSizeIsExpr )
SemError( pParent, *pCtxt, MAX_AND_SIZE, NULL );
// a conformant unsized array:
// must have string
// must not be out_only
if ( ( Kind & FA_CONFORMANT ) && !pMaxIsExpr && !pSizeIsExpr && !pUpper )
{
if ( !( Kind & FA_STRING ) )
{
if ( pCtxt->AnyAncestorBits( IN_RPC ) )
SemError( pParent, *pCtxt, UNSIZED_ARRAY, NULL );
}
else
{
if ( pCtxt->AllAncestorBits( IN_RPC |
IN_PARAM_LIST |
UNDER_OUT_PARAM ) &&
!pCtxt->AnyAncestorBits( UNDER_IN_PARAM ) )
SemError( pParent, *pCtxt, DERIVES_FROM_UNSIZED_STRING, NULL );
}
}
// min_is not alone
// constant first_is <= constant last_is + 1
// length_is not with last_is
if ( pLengthIsExpr && pLastIsExpr )
SemError( pParent, *pCtxt, LAST_AND_LENGTH, NULL );
// constant first_is, last_is both within min<->max range
// length_is <= size_is
// string attrs not with varying attrs
// string and bstring not together
// conformant strings may leave out size_is if [in] or [in,out]
// accept the NULL value ( turn expression back null, clear kind bits )
// make sure variables come from the correct context
}
//
// normalize for pointers ( no default bound )
void
FIELD_ATTR_INFO::Normalize()
{
expr_node * pTmp1;
expr_node * pTmp2;
// convert the set: min_is, max_is, size_is to min_is + size_is
if ( Kind & FA_CONFORMANT )
{
// default min_is is 0
if ( ! pMinIsExpr )
{
pMinIsExpr = GetConstant0();
}
// size_is = (max_is - min_is) + 1;
if ( ! pSizeIsExpr )
{
if ( pMaxIsExpr )
{
pTmp1 = GetConstant1();
pTmp2 = CreateSimpleBinaryArithExpression( OP_MINUS, pMaxIsExpr, pMinIsExpr);
pSizeIsExpr = CreateSimpleBinaryArithExpression( OP_PLUS, pTmp2, pTmp1 );
}
}
}
// convert the set: first_is, last_is, length_is to: first_is + length_is
if ( Kind & FA_VARYING )
{
// default first_is is 0
if ( ! pFirstIsExpr )
{
pFirstIsExpr = GetConstant0();
}
// default last_is is max_is or size_is+1
if ( ! pLastIsExpr )
{
if ( pMaxIsExpr )
pLastIsExpr = pMaxIsExpr;
else if ( pSizeIsExpr )
pLastIsExpr = CreateSimpleBinaryArithExpression( OP_MINUS, pSizeIsExpr, GetConstant1() );
}
// length_is = (last_is - first_is) + 1;
if ( ! pLengthIsExpr )
{
if ( pLastIsExpr )
{
pTmp1 = GetConstant1();
pTmp2 = CreateSimpleBinaryArithExpression( OP_MINUS, pLastIsExpr, pFirstIsExpr);
pLengthIsExpr = CreateSimpleBinaryArithExpression( OP_PLUS, pTmp2, pTmp1 );
}
}
}
}
// normalize for arrays (provided lower and upper bound)
void
FIELD_ATTR_INFO::Normalize(expr_node * pLower, expr_node * pUpper)
{
expr_node * pTmp1;
expr_node * pTmp2;
BOOL OneBound = FALSE;
if ( pLower == (expr_node *) 0 )
{
pLower = GetConstant0();
OneBound = TRUE;
}
if ( pUpper == (expr_node *) -1 )
{
pUpper = NULL;
Kind |= FA_CONFORMANT;
}
// convert the set: min_is, max_is, size_is to: min_is + size_is
// first, copy from the bounds
if ( ! pMinIsExpr )
{
pMinIsExpr = pLower;
}
if ( ! pMaxIsExpr && ! pSizeIsExpr && pUpper )
{
// note that the [n..m] case has m already incremented by 1
pTmp1 = GetConstant1();
pMaxIsExpr = CreateSimpleBinaryArithExpression( OP_MINUS, pUpper, pTmp1 );
}
// size_is = (max_is - min_is) + 1;
if ( ! pSizeIsExpr )
{
if ( pMaxIsExpr )
{
pTmp1 = GetConstant1();
pTmp2 = CreateSimpleBinaryArithExpression( OP_MINUS, pMaxIsExpr, pMinIsExpr);
pSizeIsExpr = CreateSimpleBinaryArithExpression( OP_PLUS, pTmp2, pTmp1 );
}
}
// convert the set: first_is, last_is, length_is to: first_is + length_is
// default first_is is min_is
if ( ! pFirstIsExpr )
{
pFirstIsExpr = pMinIsExpr;
}
// default last_is is max_is or size_is+1
if ( ! pLastIsExpr )
{
if ( pMaxIsExpr )
pLastIsExpr = pMaxIsExpr;
else if ( pSizeIsExpr )
pLastIsExpr = CreateSimpleBinaryArithExpression( OP_MINUS, pSizeIsExpr, GetConstant1() );
}
// length_is = (last_is - first_is) + 1;
if ( ! pLengthIsExpr )
{
if ( pLastIsExpr )
{
pTmp1 = GetConstant1();
pTmp2 = CreateSimpleBinaryArithExpression( OP_MINUS, pLastIsExpr, pFirstIsExpr);
pLengthIsExpr = CreateSimpleBinaryArithExpression( OP_PLUS, pTmp2, pTmp1 );
}
}
}
bool
FIELD_ATTR_INFO::VerifyOnlySimpleExpression()
{
const int nExprTypes = 7;
expr_node *pExpr[nExprTypes] =
{
pSizeIsExpr,
pMinIsExpr,
pMaxIsExpr,
pLengthIsExpr,
pFirstIsExpr,
pIIDIsExpr,
pLastIsExpr,
};
for ( int i = 0; i < nExprTypes; i++ )
{
// No expression is ok
if ( NULL == pExpr[i] )
continue;
// A simple variable is ok
if ( pExpr[i]->IsAVariable() )
continue;
// A pointer to a simple variable is ok
if ( OP_UNARY_INDIRECTION == pExpr[i]->GetOperator()
&& pExpr[i]->GetLeft()->IsAVariable() )
{
continue;
}
// Everything else is not ok
return false;
}
return true;
}
BOOL
FIELD_ATTR_INFO::SetExpressionVariableUsage( SIZE_LENGTH_USAGE )
{
return TRUE;
}
#if 0
BUGBUG: CG_INTERFACE_POINTER has a bug. See nodeskl.h for details
BOOL
FIELD_ATTR_INFO::SetExpressionVariableUsage( SIZE_LENGTH_USAGE usage )
{
const int nExprTypes = 7;
expr_node *pExpr[nExprTypes] =
{
pSizeIsExpr,
pMinIsExpr,
pMaxIsExpr,
pLengthIsExpr,
pFirstIsExpr,
pIIDIsExpr,
pLastIsExpr,
};
for ( int i = 0; i < nExprTypes; i++ )
if ( ! SetExpressionVariableUsage( pExpr[i], usage ) )
return false;
return true;
}
BOOL
FIELD_ATTR_INFO::SetExpressionVariableUsage(
expr_node *pExpr,
SIZE_LENGTH_USAGE usage )
{
if ( !pExpr )
return true;
if ( pExpr->IsAVariable() )
{
node_skl *pParent = NULL;
node_skl *pType = pExpr->GetType();
while ( NULL != pType && !pType->IsBasicType() )
{
pParent = pType;
pType = pType->GetChild();
}
if ( NULL != pType && pType->IsBasicType() )
{
SIZE_LENGTH_USAGE TypeUsage = ((node_base_type *) pType)
->GetSizeLengthUsage();
if ( CSSizeLengthUsage == usage
&& NoSizeLengthUsage != TypeUsage )
{
return FALSE;
}
if ( CSSizeLengthUsage == TypeUsage
&& NoSizeLengthUsage != usage )
{
return FALSE;
}
if ( NoSizeLengthUsage != usage )
{
// Typically base type nodes are preallocated and identical.
// Pointing at them with size_is, etc makes the different
// because we need to note that fact. So clone it to get
// a new one.
MIDL_ASSERT( NULL != pParent );
pType = new node_base_type( (node_base_type *) pType );
((node_base_type *) pType)->SetSizeLengthUsage( usage );
pParent->SetChild( pType );
}
}
}
if ( ! SetExpressionVariableUsage( pExpr->GetLeft(), usage ) )
return false;
return SetExpressionVariableUsage( pExpr->GetRight(), usage );
}
#endif