Leaked source code of windows server 2003
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.

910 lines
22 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. fldattr.cxx
  5. Abstract:
  6. field attribute handling routines
  7. Notes:
  8. Author:
  9. GregJen Oct-27-1993 Created.
  10. Notes:
  11. ----------------------------------------------------------------------------*/
  12. #pragma warning ( disable : 4514 )
  13. /****************************************************************************
  14. * include files
  15. ***************************************************************************/
  16. #include "allnodes.hxx"
  17. #include "fldattr.hxx"
  18. #include "semantic.hxx"
  19. /****************************************************************************
  20. * local data
  21. ***************************************************************************/
  22. expr_constant * pZero = NULL;
  23. expr_constant * pOne = NULL;
  24. node_skl * pInt = NULL;
  25. /****************************************************************************
  26. * externs
  27. ***************************************************************************/
  28. /****************************************************************************
  29. * definitions
  30. ***************************************************************************/
  31. /////////////////
  32. // helper routines for Normalize functions;
  33. //Don't add or subtract 0.
  34. expr_node *
  35. CreateSimpleBinaryArithExpression(
  36. OPERATOR Op,
  37. expr_node * pL,
  38. expr_node * pR
  39. )
  40. {
  41. MIDL_ASSERT( (Op==OP_PLUS) || (Op==OP_MINUS) );
  42. MIDL_ASSERT( pL );
  43. MIDL_ASSERT( pR );
  44. if ( pR->IsConstant() && (pR->GetValue() == 0) )
  45. return pL;
  46. if ( pL->IsConstant() && (pL->GetValue() == 0) )
  47. return pR;
  48. expr_node * pRet = new expr_b_arithmetic( Op, pL, pR );
  49. if ( pL->GetType() )
  50. pRet->SetType( pL->GetType() );
  51. else if ( pR->GetType() )
  52. pRet->SetType( pR->GetType() );
  53. else
  54. MIDL_ASSERT( !"no type for expression" );
  55. return pRet;
  56. }
  57. // return the constant 0 over and over
  58. expr_constant *
  59. GetConstant0()
  60. {
  61. if ( pZero ) return pZero;
  62. pZero = new expr_constant( 0L, VALUE_TYPE_NUMERIC );
  63. if ( !pInt )
  64. GetBaseTypeNode( &pInt, SIGN_SIGNED, SIZE_UNDEF, TYPE_INT );
  65. pZero->SetType( pInt );
  66. return pZero;
  67. }
  68. // return the constant 1 over and over
  69. expr_constant *
  70. GetConstant1()
  71. {
  72. if ( pOne ) return pOne;
  73. pOne = new expr_constant( 1L, VALUE_TYPE_NUMERIC );
  74. if ( !pInt )
  75. GetBaseTypeNode( &pInt, SIGN_SIGNED, SIZE_UNDEF, TYPE_INT );
  76. pOne->SetType( pInt );
  77. return pOne;
  78. }
  79. BOOL
  80. IsInValidOutOnly( SEM_ANALYSIS_CTXT * pCtxt )
  81. {
  82. // an out-only size is valid only on out-only non-top-level things
  83. // in, in/out things not allowed
  84. if ( pCtxt->AnyAncestorBits( UNDER_IN_PARAM ) )
  85. return TRUE;
  86. // look up the stack for a pointer (or array) that is unique
  87. SEM_ANALYSIS_CTXT * pCurCtxt = pCtxt;
  88. NODE_T Kind;
  89. node_skl * pNode;
  90. while ( pCurCtxt )
  91. {
  92. pNode = pCurCtxt->GetParent();
  93. Kind = pNode->NodeKind();
  94. switch ( Kind )
  95. {
  96. case NODE_DEF:
  97. case NODE_ARRAY:
  98. break;
  99. case NODE_POINTER:
  100. if ( pCtxt->AnyAncestorBits( IN_NON_REF_PTR ) )
  101. return FALSE;
  102. break;
  103. case NODE_PARAM:
  104. case NODE_PROC:
  105. default:
  106. return TRUE;
  107. }
  108. pCurCtxt = ( SEM_ANALYSIS_CTXT * ) pCurCtxt->GetParentContext();
  109. }
  110. return TRUE;
  111. }
  112. BOOL Xxx_Is_Type_OK( node_skl * pType)
  113. {
  114. if ( !pType )
  115. return FALSE;
  116. for (;;)
  117. {
  118. switch ( pType->NodeKind() )
  119. {
  120. case NODE_PARAM:
  121. case NODE_FIELD:
  122. if ( !pType->GetChild() )
  123. return FALSE;
  124. break;
  125. // make sure that there is no transmit_as or represent_as
  126. case NODE_DEF:
  127. if ( pType->FInSummary( ATTR_TRANSMIT ) ||
  128. pType->FInSummary( ATTR_REPRESENT_AS ) ||
  129. pType->FInSummary( ATTR_USER_MARSHAL ) ||
  130. pType->FInSummary( ATTR_WIRE_MARSHAL ) )
  131. return FALSE;
  132. break;
  133. // for an ID, make sure it is a const decl, then use its type
  134. case NODE_ID:
  135. {
  136. node_id * pID = (node_id *) pType;
  137. if ( !pID->pInit )
  138. return FALSE;
  139. break;
  140. }
  141. case NODE_ENUM:
  142. case NODE_LONG:
  143. case NODE_SHORT:
  144. case NODE_INT:
  145. case NODE_INT32:
  146. case NODE_SMALL:
  147. case NODE_CHAR:
  148. case NODE_BOOLEAN:
  149. case NODE_BYTE:
  150. return TRUE;
  151. // 64b expr support
  152. case NODE_INT3264:
  153. case NODE_INT64:
  154. case NODE_HYPER:
  155. return FALSE;
  156. // no 128b expr support
  157. case NODE_INT128:
  158. case NODE_FLOAT80:
  159. case NODE_FLOAT128:
  160. return FALSE;
  161. default:
  162. return FALSE;
  163. }
  164. pType = pType->GetChild();
  165. }
  166. }
  167. BOOL IID_Is_Type_OK( node_skl * pType )
  168. {
  169. if ( !pType )
  170. return FALSE;
  171. for (;;)
  172. {
  173. switch ( pType->NodeKind() )
  174. {
  175. case NODE_PARAM:
  176. case NODE_FIELD:
  177. if ( !pType->GetChild() )
  178. return FALSE;
  179. break;
  180. case NODE_DEF:
  181. if ( pType->FInSummary( ATTR_TRANSMIT ) ||
  182. pType->FInSummary( ATTR_REPRESENT_AS ) ||
  183. pType->FInSummary( ATTR_USER_MARSHAL ) ||
  184. pType->FInSummary( ATTR_WIRE_MARSHAL ) )
  185. return FALSE;
  186. break;
  187. case NODE_POINTER:
  188. if ( pType->GetChild() )
  189. return ( 16 == pType->GetChild()->GetSize() );
  190. default:
  191. return FALSE;
  192. }
  193. pType = pType->GetChild();
  194. }
  195. }
  196. // validate the bunch of attributes for pointers: check combinations, ranges,
  197. // and expressions
  198. void
  199. FIELD_ATTR_INFO::Validate( SEM_ANALYSIS_CTXT * pCtxt )
  200. {
  201. if ( Kind == FA_NONE )
  202. return;
  203. node_skl * pParent = pCtxt->GetParent();
  204. // things to check:
  205. // expression types (must be integral types)
  206. if ( pMaxIsExpr )
  207. {
  208. EXPR_CTXT MaxCtxt( pCtxt );
  209. pMaxIsExpr->ExprAnalyze( &MaxCtxt );
  210. if ( MaxCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  211. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  212. if ( MaxCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) && IsInValidOutOnly( pCtxt ) )
  213. RpcSemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
  214. if ( !MaxCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  215. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  216. if ( !Xxx_Is_Type_OK( pMaxIsExpr->GetType() ) &&
  217. pCtxt->AnyAncestorBits( IN_RPC ) )
  218. RpcSemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  219. }
  220. if ( pMinIsExpr )
  221. {
  222. EXPR_CTXT MinCtxt( pCtxt );
  223. pMinIsExpr->ExprAnalyze( &MinCtxt );
  224. if ( MinCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  225. RpcSemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  226. if ( MinCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) && IsInValidOutOnly( pCtxt ) )
  227. SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
  228. if ( !MinCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  229. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  230. if ( !Xxx_Is_Type_OK( pMinIsExpr->GetType() ) &&
  231. pCtxt->AnyAncestorBits( IN_RPC ) )
  232. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  233. }
  234. if ( pSizeIsExpr )
  235. {
  236. EXPR_CTXT SizeCtxt( pCtxt );
  237. pSizeIsExpr->ExprAnalyze( &SizeCtxt );
  238. if ( SizeCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  239. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  240. if ( SizeCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) && IsInValidOutOnly( pCtxt ) )
  241. SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
  242. if ( !SizeCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  243. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  244. if ( !Xxx_Is_Type_OK( pSizeIsExpr->GetType() ) &&
  245. pCtxt->AnyAncestorBits( IN_RPC ) )
  246. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  247. }
  248. if ( pFirstIsExpr )
  249. {
  250. EXPR_CTXT FirstCtxt( pCtxt );
  251. pFirstIsExpr->ExprAnalyze( &FirstCtxt );
  252. if ( FirstCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  253. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  254. if ( !FirstCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  255. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  256. if ( !Xxx_Is_Type_OK( pFirstIsExpr->GetType() ) &&
  257. pCtxt->AnyAncestorBits( IN_RPC ) )
  258. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  259. }
  260. if ( pLastIsExpr )
  261. {
  262. EXPR_CTXT LastCtxt( pCtxt );
  263. pLastIsExpr->ExprAnalyze( &LastCtxt );
  264. if ( LastCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  265. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  266. if ( !LastCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  267. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  268. if ( !Xxx_Is_Type_OK( pLastIsExpr->GetType() ) &&
  269. pCtxt->AnyAncestorBits( IN_RPC ) )
  270. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  271. }
  272. if ( pLengthIsExpr )
  273. {
  274. EXPR_CTXT LengthCtxt( pCtxt );
  275. pLengthIsExpr->ExprAnalyze( &LengthCtxt );
  276. if ( LengthCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  277. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  278. if ( !LengthCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  279. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  280. if ( !Xxx_Is_Type_OK( pLengthIsExpr->GetType() ) &&
  281. pCtxt->AnyAncestorBits( IN_RPC ) )
  282. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  283. }
  284. if ( pIIDIsExpr )
  285. {
  286. EXPR_CTXT IIDCtxt( pCtxt );
  287. pIIDIsExpr->ExprAnalyze( &IIDCtxt );
  288. if ( IIDCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  289. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  290. if ( !IIDCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  291. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  292. if ( !IID_Is_Type_OK( pIIDIsExpr->GetType() ) &&
  293. pCtxt->AnyAncestorBits( IN_RPC ) )
  294. SemError( pParent, *pCtxt, IID_IS_EXPR_NON_POINTER, NULL );
  295. }
  296. // min_is == 0 ( for now )
  297. // constant min_is <= constant max_is
  298. // size_is not with max_is
  299. if ( pMaxIsExpr && pSizeIsExpr )
  300. SemError( pParent, *pCtxt, MAX_AND_SIZE, NULL );
  301. // min_is not alone
  302. // constant first_is <= constant last_is + 1
  303. // length_is not with last_is
  304. if ( pLengthIsExpr && pLastIsExpr )
  305. SemError( pParent, *pCtxt, LAST_AND_LENGTH, NULL );
  306. // constant first_is, last_is both within min<->max range
  307. // length_is <= size_is
  308. // string attrs not with varying attrs
  309. // string and bstring not together
  310. // conformant strings may leave out size_is if [in] or [in,out]
  311. // accept the NULL value ( turn expression back null, clear kind bits )
  312. // make sure variables come from the correct context
  313. // lengthed, unsized pointer
  314. if ( ( pLengthIsExpr || pFirstIsExpr || pLastIsExpr || pMinIsExpr) &&
  315. !( pSizeIsExpr || pMaxIsExpr ) )
  316. SemError( pParent, *pCtxt, UNSIZED_ARRAY, NULL );
  317. }
  318. void
  319. FIELD_ATTR_INFO::Validate( SEM_ANALYSIS_CTXT * pCtxt,
  320. expr_node * pLower,
  321. expr_node * pUpper )
  322. {
  323. node_skl * pParent = pCtxt->GetParent();
  324. if ( pUpper == (expr_node *) -1 )
  325. {
  326. pUpper = NULL;
  327. Kind |= FA_CONFORMANT;
  328. }
  329. else if ( pUpper )
  330. {
  331. if ( pUpper->GetValue() <= 0 )
  332. {
  333. SemError( pParent, *pCtxt, ILLEGAL_ARRAY_BOUNDS, NULL );
  334. }
  335. }
  336. if ( pLower &&
  337. ( pLower != (expr_node *) -1 ) &&
  338. ( pLower->GetValue() != 0 ) )
  339. {
  340. SemError( pParent, *pCtxt, ARRAY_BOUNDS_CONSTRUCT_BAD, NULL );
  341. }
  342. if ( pUpper && ( pMaxIsExpr || pSizeIsExpr ) )
  343. {
  344. SemError( pParent, *pCtxt, SIZING_ON_FIXED_ARRAYS, NULL );
  345. }
  346. // things to check:
  347. // expression types (must be integral types)
  348. if ( pMaxIsExpr )
  349. {
  350. EXPR_CTXT MaxCtxt( pCtxt );
  351. pMaxIsExpr->ExprAnalyze( &MaxCtxt );
  352. if ( MaxCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  353. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  354. if ( MaxCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) )
  355. SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
  356. if ( !MaxCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  357. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  358. if ( !Xxx_Is_Type_OK( pMaxIsExpr->GetType() ) &&
  359. pCtxt->AnyAncestorBits( IN_RPC ) )
  360. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  361. }
  362. if ( pMinIsExpr )
  363. {
  364. EXPR_CTXT MinCtxt( pCtxt );
  365. pMinIsExpr->ExprAnalyze( &MinCtxt );
  366. if ( MinCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  367. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  368. if ( MinCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) )
  369. SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
  370. if ( !MinCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  371. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  372. if ( !Xxx_Is_Type_OK( pMinIsExpr->GetType() ) &&
  373. pCtxt->AnyAncestorBits( IN_RPC ) )
  374. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  375. }
  376. if ( pSizeIsExpr )
  377. {
  378. EXPR_CTXT SizeCtxt( pCtxt );
  379. pSizeIsExpr->ExprAnalyze( &SizeCtxt );
  380. if ( SizeCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  381. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  382. if ( SizeCtxt.AnyUpFlags( EX_OUT_ONLY_PARAM ) )
  383. SemError( pParent, *pCtxt, SIZE_SPECIFIER_CANT_BE_OUT, NULL );
  384. if ( !SizeCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  385. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  386. if ( !Xxx_Is_Type_OK( pSizeIsExpr->GetType() ) &&
  387. pCtxt->AnyAncestorBits( IN_RPC ) )
  388. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  389. }
  390. if ( pFirstIsExpr )
  391. {
  392. EXPR_CTXT FirstCtxt( pCtxt );
  393. pFirstIsExpr->ExprAnalyze( &FirstCtxt );
  394. if ( FirstCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  395. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  396. if ( !FirstCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  397. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  398. if ( !Xxx_Is_Type_OK( pFirstIsExpr->GetType() ) &&
  399. pCtxt->AnyAncestorBits( IN_RPC ) )
  400. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  401. }
  402. if ( pLastIsExpr )
  403. {
  404. EXPR_CTXT LastCtxt( pCtxt );
  405. pLastIsExpr->ExprAnalyze( &LastCtxt );
  406. if ( LastCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  407. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  408. if ( !LastCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  409. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  410. if ( !Xxx_Is_Type_OK( pLastIsExpr->GetType() ) &&
  411. pCtxt->AnyAncestorBits( IN_RPC ) )
  412. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  413. }
  414. if ( pLengthIsExpr )
  415. {
  416. EXPR_CTXT LengthCtxt( pCtxt );
  417. pLengthIsExpr->ExprAnalyze( &LengthCtxt );
  418. if ( LengthCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  419. SemError( pParent, *pCtxt, ATTRIBUTE_ID_UNRESOLVED, NULL );
  420. if ( !LengthCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  421. SemError( pParent, *pCtxt, ATTRIBUTE_ID_MUST_BE_VAR, NULL );
  422. if ( !Xxx_Is_Type_OK( pLengthIsExpr->GetType() ) &&
  423. pCtxt->AnyAncestorBits( IN_RPC ) )
  424. SemError( pParent, *pCtxt, ATTR_MUST_BE_INT, NULL );
  425. }
  426. if ( pIIDIsExpr )
  427. {
  428. SemError( pParent, *pCtxt, IID_IS_NON_POINTER, NULL );
  429. }
  430. // min_is == 0 ( for now )
  431. // constant min_is <= constant max_is
  432. // size_is not with max_is
  433. if ( pMaxIsExpr && pSizeIsExpr )
  434. SemError( pParent, *pCtxt, MAX_AND_SIZE, NULL );
  435. // a conformant unsized array:
  436. // must have string
  437. // must not be out_only
  438. if ( ( Kind & FA_CONFORMANT ) && !pMaxIsExpr && !pSizeIsExpr && !pUpper )
  439. {
  440. if ( !( Kind & FA_STRING ) )
  441. {
  442. if ( pCtxt->AnyAncestorBits( IN_RPC ) )
  443. SemError( pParent, *pCtxt, UNSIZED_ARRAY, NULL );
  444. }
  445. else
  446. {
  447. if ( pCtxt->AllAncestorBits( IN_RPC |
  448. IN_PARAM_LIST |
  449. UNDER_OUT_PARAM ) &&
  450. !pCtxt->AnyAncestorBits( UNDER_IN_PARAM ) )
  451. SemError( pParent, *pCtxt, DERIVES_FROM_UNSIZED_STRING, NULL );
  452. }
  453. }
  454. // min_is not alone
  455. // constant first_is <= constant last_is + 1
  456. // length_is not with last_is
  457. if ( pLengthIsExpr && pLastIsExpr )
  458. SemError( pParent, *pCtxt, LAST_AND_LENGTH, NULL );
  459. // constant first_is, last_is both within min<->max range
  460. // length_is <= size_is
  461. // string attrs not with varying attrs
  462. // string and bstring not together
  463. // conformant strings may leave out size_is if [in] or [in,out]
  464. // accept the NULL value ( turn expression back null, clear kind bits )
  465. // make sure variables come from the correct context
  466. }
  467. //
  468. // normalize for pointers ( no default bound )
  469. void
  470. FIELD_ATTR_INFO::Normalize()
  471. {
  472. expr_node * pTmp1;
  473. expr_node * pTmp2;
  474. // convert the set: min_is, max_is, size_is to min_is + size_is
  475. if ( Kind & FA_CONFORMANT )
  476. {
  477. // default min_is is 0
  478. if ( ! pMinIsExpr )
  479. {
  480. pMinIsExpr = GetConstant0();
  481. }
  482. // size_is = (max_is - min_is) + 1;
  483. if ( ! pSizeIsExpr )
  484. {
  485. if ( pMaxIsExpr )
  486. {
  487. pTmp1 = GetConstant1();
  488. pTmp2 = CreateSimpleBinaryArithExpression( OP_MINUS, pMaxIsExpr, pMinIsExpr);
  489. pSizeIsExpr = CreateSimpleBinaryArithExpression( OP_PLUS, pTmp2, pTmp1 );
  490. }
  491. }
  492. }
  493. // convert the set: first_is, last_is, length_is to: first_is + length_is
  494. if ( Kind & FA_VARYING )
  495. {
  496. // default first_is is 0
  497. if ( ! pFirstIsExpr )
  498. {
  499. pFirstIsExpr = GetConstant0();
  500. }
  501. // default last_is is max_is or size_is+1
  502. if ( ! pLastIsExpr )
  503. {
  504. if ( pMaxIsExpr )
  505. pLastIsExpr = pMaxIsExpr;
  506. else if ( pSizeIsExpr )
  507. pLastIsExpr = CreateSimpleBinaryArithExpression( OP_MINUS, pSizeIsExpr, GetConstant1() );
  508. }
  509. // length_is = (last_is - first_is) + 1;
  510. if ( ! pLengthIsExpr )
  511. {
  512. if ( pLastIsExpr )
  513. {
  514. pTmp1 = GetConstant1();
  515. pTmp2 = CreateSimpleBinaryArithExpression( OP_MINUS, pLastIsExpr, pFirstIsExpr);
  516. pLengthIsExpr = CreateSimpleBinaryArithExpression( OP_PLUS, pTmp2, pTmp1 );
  517. }
  518. }
  519. }
  520. }
  521. // normalize for arrays (provided lower and upper bound)
  522. void
  523. FIELD_ATTR_INFO::Normalize(expr_node * pLower, expr_node * pUpper)
  524. {
  525. expr_node * pTmp1;
  526. expr_node * pTmp2;
  527. BOOL OneBound = FALSE;
  528. if ( pLower == (expr_node *) 0 )
  529. {
  530. pLower = GetConstant0();
  531. OneBound = TRUE;
  532. }
  533. if ( pUpper == (expr_node *) -1 )
  534. {
  535. pUpper = NULL;
  536. Kind |= FA_CONFORMANT;
  537. }
  538. // convert the set: min_is, max_is, size_is to: min_is + size_is
  539. // first, copy from the bounds
  540. if ( ! pMinIsExpr )
  541. {
  542. pMinIsExpr = pLower;
  543. }
  544. if ( ! pMaxIsExpr && ! pSizeIsExpr && pUpper )
  545. {
  546. // note that the [n..m] case has m already incremented by 1
  547. pTmp1 = GetConstant1();
  548. pMaxIsExpr = CreateSimpleBinaryArithExpression( OP_MINUS, pUpper, pTmp1 );
  549. }
  550. // size_is = (max_is - min_is) + 1;
  551. if ( ! pSizeIsExpr )
  552. {
  553. if ( pMaxIsExpr )
  554. {
  555. pTmp1 = GetConstant1();
  556. pTmp2 = CreateSimpleBinaryArithExpression( OP_MINUS, pMaxIsExpr, pMinIsExpr);
  557. pSizeIsExpr = CreateSimpleBinaryArithExpression( OP_PLUS, pTmp2, pTmp1 );
  558. }
  559. }
  560. // convert the set: first_is, last_is, length_is to: first_is + length_is
  561. // default first_is is min_is
  562. if ( ! pFirstIsExpr )
  563. {
  564. pFirstIsExpr = pMinIsExpr;
  565. }
  566. // default last_is is max_is or size_is+1
  567. if ( ! pLastIsExpr )
  568. {
  569. if ( pMaxIsExpr )
  570. pLastIsExpr = pMaxIsExpr;
  571. else if ( pSizeIsExpr )
  572. pLastIsExpr = CreateSimpleBinaryArithExpression( OP_MINUS, pSizeIsExpr, GetConstant1() );
  573. }
  574. // length_is = (last_is - first_is) + 1;
  575. if ( ! pLengthIsExpr )
  576. {
  577. if ( pLastIsExpr )
  578. {
  579. pTmp1 = GetConstant1();
  580. pTmp2 = CreateSimpleBinaryArithExpression( OP_MINUS, pLastIsExpr, pFirstIsExpr);
  581. pLengthIsExpr = CreateSimpleBinaryArithExpression( OP_PLUS, pTmp2, pTmp1 );
  582. }
  583. }
  584. }
  585. bool
  586. FIELD_ATTR_INFO::VerifyOnlySimpleExpression()
  587. {
  588. const int nExprTypes = 7;
  589. expr_node *pExpr[nExprTypes] =
  590. {
  591. pSizeIsExpr,
  592. pMinIsExpr,
  593. pMaxIsExpr,
  594. pLengthIsExpr,
  595. pFirstIsExpr,
  596. pIIDIsExpr,
  597. pLastIsExpr,
  598. };
  599. for ( int i = 0; i < nExprTypes; i++ )
  600. {
  601. // No expression is ok
  602. if ( NULL == pExpr[i] )
  603. continue;
  604. // A simple variable is ok
  605. if ( pExpr[i]->IsAVariable() )
  606. continue;
  607. // A pointer to a simple variable is ok
  608. if ( OP_UNARY_INDIRECTION == pExpr[i]->GetOperator()
  609. && pExpr[i]->GetLeft()->IsAVariable() )
  610. {
  611. continue;
  612. }
  613. // Everything else is not ok
  614. return false;
  615. }
  616. return true;
  617. }
  618. BOOL
  619. FIELD_ATTR_INFO::SetExpressionVariableUsage( SIZE_LENGTH_USAGE )
  620. {
  621. return TRUE;
  622. }
  623. #if 0
  624. BUGBUG: CG_INTERFACE_POINTER has a bug. See nodeskl.h for details
  625. BOOL
  626. FIELD_ATTR_INFO::SetExpressionVariableUsage( SIZE_LENGTH_USAGE usage )
  627. {
  628. const int nExprTypes = 7;
  629. expr_node *pExpr[nExprTypes] =
  630. {
  631. pSizeIsExpr,
  632. pMinIsExpr,
  633. pMaxIsExpr,
  634. pLengthIsExpr,
  635. pFirstIsExpr,
  636. pIIDIsExpr,
  637. pLastIsExpr,
  638. };
  639. for ( int i = 0; i < nExprTypes; i++ )
  640. if ( ! SetExpressionVariableUsage( pExpr[i], usage ) )
  641. return false;
  642. return true;
  643. }
  644. BOOL
  645. FIELD_ATTR_INFO::SetExpressionVariableUsage(
  646. expr_node *pExpr,
  647. SIZE_LENGTH_USAGE usage )
  648. {
  649. if ( !pExpr )
  650. return true;
  651. if ( pExpr->IsAVariable() )
  652. {
  653. node_skl *pParent = NULL;
  654. node_skl *pType = pExpr->GetType();
  655. while ( NULL != pType && !pType->IsBasicType() )
  656. {
  657. pParent = pType;
  658. pType = pType->GetChild();
  659. }
  660. if ( NULL != pType && pType->IsBasicType() )
  661. {
  662. SIZE_LENGTH_USAGE TypeUsage = ((node_base_type *) pType)
  663. ->GetSizeLengthUsage();
  664. if ( CSSizeLengthUsage == usage
  665. && NoSizeLengthUsage != TypeUsage )
  666. {
  667. return FALSE;
  668. }
  669. if ( CSSizeLengthUsage == TypeUsage
  670. && NoSizeLengthUsage != usage )
  671. {
  672. return FALSE;
  673. }
  674. if ( NoSizeLengthUsage != usage )
  675. {
  676. // Typically base type nodes are preallocated and identical.
  677. // Pointing at them with size_is, etc makes the different
  678. // because we need to note that fact. So clone it to get
  679. // a new one.
  680. MIDL_ASSERT( NULL != pParent );
  681. pType = new node_base_type( (node_base_type *) pType );
  682. ((node_base_type *) pType)->SetSizeLengthUsage( usage );
  683. pParent->SetChild( pType );
  684. }
  685. }
  686. }
  687. if ( ! SetExpressionVariableUsage( pExpr->GetLeft(), usage ) )
  688. return false;
  689. return SetExpressionVariableUsage( pExpr->GetRight(), usage );
  690. }
  691. #endif