/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 1989 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__ /**************************************************************************** * 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. */ enum _ANCESTOR_FLAGS { // you are: IN_INTERFACE = 0x00000001, // in the base interface IN_PARAM_LIST = 0x00000002, // a descendant of a parameter IN_FUNCTION_RESULT = 0x00000004, // used as (part of) a return type IN_STRUCT = 0x00000008, // used in a struct IN_UNION = 0x00000010, // used in a union IN_ARRAY = 0x00000020, // used in an array IN_POINTER = 0x00000040, // below a pointer IN_RPC = 0x00000080, // in an RPC call UNDER_IN_PARAM = 0x00000100, // in an IN parameter UNDER_OUT_PARAM = 0x00000200, // in an OUT parameter BINDING_SEEN = 0x00000400, // binding handle already seen IN_TRANSMIT_AS = 0x00000800, // the transmitted type of transmit_as IN_REPRESENT_AS = 0x00001000, // the "transmitted" type of represent_as IN_USER_MARSHAL = 0x00002000, // transmitted type of IN_HANDLE = 0x00004000, // under generic or context hdl IN_NE_UNION = 0x00008000, // inside an non-encap union IN_INTERPRET = 0x00010000, // in an /Oi proc IN_NON_REF_PTR = 0x00020000, // under a series of unique/full ptrs UNDER_TOPLEVEL = 0x00040000, // top-level under param UNDER_TOPLVL_PTR = 0x00080000, // top-level under pointer param IN_BASE_CLASS = 0x00100000, // checking class derivation tree IN_PRESENTED_TYPE = 0x00200000, // the presented type of xmit/rep_as IN_ROOT_CLASS = 0x00400000, // a method/definition in the root class // (i.e. IUnknown) IN_ENCODE_INTF = 0x00800000, // inside an encode/decode only intf IN_RECURSIVE_DEF = 0x01000000, // inside of a recursive definition // be sure to make sure below type fits the range IN_OBJECT_INTF = 0x02000000, // in an object interface IN_LOCAL_PROC = 0x04000000, // in a [local] proc IN_INTERFACE_PTR = 0x08000000, // in the definition of an interface pointer IN_MODULE = 0x10000000, // in a module IN_COCLASS = 0x20000000, // in a coclass IN_LIBRARY = 0x40000000, // in a library IN_DISPINTERFACE = 0x80000000, // in a dispinterface }; typedef unsigned long 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. */ enum _DESCENDANT_FLAGS { UNUSED_UNUSED_1 = 0x00000001, // *** free bit position HAS_IN = 0x00000002, // has [IN] attr HAS_OUT = 0x00000004, // has [OUT] attr HAS_HANDLE = 0x00000008, // is a handle HAS_POINTER = 0x00000010, // has a pointer below HAS_INCOMPLETE_TYPE = 0x00000020, // has incomplete type spec below HAS_VAR_ARRAY = 0x00000040, // has varying array (incl string) HAS_CONF_ARRAY = 0x00000080, // has conf array HAS_CONF_VAR_ARRAY = 0x00000100, // has conf_var array DERIVES_FROM_VOID = 0x00000200, // derives from void HAS_UNSAT_REP_AS = 0x00000400, // has unsatisfied rep_as HAS_CONTEXT_HANDLE = 0x00000800, // has context handle below HAS_CONF_PTR = 0x00001000, // has conformant pointer HAS_VAR_PTR = 0x00002000, // has varying pointer HAS_CONF_VAR_PTR = 0x00004000, // has conformant varying pointer HAS_TRANSMIT_AS = 0x00008000, // has transmit_as below HAS_REPRESENT_AS = 0x00010000, // has represent_as below HAS_E_STAT_T = 0x00020000, // has error_status_t below HAS_UNION = 0x00040000, // has union below HAS_ARRAY = 0x00080000, // has array below HAS_INTERFACE_PTR = 0x00100000, // has an interface ptr below HAS_DIRECT_CONF_OR_VAR = 0x00200000, // has direct conformance or variance HAS_RECURSIVE_DEF = 0x00400000, // is defined recursively HAS_ENUM = 0x00800000, // has an enum directly or embedded HAS_FUNC = 0x01000000, // has a function below HAS_FULL_PTR = 0x02000000, // has full pointers anywhere HAS_TOO_BIG_HDL = 0x04000000, // is /Oi but handle is too big HAS_STRUCT = 0x08000000, // has struct HAS_MULTIDIM_SIZING = 0x10000000, // has multi-dimensions HAS_ARRAY_OF_REF = 0x20000000, // has array of ref pointers HAS_HRESULT = 0x40000000, // has HRESULT HAS_PIPE = 0x80000000, // has a PIPE // more tbd // be sure to make sure below type fits the range }; typedef unsigned long DESCENDANT_FLAGS; // above enum 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 { 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; } 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(); } 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; } 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); } 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); } BOOL AllDescendantBits( DESCENDANT_FLAGS f ) { return ((CurrentCtxt.DescendantBits & f) == f); } void ReturnValues( SEM_ANALYSIS_CTXT & ChildCtxt ) { // pass up the return context GetDescendantBits() |= ChildCtxt.GetDescendantBits(); } 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 ) { pParent = pMy; pSemCtxt = pMy->pSemCtxt; CurValue = 0; Flags = EX_NONE; } EXPR_CTXT( SEM_ANALYSIS_CTXT * pSCtxt ) { 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__