/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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__