windows-nt/Source/XPSP1/NT/com/rpc/midl/inc/semantic.hxx
2020-09-26 16:20:57 +08:00

473 lines
18 KiB
C++

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989-1999 Microsoft Corporation
Module Name:
semantic.hxx
Abstract:
types for semantic analysis
Notes:
Author:
GregJen Sep-24-1993 Created.
Notes:
----------------------------------------------------------------------------*/
#ifndef __SEMANTIC_HXX__
#define __SEMANTIC_HXX__
#pragma warning ( disable : 4710 )
/****************************************************************************
* include files
***************************************************************************/
#include "listhndl.hxx"
#include "midlnode.hxx"
#include "attrlist.hxx"
#include "nodeskl.hxx"
#include "fldattr.hxx"
#include "walkctxt.hxx"
#include "gramutil.hxx"
#include "cmdana.hxx"
/****************************************************************************
* local data
***************************************************************************/
/****************************************************************************
* externs
***************************************************************************/
/****************************************************************************
* definitions
***************************************************************************/
/*
* here are flag bits passed down from parents to give info on the
* current path down the typegraph. These are dynamic information only,
* and are NOT to be stored with the node.
*
* Although a few of these bits are mutually exclusive, most may be used
* in combination.
*/
#define IN_INTERFACE 0x0000000000000001 // in the base interface
#define IN_PARAM_LIST 0x0000000000000002 // a descendant of a parameter
#define IN_FUNCTION_RESULT 0x0000000000000004 // used as (part of) a return type
#define IN_STRUCT 0x0000000000000008 // used in a struct
#define IN_UNION 0x0000000000000010 // used in a union
#define IN_ARRAY 0x0000000000000020 // used in an array
#define IN_POINTER 0x0000000000000040 // below a pointer
#define IN_RPC 0x0000000000000080 // in an RPC call
#define UNDER_IN_PARAM 0x0000000000000100 // in an IN parameter
#define UNDER_OUT_PARAM 0x0000000000000200 // in an OUT parameter
#define BINDING_SEEN 0x0000000000000400 // binding handle already seen
#define IN_TRANSMIT_AS 0x0000000000000800 // the transmitted type of transmit_as
#define IN_REPRESENT_AS 0x0000000000001000 // the "transmitted" type of represent_as
#define IN_USER_MARSHAL 0x0000000000002000 // transmitted type of
#define IN_HANDLE 0x0000000000004000 // under generic or context hdl
#define IN_NE_UNION 0x0000000000008000 // inside an non-encap union
#define IN_INTERPRET 0x0000000000010000 // in an /Oi proc
#define IN_NON_REF_PTR 0x0000000000020000 // under a series of unique/full ptrs
#define UNDER_TOPLEVEL 0x0000000000040000 // top-level under param
#define UNDER_TOPLVL_PTR 0x0000000000080000 // top-level under pointer param
#define IN_BASE_CLASS 0x0000000000100000 // checking class derivation tree
#define IN_PRESENTED_TYPE 0x0000000000200000 // the presented type of xmit/rep_as
#define IN_ROOT_CLASS 0x0000000000400000 // a method/definition in the root class
#define IN_ENCODE_INTF 0x0000000000800000 // inside an encode/decode only intf
#define IN_RECURSIVE_DEF 0x0000000001000000 // inside of a recursive definition
#define IN_OBJECT_INTF 0x0000000002000000 // in an object interface
#define IN_LOCAL_PROC 0x0000000004000000 // in a [local] proc
#define IN_INTERFACE_PTR 0x0000000008000000 // in the definition of an interface pointer
#define IN_MODULE 0x0000000010000000 // in a module
#define IN_COCLASS 0x0000000020000000 // in a coclass
#define IN_LIBRARY 0x0000000040000000 // in a library
#define IN_DISPINTERFACE 0x0000000080000000 // in a dispinterface
#define HAS_OLEAUTOMATION 0x0000000100000000 // has [oleautomation] attr
#define HAS_ASYNCHANDLE 0x0000000200000000 // has [async] attribute
#define HAS_AUTO_HANDLE 0x0000000400000000 // has auto_handle
#define HAS_EXPLICIT_HANDLE 0x0000000800000000 // has explicit_handle
#define HAS_IMPLICIT_HANDLE 0x0000001000000000 // has implicit_handle
#define IN_IADVISESINK 0x0000002000000000 // processing the children of IAdviseSink(*)
#define HAS_ASYNC_UUID 0x0000004000000000 // interface has [async_uuid]
#define HAS_MESSAGE 0x0000008000000000 // interface has [message]
#define UNDER_HIDDEN_STATUS 0x0000010000000000 // hidden status param
#define UNDER_PARTIAL_IGNORE_PARAM 0x0000020000000000 // Up to first ptr under partial_ignore
typedef __int64 ANCESTOR_FLAGS; // above enum goes into here
/*
* Here are flag bits returned UP from children to give info on the current
* path down the typegraph. Again, these are dynamic information.
*/
#define HAS_STRING 0x0000000000000001 // has [string] attr
#define HAS_IN 0x0000000000000002 // has [IN] attr
#define HAS_OUT 0x0000000000000004 // has [OUT] attr
#define HAS_HANDLE 0x0000000000000008 // is a handle
#define HAS_POINTER 0x0000000000000010 // has a pointer below
#define HAS_INCOMPLETE_TYPE 0x0000000000000020 // has incomplete type spec below
#define HAS_VAR_ARRAY 0x0000000000000040 // has varying array (incl string)
#define HAS_CONF_ARRAY 0x0000000000000080 // has conf array
#define HAS_CONF_VAR_ARRAY 0x0000000000000100 // has conf_var array
#define DERIVES_FROM_VOID 0x0000000000000200 // derives from void
#define HAS_UNSAT_REP_AS 0x0000000000000400 // has unsatisfied rep_as
#define HAS_CONTEXT_HANDLE 0x0000000000000800 // has context handle below
#define HAS_CONF_PTR 0x0000000000001000 // has conformant pointer
#define HAS_VAR_PTR 0x0000000000002000 // has varying pointer
#define HAS_CONF_VAR_PTR 0x0000000000004000 // has conformant varying pointer
#define HAS_TRANSMIT_AS 0x0000000000008000 // has transmit_as below
#define HAS_REPRESENT_AS 0x0000000000010000 // has represent_as below
#define HAS_E_STAT_T 0x0000000000020000 // has error_status_t below
#define HAS_UNION 0x0000000000040000 // has union below
#define HAS_ARRAY 0x0000000000080000 // has array below
#define HAS_INTERFACE_PTR 0x0000000000100000 // has an interface ptr below
#define HAS_DIRECT_CONF_OR_VAR 0x0000000000200000 // has direct conformance or variance
#define HAS_RECURSIVE_DEF 0x0000000000400000 // is defined recursively
#define HAS_ENUM 0x0000000000800000 // has an enum directly or embedded
#define HAS_FUNC 0x0000000001000000 // has a function below
#define HAS_FULL_PTR 0x0000000002000000 // has full pointers anywhere
#define HAS_TOO_BIG_HDL 0x0000000004000000 // is /Oi but handle is too big
#define HAS_STRUCT 0x0000000008000000 // has struct
#define HAS_MULTIDIM_SIZING 0x0000000010000000 // has multi-dimensions
#define HAS_ARRAY_OF_REF 0x0000000020000000 // has array of ref pointers
#define HAS_HRESULT 0x0000000040000000 // has HRESULT
#define HAS_PIPE 0x0000000080000000 // has a PIPE
#define HAS_DEFAULT_VALUE 0x0000000100000000 // has [defaultvalue] attribute
#define HAS_SERVER_CORRELATION 0x0000000200000000 // server correlation
#define HAS_CLIENT_CORRELATION 0x0000000400000000 // client correlation
#define HAS_MULTIDIM_VECTOR 0x0000000800000000 // has multi dim array or sized ptrs
#define HAS_SIZED_ARRAY 0x0000001000000000 // not a fixed array
#define HAS_SIZED_PTR 0x0000002000000000 //
#define HAS_IN_CSTYPE 0x0000004000000000 // has in international chars
#define HAS_OUT_CSTYPE 0x0000008000000000 // has out international chars
#define HAS_DRTAG 0x0000010000000000 // some param has [cs_drtag]
#define HAS_RTAG 0x0000020000000000 // some param has [cs_rtag]
#define HAS_STAG 0x0000040000000000 // some param has [cs_stag]
#define HAS_PARTIAL_IGNORE 0x0000080000000000 // some param has [partial_ignore]
#define HAS_FORCEALLOCATE 0x0000100000000000 // some param has [force_allocate]
#define HAS_ARRAYOFPOINTERS 0x0000200000000000 // has an array of pointers
typedef __int64 DESCENDANT_FLAGS; // above defines goes into here
/*
* Here is the context information passed down from parent to child.
* These will be allocated on the stack during the traversal
*/
class node_interface;
class type_node_list;
class ATTRLIST;
class SEM_ANALYSIS_CTXT: public WALK_CTXT
{
private:
unsigned long ulCorrelations;
public:
struct _current_ctxt {
// down stuff
ANCESTOR_FLAGS AncestorBits; // where am I? stuff
// up stuff
DESCENDANT_FLAGS DescendantBits;
} CurrentCtxt;
// constructor and destructor
SEM_ANALYSIS_CTXT(node_skl * Me)
: WALK_CTXT( Me )
{
GetAncestorBits() = 0;
GetDescendantBits() = 0;
ulCorrelations = 0;
}
SEM_ANALYSIS_CTXT(node_skl * Me,
SEM_ANALYSIS_CTXT * pParentCtxt )
: WALK_CTXT( Me, pParentCtxt )
{
// clone information from parent node
CurrentCtxt = pParentCtxt->CurrentCtxt;
// get fresh information from our children
GetDescendantBits() = 0;
// remove any inapplicable attributes
CheckAttributes();
ulCorrelations = 0;
}
SEM_ANALYSIS_CTXT(SEM_ANALYSIS_CTXT * pParentCtxt )
: WALK_CTXT( pParentCtxt )
{
// clone information from parent node
CurrentCtxt = pParentCtxt->CurrentCtxt;
// get fresh information from our children
GetDescendantBits() = 0;
ulCorrelations = 0;
}
ANCESTOR_FLAGS& GetAncestorBits()
{
return CurrentCtxt.AncestorBits;
}
ANCESTOR_FLAGS& SetAncestorBits( ANCESTOR_FLAGS f )
{
CurrentCtxt.AncestorBits |= f;
return CurrentCtxt.AncestorBits;
}
ANCESTOR_FLAGS& ClearAncestorBits( ANCESTOR_FLAGS f )
{
CurrentCtxt.AncestorBits &= ~f;
return CurrentCtxt.AncestorBits;
}
BOOL AnyAncestorBits( ANCESTOR_FLAGS f )
{
return ((CurrentCtxt.AncestorBits & f) != 0);
}
BOOL AllAncestorBits( ANCESTOR_FLAGS f )
{
return ((CurrentCtxt.AncestorBits & f) == f);
}
DESCENDANT_FLAGS& GetDescendantBits()
{
return CurrentCtxt.DescendantBits;
}
DESCENDANT_FLAGS& SetDescendantBits( DESCENDANT_FLAGS f )
{
CurrentCtxt.DescendantBits |= f;
return CurrentCtxt.DescendantBits;
}
DESCENDANT_FLAGS& ClearDescendantBits( DESCENDANT_FLAGS f )
{
CurrentCtxt.DescendantBits &= ~f;
return CurrentCtxt.DescendantBits;
}
DESCENDANT_FLAGS& ClearAllDescendantBits( )
{
CurrentCtxt.DescendantBits = 0;
return CurrentCtxt.DescendantBits;
}
BOOL AnyDescendantBits( DESCENDANT_FLAGS f )
{
return ( ( CurrentCtxt.DescendantBits & f ) != 0 );
}
BOOL AllDescendantBits( DESCENDANT_FLAGS f )
{
return ((CurrentCtxt.DescendantBits & f) == f);
}
void ReturnValues( SEM_ANALYSIS_CTXT & ChildCtxt )
{
// pass up the return context
GetDescendantBits() |= ChildCtxt.GetDescendantBits();
ulCorrelations += ChildCtxt.GetCorrelationCount();
}
unsigned long GetCorrelationCount( void )
{
return ulCorrelations;
}
void IncCorrelationCount( unsigned long ulInc = 1 )
{
ulCorrelations += ulInc;
}
void ResetCorrelationCount()
{
ulCorrelations = 0;
}
void ResetDownValues( SEM_ANALYSIS_CTXT & ParentCtxt )
{
// reset the down values from the parent
// (semantically different, but really the same code )
ReturnValues( ParentCtxt );
}
void CheckAttributes();
void RejectAttributes();
}; // end of class SEM_ANALYSIS_CTXT
inline void
RpcSemError( node_skl * pNode,
SEM_ANALYSIS_CTXT & Ctxt,
STATUS_T ErrNum,
char * pExtra )
{
if ( Ctxt.AnyAncestorBits( IN_RPC ) &&
!Ctxt.AnyAncestorBits( IN_LOCAL_PROC ) )
SemError( pNode, Ctxt, ErrNum, pExtra );
}
inline void
TypeSemError( node_skl * pNode,
SEM_ANALYSIS_CTXT & Ctxt,
STATUS_T ErrNum,
char * pExtra )
{
if ( !Ctxt.AnyAncestorBits( IN_LOCAL_PROC ) )
SemError( pNode, Ctxt, ErrNum, pExtra );
}
// prototype for semantic advice routines
inline void
SemAdvice( node_skl * pNode,
WALK_CTXT & Ctxt,
STATUS_T ErrVal,
char * pSuffix )
{
if ( pCommand->IsMintRun() )
SemError( pNode, Ctxt, ErrVal, pSuffix );
}
class acf_attr;
extern void
AcfError( acf_attr*, node_skl *, WALK_CTXT &, STATUS_T, char * );
/////////////////////////////////////////////
//
// expression analysis flags (passed up)
enum _EXPR_UP_FLAGS
{
EX_NONE = 0x0000,
EX_VALUE_INVALID = 0x0001, // value is NOT valid
EX_UNSAT_FWD = 0x0002, // there is an unsatisfied fwd
EX_NON_NUMERIC = 0x0004, // expr not entirely numerics
// (can not be constant folded)
EX_OUT_ONLY_PARAM = 0x0008, // expression includes an out-only param
EX_PTR_FULL_UNIQUE = 0x0010, // has ptr deref of full or unique ptr
EX_HYPER_IN_EXPR = 0x0020, // expr has a hyper item in it
};
typedef unsigned short EXPR_UP_FLAGS;
////////////////////////////////////////////
// expression context block
class EXPR_CTXT;
class EXPR_CTXT
{
private:
// passed down
EXPR_CTXT * pParent;
SEM_ANALYSIS_CTXT * pSemCtxt;
// passed up
EXPR_VALUE CurValue;
EXPR_UP_FLAGS Flags;
public:
// type info
node_skl * pType;
struct _type_ana TypeInfo;
BOOL fIntegral; // type is an integral type (above are valid)
EXPR_CTXT( EXPR_CTXT * pMy ) : pType( 0 ), fIntegral( FALSE )
{
TypeInfo.TypeSize =
TypeInfo.BaseType =
TypeInfo.TypeSign =
TypeInfo.TypeAttrib = 0;
pParent = pMy;
pSemCtxt = pMy->pSemCtxt;
CurValue = 0;
Flags = EX_NONE;
}
EXPR_CTXT( SEM_ANALYSIS_CTXT * pSCtxt ) : pType( 0 ), fIntegral( FALSE )
{
TypeInfo.TypeSize =
TypeInfo.BaseType =
TypeInfo.TypeSign =
TypeInfo.TypeAttrib = 0;
pParent = NULL;
pSemCtxt = pSCtxt;
CurValue = 0;
Flags = EX_NONE;
}
// automatically pass up the flags
~EXPR_CTXT()
{
if ( pParent )
pParent->Flags |= Flags;
}
EXPR_VALUE& Value()
{
return CurValue;
}
EXPR_UP_FLAGS& MergeUpFlags( EXPR_CTXT * pC )
{
Flags |= pC->Flags;
return Flags;
}
EXPR_UP_FLAGS& SetUpFlags( EXPR_UP_FLAGS f )
{
Flags |= f;
return Flags;
}
EXPR_UP_FLAGS& ClearUpFlags( EXPR_UP_FLAGS f )
{
Flags &= ~f;
return Flags;
}
BOOL AnyUpFlags( EXPR_UP_FLAGS f )
{
return (Flags & f);
}
BOOL AllUpFlags( EXPR_UP_FLAGS f )
{
return ((Flags & f) == f);
}
node_skl* GetNode()
{
return pSemCtxt->GetParent();
}
SEM_ANALYSIS_CTXT * GetCtxt()
{
return pSemCtxt;
}
};
#endif // __SEMANTIC_HXX__