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