Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

472 lines
18 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. semantic.hxx
  5. Abstract:
  6. types for semantic analysis
  7. Notes:
  8. Author:
  9. GregJen Sep-24-1993 Created.
  10. Notes:
  11. ----------------------------------------------------------------------------*/
  12. #ifndef __SEMANTIC_HXX__
  13. #define __SEMANTIC_HXX__
  14. #pragma warning ( disable : 4710 )
  15. /****************************************************************************
  16. * include files
  17. ***************************************************************************/
  18. #include "listhndl.hxx"
  19. #include "midlnode.hxx"
  20. #include "attrlist.hxx"
  21. #include "nodeskl.hxx"
  22. #include "fldattr.hxx"
  23. #include "walkctxt.hxx"
  24. #include "gramutil.hxx"
  25. #include "cmdana.hxx"
  26. /****************************************************************************
  27. * local data
  28. ***************************************************************************/
  29. /****************************************************************************
  30. * externs
  31. ***************************************************************************/
  32. /****************************************************************************
  33. * definitions
  34. ***************************************************************************/
  35. /*
  36. * here are flag bits passed down from parents to give info on the
  37. * current path down the typegraph. These are dynamic information only,
  38. * and are NOT to be stored with the node.
  39. *
  40. * Although a few of these bits are mutually exclusive, most may be used
  41. * in combination.
  42. */
  43. #define IN_INTERFACE 0x0000000000000001 // in the base interface
  44. #define IN_PARAM_LIST 0x0000000000000002 // a descendant of a parameter
  45. #define IN_FUNCTION_RESULT 0x0000000000000004 // used as (part of) a return type
  46. #define IN_STRUCT 0x0000000000000008 // used in a struct
  47. #define IN_UNION 0x0000000000000010 // used in a union
  48. #define IN_ARRAY 0x0000000000000020 // used in an array
  49. #define IN_POINTER 0x0000000000000040 // below a pointer
  50. #define IN_RPC 0x0000000000000080 // in an RPC call
  51. #define UNDER_IN_PARAM 0x0000000000000100 // in an IN parameter
  52. #define UNDER_OUT_PARAM 0x0000000000000200 // in an OUT parameter
  53. #define BINDING_SEEN 0x0000000000000400 // binding handle already seen
  54. #define IN_TRANSMIT_AS 0x0000000000000800 // the transmitted type of transmit_as
  55. #define IN_REPRESENT_AS 0x0000000000001000 // the "transmitted" type of represent_as
  56. #define IN_USER_MARSHAL 0x0000000000002000 // transmitted type of
  57. #define IN_HANDLE 0x0000000000004000 // under generic or context hdl
  58. #define IN_NE_UNION 0x0000000000008000 // inside an non-encap union
  59. #define IN_INTERPRET 0x0000000000010000 // in an /Oi proc
  60. #define IN_NON_REF_PTR 0x0000000000020000 // under a series of unique/full ptrs
  61. #define UNDER_TOPLEVEL 0x0000000000040000 // top-level under param
  62. #define UNDER_TOPLVL_PTR 0x0000000000080000 // top-level under pointer param
  63. #define IN_BASE_CLASS 0x0000000000100000 // checking class derivation tree
  64. #define IN_PRESENTED_TYPE 0x0000000000200000 // the presented type of xmit/rep_as
  65. #define IN_ROOT_CLASS 0x0000000000400000 // a method/definition in the root class
  66. #define IN_ENCODE_INTF 0x0000000000800000 // inside an encode/decode only intf
  67. #define IN_RECURSIVE_DEF 0x0000000001000000 // inside of a recursive definition
  68. #define IN_OBJECT_INTF 0x0000000002000000 // in an object interface
  69. #define IN_LOCAL_PROC 0x0000000004000000 // in a [local] proc
  70. #define IN_INTERFACE_PTR 0x0000000008000000 // in the definition of an interface pointer
  71. #define IN_MODULE 0x0000000010000000 // in a module
  72. #define IN_COCLASS 0x0000000020000000 // in a coclass
  73. #define IN_LIBRARY 0x0000000040000000 // in a library
  74. #define IN_DISPINTERFACE 0x0000000080000000 // in a dispinterface
  75. #define HAS_OLEAUTOMATION 0x0000000100000000 // has [oleautomation] attr
  76. #define HAS_ASYNCHANDLE 0x0000000200000000 // has [async] attribute
  77. #define HAS_AUTO_HANDLE 0x0000000400000000 // has auto_handle
  78. #define HAS_EXPLICIT_HANDLE 0x0000000800000000 // has explicit_handle
  79. #define HAS_IMPLICIT_HANDLE 0x0000001000000000 // has implicit_handle
  80. #define IN_IADVISESINK 0x0000002000000000 // processing the children of IAdviseSink(*)
  81. #define HAS_ASYNC_UUID 0x0000004000000000 // interface has [async_uuid]
  82. #define HAS_MESSAGE 0x0000008000000000 // interface has [message]
  83. #define UNDER_HIDDEN_STATUS 0x0000010000000000 // hidden status param
  84. #define UNDER_PARTIAL_IGNORE_PARAM 0x0000020000000000 // Up to first ptr under partial_ignore
  85. typedef __int64 ANCESTOR_FLAGS; // above enum goes into here
  86. /*
  87. * Here are flag bits returned UP from children to give info on the current
  88. * path down the typegraph. Again, these are dynamic information.
  89. */
  90. #define HAS_STRING 0x0000000000000001 // has [string] attr
  91. #define HAS_IN 0x0000000000000002 // has [IN] attr
  92. #define HAS_OUT 0x0000000000000004 // has [OUT] attr
  93. #define HAS_HANDLE 0x0000000000000008 // is a handle
  94. #define HAS_POINTER 0x0000000000000010 // has a pointer below
  95. #define HAS_INCOMPLETE_TYPE 0x0000000000000020 // has incomplete type spec below
  96. #define HAS_VAR_ARRAY 0x0000000000000040 // has varying array (incl string)
  97. #define HAS_CONF_ARRAY 0x0000000000000080 // has conf array
  98. #define HAS_CONF_VAR_ARRAY 0x0000000000000100 // has conf_var array
  99. #define DERIVES_FROM_VOID 0x0000000000000200 // derives from void
  100. #define HAS_UNSAT_REP_AS 0x0000000000000400 // has unsatisfied rep_as
  101. #define HAS_CONTEXT_HANDLE 0x0000000000000800 // has context handle below
  102. #define HAS_CONF_PTR 0x0000000000001000 // has conformant pointer
  103. #define HAS_VAR_PTR 0x0000000000002000 // has varying pointer
  104. #define HAS_CONF_VAR_PTR 0x0000000000004000 // has conformant varying pointer
  105. #define HAS_TRANSMIT_AS 0x0000000000008000 // has transmit_as below
  106. #define HAS_REPRESENT_AS 0x0000000000010000 // has represent_as below
  107. #define HAS_E_STAT_T 0x0000000000020000 // has error_status_t below
  108. #define HAS_UNION 0x0000000000040000 // has union below
  109. #define HAS_ARRAY 0x0000000000080000 // has array below
  110. #define HAS_INTERFACE_PTR 0x0000000000100000 // has an interface ptr below
  111. #define HAS_DIRECT_CONF_OR_VAR 0x0000000000200000 // has direct conformance or variance
  112. #define HAS_RECURSIVE_DEF 0x0000000000400000 // is defined recursively
  113. #define HAS_ENUM 0x0000000000800000 // has an enum directly or embedded
  114. #define HAS_FUNC 0x0000000001000000 // has a function below
  115. #define HAS_FULL_PTR 0x0000000002000000 // has full pointers anywhere
  116. #define HAS_TOO_BIG_HDL 0x0000000004000000 // is /Oi but handle is too big
  117. #define HAS_STRUCT 0x0000000008000000 // has struct
  118. #define HAS_MULTIDIM_SIZING 0x0000000010000000 // has multi-dimensions
  119. #define HAS_ARRAY_OF_REF 0x0000000020000000 // has array of ref pointers
  120. #define HAS_HRESULT 0x0000000040000000 // has HRESULT
  121. #define HAS_PIPE 0x0000000080000000 // has a PIPE
  122. #define HAS_DEFAULT_VALUE 0x0000000100000000 // has [defaultvalue] attribute
  123. #define HAS_SERVER_CORRELATION 0x0000000200000000 // server correlation
  124. #define HAS_CLIENT_CORRELATION 0x0000000400000000 // client correlation
  125. #define HAS_MULTIDIM_VECTOR 0x0000000800000000 // has multi dim array or sized ptrs
  126. #define HAS_SIZED_ARRAY 0x0000001000000000 // not a fixed array
  127. #define HAS_SIZED_PTR 0x0000002000000000 //
  128. #define HAS_IN_CSTYPE 0x0000004000000000 // has in international chars
  129. #define HAS_OUT_CSTYPE 0x0000008000000000 // has out international chars
  130. #define HAS_DRTAG 0x0000010000000000 // some param has [cs_drtag]
  131. #define HAS_RTAG 0x0000020000000000 // some param has [cs_rtag]
  132. #define HAS_STAG 0x0000040000000000 // some param has [cs_stag]
  133. #define HAS_PARTIAL_IGNORE 0x0000080000000000 // some param has [partial_ignore]
  134. #define HAS_FORCEALLOCATE 0x0000100000000000 // some param has [force_allocate]
  135. #define HAS_ARRAYOFPOINTERS 0x0000200000000000 // has an array of pointers
  136. typedef __int64 DESCENDANT_FLAGS; // above defines goes into here
  137. /*
  138. * Here is the context information passed down from parent to child.
  139. * These will be allocated on the stack during the traversal
  140. */
  141. class node_interface;
  142. class type_node_list;
  143. class ATTRLIST;
  144. class SEM_ANALYSIS_CTXT: public WALK_CTXT
  145. {
  146. private:
  147. unsigned long ulCorrelations;
  148. public:
  149. struct _current_ctxt {
  150. // down stuff
  151. ANCESTOR_FLAGS AncestorBits; // where am I? stuff
  152. // up stuff
  153. DESCENDANT_FLAGS DescendantBits;
  154. } CurrentCtxt;
  155. // constructor and destructor
  156. SEM_ANALYSIS_CTXT(node_skl * Me)
  157. : WALK_CTXT( Me )
  158. {
  159. GetAncestorBits() = 0;
  160. GetDescendantBits() = 0;
  161. ulCorrelations = 0;
  162. }
  163. SEM_ANALYSIS_CTXT(node_skl * Me,
  164. SEM_ANALYSIS_CTXT * pParentCtxt )
  165. : WALK_CTXT( Me, pParentCtxt )
  166. {
  167. // clone information from parent node
  168. CurrentCtxt = pParentCtxt->CurrentCtxt;
  169. // get fresh information from our children
  170. GetDescendantBits() = 0;
  171. // remove any inapplicable attributes
  172. CheckAttributes();
  173. ulCorrelations = 0;
  174. }
  175. SEM_ANALYSIS_CTXT(SEM_ANALYSIS_CTXT * pParentCtxt )
  176. : WALK_CTXT( pParentCtxt )
  177. {
  178. // clone information from parent node
  179. CurrentCtxt = pParentCtxt->CurrentCtxt;
  180. // get fresh information from our children
  181. GetDescendantBits() = 0;
  182. ulCorrelations = 0;
  183. }
  184. ANCESTOR_FLAGS& GetAncestorBits()
  185. {
  186. return CurrentCtxt.AncestorBits;
  187. }
  188. ANCESTOR_FLAGS& SetAncestorBits( ANCESTOR_FLAGS f )
  189. {
  190. CurrentCtxt.AncestorBits |= f;
  191. return CurrentCtxt.AncestorBits;
  192. }
  193. ANCESTOR_FLAGS& ClearAncestorBits( ANCESTOR_FLAGS f )
  194. {
  195. CurrentCtxt.AncestorBits &= ~f;
  196. return CurrentCtxt.AncestorBits;
  197. }
  198. BOOL AnyAncestorBits( ANCESTOR_FLAGS f )
  199. {
  200. return ((CurrentCtxt.AncestorBits & f) != 0);
  201. }
  202. BOOL AllAncestorBits( ANCESTOR_FLAGS f )
  203. {
  204. return ((CurrentCtxt.AncestorBits & f) == f);
  205. }
  206. DESCENDANT_FLAGS& GetDescendantBits()
  207. {
  208. return CurrentCtxt.DescendantBits;
  209. }
  210. DESCENDANT_FLAGS& SetDescendantBits( DESCENDANT_FLAGS f )
  211. {
  212. CurrentCtxt.DescendantBits |= f;
  213. return CurrentCtxt.DescendantBits;
  214. }
  215. DESCENDANT_FLAGS& ClearDescendantBits( DESCENDANT_FLAGS f )
  216. {
  217. CurrentCtxt.DescendantBits &= ~f;
  218. return CurrentCtxt.DescendantBits;
  219. }
  220. DESCENDANT_FLAGS& ClearAllDescendantBits( )
  221. {
  222. CurrentCtxt.DescendantBits = 0;
  223. return CurrentCtxt.DescendantBits;
  224. }
  225. BOOL AnyDescendantBits( DESCENDANT_FLAGS f )
  226. {
  227. return ( ( CurrentCtxt.DescendantBits & f ) != 0 );
  228. }
  229. BOOL AllDescendantBits( DESCENDANT_FLAGS f )
  230. {
  231. return ((CurrentCtxt.DescendantBits & f) == f);
  232. }
  233. void ReturnValues( SEM_ANALYSIS_CTXT & ChildCtxt )
  234. {
  235. // pass up the return context
  236. GetDescendantBits() |= ChildCtxt.GetDescendantBits();
  237. ulCorrelations += ChildCtxt.GetCorrelationCount();
  238. }
  239. unsigned long GetCorrelationCount( void )
  240. {
  241. return ulCorrelations;
  242. }
  243. void IncCorrelationCount( unsigned long ulInc = 1 )
  244. {
  245. ulCorrelations += ulInc;
  246. }
  247. void ResetCorrelationCount()
  248. {
  249. ulCorrelations = 0;
  250. }
  251. void ResetDownValues( SEM_ANALYSIS_CTXT & ParentCtxt )
  252. {
  253. // reset the down values from the parent
  254. // (semantically different, but really the same code )
  255. ReturnValues( ParentCtxt );
  256. }
  257. void CheckAttributes();
  258. void RejectAttributes();
  259. }; // end of class SEM_ANALYSIS_CTXT
  260. inline void
  261. RpcSemError( node_skl * pNode,
  262. SEM_ANALYSIS_CTXT & Ctxt,
  263. STATUS_T ErrNum,
  264. char * pExtra )
  265. {
  266. if ( Ctxt.AnyAncestorBits( IN_RPC ) &&
  267. !Ctxt.AnyAncestorBits( IN_LOCAL_PROC ) )
  268. SemError( pNode, Ctxt, ErrNum, pExtra );
  269. }
  270. inline void
  271. TypeSemError( node_skl * pNode,
  272. SEM_ANALYSIS_CTXT & Ctxt,
  273. STATUS_T ErrNum,
  274. char * pExtra )
  275. {
  276. if ( !Ctxt.AnyAncestorBits( IN_LOCAL_PROC ) )
  277. SemError( pNode, Ctxt, ErrNum, pExtra );
  278. }
  279. // prototype for semantic advice routines
  280. inline void
  281. SemAdvice( node_skl * pNode,
  282. WALK_CTXT & Ctxt,
  283. STATUS_T ErrVal,
  284. char * pSuffix )
  285. {
  286. if ( pCommand->IsMintRun() )
  287. SemError( pNode, Ctxt, ErrVal, pSuffix );
  288. }
  289. class acf_attr;
  290. extern void
  291. AcfError( acf_attr*, node_skl *, WALK_CTXT &, STATUS_T, char * );
  292. /////////////////////////////////////////////
  293. //
  294. // expression analysis flags (passed up)
  295. enum _EXPR_UP_FLAGS
  296. {
  297. EX_NONE = 0x0000,
  298. EX_VALUE_INVALID = 0x0001, // value is NOT valid
  299. EX_UNSAT_FWD = 0x0002, // there is an unsatisfied fwd
  300. EX_NON_NUMERIC = 0x0004, // expr not entirely numerics
  301. // (can not be constant folded)
  302. EX_OUT_ONLY_PARAM = 0x0008, // expression includes an out-only param
  303. EX_PTR_FULL_UNIQUE = 0x0010, // has ptr deref of full or unique ptr
  304. EX_HYPER_IN_EXPR = 0x0020, // expr has a hyper item in it
  305. };
  306. typedef unsigned short EXPR_UP_FLAGS;
  307. ////////////////////////////////////////////
  308. // expression context block
  309. class EXPR_CTXT;
  310. class EXPR_CTXT
  311. {
  312. private:
  313. // passed down
  314. EXPR_CTXT * pParent;
  315. SEM_ANALYSIS_CTXT * pSemCtxt;
  316. // passed up
  317. EXPR_VALUE CurValue;
  318. EXPR_UP_FLAGS Flags;
  319. public:
  320. // type info
  321. node_skl * pType;
  322. struct _type_ana TypeInfo;
  323. BOOL fIntegral; // type is an integral type (above are valid)
  324. EXPR_CTXT( EXPR_CTXT * pMy ) : pType( 0 ), fIntegral( FALSE )
  325. {
  326. TypeInfo.TypeSize =
  327. TypeInfo.BaseType =
  328. TypeInfo.TypeSign =
  329. TypeInfo.TypeAttrib = 0;
  330. pParent = pMy;
  331. pSemCtxt = pMy->pSemCtxt;
  332. CurValue = 0;
  333. Flags = EX_NONE;
  334. }
  335. EXPR_CTXT( SEM_ANALYSIS_CTXT * pSCtxt ) : pType( 0 ), fIntegral( FALSE )
  336. {
  337. TypeInfo.TypeSize =
  338. TypeInfo.BaseType =
  339. TypeInfo.TypeSign =
  340. TypeInfo.TypeAttrib = 0;
  341. pParent = NULL;
  342. pSemCtxt = pSCtxt;
  343. CurValue = 0;
  344. Flags = EX_NONE;
  345. }
  346. // automatically pass up the flags
  347. ~EXPR_CTXT()
  348. {
  349. if ( pParent )
  350. pParent->Flags |= Flags;
  351. }
  352. EXPR_VALUE& Value()
  353. {
  354. return CurValue;
  355. }
  356. EXPR_UP_FLAGS& MergeUpFlags( EXPR_CTXT * pC )
  357. {
  358. Flags |= pC->Flags;
  359. return Flags;
  360. }
  361. EXPR_UP_FLAGS& SetUpFlags( EXPR_UP_FLAGS f )
  362. {
  363. Flags |= f;
  364. return Flags;
  365. }
  366. EXPR_UP_FLAGS& ClearUpFlags( EXPR_UP_FLAGS f )
  367. {
  368. Flags &= ~f;
  369. return Flags;
  370. }
  371. BOOL AnyUpFlags( EXPR_UP_FLAGS f )
  372. {
  373. return (Flags & f);
  374. }
  375. BOOL AllUpFlags( EXPR_UP_FLAGS f )
  376. {
  377. return ((Flags & f) == f);
  378. }
  379. node_skl* GetNode()
  380. {
  381. return pSemCtxt->GetParent();
  382. }
  383. SEM_ANALYSIS_CTXT * GetCtxt()
  384. {
  385. return pSemCtxt;
  386. }
  387. };
  388. #endif // __SEMANTIC_HXX__