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.

7046 lines
240 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. semantic.cxx
  5. Abstract:
  6. semantic analysis routines
  7. Notes:
  8. Author:
  9. GregJen Jun-11-1993 Created.
  10. Notes:
  11. ----------------------------------------------------------------------------*/
  12. // unreferenced inline/local function has been removed
  13. #pragma warning ( disable : 4514 )
  14. /****************************************************************************
  15. * include files
  16. ***************************************************************************/
  17. #include <basetsd.h>
  18. #include "allnodes.hxx"
  19. #include "semantic.hxx"
  20. #include "cmdana.hxx"
  21. extern "C"
  22. {
  23. #include <string.h>
  24. }
  25. #include "treg.hxx"
  26. #include "tlgen.hxx"
  27. #include "Pragma.hxx"
  28. // #include "attrguid.hxx"
  29. BOOL
  30. IsOLEAutomationType (
  31. char*
  32. );
  33. BOOL
  34. IsOLEAutomationCompliant(
  35. node_skl*
  36. );
  37. node_interface*
  38. CloneIFAndSplitMethods (
  39. node_interface*
  40. );
  41. node_skl*
  42. GetInOnlyParamPairedWithOut (
  43. MEM_ITER& MemParamList
  44. );
  45. bool
  46. HasCorrelation (
  47. node_skl*
  48. );
  49. #define RPC_ASYNC_HANDLE_NAME "PRPC_ASYNC_STATE"
  50. #define RPC_ASYNC_STRUCT_NAME "_RPC_ASYNC_STATE"
  51. #define OBJECT_ASYNC_HANDLE_NAME "IAsyncManager"
  52. #define IS_OLD_INTERPRETER( x ) ( ((x) & OPTIMIZE_INTERPRETER) && !((x) & OPTIMIZE_INTERPRETER_V2) )
  53. #define IsCoclassOrDispKind(x) ( (x) == NODE_DISPINTERFACE || (x) == NODE_COCLASS )
  54. #define IsInterfaceKind(x) ( (x) == NODE_INTERFACE_REFERENCE || (x) == NODE_INTERFACE )
  55. //
  56. // This state table defines the rules that govern valid [propput] methods.
  57. //
  58. namespace PropPut
  59. {
  60. enum State
  61. {
  62. NoParam = 0,
  63. GeneralParam = 1,
  64. Optional = 2,
  65. Default = 3,
  66. LCID = 4,
  67. LastParam = 5,
  68. Reject = 6,
  69. Accept = 7,
  70. };
  71. // Accept = Param* (optional|default)* (param|lcidparam|default)
  72. State StateTable[][5] =
  73. {
  74. // no param regular optional default lcid
  75. // -----------------------------------------------------------
  76. {Reject, GeneralParam, Optional, Default, LCID}, // NoParam
  77. {Accept, GeneralParam, Optional, Default, LCID}, // GeneralParam
  78. {Reject, LastParam, Optional, Default, LCID}, // Optional
  79. {Accept, LastParam, Optional, Default, LCID}, // Default
  80. {Reject, LastParam, Reject, Reject, Reject}, // LCID
  81. {Accept, Reject, Reject, Reject, Reject}, // LastParam
  82. {Reject, Reject, Reject, Reject, Reject}, // Reject
  83. {Accept, Reject, Reject, Reject, Reject} // Accept
  84. };
  85. }
  86. /****************************************************************************
  87. * externs
  88. ***************************************************************************/
  89. extern BOOL IsTempName( char * );
  90. extern CMD_ARG * pCommand;
  91. extern SymTable * pUUIDTable;
  92. extern SymTable * pBaseSymTbl;
  93. extern TREGISTRY * pCallAsTable;
  94. extern BOOL Xxx_Is_Type_OK( node_skl * pType );
  95. extern "C"
  96. {
  97. #ifndef GUID_DEFINED
  98. #define GUID_DEFINED
  99. typedef struct _GUID { // size is 16
  100. unsigned long Data1;
  101. unsigned short Data2;
  102. unsigned short Data3;
  103. unsigned char Data4[8];
  104. } GUID;
  105. #endif
  106. typedef GUID IID;
  107. extern const GUID IID_IAdviseSink;
  108. extern const GUID IID_IAdviseSink2;
  109. extern const GUID IID_IAdviseSinkEx;
  110. extern const GUID IID_AsyncIAdviseSink;
  111. extern const GUID IID_AsyncIAdviseSink2;
  112. // {DE77BA62-517C-11d1-A2DA-0000F8773CE9}
  113. static const GUID IID_AsyncIAdviseSinkEx2 =
  114. { 0xde77ba62, 0x517c, 0x11d1, { 0xa2, 0xda, 0x0, 0x0, 0xf8, 0x77, 0x3c, 0xe9 } };
  115. };
  116. bool
  117. IsAnyIAdviseSinkIID (
  118. GUID& rIID
  119. )
  120. {
  121. return (
  122. !memcmp( &IID_IAdviseSink, &rIID, sizeof(GUID) )
  123. || !memcmp( &IID_IAdviseSink2, &rIID, sizeof(GUID) )
  124. || !memcmp( &IID_AsyncIAdviseSink, &rIID, sizeof(GUID) )
  125. || !memcmp( &IID_AsyncIAdviseSink2, &rIID, sizeof(GUID) )
  126. // IAdviseSinkEx will be converted to sync interface.
  127. || !memcmp( &IID_IAdviseSinkEx, &rIID, sizeof(GUID) )
  128. );
  129. }
  130. node_skl*
  131. GetIndirectionLevel (
  132. node_skl* pType,
  133. unsigned int& nIndirectionLevel
  134. )
  135. {
  136. if ( pType )
  137. {
  138. node_skl* pChild = pType->GetChild();
  139. if ( pChild )
  140. {
  141. pType = pChild;
  142. NODE_T nodeKind = pType->NodeKind();
  143. if ( nodeKind == NODE_POINTER )
  144. {
  145. return GetIndirectionLevel( pType, ++nIndirectionLevel );
  146. }
  147. else if ( nodeKind == NODE_INTERFACE )
  148. {
  149. return pType;
  150. }
  151. else
  152. {
  153. return GetIndirectionLevel( pType, nIndirectionLevel );
  154. }
  155. }
  156. }
  157. return pType;
  158. }
  159. node_skl*
  160. GetNonDefType (
  161. node_skl* pType
  162. )
  163. {
  164. node_skl* pChild = pType->GetChild();
  165. if ( pChild && pType->NodeKind() == NODE_DEF )
  166. {
  167. pType = GetNonDefType( pChild );
  168. }
  169. return pType;
  170. }
  171. void
  172. node_skl::SemanticAnalysis( SEM_ANALYSIS_CTXT * )
  173. {
  174. MIDL_ASSERT( !"node_skl semantic analysis called" );
  175. }
  176. void
  177. node_skl::CheckDeclspecAlign( SEM_ANALYSIS_CTXT & MyContext )
  178. {
  179. if (GetModifiers().IsModifierSet( ATTR_DECLSPEC_ALIGN ) &&
  180. MyContext.AnyAncestorBits( IN_LIBRARY ) )
  181. {
  182. SemError( this, MyContext, DECLSPEC_ALIGN_IN_LIBRARY, GetSymName() );
  183. }
  184. }
  185. void
  186. node_href::SemanticAnalysis( SEM_ANALYSIS_CTXT * )
  187. {
  188. // If this reference hasn't already been expanded, Resolve() will expand it.
  189. named_node * pRef = Resolve();
  190. MIDL_ASSERT(pRef || !"node_href::Resolve() failed" );
  191. // NOTE - we might want to just skip this step and simply clear any
  192. // remaining attributes.
  193. // Presumably, if it came from a type library, it must have
  194. // been previously analyzed and found to be correct.
  195. // pRef->SemanticAnalysis(pParentCtxt);
  196. // pParentCtxt->ClearAttributes();
  197. }
  198. void
  199. node_forward::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  200. {
  201. if ( fBeingAnalyzed )
  202. {
  203. return;
  204. }
  205. fBeingAnalyzed = TRUE;
  206. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  207. named_node * pRef = ResolveFDecl();
  208. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  209. MyContext.ExtractAttribute( ATTR_DEFAULT );
  210. while(MyContext.ExtractAttribute( ATTR_CUSTOM ));
  211. // check for illegal member attributes
  212. node_member_attr * pMA;
  213. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  214. {
  215. switch (pMA->GetAttr())
  216. {
  217. case MATTR_PROPGET:
  218. case MATTR_PROPPUT:
  219. case MATTR_PROPPUTREF:
  220. case MATTR_BINDABLE:
  221. case MATTR_DISPLAYBIND:
  222. case MATTR_DEFAULTBIND:
  223. case MATTR_REQUESTEDIT:
  224. case MATTR_RETVAL:
  225. case MATTR_VARARG:
  226. case MATTR_SOURCE:
  227. case MATTR_DEFAULTVTABLE:
  228. case MATTR_RESTRICTED:
  229. case MATTR_OPTIONAL:
  230. case MATTR_PREDECLID:
  231. case MATTR_UIDEFAULT:
  232. case MATTR_NONBROWSABLE:
  233. case MATTR_DEFAULTCOLLELEM:
  234. case MATTR_IMMEDIATEBIND:
  235. case MATTR_USESGETLASTERROR:
  236. break;
  237. case MATTR_REPLACEABLE:
  238. default:
  239. {
  240. char * pAttrName = pMA->GetNodeNameString();
  241. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  242. break;
  243. }
  244. }
  245. }
  246. if ( !pRef && MyContext.AnyAncestorBits( IN_RPC ) )
  247. {
  248. SemError( this, MyContext, UNRESOLVED_TYPE, GetSymName() );
  249. }
  250. if ( pRef && ( pRef->NodeKind() == NODE_HREF ))
  251. {
  252. // expand the href
  253. pRef->SemanticAnalysis( &MyContext );
  254. node_skl* pChild = pRef->GetChild();
  255. if (pChild && pChild->NodeKind() == NODE_INTERFACE)
  256. {
  257. pRef = new node_interface_reference((node_interface *)pRef->GetChild());
  258. }
  259. }
  260. // we must go on and process interface references; they will
  261. // control any recursing and eliminate the forward reference.
  262. if ( pRef )
  263. {
  264. pRef->SemanticAnalysis( &MyContext );
  265. node_skl * pParent = pParentCtxt->GetParent();
  266. if ( pParent )
  267. {
  268. // if we came from an interface, set the base interface
  269. if ( pParent->IsInterfaceOrObject() && pRef->NodeKind() == NODE_INTERFACE_REFERENCE )
  270. {
  271. ((node_interface *)pParent)->SetMyBaseInterfaceReference( pRef );
  272. }
  273. else // otherwise, probably an interface pointer
  274. {
  275. pParent->SetChild( pRef );
  276. }
  277. }
  278. }
  279. else
  280. {
  281. // incomplete types may only be used in certain contexts...
  282. MyContext.SetDescendantBits( HAS_INCOMPLETE_TYPE );
  283. }
  284. if ( MyContext.FindRecursiveContext( pRef ) )
  285. {
  286. MyContext.SetDescendantBits( HAS_RECURSIVE_DEF );
  287. MyContext.SetAncestorBits( IN_RECURSIVE_DEF );
  288. }
  289. MyContext.RejectAttributes();
  290. pParentCtxt->ReturnValues( MyContext );
  291. fBeingAnalyzed = FALSE;
  292. }
  293. // checking the void usage in dispinterface.
  294. // currently we only check:
  295. // . void is not allowed as property or part of a structure.
  296. void node_base_type::CheckVoidUsageInDispinterface( SEM_ANALYSIS_CTXT * pContext )
  297. {
  298. SEM_ANALYSIS_CTXT * pCtxt = (SEM_ANALYSIS_CTXT *)
  299. pContext->GetParentContext();
  300. node_skl * pCur = pCtxt->GetParent();
  301. BOOL fHasPointer = FALSE;
  302. while ( pCur->NodeKind() != NODE_FIELD && pCur->NodeKind() != NODE_PROC )
  303. {
  304. if ( pCur->NodeKind() == NODE_POINTER )
  305. fHasPointer = TRUE;
  306. else
  307. {
  308. if ( pCur->NodeKind() != NODE_DEF )
  309. {
  310. RpcSemError( this, *pContext, NON_RPC_RTYPE_VOID, NULL );
  311. return;
  312. }
  313. }
  314. pCtxt = (SEM_ANALYSIS_CTXT *) pCtxt->GetParentContext();
  315. pCur = pCtxt->GetParent();
  316. }
  317. // This is either a property or part of a structure.
  318. if ( pCur->NodeKind() == NODE_FIELD )
  319. {
  320. if ( !fHasPointer )
  321. {
  322. SemError( this, *pContext, INVALID_VOID_IN_DISPINTERFACE, NULL );
  323. return;
  324. }
  325. }
  326. }
  327. void
  328. node_base_type::CheckVoidUsage( SEM_ANALYSIS_CTXT * pContext )
  329. {
  330. SEM_ANALYSIS_CTXT * pCtxt = (SEM_ANALYSIS_CTXT *)
  331. pContext->GetParentContext();
  332. node_skl * pCur = pCtxt->GetParent();
  333. // we assume that we are in an RPC, so we are in the return type
  334. // or we are in the param list
  335. if (pContext->AnyAncestorBits( IN_FUNCTION_RESULT ) )
  336. {
  337. // check up for anything other than def below proc
  338. while ( pCur->NodeKind() != NODE_PROC )
  339. {
  340. if ( pCur->NodeKind() != NODE_DEF )
  341. {
  342. RpcSemError( this, *pContext, NON_RPC_RTYPE_VOID, NULL );
  343. return;
  344. }
  345. pCtxt = (SEM_ANALYSIS_CTXT *) pCtxt->GetParentContext();
  346. pCur = pCtxt->GetParent();
  347. }
  348. return;
  349. }
  350. // else param list...
  351. node_proc * pProc;
  352. node_param * pParam;
  353. // check up for anything other than def below proc
  354. // make sure the proc only has one param
  355. while ( pCur->NodeKind() != NODE_PARAM )
  356. {
  357. if ( pCur->NodeKind() != NODE_DEF )
  358. {
  359. RpcSemError( this, *pContext, NON_RPC_PARAM_VOID, NULL );
  360. return;
  361. }
  362. pCtxt = (SEM_ANALYSIS_CTXT *) pCtxt->GetParentContext();
  363. pCur = pCtxt->GetParent();
  364. }
  365. // now we know the param derives directly from void
  366. // assume the proc is the immediate parent of the param
  367. pParam = ( node_param * ) pCur;
  368. pProc = ( node_proc * ) pCtxt->GetParentContext()->GetParent();
  369. MIDL_ASSERT ( pProc->NodeKind() == NODE_PROC );
  370. if ( ! IsTempName( pParam->GetSymName() ) )
  371. SemError( this, *pContext, VOID_PARAM_WITH_NAME, NULL );
  372. if ( pProc->GetNumberOfArguments() != 1 )
  373. SemError( this, *pContext, VOID_NON_FIRST_PARAM, NULL );
  374. // We know that the parameter is void.
  375. // So, chop it off to prevent complications from renaming etc.
  376. // and then using in a node_def in ILxlate.
  377. pProc->SetFirstMember( NULL );
  378. pProc->SetSibling( NULL );
  379. }
  380. void
  381. node_base_type::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  382. {
  383. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  384. CheckContextHandle( MyContext );
  385. CheckDeclspecAlign( MyContext );
  386. // warn about OUT const things
  387. if ( FInSummary( ATTR_CONST ) )
  388. {
  389. if ( MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) )
  390. RpcSemError( this, MyContext, CONST_ON_OUT_PARAM, NULL );
  391. else if ( MyContext.AnyAncestorBits( IN_FUNCTION_RESULT ) )
  392. RpcSemError( this, MyContext, CONST_ON_RETVAL, NULL );
  393. }
  394. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  395. node_range_attr* pRange = ( node_range_attr* ) MyContext.ExtractAttribute(ATTR_RANGE);
  396. MyContext.ExtractAttribute(ATTR_RANGE);
  397. if ( pRange )
  398. {
  399. if ( pRange->GetMinExpr()->GetValue() > pRange->GetMaxExpr()->GetValue() )
  400. {
  401. SemError(this, MyContext, INCORRECT_RANGE_DEFN, 0);
  402. }
  403. }
  404. switch ( NodeKind() )
  405. {
  406. case NODE_FLOAT:
  407. case NODE_DOUBLE:
  408. case NODE_HYPER:
  409. case NODE_INT64:
  410. case NODE_LONGLONG:
  411. if ( pRange )
  412. {
  413. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, 0 );
  414. }
  415. break;
  416. case NODE_INT3264:
  417. if ( MyContext.AnyAncestorBits( IN_LIBRARY ) )
  418. {
  419. SemError( this, MyContext, NO_SUPPORT_IN_TLB, 0 );
  420. }
  421. if ( pRange && pCommand->Is64BitEnv() )
  422. {
  423. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, 0 );
  424. }
  425. break;
  426. case NODE_INT:
  427. if ( MyContext.AnyAncestorBits( IN_FUNCTION_RESULT ) )
  428. RpcSemError( this, MyContext, NON_RPC_RTYPE_INT, NULL );
  429. else
  430. RpcSemError( this, MyContext, NON_RPC_PARAM_INT, NULL );
  431. break;
  432. case NODE_INT128:
  433. case NODE_FLOAT80:
  434. case NODE_FLOAT128:
  435. if ( pRange )
  436. {
  437. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, 0 );
  438. }
  439. if ( MyContext.AnyAncestorBits( IN_LIBRARY ) )
  440. {
  441. SemError( this, MyContext, NO_SUPPORT_IN_TLB, 0 );
  442. }
  443. break;
  444. case NODE_VOID:
  445. MyContext.SetDescendantBits( DERIVES_FROM_VOID );
  446. // if we are in an RPC, then we must be THE return type,
  447. // or we must be the sole parameter, which must be tempname'd
  448. // (except that void * is allowed in [iid_is] constructs)
  449. if (MyContext.AnyAncestorBits( IN_RPC ) && !MyContext.AnyAncestorBits( IN_INTERFACE_PTR ) )
  450. CheckVoidUsage( &MyContext );
  451. if ( MyContext.AnyAncestorBits( IN_DISPINTERFACE ) )
  452. CheckVoidUsageInDispinterface( &MyContext );
  453. break;
  454. case NODE_HANDLE_T:
  455. MyContext.SetDescendantBits( HAS_HANDLE );
  456. if (MyContext.AnyAncestorBits( IN_PARAM_LIST ) )
  457. {
  458. SEM_ANALYSIS_CTXT * pParamCtxt;
  459. node_param * pParamNode;
  460. pParamCtxt = (SEM_ANALYSIS_CTXT *)
  461. pParentCtxt->FindAncestorContext( NODE_PARAM );
  462. pParamNode = (node_param *) pParamCtxt->GetParent();
  463. if ( MyContext.AnyAncestorBits( IN_RPC ) )
  464. pParamNode->HandleKind = HDL_PRIM;
  465. if ( MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) &&
  466. !MyContext.AnyAncestorBits( UNDER_IN_PARAM ) )
  467. RpcSemError( this, MyContext, HANDLE_T_CANNOT_BE_OUT, NULL );
  468. if ( MyContext.AnyAncestorBits( IN_HANDLE ) )
  469. {
  470. RpcSemError( this, MyContext, GENERIC_HDL_HANDLE_T, NULL );
  471. }
  472. node_skl * pParamBasic = pParamNode->GetBasicType();
  473. if ( pParamBasic->NodeKind() == NODE_POINTER )
  474. {
  475. if ( pParamBasic->GetBasicType()->NodeKind() != NODE_HANDLE_T )
  476. RpcSemError( pParamNode, *pParamCtxt, HANDLE_T_NO_TRANSMIT, NULL );
  477. }
  478. }
  479. break;
  480. default:
  481. break;
  482. }
  483. MyContext.RejectAttributes();
  484. pParentCtxt->ReturnValues( MyContext );
  485. };
  486. BOOL
  487. node_id::IsConstantString()
  488. {
  489. // check for *, and const stringable type below
  490. node_skl * pBasic = GetBasicType();
  491. if ( pBasic->NodeKind() != NODE_POINTER )
  492. return FALSE;
  493. node_skl * pParent = pBasic;
  494. node_skl * pChild = pParent->GetChild();
  495. BOOL fConst = FALSE;
  496. while ( pChild )
  497. {
  498. // if we reached a stringable type, report it's constness
  499. if ( pChild->IsStringableType() || ( pChild->NodeKind() == NODE_VOID ) )
  500. {
  501. return fConst || pParent->FInSummary( ATTR_CONST );
  502. }
  503. // skip only typedefs looking for the base type
  504. if ( pChild->NodeKind() != NODE_DEF )
  505. return FALSE;
  506. // catch intervening const's
  507. if ( pParent->FInSummary( ATTR_CONST ) )
  508. fConst = TRUE;
  509. pParent = pChild;
  510. pChild = pParent->GetChild();
  511. }
  512. return FALSE;
  513. }
  514. void
  515. node_id::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  516. {
  517. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  518. BOOL fIsConstant;
  519. node_constant_attr * pID = (node_constant_attr *) MyContext.ExtractAttribute(ATTR_ID);
  520. MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
  521. MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
  522. MyContext.ExtractAttribute(ATTR_HELPSTRING);
  523. if ( HasCorrelation( this ) )
  524. {
  525. MyContext.IncCorrelationCount();
  526. }
  527. CheckDeclspecAlign( MyContext );
  528. /*
  529. // NishadM: Stricter type checking
  530. if ( pID && pID->GetExpr()->AlwaysGetType() )
  531. {
  532. if ( !( ( node_base_type*) pID->GetExpr()->GetType() )->IsCompatibleType( ts_FixedPoint ) )
  533. {
  534. SemError( this, MyContext, EXPR_INCOMPATIBLE_TYPES, NULL);
  535. }
  536. }
  537. if ( pHC && pHC->GetExpr()->AlwaysGetType() )
  538. {
  539. if ( !( ( node_base_type*) pHC->GetExpr()->GetType() )->IsCompatibleType( ts_UnsignedFixedPoint ) )
  540. {
  541. SemError( this, MyContext, EXPR_INCOMPATIBLE_TYPES, NULL);
  542. }
  543. }
  544. if ( pHSC && pHSC->GetExpr()->AlwaysGetType() )
  545. {
  546. if ( !( ( node_base_type*) pHSC->GetExpr()->GetType() )->IsCompatibleType( ts_UnsignedFixedPoint ) )
  547. {
  548. SemError( this, MyContext, EXPR_INCOMPATIBLE_TYPES, NULL);
  549. }
  550. }
  551. */
  552. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  553. {
  554. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  555. }
  556. MyContext.ExtractAttribute(ATTR_HIDDEN);
  557. GetChild()->SemanticAnalysis( &MyContext );
  558. fIsConstant = FInSummary( ATTR_CONST ) ||
  559. IsConstantString() ||
  560. GetChild()->FInSummary( ATTR_CONST );
  561. if (pID)
  562. {
  563. SEM_ANALYSIS_CTXT * pIntfCtxt = (SEM_ANALYSIS_CTXT *)
  564. MyContext.GetInterfaceContext();
  565. node_interface * pIntf = (node_interface *) pIntfCtxt->GetParent();
  566. if (!pIntf->AddId(pID->GetExpr()->GetValue(), GetSymName()))
  567. SemError( this, MyContext, DUPLICATE_IID, NULL);
  568. if (fIsConstant)
  569. {
  570. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  571. }
  572. }
  573. // don't allow instantiation of data
  574. if ( GetChild()->NodeKind() != NODE_PROC )
  575. {
  576. if ( !FInSummary( ATTR_EXTERN ) &&
  577. !FInSummary( ATTR_STATIC ) &&
  578. !fIsConstant )
  579. SemError( this, MyContext, ACTUAL_DECLARATION, NULL );
  580. // error here if dce for extern or static, too
  581. if ( !GetInitList() || !fIsConstant )
  582. SemError( this, MyContext, ILLEGAL_OSF_MODE_DECL, NULL );
  583. }
  584. if ( pInit )
  585. {
  586. EXPR_CTXT InitCtxt( &MyContext );
  587. node_skl * pBasicType = GetBasicType();
  588. node_skl * pInitType = NULL;
  589. pInit->ExprAnalyze( &InitCtxt );
  590. if ( InitCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  591. TypeSemError( this,
  592. MyContext,
  593. EXPR_NOT_EVALUATABLE,
  594. NULL );
  595. pInitType = pInit->GetType();
  596. if ( pInitType && !pInitType->IsBasicType() )
  597. pInitType = pInitType->GetBasicType();
  598. if ( pBasicType &&
  599. pInitType &&
  600. pBasicType->IsBasicType() &&
  601. pInitType->IsBasicType() )
  602. {
  603. if ( !((node_base_type *)pBasicType)
  604. ->RangeCheck( pInit->GetValue() ) )
  605. TypeSemError( this, MyContext, VALUE_OUT_OF_RANGE, NULL );
  606. }
  607. if ( !pInit->IsConstant() )
  608. TypeSemError( this, MyContext, RHS_OF_ASSIGN_NOT_CONST, NULL );
  609. }
  610. if ( MyContext.AnyAncestorBits( HAS_OLEAUTOMATION )|| MyContext.AnyAncestorBits( IN_DISPINTERFACE ) )
  611. {
  612. if ( !IsOLEAutomationCompliant( this ) )
  613. {
  614. SemError(this, MyContext, NOT_OLEAUTOMATION_INTERFACE, NULL);
  615. }
  616. }
  617. // disallow forward references on declarations
  618. if ( MyContext.AnyDescendantBits( HAS_INCOMPLETE_TYPE ) )
  619. {
  620. if (! MyContext.AnyAncestorBits( IN_LIBRARY ))
  621. SemError( this, MyContext, UNDEFINED_SYMBOL, NULL );
  622. MyContext.ClearDescendantBits( HAS_INCOMPLETE_TYPE );
  623. }
  624. MyContext.ClearDescendantBits( HAS_RECURSIVE_DEF );
  625. pParentCtxt->ReturnValues( MyContext );
  626. }
  627. void
  628. node_label::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  629. {
  630. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  631. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  632. if ( MyContext.ExtractAttribute(ATTR_IDLDESCATTR) )
  633. {
  634. SemError(this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, 0);
  635. }
  636. if ( MyContext.ExtractAttribute(ATTR_VARDESCATTR) )
  637. {
  638. SemError(this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, 0);
  639. }
  640. if ( MyContext.ExtractAttribute(ATTR_ID) )
  641. {
  642. SemError(this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, 0);
  643. }
  644. MyContext.ExtractAttribute(ATTR_HIDDEN);
  645. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  646. MyContext.ExtractAttribute( ATTR_HELPSTRINGCONTEXT );
  647. MyContext.ExtractAttribute( ATTR_HELPCONTEXT );
  648. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  649. {
  650. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  651. }
  652. // check for illegal member attributes
  653. node_member_attr * pMA;
  654. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  655. {
  656. switch (pMA->GetAttr())
  657. {
  658. case MATTR_PROPGET:
  659. case MATTR_PROPPUT:
  660. case MATTR_PROPPUTREF:
  661. case MATTR_BINDABLE:
  662. case MATTR_DISPLAYBIND:
  663. case MATTR_DEFAULTBIND:
  664. case MATTR_REQUESTEDIT:
  665. case MATTR_RETVAL:
  666. case MATTR_VARARG:
  667. case MATTR_SOURCE:
  668. case MATTR_DEFAULTVTABLE:
  669. case MATTR_RESTRICTED:
  670. case MATTR_OPTIONAL:
  671. case MATTR_PREDECLID:
  672. case MATTR_UIDEFAULT:
  673. case MATTR_NONBROWSABLE:
  674. case MATTR_DEFAULTCOLLELEM:
  675. case MATTR_IMMEDIATEBIND:
  676. case MATTR_USESGETLASTERROR:
  677. break;
  678. case MATTR_REPLACEABLE:
  679. default:
  680. {
  681. char * pAttrName = pMA->GetNodeNameString();
  682. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  683. break;
  684. }
  685. }
  686. }
  687. if ( HasCorrelation( this ) )
  688. {
  689. MyContext.IncCorrelationCount();
  690. }
  691. CheckDeclspecAlign( MyContext );
  692. if ( pExpr )
  693. {
  694. EXPR_CTXT ExprCtxt( &MyContext );
  695. pExpr->ExprAnalyze( &ExprCtxt );
  696. if ( ExprCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  697. TypeSemError( this,
  698. MyContext,
  699. EXPR_NOT_EVALUATABLE,
  700. NULL );
  701. }
  702. pParentCtxt->ReturnValues( MyContext );
  703. };
  704. #define DIRECT_NONE 0
  705. #define DIRECT_IN 1
  706. #define DIRECT_OUT 2
  707. #define DIRECT_PARTIAL_IGNORE (DIRECT_IN | DIRECT_OUT | 4 )
  708. #define DIRECT_IN_OUT (DIRECT_IN | DIRECT_OUT)
  709. void
  710. node_param::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  711. {
  712. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  713. unsigned short Direction = DIRECT_NONE;
  714. char * pName = GetSymName();
  715. node_skl * pChild = GetChild();
  716. BOOL NoDirection = FALSE;
  717. MyContext.SetAncestorBits( IN_PARAM_LIST );
  718. MyContext.MarkImportantPosition();
  719. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  720. MyContext.ExtractAttribute(ATTR_IDLDESCATTR);
  721. if ( MyContext.ExtractAttribute(ATTR_FLCID) )
  722. {
  723. LCID();
  724. }
  725. CheckDeclspecAlign( MyContext );
  726. // check for illegal member attributes
  727. node_member_attr * pMA;
  728. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  729. {
  730. switch (pMA->GetAttr())
  731. {
  732. case MATTR_OPTIONAL:
  733. {
  734. node_skl * pBase = this;
  735. do {
  736. pBase = pBase->GetChild()->GetBasicType();
  737. } while (NODE_ARRAY == pBase->NodeKind() || NODE_POINTER == pBase->NodeKind());
  738. if ( !pBase->GetSymName() ||
  739. ( (0 != _stricmp(pBase->GetSymName(), "tagVARIANT") )
  740. && FNewTypeLib()
  741. && ( MyContext.AnyAncestorBits( HAS_OLEAUTOMATION )
  742. || MyContext.AnyAncestorBits( IN_DISPINTERFACE ) ) ) )
  743. {
  744. SemError(this, MyContext, INAPPLICABLE_OPTIONAL_ATTRIBUTE, pMA->GetNodeNameString());
  745. }
  746. if ( ! MyContext.AnyAncestorBits( IN_LIBRARY ) )
  747. {
  748. SemError(this, MyContext, OPTIONAL_OUTSIDE_LIBRARY, NULL);
  749. }
  750. Optional();
  751. break;
  752. }
  753. case MATTR_RETVAL:
  754. Retval();
  755. break;
  756. case MATTR_RESTRICTED:
  757. case MATTR_SOURCE:
  758. case MATTR_PROPGET:
  759. case MATTR_PROPPUT:
  760. case MATTR_PROPPUTREF:
  761. {
  762. char * pAttrName = pMA->GetNodeNameString();
  763. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  764. break;
  765. }
  766. case MATTR_BINDABLE:
  767. case MATTR_DISPLAYBIND:
  768. case MATTR_DEFAULTBIND:
  769. case MATTR_REQUESTEDIT:
  770. case MATTR_VARARG:
  771. case MATTR_DEFAULTVTABLE:
  772. case MATTR_PREDECLID:
  773. case MATTR_UIDEFAULT:
  774. case MATTR_NONBROWSABLE:
  775. case MATTR_DEFAULTCOLLELEM:
  776. case MATTR_USESGETLASTERROR:
  777. case MATTR_IMMEDIATEBIND:
  778. break;
  779. case MATTR_REPLACEABLE:
  780. default:
  781. {
  782. char * pAttrName = pMA->GetNodeNameString();
  783. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  784. break;
  785. }
  786. }
  787. }
  788. node_constant_attr * pcaDefaultValue = (node_constant_attr *)MyContext.ExtractAttribute(ATTR_DEFAULTVALUE);
  789. if ( pcaDefaultValue )
  790. {
  791. // UNDONE: Check that this attribute has a legal default value
  792. // We already have an [optional] flag. MIDL should issue a warning
  793. // that we shouldn't have both.
  794. if ( IsOptional() )
  795. {
  796. SemError( this, MyContext, DEFAULTVALUE_WITH_OPTIONAL, 0);
  797. }
  798. pParentCtxt->SetDescendantBits( HAS_DEFAULT_VALUE );
  799. Optional();
  800. }
  801. if ( MyContext.ExtractAttribute(ATTR_IN) )
  802. {
  803. pParentCtxt->SetDescendantBits( HAS_IN );
  804. MyContext.SetAncestorBits( UNDER_IN_PARAM );
  805. Direction |= DIRECT_IN;
  806. }
  807. if ( MyContext.ExtractAttribute(ATTR_OUT) )
  808. {
  809. pParentCtxt->SetDescendantBits( HAS_OUT );
  810. MyContext.SetAncestorBits( UNDER_OUT_PARAM );
  811. Direction |= DIRECT_OUT;
  812. }
  813. if ( MyContext.ExtractAttribute( ATTR_PARTIAL_IGNORE ) )
  814. {
  815. pCommand->GetNdrVersionControl().SetHasPartialIgnore();
  816. pParentCtxt->SetDescendantBits( HAS_PARTIAL_IGNORE );
  817. MyContext.SetAncestorBits( UNDER_PARTIAL_IGNORE_PARAM );
  818. if ( !( Direction & DIRECT_IN ) || !( Direction & DIRECT_OUT ) )
  819. {
  820. SemError( this, MyContext, PARTIAL_IGNORE_IN_OUT, GetSymName() );
  821. }
  822. if ( FInSummary( ATTR_STRING )
  823. && ! ( FInSummary( ATTR_SIZE ) || FInSummary( ATTR_MAX) ) )
  824. {
  825. SemError( this, MyContext, UNSIZED_PARTIAL_IGNORE, GetSymName() );
  826. }
  827. Direction |= DIRECT_PARTIAL_IGNORE;
  828. }
  829. if ( IsExtraStatusParam() )
  830. MyContext.SetAncestorBits( UNDER_HIDDEN_STATUS );
  831. // [retval] parameter must be on an [out] parameter and it
  832. // must be the last parameter in the list
  833. if (IsRetval() && (Direction != DIRECT_OUT || GetSibling() != NULL))
  834. SemError(this, MyContext, INVALID_USE_OF_RETVAL, NULL );
  835. // if the parameter has no IN or OUT, it is an IN parameter by default.
  836. // if so, issue a warning message
  837. // REVIEW: No warning is being issued. What about hidden status params
  838. // which are neither in nor out?
  839. if ( (Direction == DIRECT_NONE) &&
  840. MyContext.AnyAncestorBits( IN_RPC ) )
  841. {
  842. NoDirection = TRUE;
  843. MyContext.SetAncestorBits( UNDER_IN_PARAM );
  844. Direction |= DIRECT_IN;
  845. }
  846. // warn about OUT const things
  847. if ( ( Direction & DIRECT_OUT ) &&
  848. FInSummary( ATTR_CONST ) )
  849. RpcSemError( this, MyContext, CONST_ON_OUT_PARAM, NULL );
  850. if ( MyContext.FInSummary(ATTR_HANDLE) )
  851. {
  852. HandleKind |= HDL_GEN;
  853. fAppliedHere = 1;
  854. }
  855. if ( MyContext.FInSummary(ATTR_CONTEXT) )
  856. {
  857. HandleKind |= HDL_CTXT;
  858. fAppliedHere = 1;
  859. }
  860. if (HandleKind != HDL_NONE)
  861. MyContext.SetDescendantBits( HAS_HANDLE | HAS_CONTEXT_HANDLE );
  862. // notice comm and fault statuses; the attributes are extracted by
  863. // the error_status_t
  864. if ( MyContext.FInSummary( ATTR_COMMSTAT ) )
  865. {
  866. Statuses |= STATUS_COMM;
  867. }
  868. if ( MyContext.FInSummary( ATTR_FAULTSTAT ) )
  869. {
  870. Statuses |= STATUS_FAULT;
  871. }
  872. acf_attr *pDRtag = (acf_attr *) MyContext.ExtractAttribute( ATTR_DRTAG );
  873. acf_attr *pStag = (acf_attr *) MyContext.ExtractAttribute( ATTR_STAG );
  874. acf_attr *pRtag = (acf_attr *) MyContext.ExtractAttribute( ATTR_RTAG );
  875. if ( pDRtag )
  876. {
  877. if ( !( Direction & DIRECT_IN ) )
  878. AcfError(pDRtag, this, MyContext, IN_TAG_WITHOUT_IN, NULL);
  879. SetHasCSDRTag();
  880. MyContext.SetDescendantBits( HAS_DRTAG );
  881. }
  882. if ( pStag )
  883. {
  884. if ( !( Direction & DIRECT_IN ) )
  885. AcfError(pStag, this, MyContext, IN_TAG_WITHOUT_IN, NULL);
  886. SetHasCSSTag();
  887. MyContext.SetDescendantBits( HAS_STAG );
  888. }
  889. if ( pRtag )
  890. {
  891. if ( !( Direction & DIRECT_OUT ) )
  892. AcfError(pRtag, this, MyContext, OUT_TAG_WITHOUT_OUT, NULL);
  893. SetHasCSRTag();
  894. MyContext.SetDescendantBits( HAS_RTAG );
  895. }
  896. acf_attr * pForceAllocate = (acf_attr *) MyContext.ExtractAttribute( ATTR_FORCEALLOCATE );
  897. if ( pForceAllocate )
  898. {
  899. // we allow force allocation on [in] and [in,out] parameters. server allocate
  900. if ( ! (Direction & DIRECT_IN ) )
  901. AcfError( pForceAllocate, this, MyContext, OUT_ONLY_FORCEALLOCATE, NULL );
  902. MyContext.SetDescendantBits ( HAS_FORCEALLOCATE );
  903. pCommand->GetNdrVersionControl().SetHasForceAllocate();
  904. }
  905. pChild->SemanticAnalysis( &MyContext );
  906. // OUT parameters should be pointers or arrays.
  907. // Don't use HAS_POINTER or arrays as it may come from a field.
  908. if ( ( Direction & DIRECT_PARTIAL_IGNORE ) == DIRECT_PARTIAL_IGNORE )
  909. {
  910. node_skl *pPointer = GetNonDefChild();
  911. if ( ( pPointer->NodeKind() != NODE_POINTER ) ||
  912. MyContext.AnyDescendantBits((DESCENDANT_FLAGS) HAS_PIPE) )
  913. {
  914. SemError( this, MyContext, PARTIAL_IGNORE_UNIQUE, NULL );
  915. }
  916. node_skl *pPointee = pPointer->GetNonDefChild();
  917. if ( pPointee->IsStructOrUnion() )
  918. if ( ((node_su_base *) pPointee)->HasConformance() )
  919. SemError( this, MyContext, UNSIZED_PARTIAL_IGNORE, NULL );
  920. }
  921. else if ( (Direction & DIRECT_OUT) && !(
  922. GetNonDefChild()->IsPtrOrArray()
  923. || MyContext.AnyDescendantBits((DESCENDANT_FLAGS) HAS_PIPE)))
  924. {
  925. SemError( this, MyContext, NON_PTR_OUT, NULL );
  926. }
  927. if ( pForceAllocate )
  928. {
  929. if ( MyContext.AnyDescendantBits((DESCENDANT_FLAGS) HAS_PIPE) )
  930. AcfError( pForceAllocate, this, MyContext, FORCEALLOCATE_ON_PIPE, NULL );
  931. }
  932. // if no direction was specified, and we are not just void or a hidden
  933. // status parameter, then error
  934. if ( NoDirection )
  935. {
  936. pParentCtxt->SetDescendantBits( HAS_IN );
  937. if ( !MyContext.AnyDescendantBits( DERIVES_FROM_VOID )
  938. && !IsExtraStatusParam() )
  939. {
  940. RpcSemError( this, MyContext, NO_EXPLICIT_IN_OUT_ON_PARAM, NULL );
  941. }
  942. }
  943. // disallow forward references as union members
  944. if ( MyContext.AnyDescendantBits( HAS_INCOMPLETE_TYPE ) )
  945. {
  946. if (! MyContext.AnyAncestorBits( IN_LIBRARY ))
  947. SemError( this, MyContext, UNDEFINED_SYMBOL, NULL );
  948. MyContext.ClearDescendantBits( HAS_INCOMPLETE_TYPE );
  949. }
  950. MyContext.ClearDescendantBits( HAS_RECURSIVE_DEF );
  951. // disallow module as params
  952. if ( GetBasicType()->NodeKind() == NODE_MODULE )
  953. {
  954. SemError( this, MyContext, DERIVES_FROM_COCLASS_OR_MODULE, 0);
  955. }
  956. else if (GetBasicType()->NodeKind() == NODE_POINTER)
  957. {
  958. if (GetBasicType()->GetChild()->NodeKind() == NODE_MODULE )
  959. {
  960. SemError( this, MyContext, DERIVES_FROM_COCLASS_OR_MODULE, 0);
  961. }
  962. }
  963. if ( GetBasicType()->NodeKind() == NODE_INTERFACE ||
  964. GetBasicType()->NodeKind() == NODE_DISPINTERFACE )
  965. {
  966. SemError( this, MyContext, INTF_NON_POINTER, 0);
  967. }
  968. // compound types may not be declared in param lists
  969. NODE_T ChildKind = pChild->NodeKind();
  970. if ( ( ChildKind == NODE_ENUM )
  971. || ( ChildKind == NODE_STRUCT )
  972. || ( ChildKind == NODE_UNION ) )
  973. {
  974. if ( IsDef() )
  975. SemError( this, MyContext, COMP_DEF_IN_PARAM_LIST, NULL );
  976. }
  977. // things not allowed in an RPC
  978. if ( MyContext.AnyAncestorBits( IN_RPC | IN_LIBRARY ) )
  979. {
  980. if ( strcmp( pName, "..." ) == 0 )
  981. SemError( this, MyContext, PARAM_IS_ELIPSIS, NULL );
  982. if ( IsTempName( pName ) )
  983. RpcSemError( this, MyContext, ABSTRACT_DECL, NULL );
  984. }
  985. if ( ( HandleKind != HDL_NONE ) &&
  986. ( Direction & DIRECT_IN ) )
  987. fBindingParam = TRUE;
  988. if ( ( HandleKind == HDL_CTXT ) &&
  989. MyContext.AnyDescendantBits( HAS_TRANSMIT_AS ) )
  990. RpcSemError( this, MyContext, CTXT_HDL_TRANSMIT_AS, NULL );
  991. if ( MyContext.AnyAncestorBits( HAS_OLEAUTOMATION ) || MyContext.AnyAncestorBits( IN_DISPINTERFACE ) )
  992. {
  993. // check the child type instead of NODE_PARAM directly. nt bug #371499
  994. if ( !IsOLEAutomationCompliant( GetBasicType() ) )
  995. {
  996. SemError(this, MyContext, NOT_OLEAUTOMATION_INTERFACE, NULL);
  997. }
  998. }
  999. // don't allow functions as params
  1000. if ( MyContext.AnyDescendantBits( HAS_FUNC ) &&
  1001. MyContext.AllAncestorBits( IN_INTERFACE | IN_RPC ) )
  1002. RpcSemError( this, MyContext, BAD_CON_PARAM_FUNC, NULL );
  1003. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  1004. {
  1005. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  1006. }
  1007. if ( HasCorrelation( this ) )
  1008. {
  1009. MyContext.IncCorrelationCount();
  1010. }
  1011. if ( ( Direction & DIRECT_OUT ) && MyContext.GetCorrelationCount() )
  1012. {
  1013. MyContext.SetDescendantBits( HAS_CLIENT_CORRELATION );
  1014. }
  1015. if ( ( Direction & DIRECT_IN ) && MyContext.GetCorrelationCount() )
  1016. {
  1017. MyContext.SetDescendantBits( HAS_SERVER_CORRELATION );
  1018. }
  1019. if ( MyContext.AnyAncestorBits( HAS_ASYNCHANDLE ) &&
  1020. MyContext.AnyDescendantBits( (DESCENDANT_FLAGS) HAS_PIPE ) &&
  1021. pChild->GetNonDefSelf()->NodeKind() != NODE_POINTER )
  1022. {
  1023. SemError(this, MyContext, ASYNC_PIPE_BY_REF, GetSymName() );
  1024. }
  1025. // This is completely banned with the new transfer syntax.
  1026. if ( pCommand->NeedsNDR64Run() )
  1027. {
  1028. if ( MyContext.AnyDescendantBits( HAS_UNSAT_REP_AS ) )
  1029. {
  1030. RpcSemError( this, MyContext, UNSPECIFIED_EMBEDDED_REPRESENT_AS_NOT_SUPPORTED, NULL );
  1031. }
  1032. }
  1033. pParentCtxt->ReturnValues( MyContext );
  1034. }
  1035. void
  1036. node_file::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  1037. {
  1038. MEM_ITER MemIter( this );
  1039. node_skl * pN;
  1040. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  1041. if ( ImportLevel == 0 )
  1042. {
  1043. MyContext.SetAncestorBits( IN_INTERFACE );
  1044. }
  1045. #ifdef ReducedImportSemAnalysis
  1046. else
  1047. return;
  1048. #endif
  1049. while ( ( pN = MemIter.GetNext() ) != 0 )
  1050. {
  1051. // each interface node gets a fresh context
  1052. MyContext.SetInterfaceContext( &MyContext );
  1053. // allow echo string and midl_grama outside library block,
  1054. // even in mktyplib compatible mode
  1055. if ( ( 0 == ImportLevel )
  1056. && ( NODE_LIBRARY != pN->NodeKind() )
  1057. && ( NODE_ECHO_STRING != pN->NodeKind() )
  1058. && ( NODE_MIDL_PRAGMA != pN->NodeKind() )
  1059. && ( pCommand->IsSwitchDefined(SWITCH_MKTYPLIB ) ) )
  1060. {
  1061. SEM_ANALYSIS_CTXT DummyContext( pN, &MyContext );
  1062. SemError(pN, DummyContext, ILLEGAL_IN_MKTYPLIB_MODE, NULL);
  1063. }
  1064. pN->SemanticAnalysis( &MyContext );
  1065. };
  1066. pParentCtxt->ReturnValues( MyContext );
  1067. };
  1068. // for fault_status and comm_status
  1069. #define NOT_SEEN 0
  1070. #define SEEN_ON_RETURN 1
  1071. #define SEEN_ON_PARAM 2
  1072. void
  1073. node_proc::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  1074. {
  1075. node_param* pN;
  1076. node_optimize* pOptAttr;
  1077. acf_attr* pAttr;
  1078. ATTR_T CallingConv;
  1079. MEM_ITER MemIter( this );
  1080. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  1081. SEM_ANALYSIS_CTXT* pIntfCtxt = (SEM_ANALYSIS_CTXT *) MyContext.GetInterfaceContext();
  1082. node_interface* pIntf = (node_interface *) pIntfCtxt->GetParent();
  1083. node_entry_attr* pEntry = NULL;
  1084. node_base_attr* pAttrAsync = MyContext.ExtractAttribute( ATTR_ASYNC );
  1085. unsigned short Faultstat = NOT_SEEN;
  1086. unsigned short Commstat = NOT_SEEN;
  1087. unsigned short OpBits = MyContext.GetOperationBits();
  1088. BOOL fNoCode = FALSE;
  1089. BOOL fCode = FALSE;
  1090. BOOL Skipme = FALSE;
  1091. BOOL fNonOperation = FALSE;
  1092. BOOL fEncode = (NULL != MyContext.ExtractAttribute( ATTR_ENCODE ));
  1093. BOOL fDecode = (NULL != MyContext.ExtractAttribute( ATTR_DECODE ));
  1094. // Use bitwise or because otherwise the C/C++ compiler will incorrectly
  1095. // short-circuit the call to ExtractAttribute(ATTR_DECODE).
  1096. BOOL HasPickle = fEncode | fDecode;
  1097. BOOL fExpHdlAttr = FALSE;
  1098. BOOL fMaybe = OpBits & OPERATION_MAYBE;
  1099. BOOL fMessage = OpBits & OPERATION_MESSAGE;
  1100. BOOL fBindingFound = FALSE;
  1101. BOOL fProcIsCallback= (NULL != MyContext.ExtractAttribute( ATTR_CALLBACK ));
  1102. BOOL fLocal = (NULL != MyContext.ExtractAttribute( ATTR_LOCAL ));
  1103. BOOL fNotify = (NULL != MyContext.ExtractAttribute( ATTR_NOTIFY ));
  1104. BOOL fNotifyFlag = (NULL != MyContext.ExtractAttribute( ATTR_NOTIFY_FLAG ));
  1105. node_skl* pRet = GetReturnType();
  1106. NODE_T BasicChildKind = pRet->GetBasicType()->NodeKind();
  1107. node_call_as* pCallAs = (node_call_as *) MyContext.ExtractAttribute( ATTR_CALL_AS );
  1108. acf_attr* pEnableAllocate = (acf_attr *) MyContext.ExtractAttribute( ATTR_ENABLE_ALLOCATE );
  1109. node_constant_attr* pID = (node_constant_attr *) MyContext.ExtractAttribute(ATTR_ID);
  1110. node_constant_attr* pHC = (node_constant_attr *) MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
  1111. node_constant_attr* pHSC = (node_constant_attr *) MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
  1112. node_text_attr* pHelpStr = (node_text_attr *) MyContext.ExtractAttribute(ATTR_HELPSTRING);
  1113. bool fAddExplicitHandle = false;
  1114. long nAfterLastOptionalParam = 0;
  1115. node_cs_tag_rtn * pCSTagAttr = (node_cs_tag_rtn *) MyContext.ExtractAttribute( ATTR_CSTAGRTN );
  1116. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  1117. {
  1118. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  1119. }
  1120. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  1121. MyContext.ExtractAttribute(ATTR_FUNCDESCATTR);
  1122. MyContext.ExtractAttribute( ATTR_HIDDEN );
  1123. fHasDeny = pCommand->IsSwitchDefined( SWITCH_ROBUST );
  1124. if (MyContext.AnyAncestorBits( IN_MODULE ))
  1125. {
  1126. pEntry = (node_entry_attr *) MyContext.ExtractAttribute( ATTR_ENTRY );
  1127. if (pEntry)
  1128. {
  1129. if (pEntry->IsNumeric())
  1130. {
  1131. char * szEntry = (char *)pEntry->GetID();
  1132. if ( ((LONG_PTR) szEntry) > 0xFFFF )
  1133. {
  1134. SemError( this, MyContext, BAD_ENTRY_VALUE, NULL);
  1135. }
  1136. }
  1137. else
  1138. {
  1139. char * szEntry = pEntry->GetSz();
  1140. if ( ((LONG_PTR) szEntry) <= 0xFFFF )
  1141. {
  1142. SemError( this, MyContext, BAD_ENTRY_VALUE, NULL);
  1143. }
  1144. }
  1145. }
  1146. else
  1147. {
  1148. SemError(this, MyContext, BAD_ENTRY_VALUE, NULL);
  1149. }
  1150. }
  1151. bool fBindable = false;
  1152. bool fPropSomething = false;
  1153. bool fPropGet = false;
  1154. int nchSkip = 0;
  1155. bool fHasVarArg = false;
  1156. // check for illegal member attributes
  1157. node_member_attr * pMA;
  1158. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  1159. {
  1160. switch (pMA->GetAttr())
  1161. {
  1162. case MATTR_BINDABLE:
  1163. fBindable = TRUE;
  1164. break;
  1165. case MATTR_PROPGET:
  1166. nchSkip = 4;
  1167. fPropSomething = TRUE;
  1168. fPropGet = TRUE;
  1169. break;
  1170. case MATTR_PROPPUT:
  1171. nchSkip = 4;
  1172. fPropSomething = TRUE;
  1173. break;
  1174. case MATTR_PROPPUTREF:
  1175. nchSkip = 7;
  1176. fPropSomething = TRUE;
  1177. break;
  1178. case MATTR_VARARG:
  1179. fHasVarArg = true;
  1180. break;
  1181. case MATTR_RESTRICTED:
  1182. case MATTR_SOURCE:
  1183. if ( MyContext.AnyAncestorBits( IN_MODULE ))
  1184. {
  1185. char * pAttrName = pMA->GetNodeNameString();
  1186. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  1187. break;
  1188. }
  1189. case MATTR_DISPLAYBIND:
  1190. case MATTR_DEFAULTBIND:
  1191. case MATTR_REQUESTEDIT:
  1192. case MATTR_UIDEFAULT:
  1193. case MATTR_NONBROWSABLE:
  1194. case MATTR_DEFAULTCOLLELEM:
  1195. case MATTR_DEFAULTVTABLE:
  1196. case MATTR_IMMEDIATEBIND:
  1197. case MATTR_REPLACEABLE:
  1198. case MATTR_READONLY:
  1199. break;
  1200. case MATTR_USESGETLASTERROR:
  1201. {
  1202. if ( !MyContext.AnyAncestorBits( IN_MODULE ) )
  1203. {
  1204. char * pAttrName = pMA->GetNodeNameString();
  1205. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  1206. }
  1207. break;
  1208. }
  1209. case MATTR_RETVAL:
  1210. case MATTR_OPTIONAL:
  1211. case MATTR_PREDECLID:
  1212. {
  1213. char * pAttrName = pMA->GetNodeNameString();
  1214. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  1215. break;
  1216. }
  1217. }
  1218. }
  1219. if (pID)
  1220. {
  1221. if (!pIntf->AddId(pID->GetExpr()->GetValue(),GetSymName() + nchSkip))
  1222. SemError( this, MyContext, DUPLICATE_IID, NULL);
  1223. }
  1224. if (fBindable && !fPropSomething)
  1225. SemError(this, MyContext, INVALID_USE_OF_BINDABLE, NULL);
  1226. if ( pEnableAllocate )
  1227. pIntf->SetHasProcsWithRpcSs();
  1228. fNonOperation = !pParentCtxt->GetParent()->IsInterfaceOrObject();
  1229. if ( !GetCallingConvention( CallingConv ) )
  1230. SemError( this, MyContext, MULTIPLE_CALLING_CONVENTIONS, NULL );
  1231. // locally applied [code] attribute overrides global [nocode] attribute
  1232. fNoCode = (NULL != MyContext.ExtractAttribute( ATTR_NOCODE ));
  1233. fCode = (NULL != MyContext.ExtractAttribute( ATTR_CODE ));
  1234. if ( fCode && fNoCode )
  1235. {
  1236. SemError( this, MyContext, CODE_NOCODE_CONFLICT, NULL );
  1237. }
  1238. fNoCode = fNoCode || pIntfCtxt->FInSummary( ATTR_NOCODE );
  1239. fNoCode = !fCode && fNoCode;
  1240. if ( fNoCode && pCommand->GenerateSStub() )
  1241. RpcSemError( this, MyContext, NOCODE_WITH_SERVER_STUBS, NULL );
  1242. // do my attribute parsing...
  1243. fObjectProc = MyContext.ExtractAttribute( ATTR_OBJECT ) || pIntfCtxt->FInSummary( ATTR_OBJECT );
  1244. SetObjectProc( fObjectProc );
  1245. if ( fObjectProc )
  1246. {
  1247. if ( pCommand->GetEnv() != ENV_WIN32 &&
  1248. pCommand->GetEnv() != ENV_WIN64 &&
  1249. !pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
  1250. {
  1251. // REVIEW: We can eliminate the warning if object procs can be
  1252. // in win64. It was necessary for dos, mac, etc.
  1253. SemError( this, MyContext, OBJECT_PROC_MUST_BE_WIN32, NULL );
  1254. }
  1255. if ( pEnableAllocate )
  1256. {
  1257. AcfError( pEnableAllocate, this, MyContext, INAPPROPRIATE_ON_OBJECT_PROC, NULL );
  1258. }
  1259. if ( HasPickle )
  1260. {
  1261. SemError( this, MyContext, PICKLING_INVALID_IN_OBJECT, NULL );
  1262. }
  1263. }
  1264. bool fAsync = ( MyContext.AnyAncestorBits( HAS_ASYNCHANDLE ) != 0 ) || ( pAttrAsync != 0 );
  1265. if ( fAsync )
  1266. {
  1267. MyContext.SetAncestorBits( HAS_ASYNCHANDLE );
  1268. // because we don't support async retry now, we need to issue an
  1269. // explicit warning about this.
  1270. if ( pCommand->NeedsNDR64Run() && !pCommand->NeedsNDRRun() )
  1271. SemError( this, MyContext, ASYNC_NDR64_ONLY, 0 );
  1272. }
  1273. // check return types for non object proc.s with maybe, message
  1274. // object proc.s should have HRESULT. This is checked later.
  1275. if ( ( fMessage || fMaybe ) && !fObjectProc )
  1276. {
  1277. if ( BasicChildKind != NODE_VOID )
  1278. {
  1279. if ( BasicChildKind != NODE_E_STATUS_T )
  1280. {
  1281. SemError( this, MyContext, MAYBE_NO_OUT_RETVALS, NULL );
  1282. }
  1283. else
  1284. {
  1285. unsigned long ulCommStat = (unsigned long) ( MyContext.FInSummary(ATTR_COMMSTAT) ? 1 : 0 ),
  1286. ulFaultStat = (unsigned long) ( MyContext.FInSummary(ATTR_FAULTSTAT) ? 1 : 0);
  1287. if ( ulCommStat ^ ulFaultStat )
  1288. {
  1289. SemError( this, MyContext, ASYNC_INCORRECT_ERROR_STATUS_T, 0 );
  1290. }
  1291. }
  1292. }
  1293. }
  1294. // check call_as characteristics
  1295. if ( pCallAs )
  1296. {
  1297. node_proc* pCallType = pCallAs->GetCallAsType();
  1298. // if we don't have it yet, search for the call_as target
  1299. if ( !pCallType )
  1300. {
  1301. // search the proc table for the particular proc
  1302. SymKey SKey( pCallAs->GetCallAsName(), NAME_PROC );
  1303. pCallType = ( node_proc* ) pIntf->GetProcTbl()->SymSearch( SKey );
  1304. if ( !pCallType )
  1305. {
  1306. if ( pIntfCtxt->FInSummary( ATTR_OBJECT ) )
  1307. AcfError( pCallAs,
  1308. this,
  1309. MyContext,
  1310. CALL_AS_UNSPEC_IN_OBJECT,
  1311. pCallAs->GetCallAsName() );
  1312. }
  1313. else
  1314. {
  1315. pCallAs->SetCallAsType(pCallType);
  1316. }
  1317. }
  1318. // now we should have the call_as type
  1319. if ( pCallType ) // found the call_as proc
  1320. {
  1321. ((node_proc *)pCallType)->fCallAsTarget = TRUE;
  1322. if ( ( pCallType->NodeKind() != NODE_PROC ) ||
  1323. !pCallType->FInSummary( ATTR_LOCAL ) )
  1324. AcfError( pCallAs,
  1325. this,
  1326. MyContext,
  1327. CALL_AS_NON_LOCAL_PROC,
  1328. pCallType->GetSymName() );
  1329. // insert pCallType into pCallAsTable
  1330. if ( pCallAsTable->IsRegistered( pCallType ) )
  1331. // error
  1332. AcfError( pCallAs,
  1333. this,
  1334. MyContext,
  1335. CALL_AS_USED_MULTIPLE_TIMES,
  1336. pCallType->GetSymName() );
  1337. else
  1338. pCallAsTable->Register( pCallType );
  1339. }
  1340. SetCallAsType( pCallType );
  1341. }
  1342. // local procs don't add to count
  1343. Skipme = fLocal;
  1344. if ( Skipme )
  1345. {
  1346. SemError( this, MyContext, LOCAL_ATTR_ON_PROC, NULL );
  1347. }
  1348. Skipme = Skipme || pIntfCtxt->FInSummary( ATTR_LOCAL );
  1349. if ( Skipme )
  1350. {
  1351. MyContext.SetAncestorBits( IN_LOCAL_PROC );
  1352. }
  1353. // do my attribute parsing...
  1354. // check for the [explicit_handle] attribute
  1355. fExpHdlAttr = (NULL != MyContext.ExtractAttribute( ATTR_EXPLICIT ));
  1356. fExpHdlAttr = fExpHdlAttr || pIntfCtxt->FInSummary( ATTR_EXPLICIT );
  1357. // we are in an RPC if we are in the main interface, its not local, and
  1358. // we are not a typedef of a proc...
  1359. if (
  1360. (ImportLevel == 0) &&
  1361. !MyContext.FindAncestorContext( NODE_DEF ) &&
  1362. pIntf &&
  1363. !Skipme
  1364. )
  1365. {
  1366. MyContext.SetAncestorBits( IN_RPC );
  1367. }
  1368. else
  1369. {
  1370. MyContext.ClearAncestorBits( IN_RPC );
  1371. }
  1372. // our optimization is controlled either locally or for the whole interface
  1373. if ( ( pOptAttr = (node_optimize *) MyContext.ExtractAttribute( ATTR_OPTIMIZE ) ) != 0 )
  1374. {
  1375. SetOptimizationFlags( pOptAttr->GetOptimizationFlags() );
  1376. SetOptimizationLevel( pOptAttr->GetOptimizationLevel() );
  1377. }
  1378. else
  1379. {
  1380. SetOptimizationFlags( pIntf->GetOptimizationFlags() );
  1381. SetOptimizationLevel( pIntf->GetOptimizationLevel() );
  1382. }
  1383. unsigned long fOptimize = GetOptimizationFlags();
  1384. if ( fOptimize & OPTIMIZE_INTERPRETER )
  1385. {
  1386. MyContext.SetAncestorBits( IN_INTERPRET );
  1387. }
  1388. HasPickle = HasPickle || pIntfCtxt->FInSummary( ATTR_ENCODE )
  1389. || pIntfCtxt->FInSummary( ATTR_DECODE );
  1390. if ( HasPickle && pCommand->IsSwitchDefined( SWITCH_ROBUST ) )
  1391. {
  1392. if ( fOptimize & OPTIMIZE_INTERPRETER_V2 )
  1393. {
  1394. pCommand->GetNdrVersionControl().SetHasOicfPickling();
  1395. if ( pCommand->GetTargetSystem() == NT40 )
  1396. SemError( this, MyContext, INVALID_FEATURE_FOR_TARGET, ":oicf pickling" );
  1397. }
  1398. else
  1399. {
  1400. SemError( this, MyContext, ROBUST_PICKLING_NO_OICF, 0 );
  1401. }
  1402. }
  1403. BOOL HasCommFault = MyContext.FInSummary( ATTR_COMMSTAT )
  1404. || MyContext.FInSummary( ATTR_FAULTSTAT );
  1405. if ( HasPickle && HasCommFault )
  1406. {
  1407. if ( ! ( fOptimize & OPTIMIZE_INTERPRETER_V2 ) )
  1408. {
  1409. SemError( this, MyContext, COMMFAULT_PICKLING_NO_OICF, 0 );
  1410. }
  1411. }
  1412. // determine the proc number (local procs don't get a number)
  1413. if ( !fNonOperation )
  1414. {
  1415. if ( !fLocal )
  1416. {
  1417. if ( fProcIsCallback )
  1418. {
  1419. ProcNum = ( pIntf ->GetCallBackProcCount() )++;
  1420. RpcSemError( this, MyContext, CALLBACK_NOT_OSF, NULL );
  1421. }
  1422. else
  1423. {
  1424. ProcNum = ( pIntf ->GetProcCount() )++;
  1425. }
  1426. }
  1427. // object procs need the procnum set for local procs, too
  1428. else if ( fObjectProc && fLocal )
  1429. {
  1430. ProcNum = ( pIntf ->GetProcCount() )++;
  1431. }
  1432. }
  1433. else if ( MyContext.AnyAncestorBits( IN_RPC ) )
  1434. {
  1435. RpcSemError( this, MyContext, FUNC_NON_RPC, NULL );
  1436. }
  1437. else // proc not an operation, validate its usage
  1438. {
  1439. SEM_ANALYSIS_CTXT * pAbove = (SEM_ANALYSIS_CTXT *)
  1440. MyContext.FindNonDefAncestorContext();
  1441. node_skl * pAboveNode = pAbove->GetParent();
  1442. if ( !pAboveNode->IsInterfaceOrObject() )
  1443. {
  1444. if ( pAboveNode->NodeKind() != NODE_POINTER )
  1445. {
  1446. TypeSemError( this, MyContext, FUNC_NON_POINTER, NULL );
  1447. }
  1448. }
  1449. }
  1450. if ( MyContext.FInSummary( ATTR_COMMSTAT ) )
  1451. Commstat = SEEN_ON_RETURN;
  1452. if ( MyContext.FInSummary( ATTR_FAULTSTAT ) )
  1453. Faultstat = SEEN_ON_RETURN;
  1454. //////////////////////////////////////
  1455. // process the return type (it will eat commstat or faultstat)
  1456. MyContext.SetAncestorBits( IN_FUNCTION_RESULT );
  1457. MyContext.MarkImportantPosition();
  1458. // warn about OUT const things
  1459. if ( FInSummary( ATTR_CONST ) )
  1460. RpcSemError( this, MyContext, CONST_ON_RETVAL, NULL );
  1461. pRet->SemanticAnalysis( &MyContext );
  1462. MyContext.UnMarkImportantPosition();
  1463. if ( MyContext.AnyDescendantBits( HAS_UNION | HAS_STRUCT )
  1464. && !pCommand->GetNdrVersionControl().AllowIntrepretedComplexReturns() )
  1465. {
  1466. // REVIEW: complex return types work for protocol all and ndr64.
  1467. // make it work for dce also.
  1468. if (HasPickle)
  1469. {
  1470. if (pCommand->Is64BitEnv())
  1471. RpcSemError( this, MyContext, PICKLING_RETVAL_TO_COMPLEX64, NULL );
  1472. }
  1473. else if (ForceNonInterpret())
  1474. {
  1475. RpcSemError( this, MyContext, NON_OI_BIG_RETURN, NULL );
  1476. }
  1477. }
  1478. else if ( MyContext.AnyDescendantBits( HAS_TOO_BIG_HDL ) )
  1479. {
  1480. if (ForceNonInterpret())
  1481. RpcSemError( this, MyContext, NON_OI_BIG_GEN_HDL, NULL );
  1482. }
  1483. else if ( !pCommand->NeedsNDR64Run()
  1484. && MyContext.AnyDescendantBits( HAS_UNSAT_REP_AS ))
  1485. {
  1486. // REVIEW: Another case of an error that has already been caught
  1487. // elsewhere. Investigate removing this check.
  1488. if (ForceNonInterpret())
  1489. RpcSemError( this, MyContext, NON_OI_UNK_REP_AS, NULL );
  1490. }
  1491. else if ( !pCommand->NeedsNDR64Run() &&
  1492. ( MyContext.AnyDescendantBits( HAS_REPRESENT_AS
  1493. | HAS_TRANSMIT_AS ) &&
  1494. MyContext.AnyDescendantBits( HAS_ARRAY ) ) )
  1495. {
  1496. if (ForceNonInterpret())
  1497. RpcSemError( this, MyContext, NON_OI_XXX_AS_ON_RETURN, NULL );
  1498. }
  1499. else if ( ( BasicChildKind == NODE_INT128 ) ||
  1500. ( BasicChildKind == NODE_FLOAT80 ) ||
  1501. ( BasicChildKind == NODE_FLOAT128 ) )
  1502. {
  1503. if (ForceNonInterpret())
  1504. RpcSemError( this, MyContext, RETURNVAL_TOO_COMPLEX_FORCE_OS, NULL );
  1505. }
  1506. else if ( !pCommand->GetNdrVersionControl().AllowIntrepretedComplexReturns() &&
  1507. ( ( ( BasicChildKind == NODE_HYPER ) && !pCommand->Is64BitEnv() )
  1508. || ( BasicChildKind == NODE_FLOAT )
  1509. || ( BasicChildKind == NODE_DOUBLE ) ) )
  1510. {
  1511. if ( HasPickle )
  1512. {
  1513. if ( fOptimize & OPTIMIZE_INTERPRETER_V2 )
  1514. {
  1515. if ( pCommand->Is64BitEnv() )
  1516. {
  1517. RpcSemError( this, MyContext, PICKLING_RETVAL_TO_COMPLEX64, NULL );
  1518. }
  1519. else if (ForceNonInterpret())
  1520. {
  1521. // For pickling -Os is the same as -Oi
  1522. RpcSemError( this, MyContext, PICKLING_RETVAL_FORCING_OI, NULL );
  1523. }
  1524. }
  1525. }
  1526. else if ( ( fOptimize & OPTIMIZE_INTERPRETER_V2) )
  1527. {
  1528. if ( fObjectProc )
  1529. {
  1530. // Don't switch, generate NT 4.0 guard
  1531. pCommand->GetNdrVersionControl().SetHasFloatOrDoubleInOi();
  1532. }
  1533. else
  1534. if (ForceNonInterpret())
  1535. RpcSemError( this, MyContext, NON_OI_RETVAL_64BIT, NULL );
  1536. }
  1537. else if ( ( fOptimize & OPTIMIZE_ALL_I1_FLAGS ) )
  1538. {
  1539. if (ForceNonInterpret())
  1540. RpcSemError( this, MyContext, NON_OI_RETVAL_64BIT, NULL );
  1541. }
  1542. }
  1543. else if ( ( CallingConv != ATTR_NONE ) &&
  1544. ( CallingConv != ATTR_STDCALL ) &&
  1545. ( CallingConv != ATTR_CDECL ) &&
  1546. !Skipme )
  1547. {
  1548. if (ForceNonInterpret())
  1549. RpcSemError( this, MyContext, NON_OI_WRONG_CALL_CONV, NULL );
  1550. }
  1551. if ( fProcIsCallback )
  1552. {
  1553. if ( MyContext.AnyDescendantBits( HAS_HANDLE) )
  1554. RpcSemError( this, MyContext, HANDLES_WITH_CALLBACK, NULL );
  1555. if ( fObjectProc )
  1556. RpcSemError( this, MyContext, INVALID_ON_OBJECT_PROC, "[callback]" );
  1557. }
  1558. if ( MyContext.AnyDescendantBits( HAS_FULL_PTR ) )
  1559. fHasFullPointer = TRUE;
  1560. // all object methods must return HRESULT (except those of IUnknown and async methods)
  1561. if ( fObjectProc &&
  1562. !Skipme &&
  1563. !MyContext.AnyDescendantBits( HAS_HRESULT ) )
  1564. {
  1565. if ( !MyContext.AnyAncestorBits( IN_ROOT_CLASS ) && // not IUnknown
  1566. !fAsync ) // not [async]
  1567. {
  1568. RpcSemError( this, MyContext, OBJECT_PROC_NON_HRESULT_RETURN, NULL );
  1569. }
  1570. }
  1571. //////////////////////////////////////
  1572. // process the parameters
  1573. if ( !pIntf->IsAsyncClone() )
  1574. {
  1575. if ( MyContext.AnyAncestorBits( HAS_ASYNC_UUID ) )
  1576. {
  1577. node_skl* pParam = GetInOnlyParamPairedWithOut( MemIter );
  1578. if ( pParam )
  1579. {
  1580. SemError( this, MyContext, ASYNC_INVALID_IN_OUT_PARAM_COMBO, pParam->GetSymName() );
  1581. }
  1582. }
  1583. }
  1584. BOOL fParentIsAnyIAdviseSink = MyContext.AnyAncestorBits( IN_IADVISESINK );
  1585. BOOL fHasAsyncManager = FALSE;
  1586. MyContext.ClearAncestorBits( IN_FUNCTION_RESULT );
  1587. MyContext.SetAncestorBits( IN_PARAM_LIST );
  1588. BOOL fLastParamWasOptional = FALSE;
  1589. BOOL fHasInPipeParam = FALSE;
  1590. BOOL fHasInConfOrVaryingParam = FALSE;
  1591. BOOL fGenDefaultValueExpr = FALSE;
  1592. BOOL fHasDRtag = FALSE;
  1593. BOOL fHasRtag = FALSE;
  1594. BOOL fHasStag = FALSE;
  1595. BOOL fHasInCSType = FALSE;
  1596. BOOL fHasOutCSType = FALSE;
  1597. node_param* pFirstParamWithDefValue = 0;
  1598. node_param* pLastParam = 0;
  1599. node_param* p2LastParam = 0;
  1600. node_param* p3LastParam = 0;
  1601. bool fRetval = false;
  1602. bool fLCID = false;
  1603. unsigned long ulParamNumber = 0;
  1604. MemIter.Init();
  1605. while ( ( pN = (node_param *) MemIter.GetNext() ) != 0 )
  1606. {
  1607. fOptimize = GetOptimizationFlags();
  1608. BasicChildKind = pN->GetBasicType()->NodeKind();
  1609. p3LastParam = p2LastParam;
  1610. p2LastParam = pLastParam;
  1611. pLastParam = pN;
  1612. MyContext.ClearAllDescendantBits();
  1613. MyContext.ResetCorrelationCount();
  1614. pN->SemanticAnalysis( &MyContext );
  1615. fRetval = fRetval || pN->IsRetval();
  1616. if ( pN->IsLCID() )
  1617. {
  1618. if (BasicChildKind != NODE_LONG)
  1619. {
  1620. SemError( this, MyContext, LCID_SHOULD_BE_LONG, 0 );
  1621. }
  1622. if (fLCID)
  1623. {
  1624. SemError( this, MyContext, INVALID_USE_OF_LCID, 0 );
  1625. }
  1626. else
  1627. fLCID = true;
  1628. }
  1629. if ( MyContext.AnyDescendantBits( HAS_MULTIDIM_VECTOR ) )
  1630. {
  1631. if ( ForceInterpret2() )
  1632. {
  1633. RpcSemError( this, MyContext, MULTI_DIM_VECTOR, NULL );
  1634. }
  1635. }
  1636. if ( MyContext.AnyDescendantBits( HAS_PARTIAL_IGNORE ) )
  1637. {
  1638. if ( (fOptimize & OPTIMIZE_INTERPRETER ) )
  1639. {
  1640. if ( ForceInterpret2() )
  1641. {
  1642. RpcSemError( this, MyContext, PARTIAL_IGNORE_NO_OI, NULL );
  1643. }
  1644. }
  1645. if ( MyContext.AnyAncestorBits( IN_LIBRARY ) )
  1646. {
  1647. SemError( this, MyContext, PARTIAL_IGNORE_IN_TLB, NULL );
  1648. }
  1649. if ( pCommand->IsSwitchDefined( SWITCH_OSF ) )
  1650. {
  1651. SemError( this, MyContext, INVALID_OSF_ATTRIBUTE, "[partial_ignore]" );
  1652. }
  1653. }
  1654. if ( MyContext.AnyDescendantBits( HAS_SERVER_CORRELATION ) )
  1655. {
  1656. SetHasServerCorr();
  1657. IncServerCorrelationCount( MyContext.GetCorrelationCount() );
  1658. }
  1659. if ( MyContext.AnyDescendantBits( HAS_CLIENT_CORRELATION ) )
  1660. {
  1661. SetHasClientCorr();
  1662. IncClientCorrelationCount( MyContext.GetCorrelationCount() );
  1663. }
  1664. BOOL fDefaultValue = MyContext.AnyDescendantBits( HAS_DEFAULT_VALUE );
  1665. if ( fDefaultValue )
  1666. {
  1667. if ( !pFirstParamWithDefValue )
  1668. {
  1669. pFirstParamWithDefValue = pN;
  1670. fGenDefaultValueExpr = TRUE;
  1671. }
  1672. // can't have defaultvalue in vararg
  1673. if ( fHasVarArg )
  1674. SemError(this, MyContext, NOT_VARARG_COMPATIBLE, 0);
  1675. }
  1676. else
  1677. {
  1678. // don't generate defaultvalue is c++ header if we have
  1679. // non-defaultvalue parameter after it.
  1680. fGenDefaultValueExpr = FALSE;
  1681. pFirstParamWithDefValue = 0;
  1682. }
  1683. if ( MyContext.AnyDescendantBits( HAS_PIPE ) )
  1684. {
  1685. if ( MyContext.AnyDescendantBits( HAS_IN ) )
  1686. fHasInPipeParam = TRUE;
  1687. node_skl* pBasicType = pN->GetBasicType();
  1688. while ( pBasicType && pBasicType->NodeKind() == NODE_POINTER )
  1689. {
  1690. pBasicType = pBasicType->GetChild();
  1691. }
  1692. if ( ( pBasicType->NodeKind() == NODE_INTERFACE_REFERENCE && !fObjectProc ) ||
  1693. ( pBasicType->NodeKind() == NODE_PIPE && fObjectProc ) )
  1694. {
  1695. SemError(this, MyContext, UNIMPLEMENTED_FEATURE, pN->GetSymName() );
  1696. }
  1697. }
  1698. else if ( MyContext.AnyDescendantBits( HAS_IN ) &&
  1699. MyContext.AnyDescendantBits (
  1700. HAS_STRING |
  1701. HAS_FULL_PTR |
  1702. HAS_VAR_ARRAY |
  1703. HAS_CONF_ARRAY |
  1704. HAS_CONF_VAR_ARRAY
  1705. ) )
  1706. {
  1707. fHasInConfOrVaryingParam = TRUE;
  1708. }
  1709. if ( ulParamNumber == 0 ) // first parameter
  1710. {
  1711. // if parent interface is is any IAdviseSink ignore [async].
  1712. if ( fAsync && fObjectProc )
  1713. {
  1714. unsigned int nIndirection = 0;
  1715. node_skl* pFType = GetIndirectionLevel (
  1716. pN,
  1717. nIndirection
  1718. );
  1719. // check async handle type
  1720. if ( nIndirection != 2 )
  1721. {
  1722. if ( !fParentIsAnyIAdviseSink )
  1723. {
  1724. SemError(this, MyContext, OBJECT_ASYNC_NOT_DOUBLE_PTR, pN->GetChild()->GetSymName() );
  1725. }
  1726. }
  1727. if ( strcmp( pFType->GetSymName(), OBJECT_ASYNC_HANDLE_NAME ) )
  1728. {
  1729. if ( !fParentIsAnyIAdviseSink )
  1730. {
  1731. SemError(this, MyContext, ASYNC_INCORRECT_TYPE, pN->GetChild()->GetSymName() );
  1732. }
  1733. }
  1734. else
  1735. {
  1736. fHasAsyncManager = TRUE;
  1737. }
  1738. // flag the first param of an object interface as async handle
  1739. pN->SetIsAsyncHandleParam();
  1740. if ( MyContext.AnyDescendantBits( HAS_OUT ) )
  1741. {
  1742. SemError( this, MyContext, ASYNC_NOT_IN, NULL );
  1743. }
  1744. }
  1745. // Oicf interpreter cannot handle floats as first param, switch to Os.
  1746. // This is a non-issue for ORPC because of the 'this' pointer.
  1747. if ( ! pCommand->NeedsNDR64Run()
  1748. && ( ( BasicChildKind == NODE_FLOAT )
  1749. || ( BasicChildKind == NODE_DOUBLE ) ) )
  1750. {
  1751. if ( ( fOptimize & OPTIMIZE_INTERPRETER_V2) )
  1752. {
  1753. if ( fObjectProc )
  1754. {
  1755. // Don't switch, generate NT 4.0 guard
  1756. pCommand->GetNdrVersionControl().SetHasFloatOrDoubleInOi();
  1757. }
  1758. else
  1759. if ( ForceNonInterpret() )
  1760. {
  1761. RpcSemError( this, MyContext, NON_OI_TOPLEVEL_FLOAT, NULL );
  1762. }
  1763. }
  1764. }
  1765. } // first parameter
  1766. // Oi/Oic interpreter cannot handle float params on alpha, switch to Os.
  1767. if ( ( BasicChildKind == NODE_FLOAT )
  1768. || ( BasicChildKind == NODE_DOUBLE ) )
  1769. {
  1770. if ( ! pCommand->NeedsNDR64Run() &&
  1771. ( fOptimize & OPTIMIZE_INTERPRETER ) )
  1772. {
  1773. // Old interpreter, always switch to -Os.
  1774. if ( !( fOptimize & OPTIMIZE_INTERPRETER_V2 ) )
  1775. {
  1776. if (ForceNonInterpret())
  1777. {
  1778. RpcSemError( this, MyContext, NON_OI_TOPLEVEL_FLOAT, NULL );
  1779. }
  1780. }
  1781. // For -Oicf, there were no problems for object rpc; check standard
  1782. else if ( !fObjectProc && ulParamNumber > 0 )
  1783. {
  1784. // For 64b, float and double work for object and standard rpc.
  1785. // The 32b NT4 engine didn't work for float args in standard rpc.
  1786. if ( !pCommand->Is64BitEnv() && ( BasicChildKind == NODE_FLOAT ) )
  1787. {
  1788. if (ForceNonInterpret())
  1789. {
  1790. RpcSemError( this, MyContext, NON_OI_TOPLEVEL_FLOAT, NULL );
  1791. }
  1792. }
  1793. }
  1794. // For param0 and retval we force above.
  1795. }
  1796. }
  1797. /*
  1798. parameter sequence of odl:
  1799. 1. Required parameters (parameters that do not have the defaultvalue or optional
  1800. attributes),
  1801. 2. optional parameters with or without the defaultvalue attribute,
  1802. 3. parameters with the optional attribute and without the defaultvalue attribute,
  1803. 4. lcid parameter, if any,
  1804. 5. retval parameter
  1805. */
  1806. if ( pN->IsOptional() )
  1807. {
  1808. fLastParamWasOptional = TRUE;
  1809. // [in,optional] VARIANT v1, [in] long l1, [in,optional] VARIANT v2
  1810. if (nAfterLastOptionalParam > 0)
  1811. nAfterLastOptionalParam++;
  1812. // vararg can't coexist with optional parameter.
  1813. if ( fHasVarArg )
  1814. SemError(this, MyContext , NOT_VARARG_COMPATIBLE, 0 );
  1815. }
  1816. else
  1817. {
  1818. // If the following parameter after [optional] is either a RetVal or
  1819. // LCID, we don't fail. The logic between Retval and LCID will be
  1820. // checked later.
  1821. if ( fLastParamWasOptional )
  1822. {
  1823. // The only other parameter allowed to come after [optional]
  1824. // in a propput/propget method is lcid.
  1825. if ( fPropSomething && !pN->IsLCID() )
  1826. nAfterLastOptionalParam++;
  1827. else
  1828. if ( (!pN->IsRetval() && !pN->IsLCID()) && FNewTypeLib() )
  1829. {
  1830. // In regular method, we can only have retval and lcid coming
  1831. // after optional
  1832. SemError( this, MyContext, OPTIONAL_PARAMS_MUST_BE_LAST, NULL );
  1833. }
  1834. }
  1835. }
  1836. if ( ( pAttr = (acf_attr *) pN->GetAttribute( ATTR_COMMSTAT ) ) != 0 )
  1837. {
  1838. if ( !MyContext.AnyDescendantBits( HAS_E_STAT_T ) )
  1839. AcfError( pAttr, this, MyContext, INVALID_COMM_STATUS_PARAM, NULL );
  1840. if ( Commstat == NOT_SEEN )
  1841. Commstat = SEEN_ON_PARAM;
  1842. else if ( Commstat == SEEN_ON_RETURN )
  1843. AcfError( pAttr, this, MyContext, PROC_PARAM_COMM_STATUS, NULL );
  1844. else // already on another parameter
  1845. AcfError( pAttr, this, MyContext, ERROR_STATUS_T_REPEATED, NULL );
  1846. }
  1847. if ( ( pAttr = (acf_attr *) pN->GetAttribute( ATTR_FAULTSTAT ) ) != 0 )
  1848. {
  1849. if ( !MyContext.AnyDescendantBits( HAS_E_STAT_T ) )
  1850. AcfError( pAttr, this, MyContext, INVALID_COMM_STATUS_PARAM, NULL );
  1851. if ( Faultstat == NOT_SEEN )
  1852. Faultstat = SEEN_ON_PARAM;
  1853. else if ( Faultstat == SEEN_ON_RETURN )
  1854. AcfError( pAttr, this, MyContext, PROC_PARAM_FAULT_STATUS, NULL );
  1855. else // already on another parameter
  1856. AcfError( pAttr, this, MyContext, ERROR_STATUS_T_REPEATED, NULL );
  1857. }
  1858. if (MyContext.AnyDescendantBits( HAS_HANDLE) )
  1859. fHasExplicitHandle = TRUE;
  1860. if (MyContext.AnyDescendantBits( HAS_IN ) )
  1861. fHasAtLeastOneIn = TRUE;
  1862. if ( MyContext.AnyDescendantBits( HAS_POINTER ) )
  1863. fHasPointer = TRUE;
  1864. if ( MyContext.AnyDescendantBits( HAS_FULL_PTR ) )
  1865. fHasFullPointer = TRUE;
  1866. if (MyContext.AnyDescendantBits( HAS_OUT) )
  1867. {
  1868. fHasAtLeastOneOut = TRUE;
  1869. // complain about [out] on [maybe] procs
  1870. if ( fMaybe )
  1871. RpcSemError( this, MyContext, MAYBE_NO_OUT_RETVALS, NULL );
  1872. }
  1873. if (MyContext.AnyDescendantBits( (DESCENDANT_FLAGS) HAS_PIPE ))
  1874. {
  1875. #if defined(TARGET_RKK)
  1876. if ( pCommand->GetTargetSystem() < NT40 )
  1877. RpcSemError( this, MyContext, REQUIRES_NT40, NULL );
  1878. #endif
  1879. if (ForceInterpret2())
  1880. RpcSemError( this, MyContext, REQUIRES_OI2, NULL );
  1881. fHasPipes = TRUE;
  1882. if ( HasPickle )
  1883. RpcSemError( this, MyContext, PIPES_WITH_PICKLING, NULL );
  1884. }
  1885. // handle checks
  1886. if ( pN->GetHandleKind() != HDL_NONE )
  1887. {
  1888. if ( !fBindingFound ) // first handle seen
  1889. {
  1890. // dce only allows in handles as the first param
  1891. if ( ulParamNumber != 0 )
  1892. RpcSemError( this, MyContext, HANDLE_NOT_FIRST, NULL );
  1893. // if the first binding handle is out-only, complain
  1894. if ( !MyContext.AnyDescendantBits( HAS_IN ) &&
  1895. MyContext.AnyDescendantBits( HAS_OUT ) )
  1896. {
  1897. if ( !( MyContext.AnyAncestorBits( HAS_AUTO_HANDLE | HAS_IMPLICIT_HANDLE ) ||
  1898. fExpHdlAttr ) )
  1899. {
  1900. RpcSemError( this, MyContext, BINDING_HANDLE_IS_OUT_ONLY, NULL );
  1901. }
  1902. else if ( fExpHdlAttr )
  1903. {
  1904. fAddExplicitHandle = true;
  1905. }
  1906. }
  1907. else if ( MyContext.AnyDescendantBits( HAS_OUT ) &&
  1908. ( pN->GetHandleKind() == HDL_PRIM ) )
  1909. {
  1910. RpcSemError( this, MyContext, HANDLE_T_CANNOT_BE_OUT, NULL );
  1911. }
  1912. else // plain [in], or [in,out]
  1913. {
  1914. fBindingFound = TRUE;
  1915. MyContext.SetAncestorBits( BINDING_SEEN );
  1916. }
  1917. }
  1918. else // binding handle after the real one
  1919. {
  1920. if ( pN->GetHandleKind() == HDL_PRIM )
  1921. RpcSemError( this, MyContext, HANDLE_T_NO_TRANSMIT, NULL );
  1922. }
  1923. } // if it had a handle
  1924. if ( MyContext.AnyDescendantBits( HAS_TOO_BIG_HDL ) )
  1925. {
  1926. if (ForceNonInterpret())
  1927. RpcSemError( this, MyContext, NON_OI_BIG_GEN_HDL, NULL );
  1928. }
  1929. else if ( !pCommand->NeedsNDR64Run()
  1930. &&MyContext.AnyDescendantBits( HAS_UNSAT_REP_AS ) )
  1931. {
  1932. // This case should have been caught earlier.
  1933. // REVIEW: Is this still relevant?
  1934. if (ForceNonInterpret())
  1935. RpcSemError( this, MyContext, NON_OI_UNK_REP_AS, NULL );
  1936. }
  1937. else if ( MyContext.AnyDescendantBits( HAS_UNION ) && IS_OLD_INTERPRETER( GetOptimizationFlags() ) )
  1938. {
  1939. node_skl * pNDC = pN->GetNonDefChild();
  1940. if (pNDC->NodeKind() != NODE_PIPE && !pNDC->IsPtrOrArray())
  1941. {
  1942. // unions by value but not arrays of unions
  1943. if (ForceNonInterpret())
  1944. RpcSemError( this, MyContext, NON_OI_UNION_PARM, NULL );
  1945. }
  1946. }
  1947. if ( MyContext.AnyDescendantBits( HAS_DRTAG ) )
  1948. fHasDRtag = TRUE;
  1949. if ( MyContext.AnyDescendantBits( HAS_RTAG ) )
  1950. fHasRtag = TRUE;
  1951. if ( MyContext.AnyDescendantBits( HAS_STAG ) )
  1952. fHasStag = TRUE;
  1953. if ( MyContext.AnyDescendantBits( HAS_IN_CSTYPE ) )
  1954. fHasInCSType = TRUE;
  1955. if ( MyContext.AnyDescendantBits( HAS_OUT_CSTYPE ) )
  1956. fHasOutCSType = TRUE;
  1957. ulParamNumber++;
  1958. } // end of param list
  1959. if ( MyContext.AnyDescendantBits( HAS_FORCEALLOCATE ) )
  1960. {
  1961. if ( ! ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) )
  1962. SemError( this, MyContext, FORCEALLOCATE_SUPPORTED_IN_OICF_ONLY, NULL );
  1963. }
  1964. if ( fGenDefaultValueExpr )
  1965. {
  1966. bool fReallyGenDefaultValueExpr = true;
  1967. MemIter.Init();
  1968. do
  1969. {
  1970. pN = (node_param *) MemIter.GetNext();
  1971. }
  1972. while ( pN != pFirstParamWithDefValue );
  1973. do
  1974. {
  1975. node_skl* pType = GetNonDefType( pN->GetChild() );
  1976. if ( !pType->IsBasicType() && pType->NodeKind() != NODE_POINTER &&
  1977. pType->NodeKind() != NODE_ENUM )
  1978. {
  1979. SemError( this, MyContext, DEFAULTVALUE_NOT_ALLOWED, pN->GetSymName() );
  1980. fReallyGenDefaultValueExpr = false;
  1981. break;
  1982. }
  1983. pN->GenDefaultValueExpr();
  1984. pN = (node_param *) MemIter.GetNext();
  1985. }
  1986. while ( pN != 0 );
  1987. // don't genereate any defaultvalue in c++ header at all
  1988. if ( !fReallyGenDefaultValueExpr )
  1989. {
  1990. MemIter.Init();
  1991. while ( ( pN = (node_param *) MemIter.GetNext() ) != 0 )
  1992. {
  1993. pN->GenDefaultValueExpr( false );
  1994. }
  1995. }
  1996. }
  1997. if ( fHasInConfOrVaryingParam )
  1998. {
  1999. if ( fHasInPipeParam )
  2000. SemError( this, MyContext, PIPE_INCOMPATIBLE_PARAMS, 0 );
  2001. else if (fHasPipes )
  2002. SemError( this, MyContext, OUT_PIPE_INCOMPATIBLE_PARAMS, 0 );
  2003. }
  2004. ///////////////////////////////////////////////////////////////////////
  2005. if ( fHasExplicitHandle )
  2006. {
  2007. if ( fProcIsCallback )
  2008. RpcSemError( this, MyContext, HANDLES_WITH_CALLBACK, NULL );
  2009. }
  2010. if ( !fHasExplicitHandle || fAddExplicitHandle )
  2011. {
  2012. if ( fExpHdlAttr )
  2013. {
  2014. // async handle should be first param,
  2015. // programmer supplies IAsyncManager in ORPC
  2016. // MIDL adds PRPC_ASYNC_STATE in RPC
  2017. // if parent interface is is any IAdviseSink ignore async.
  2018. if ( fObjectProc && fAsync && fHasAsyncManager )
  2019. {
  2020. AddExplicitHandle( &MyContext, 2 );
  2021. }
  2022. else
  2023. {
  2024. // MIDL will add async handle later
  2025. AddExplicitHandle( &MyContext, 1 );
  2026. }
  2027. }
  2028. else if ( !(pIntfCtxt->FInSummary( ATTR_IMPLICIT ) ) )
  2029. {
  2030. // no explicit handle, no implicit handle, use auto_handle
  2031. if ( !fProcIsCallback &&
  2032. MyContext.AnyAncestorBits( IN_RPC ) &&
  2033. !fObjectProc )
  2034. {
  2035. if ( !pIntfCtxt->FInSummary( ATTR_AUTO ) )
  2036. RpcSemError( this, MyContext, NO_HANDLE_DEFINED_FOR_PROC, NULL );
  2037. }
  2038. }
  2039. }
  2040. if ( fObjectProc || MyContext.AnyAncestorBits( IN_LIBRARY ))
  2041. {
  2042. if (fHasExplicitHandle ||
  2043. fExpHdlAttr ||
  2044. MyContext.FInSummary( ATTR_IMPLICIT ) ||
  2045. MyContext.FInSummary( ATTR_AUTO ) ||
  2046. pIntfCtxt->FInSummary( ATTR_AUTO ) ||
  2047. pIntfCtxt->FInSummary( ATTR_IMPLICIT ) ||
  2048. pIntfCtxt->FInSummary( ATTR_EXPLICIT ) )
  2049. {
  2050. SemError( this, MyContext, HANDLES_WITH_OBJECT, NULL );
  2051. }
  2052. }
  2053. // record whether there are any comm/fault statuses
  2054. if ( ( Faultstat != NOT_SEEN ) || ( Commstat != NOT_SEEN ) )
  2055. {
  2056. fHasStatuses = TRUE;
  2057. // [comm_status] and [fault_status] are supported in -Os. Intrepreted
  2058. // modes are only supported in NT 3.51 or later. Hidden status
  2059. // params are only supported in interpreted mode post-Win2000.
  2060. // REVIEW: We can get hidden status params to work for Win2000 by
  2061. // adding a line to the client stub that zero's the status
  2062. // before calling the interpreter.
  2063. if ( GetOptimizationFlags() & OPTIMIZE_ANY_INTERPRETER )
  2064. {
  2065. if ( HasExtraStatusParam()
  2066. && ( ! ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 )
  2067. || !pCommand->NeedsNDR64Run() ) )
  2068. {
  2069. // invisible fault/comm status are not supported in the V1
  2070. // interpreter. Switch to -Os
  2071. // REVIEW: For now, only support hidden status params in the
  2072. // V2 interpreter in -protocol all and -protocol ndr64
  2073. if (ForceNonInterpret())
  2074. RpcSemError( this, MyContext, NON_OI_ERR_STATS, NULL );
  2075. }
  2076. else
  2077. pCommand->GetNdrVersionControl().SetHasCommFaultStatusInOi12();
  2078. }
  2079. }
  2080. // record info for statuses on the return type
  2081. if ( Faultstat == SEEN_ON_RETURN )
  2082. RTStatuses |= STATUS_FAULT;
  2083. if ( Commstat == SEEN_ON_RETURN )
  2084. RTStatuses |= STATUS_COMM;
  2085. if ( fHasPointer && !pCommand->IsSwitchDefined( SWITCH_MS_EXT ) )
  2086. pIntf->SetHasProcsWithRpcSs();
  2087. if ( ( OpBits & ( OPERATION_MAYBE | OPERATION_BROADCAST | OPERATION_IDEMPOTENT ) ) != 0 &&
  2088. fObjectProc )
  2089. {
  2090. SemError(this, MyContext, ILLEGAL_COMBINATION_OF_ATTRIBUTES, NULL);
  2091. }
  2092. // [message] only allowed in ORPC interfaces and RPC procs.
  2093. if ( fMessage && fObjectProc )
  2094. {
  2095. // [message] applied on proc.
  2096. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  2097. }
  2098. if ( MyContext.AnyAncestorBits( HAS_MESSAGE ) )
  2099. {
  2100. // [message] applied on interface.
  2101. if ( !fObjectProc )
  2102. {
  2103. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  2104. }
  2105. fMessage = TRUE;
  2106. }
  2107. if ( fMessage )
  2108. {
  2109. if ( OpBits & OPERATION_BROADCAST
  2110. || OpBits & OPERATION_IDEMPOTENT
  2111. || OpBits & OPERATION_INPUT_SYNC
  2112. || fMaybe
  2113. || fAsync
  2114. || fProcIsCallback
  2115. || pCallAs
  2116. || HasPickle
  2117. || pHC
  2118. || pHSC
  2119. || pID
  2120. || pHelpStr
  2121. || MyContext.FInSummary(ATTR_BYTE_COUNT)
  2122. || MyContext.FInSummary(ATTR_COMMSTAT)
  2123. || MyContext.FInSummary(ATTR_CONTEXT)
  2124. || MyContext.FInSummary(ATTR_CUSTOM)
  2125. || MyContext.FInSummary(ATTR_ENABLE_ALLOCATE)
  2126. || MyContext.FInSummary(ATTR_ENTRY)
  2127. || MyContext.FInSummary(ATTR_FAULTSTAT)
  2128. || MyContext.FInSummary(ATTR_FUNCDESCATTR)
  2129. || MyContext.FInSummary(ATTR_HIDDEN)
  2130. || MyContext.FInSummary(ATTR_MEMBER)
  2131. || MyContext.FInSummary(ATTR_PTR_KIND)
  2132. || MyContext.FInSummary(ATTR_VARDESCATTR)
  2133. || MyContext.FInSummary(ATTR_OBJECT)
  2134. || MyContext.FInSummary(ATTR_TYPEDESCATTR)
  2135. || MyContext.FInSummary(ATTR_TYPE)
  2136. )
  2137. {
  2138. SemError(this, MyContext, ILLEGAL_COMBINATION_OF_ATTRIBUTES, NULL);
  2139. }
  2140. if ( HasAtLeastOneOut() )
  2141. {
  2142. SemError(this, MyContext, MAYBE_NO_OUT_RETVALS, NULL);
  2143. }
  2144. }
  2145. if ( MyContext.AnyAncestorBits( HAS_OLEAUTOMATION ) )
  2146. {
  2147. char* szRetTypeNonDefName = 0;
  2148. node_skl* pReturnType = GetReturnType();
  2149. if (pReturnType)
  2150. {
  2151. szRetTypeNonDefName = pReturnType->GetSymName();
  2152. }
  2153. if ( GetReturnType()->GetBasicType()->NodeKind() != NODE_VOID &&
  2154. ( !szRetTypeNonDefName ||
  2155. _stricmp(szRetTypeNonDefName, "HRESULT") ) )
  2156. {
  2157. SemError(this, MyContext, NOT_OLEAUTOMATION_INTERFACE, NULL);
  2158. }
  2159. }
  2160. if ( fPropSomething && MyContext.AnyAncestorBits( IN_LIBRARY ) )
  2161. {
  2162. // propget can either return the property in an out parameter or
  2163. // in the return value.
  2164. if ( fPropGet && !HasAParameter() && !HasReturn() )
  2165. {
  2166. SemError(this, MyContext, INVALID_USE_OF_PROPGET, NULL);
  2167. }
  2168. // propput must set the property in a parameter
  2169. else if ( !fPropGet && !HasAParameter() )
  2170. {
  2171. SemError(this, MyContext, INVALID_USE_OF_PROPPUT, NULL);
  2172. }
  2173. }
  2174. if (MyContext.AnyAncestorBits( (ANCESTOR_FLAGS) IN_DISPINTERFACE ) && !pID)
  2175. {
  2176. SemError(this, MyContext, DISPATCH_ID_REQUIRED, NULL);
  2177. }
  2178. if ( fAsync )
  2179. {
  2180. if ( fForcedS ||
  2181. pOptAttr ||
  2182. fNotify ||
  2183. HasPickle ||
  2184. fProcIsCallback ||
  2185. fLocal ||
  2186. fCode ||
  2187. fNoCode ||
  2188. fMaybe ||
  2189. fMessage ||
  2190. OpBits & OPERATION_INPUT_SYNC ||
  2191. pIntfCtxt->FInSummary( ATTR_AUTO ) )
  2192. {
  2193. SemError(this, MyContext, ILLEGAL_COMBINATION_OF_ATTRIBUTES, NULL);
  2194. }
  2195. // async handle should be first param,
  2196. // programmer supplies IAsyncManager in ORPC
  2197. // MIDL adds PRPC_ASYNC_STATE in RPC
  2198. if ( fObjectProc )
  2199. {
  2200. if ( fHasAsyncManager )
  2201. {
  2202. SetHasAsyncHandle();
  2203. }
  2204. // if parent interface is is any IAdviseSink ignore.
  2205. if ( !fParentIsAnyIAdviseSink )
  2206. {
  2207. if ( ulParamNumber == 0 )
  2208. {
  2209. SemError( this, MyContext, ASYNC_INCORRECT_TYPE, 0);
  2210. }
  2211. pCommand->GetNdrVersionControl().SetHasAsyncHandleRpc();
  2212. }
  2213. }
  2214. else
  2215. {
  2216. AddFullAsyncHandle( &MyContext, 0, RPC_ASYNC_HANDLE_NAME );
  2217. if ( pAttrAsync && !pAttrAsync->IsAcfAttr() )
  2218. {
  2219. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  2220. }
  2221. if ( !pIntfCtxt->FInSummary( ATTR_IMPLICIT ) &&
  2222. !fExpHdlAttr &&
  2223. !fHasExplicitHandle )
  2224. {
  2225. SemError( this, MyContext, ASYNC_INCORRECT_BINDING_HANDLE, 0 );
  2226. }
  2227. pCommand->GetNdrVersionControl().SetHasAsyncHandleRpc();
  2228. }
  2229. if ( pCommand->IsSwitchDefined( SWITCH_OSF ) )
  2230. {
  2231. SemError( this, MyContext, INVALID_OSF_ATTRIBUTE, "[async]" );
  2232. }
  2233. // switch compiler modes
  2234. if (ForceInterpret2())
  2235. {
  2236. RpcSemError( this, MyContext, ASYNC_REQUIRES_OI2, NULL );
  2237. }
  2238. }
  2239. // I don't like this complex logic, but unfortunately this is the right logic. It's easier
  2240. // to code this logic in mktyplib code structure but hard to do it here...
  2241. if ( fLCID )
  2242. {
  2243. node_param* pLCID;
  2244. // if there is a [retval], [lcid] must be the second last
  2245. if ( fRetval)
  2246. pLCID = p2LastParam;
  2247. else
  2248. {
  2249. if (fPropSomething)
  2250. {
  2251. // in propget without a retval, the lcid must be the last.
  2252. // in propput/propputref, lcid is second last.
  2253. if (fPropGet)
  2254. pLCID = pLastParam;
  2255. else
  2256. pLCID = p2LastParam;
  2257. }
  2258. // lcid should be the last if it's a regular method without propsomething & retval
  2259. else
  2260. pLCID = pLastParam;
  2261. }
  2262. if ( !pLCID || !pLCID->IsLCID() )
  2263. {
  2264. SemError( this, MyContext, INVALID_USE_OF_LCID, 0 );
  2265. }
  2266. }
  2267. // we can only have one parameter after optioanl in propput/propget, other than lcid.
  2268. if ( fLastParamWasOptional && fPropSomething && ( nAfterLastOptionalParam > 1 ) )
  2269. SemError(this, MyContext , INVALID_PROP_PARAMS , 0);
  2270. // Verify that a propput method is valid.
  2271. // TODO: much of the above code relating to propput/get could be simplified
  2272. // with state driven logic and is redundent with the code below
  2273. if ( fPropSomething & !fPropGet )
  2274. {
  2275. using namespace PropPut;
  2276. State state = NoParam;
  2277. node_param *pParam;
  2278. MemIter.Init();
  2279. while ( NULL != (pParam = (node_param *) MemIter.GetNext()) )
  2280. {
  2281. if ( pParam->FInSummary( ATTR_DEFAULTVALUE ) )
  2282. state = StateTable[state][Default];
  2283. else if ( pParam->IsOptional() )
  2284. state = StateTable[state][Optional];
  2285. else if ( pParam->IsLCID() )
  2286. state = StateTable[state][LCID];
  2287. else
  2288. state = StateTable[state][GeneralParam];
  2289. }
  2290. state = StateTable[state][NoParam];
  2291. if ( Accept != state )
  2292. SemError(this, MyContext , INVALID_PROPPUT , 0);
  2293. }
  2294. if ( fHasVarArg )
  2295. {
  2296. // [vararg] [lcid] [retval]
  2297. // last 0 0
  2298. // 2 last last 0
  2299. // 2 last 0 last
  2300. // 3 last 2last last
  2301. node_param* pVarargParam = fRetval ? ( fLCID ? p3LastParam : p2LastParam ) : ( fLCID ? p2LastParam : pLastParam );
  2302. if ( pVarargParam )
  2303. {
  2304. node_skl* pType = pVarargParam->GetChild();
  2305. if ( pType->NodeKind() == NODE_POINTER )
  2306. {
  2307. pType = pType->GetChild();
  2308. }
  2309. pType = GetNonDefType( pType );
  2310. if ( pType->NodeKind() != NODE_SAFEARRAY ||
  2311. strcmp( GetNonDefType( pType->GetChild() )->GetSymName(), "tagVARIANT" ) )
  2312. {
  2313. SemError( this, MyContext, NOT_VARARG_COMPATIBLE, 0 );
  2314. }
  2315. }
  2316. else
  2317. {
  2318. SemError( this, MyContext, NOT_VARARG_COMPATIBLE, 0 );
  2319. }
  2320. }
  2321. if ( pIntf->IsAsyncClone() )
  2322. {
  2323. SetHasAsyncUUID();
  2324. ForceInterpret2();
  2325. }
  2326. if ( fNotify || fNotifyFlag )
  2327. {
  2328. unsigned short uOpt = GetOptimizationFlags();
  2329. if ( !( uOpt & OPTIMIZE_SIZE ) )
  2330. {
  2331. pCommand->GetNdrVersionControl().SetHasInterpretedNotify();
  2332. if ( pCommand->GetTargetSystem() == NT40 )
  2333. SemError( this, MyContext, INVALID_FEATURE_FOR_TARGET, "interpreted notify" );
  2334. if ( IS_OLD_INTERPRETER(uOpt) )
  2335. {
  2336. if (ForceInterpret2())
  2337. RpcSemError( this, MyContext, NON_OI_NOTIFY, NULL );
  2338. }
  2339. }
  2340. }
  2341. if ( fHasInCSType && !fHasStag )
  2342. SemError( this, MyContext, NO_TAGS_FOR_IN_CSTYPE, 0 );
  2343. if ( fHasOutCSType && ( !fHasDRtag || !fHasRtag ) )
  2344. SemError( this, MyContext, NO_TAGS_FOR_OUT_CSTYPE, 0 );
  2345. if ( fHasInCSType || fHasOutCSType )
  2346. {
  2347. if ( NULL != pCSTagAttr )
  2348. SetCSTagRoutine( pCSTagAttr->GetCSTagRoutine() );
  2349. else
  2350. MyContext.SetDescendantBits( HAS_IN_CSTYPE );
  2351. }
  2352. if ( HasPickle && MyContext.AnyDescendantBits( HAS_PARTIAL_IGNORE ) )
  2353. {
  2354. SemError( this, MyContext, PARTIAL_IGNORE_PICKLING, GetSymName() );
  2355. }
  2356. MyContext.SetDescendantBits( HAS_FUNC );
  2357. pParentCtxt->ReturnValues( MyContext );
  2358. }
  2359. void
  2360. node_field::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  2361. {
  2362. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  2363. BOOL fLastField = ( GetSibling() == NULL );
  2364. node_case * pCaseAttr;
  2365. expr_list * pCaseExprList;
  2366. expr_node * pCaseExpr;
  2367. BOOL fHasCases = FALSE;
  2368. node_su_base * pParent = (node_su_base *)
  2369. MyContext.GetParentContext()->GetParent();
  2370. BOOL fInUnion = ( pParent->NodeKind() == NODE_UNION );
  2371. node_switch_type * pSwTypeAttr = ( node_switch_type *)
  2372. pParent->GetAttribute( ATTR_SWITCH_TYPE );
  2373. node_skl * pSwType = NULL;
  2374. char * pName = GetSymName();
  2375. node_constant_attr * pID = (node_constant_attr *) MyContext.ExtractAttribute(ATTR_ID);
  2376. MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
  2377. MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
  2378. MyContext.ExtractAttribute(ATTR_HELPSTRING);
  2379. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  2380. {
  2381. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  2382. }
  2383. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  2384. if ( MyContext.ExtractAttribute(ATTR_IDLDESCATTR) )
  2385. {
  2386. SemError(this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, 0);
  2387. }
  2388. if ( MyContext.ExtractAttribute(ATTR_VARDESCATTR) )
  2389. {
  2390. SemError(this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, 0);
  2391. }
  2392. MyContext.ExtractAttribute(ATTR_HIDDEN);
  2393. if ( HasCorrelation( this ) )
  2394. {
  2395. MyContext.IncCorrelationCount();
  2396. }
  2397. CheckDeclspecAlign( MyContext );
  2398. if (pID)
  2399. {
  2400. SEM_ANALYSIS_CTXT * pIntfCtxt = (SEM_ANALYSIS_CTXT *)
  2401. MyContext.GetInterfaceContext();
  2402. node_interface * pIntf = (node_interface *) pIntfCtxt->GetParent();
  2403. if (!pIntf->AddId(pID->GetExpr()->GetValue(), GetSymName()))
  2404. SemError( this, MyContext, DUPLICATE_IID, NULL);
  2405. }
  2406. else
  2407. {
  2408. if ( MyContext.AnyAncestorBits( (ANCESTOR_FLAGS) IN_DISPINTERFACE ) &&
  2409. pParent->NodeKind() == NODE_DISPINTERFACE)
  2410. {
  2411. SemError(this, MyContext, DISPATCH_ID_REQUIRED, NULL);
  2412. }
  2413. }
  2414. node_entry_attr * pEntry = NULL;
  2415. // check for illegal member attributes
  2416. node_member_attr * pMA;
  2417. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  2418. {
  2419. switch (pMA->GetAttr())
  2420. {
  2421. case MATTR_BINDABLE:
  2422. case MATTR_DISPLAYBIND:
  2423. case MATTR_DEFAULTBIND:
  2424. case MATTR_REQUESTEDIT:
  2425. case MATTR_DEFAULTVTABLE:
  2426. case MATTR_PREDECLID:
  2427. case MATTR_READONLY:
  2428. case MATTR_UIDEFAULT:
  2429. case MATTR_NONBROWSABLE:
  2430. case MATTR_DEFAULTCOLLELEM:
  2431. case MATTR_IMMEDIATEBIND:
  2432. case MATTR_REPLACEABLE:
  2433. break;
  2434. case MATTR_SOURCE:
  2435. {
  2436. char * pAttrName = pMA->GetNodeNameString();
  2437. if ( MyContext.AnyAncestorBits( IN_STRUCT | IN_UNION ) )
  2438. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  2439. break;
  2440. }
  2441. case MATTR_RESTRICTED:
  2442. {
  2443. char * pAttrName = pMA->GetNodeNameString();
  2444. if ( !MyContext.AnyAncestorBits( IN_DISPINTERFACE ) )
  2445. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  2446. break;
  2447. }
  2448. case MATTR_PROPGET:
  2449. case MATTR_PROPPUT:
  2450. case MATTR_PROPPUTREF:
  2451. case MATTR_OPTIONAL:
  2452. case MATTR_RETVAL:
  2453. case MATTR_VARARG:
  2454. case MATTR_USESGETLASTERROR:
  2455. default:
  2456. {
  2457. char * pAttrName = pMA->GetNodeNameString();
  2458. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  2459. break;
  2460. }
  2461. }
  2462. }
  2463. if (MyContext.AnyAncestorBits( IN_MODULE ))
  2464. pEntry = (node_entry_attr *) MyContext.ExtractAttribute( ATTR_ENTRY );
  2465. if ( pSwTypeAttr )
  2466. pSwType = pSwTypeAttr->GetType();
  2467. // process all the cases and the default
  2468. while ( ( pCaseAttr = (node_case *) MyContext.ExtractAttribute( ATTR_CASE ) ) != 0 )
  2469. {
  2470. if ( !fInUnion )
  2471. TypeSemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, "[case]" );
  2472. fHasCases = TRUE;
  2473. if ( pSwType )
  2474. {
  2475. pCaseExprList = pCaseAttr->GetExprList();
  2476. pCaseExprList->Init();
  2477. while ( pCaseExprList->GetPeer( &pCaseExpr ) == STATUS_OK )
  2478. {
  2479. // make sure the expression has the proper type, so sign extension behaves
  2480. node_skl * pCaseType = pCaseExpr->GetType();
  2481. if ( ( !pCaseType ) ||
  2482. ( pCaseType->GetNonDefSelf()->IsBasicType() ) )
  2483. {
  2484. pCaseExpr->SetType( pSwType->GetBasicType() );
  2485. }
  2486. // range/type checks
  2487. __int64 CaseValue = pCaseExpr->GetValue();
  2488. if ( !((node_base_type *)pSwType)->RangeCheck( CaseValue ) )
  2489. TypeSemError( this, MyContext, CASE_VALUE_OUT_OF_RANGE, NULL );
  2490. }
  2491. }
  2492. }
  2493. if ( MyContext.ExtractAttribute( ATTR_DEFAULT ) )
  2494. {
  2495. if ( !fInUnion )
  2496. TypeSemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, "[default]" );
  2497. fHasCases = TRUE;
  2498. }
  2499. // union fields in an RPC MUST have cases
  2500. if ( fInUnion && !fHasCases )
  2501. RpcSemError( this, MyContext, CASE_LABELS_MISSING_IN_UNION, NULL );
  2502. // temp field names valid for: structs/enums/empty arms
  2503. if ( IsTempName( pName ) )
  2504. {
  2505. NODE_T BaseType = GetBasicType()->NodeKind();
  2506. if ( ( BaseType != NODE_UNION ) &&
  2507. ( BaseType != NODE_STRUCT ) &&
  2508. ( BaseType != NODE_ERROR ) )
  2509. SemError( GetBasicType(), MyContext, BAD_CON_UNNAMED_FIELD_NO_STRUCT, NULL );
  2510. }
  2511. GetChild()->SemanticAnalysis( &MyContext );
  2512. // allow conformant array or struct only as last field, and not in unions!
  2513. if ( MyContext.AnyDescendantBits( HAS_CONF_ARRAY
  2514. | HAS_CONF_VAR_ARRAY ) )
  2515. {
  2516. if ( fInUnion )
  2517. {
  2518. RpcSemError( this, MyContext, BAD_CON_UNION_FIELD_CONF , NULL );
  2519. }
  2520. else if (!fLastField )
  2521. {
  2522. SemError( this, MyContext, CONFORMANT_ARRAY_NOT_LAST, NULL );
  2523. }
  2524. }
  2525. // disallow forward references as members
  2526. if ( MyContext.AnyDescendantBits( HAS_INCOMPLETE_TYPE ) )
  2527. {
  2528. if (! MyContext.AnyAncestorBits( IN_LIBRARY ))
  2529. SemError( this, MyContext, UNDEFINED_SYMBOL, NULL );
  2530. MyContext.ClearDescendantBits( HAS_INCOMPLETE_TYPE );
  2531. }
  2532. MyContext.ClearDescendantBits( HAS_RECURSIVE_DEF );
  2533. // don't allow functions as fields
  2534. if ( MyContext.AnyDescendantBits( HAS_FUNC ) &&
  2535. MyContext.AllAncestorBits( IN_INTERFACE | IN_RPC ) )
  2536. RpcSemError( this, MyContext, BAD_CON_FIELD_FUNC, NULL );
  2537. if ( MyContext.AnyDescendantBits( HAS_UNSAT_REP_AS ) )
  2538. SetHasUnknownRepAs();
  2539. pParentCtxt->ReturnValues( MyContext );
  2540. }
  2541. void
  2542. node_bitfield::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  2543. {
  2544. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  2545. CheckDeclspecAlign( MyContext );
  2546. RpcSemError( this, MyContext, BAD_CON_BIT_FIELDS, NULL );
  2547. if ( MyContext.AnyAncestorBits( IN_PARAM_LIST ) )
  2548. {
  2549. RpcSemError( this, MyContext, NON_RPC_PARAM_BIT_FIELDS, NULL );
  2550. }
  2551. else
  2552. {
  2553. RpcSemError( this, MyContext, NON_RPC_RTYPE_BIT_FIELDS, NULL );
  2554. }
  2555. GetChild()->SemanticAnalysis( &MyContext );
  2556. node_skl * pType = GetBasicType();
  2557. switch ( pType->NodeKind() )
  2558. {
  2559. case NODE_INT:
  2560. break;
  2561. case NODE_BOOLEAN:
  2562. case NODE_SHORT:
  2563. case NODE_CHAR:
  2564. case NODE_LONG:
  2565. case NODE_INT32:
  2566. case NODE_INT3264:
  2567. case NODE_INT64:
  2568. case NODE_INT128:
  2569. case NODE_HYPER:
  2570. SemError( this, MyContext, BAD_CON_BIT_FIELD_NON_ANSI, NULL );
  2571. break;
  2572. default:
  2573. SemError( this, MyContext, BAD_CON_BIT_FIELD_NOT_INTEGRAL, NULL );
  2574. break;
  2575. }
  2576. // disallow forward references as members
  2577. if ( MyContext.AnyDescendantBits( HAS_INCOMPLETE_TYPE ) )
  2578. {
  2579. if (! MyContext.AnyAncestorBits( IN_LIBRARY ))
  2580. SemError( this, MyContext, UNDEFINED_SYMBOL, NULL );
  2581. MyContext.ClearDescendantBits( HAS_INCOMPLETE_TYPE );
  2582. }
  2583. MyContext.ClearDescendantBits( HAS_RECURSIVE_DEF );
  2584. pParentCtxt->ReturnValues( MyContext );
  2585. }
  2586. void
  2587. node_su_base::CheckLegalParent(SEM_ANALYSIS_CTXT & MyContext)
  2588. {
  2589. WALK_CTXT * pParentCtxt = MyContext.GetParentContext();
  2590. node_file * pFile = GetDefiningFile();
  2591. if (NULL == pFile)
  2592. {
  2593. node_skl * pParent = pParentCtxt->GetParent();
  2594. if (NULL == pParent || pParent->NodeKind() == NODE_LIBRARY)
  2595. SemError( this, MyContext, ILLEGAL_SU_DEFINITION, NULL );
  2596. }
  2597. };
  2598. void
  2599. node_enum::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  2600. {
  2601. MEM_ITER MemIter( this );
  2602. node_skl * pN;
  2603. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  2604. MyContext.ExtractAttribute( ATTR_V1_ENUM );
  2605. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  2606. MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
  2607. MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
  2608. MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
  2609. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  2610. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  2611. {
  2612. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  2613. }
  2614. if ( MyContext.ExtractAttribute(ATTR_IDLDESCATTR) )
  2615. {
  2616. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  2617. }
  2618. // check for illegal type attributes
  2619. node_type_attr * pTA;
  2620. while ( ( pTA = (node_type_attr *)MyContext.ExtractAttribute(ATTR_TYPE) ) != 0 )
  2621. {
  2622. switch (pTA->GetAttr())
  2623. {
  2624. // acceptable attributes
  2625. case TATTR_PUBLIC:
  2626. {
  2627. char * pAttrName = pTA->GetNodeNameString();
  2628. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  2629. break;
  2630. }
  2631. }
  2632. }
  2633. // check for illegal member attributes
  2634. node_member_attr * pMA;
  2635. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  2636. {
  2637. switch (pMA->GetAttr())
  2638. {
  2639. case MATTR_USESGETLASTERROR:
  2640. {
  2641. char * pAttrName = pMA->GetNodeNameString();
  2642. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  2643. break;
  2644. }
  2645. }
  2646. }
  2647. CheckDeclspecAlign( MyContext );
  2648. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  2649. // make sure the UUID is unique
  2650. if ( pGuid )
  2651. {
  2652. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  2653. if ( pDuplicate )
  2654. {
  2655. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  2656. }
  2657. }
  2658. if (pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
  2659. CheckLegalParent(MyContext);
  2660. node_range_attr* pRange = ( node_range_attr* ) MyContext.ExtractAttribute(ATTR_RANGE);
  2661. if ( pRange )
  2662. {
  2663. if ( pRange->GetMinExpr()->GetValue() > pRange->GetMaxExpr()->GetValue() )
  2664. {
  2665. SemError(this, MyContext, INCORRECT_RANGE_DEFN, 0);
  2666. }
  2667. }
  2668. while ( ( pN = MemIter.GetNext() ) != 0 )
  2669. {
  2670. pN->SemanticAnalysis( &MyContext );
  2671. }
  2672. MyContext.SetDescendantBits( HAS_ENUM );
  2673. pParentCtxt->ReturnValues( MyContext );
  2674. }
  2675. // structs are stringable if all the fields are "byte"
  2676. BOOL
  2677. node_struct::IsStringableType()
  2678. {
  2679. MEM_ITER MemIter( this );
  2680. node_skl * pBasic;
  2681. node_skl * pN;
  2682. // make sure all the fields are BYTE! with no attributes on the way
  2683. while ( ( pN = (node_skl *) MemIter.GetNext() ) != 0 )
  2684. {
  2685. pBasic = pN->GetBasicType();
  2686. do {
  2687. if ( pN->HasAttributes() )
  2688. return FALSE;
  2689. pN = pN->GetChild();
  2690. }
  2691. while ( pN != pBasic );
  2692. pBasic = pN->GetBasicType();
  2693. if ( pBasic &&
  2694. (pBasic->NodeKind() != NODE_BYTE ) )
  2695. {
  2696. return FALSE;
  2697. }
  2698. }
  2699. return TRUE;
  2700. }
  2701. void
  2702. node_struct::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  2703. {
  2704. MEM_ITER MemIter( this );
  2705. node_skl * pN;
  2706. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  2707. if ( fBeingAnalyzed )
  2708. {
  2709. // if we hit the same node more than once (it can only be through a ptr),
  2710. // and the ptr type is ref, we flag an error; recursive defn. through a ref ptr.
  2711. if ( !MyContext.AnyAncestorBits( IN_NON_REF_PTR ) &&
  2712. MyContext.AnyAncestorBits( IN_RPC ) )
  2713. {
  2714. TypeSemError( this, MyContext, RECURSION_THRU_REF, NULL );
  2715. }
  2716. return;
  2717. }
  2718. fBeingAnalyzed = TRUE;
  2719. CheckDeclspecAlign( MyContext );
  2720. BOOL fString = (NULL != MyContext.ExtractAttribute( ATTR_STRING ));
  2721. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  2722. // make sure the UUID is unique
  2723. if ( pGuid )
  2724. {
  2725. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  2726. if ( pDuplicate )
  2727. {
  2728. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  2729. }
  2730. }
  2731. MyContext.MarkImportantPosition();
  2732. MyContext.SetAncestorBits( IN_STRUCT );
  2733. // clear NE union flag
  2734. MyContext.ClearAncestorBits( IN_UNION | IN_NE_UNION );
  2735. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  2736. MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
  2737. MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
  2738. MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
  2739. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  2740. if ( MyContext.ExtractAttribute( ATTR_VERSION ) )
  2741. {
  2742. SemError(this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, 0);
  2743. }
  2744. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  2745. {
  2746. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  2747. }
  2748. // clear member attributes
  2749. while (MyContext.ExtractAttribute(ATTR_MEMBER));
  2750. if (pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
  2751. CheckLegalParent(MyContext);
  2752. // See if context_handle applied to param reached us
  2753. if ( CheckContextHandle( MyContext ) )
  2754. {
  2755. MyContext.SetDescendantBits( HAS_HANDLE | HAS_CONTEXT_HANDLE );
  2756. }
  2757. while ( ( pN = MemIter.GetNext() ) != 0 )
  2758. {
  2759. pN->SemanticAnalysis( &MyContext );
  2760. if ( MyContext.AnyDescendantBits( HAS_HANDLE ) )
  2761. TypeSemError( pN, MyContext, BAD_CON_CTXT_HDL_FIELD, NULL );
  2762. }
  2763. if ( fString && !IsStringableType() )
  2764. {
  2765. TypeSemError( this, MyContext, WRONG_TYPE_IN_STRING_STRUCT, NULL );
  2766. }
  2767. // If a structure has an embedded array of pointers the back end gets
  2768. // really confused and generates bad pointer layouts. Work around the
  2769. // problem by forcing the structure to be complex.
  2770. if ( MyContext.AnyDescendantBits( HAS_VAR_ARRAY | HAS_ARRAYOFPOINTERS ) )
  2771. Complexity |= FLD_VAR;
  2772. if ( MyContext.AnyDescendantBits( HAS_CONF_ARRAY ) )
  2773. {
  2774. Complexity |= FLD_CONF;
  2775. fHasConformance = 1;
  2776. }
  2777. if ( MyContext.AnyDescendantBits( HAS_CONF_VAR_ARRAY ) )
  2778. {
  2779. Complexity |= FLD_CONF_VAR;
  2780. fHasConformance = 1;
  2781. }
  2782. // don't pass up direct conformance characteristic
  2783. MyContext.ClearDescendantBits( HAS_DIRECT_CONF_OR_VAR );
  2784. // disallow direct forward references as struct members
  2785. if ( MyContext.AnyDescendantBits( HAS_INCOMPLETE_TYPE ) )
  2786. {
  2787. if (! MyContext.AnyAncestorBits( IN_LIBRARY ))
  2788. SemError( this, MyContext, UNDEFINED_SYMBOL, NULL );
  2789. MyContext.ClearDescendantBits( HAS_INCOMPLETE_TYPE );
  2790. }
  2791. MyContext.ClearDescendantBits( HAS_RECURSIVE_DEF );
  2792. if ( MyContext.AnyDescendantBits( HAS_POINTER ) )
  2793. SetHasAtLeastOnePointer( TRUE );
  2794. // save info on complexity for code generation
  2795. if ( MyContext.AnyDescendantBits( HAS_VAR_ARRAY |
  2796. HAS_TRANSMIT_AS |
  2797. HAS_REPRESENT_AS |
  2798. HAS_INTERFACE_PTR |
  2799. HAS_MULTIDIM_SIZING |
  2800. HAS_ARRAY_OF_REF ) )
  2801. {
  2802. Complexity |= FLD_COMPLEX;
  2803. }
  2804. if( fHasConformance &&
  2805. !MyContext.AnyAncestorBits(IN_POINTER ) &&
  2806. !MyContext.AnyAncestorBits(IN_TRANSMIT_AS ))
  2807. {
  2808. RpcSemError( this, MyContext, CONF_BY_VALUE , NULL );
  2809. }
  2810. if ( pCommand->NeedsNDR64Run() )
  2811. {
  2812. if ( MyContext.AnyDescendantBits( HAS_UNSAT_REP_AS ) )
  2813. {
  2814. RpcSemError( this, MyContext, UNSPECIFIED_EMBEDDED_REPRESENT_AS_NOT_SUPPORTED, NULL );
  2815. }
  2816. }
  2817. MyContext.ClearDescendantBits( HAS_ARRAY | HAS_MULTIDIM_VECTOR );
  2818. MyContext.SetDescendantBits( HAS_STRUCT );
  2819. pParentCtxt->ReturnValues( MyContext );
  2820. fBeingAnalyzed = FALSE;
  2821. }
  2822. // note: this lets HAS_UNION propogate up to any enclosing structs
  2823. void
  2824. node_en_struct::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  2825. {
  2826. MEM_ITER MemIter( this );
  2827. node_skl * pN;
  2828. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  2829. if ( fBeingAnalyzed )
  2830. {
  2831. // if we hit the same node more than once (it can only be through a ptr),
  2832. // and the ptr type is ref, we flag an error; recursive defn. through a ref ptr.
  2833. if ( !MyContext.AnyAncestorBits( IN_NON_REF_PTR ) &&
  2834. MyContext.AnyAncestorBits( IN_RPC ) )
  2835. {
  2836. TypeSemError( this, MyContext, RECURSION_THRU_REF, NULL );
  2837. }
  2838. return;
  2839. }
  2840. fBeingAnalyzed = TRUE;
  2841. MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
  2842. MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
  2843. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  2844. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  2845. {
  2846. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  2847. }
  2848. CheckDeclspecAlign( MyContext );
  2849. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  2850. // make sure the UUID is unique
  2851. if ( pGuid )
  2852. {
  2853. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  2854. if ( pDuplicate )
  2855. {
  2856. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  2857. }
  2858. }
  2859. if (pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
  2860. CheckLegalParent(MyContext);
  2861. MyContext.SetAncestorBits( IN_STRUCT );
  2862. // See if context_handle applied to param reached us
  2863. if ( CheckContextHandle( MyContext ) )
  2864. {
  2865. MyContext.SetDescendantBits( HAS_HANDLE | HAS_CONTEXT_HANDLE );
  2866. }
  2867. while ( ( pN = MemIter.GetNext() ) != 0 )
  2868. {
  2869. pN->SemanticAnalysis( &MyContext );
  2870. };
  2871. if ( pCommand->NeedsNDR64Run() )
  2872. {
  2873. if ( MyContext.AnyDescendantBits( HAS_UNSAT_REP_AS ) )
  2874. {
  2875. RpcSemError( this, MyContext, UNSPECIFIED_EMBEDDED_REPRESENT_AS_NOT_SUPPORTED, NULL );
  2876. }
  2877. }
  2878. if ( MyContext.AnyDescendantBits( HAS_POINTER ) )
  2879. SetHasAtLeastOnePointer( TRUE );
  2880. pParentCtxt->ReturnValues( MyContext );
  2881. fBeingAnalyzed = FALSE;
  2882. }
  2883. void
  2884. node_union::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  2885. {
  2886. MEM_ITER MemIter( this );
  2887. node_field * pN;
  2888. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  2889. BOOL fEncap = IsEncapsulatedUnion();
  2890. node_switch_type * pSwTypeAttr = (node_switch_type *) MyContext.ExtractAttribute( ATTR_SWITCH_TYPE );
  2891. node_switch_is * pSwIsAttr = (node_switch_is *) MyContext.ExtractAttribute( ATTR_SWITCH_IS );
  2892. BOOL NonEmptyArm = FALSE;
  2893. BOOL HasCases = FALSE;
  2894. BOOL HasBadExpr = FALSE;
  2895. if ( HasCorrelation( this ) )
  2896. {
  2897. MyContext.IncCorrelationCount();
  2898. }
  2899. if (pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
  2900. CheckLegalParent(MyContext);
  2901. MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
  2902. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  2903. MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
  2904. MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
  2905. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  2906. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  2907. {
  2908. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  2909. }
  2910. if ( MyContext.ExtractAttribute( ATTR_HIDDEN ) )
  2911. {
  2912. SemError(this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, 0);
  2913. }
  2914. if ( MyContext.ExtractAttribute( ATTR_VERSION ) )
  2915. {
  2916. SemError(this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, 0);
  2917. }
  2918. if ( fBeingAnalyzed )
  2919. {
  2920. // if we hit the same node more than once (it can only be through a ptr),
  2921. // and the ptr type is ref, we flag an error; recursive defn. through a ref ptr.
  2922. if ( !MyContext.AnyAncestorBits( IN_NON_REF_PTR ) &&
  2923. MyContext.AnyAncestorBits( IN_RPC ) )
  2924. {
  2925. TypeSemError( this, MyContext, RECURSION_THRU_REF, NULL );
  2926. }
  2927. return;
  2928. }
  2929. fBeingAnalyzed = TRUE;
  2930. CheckDeclspecAlign( MyContext );
  2931. if ( pSwIsAttr )
  2932. {
  2933. EXPR_CTXT SwCtxt( &MyContext );
  2934. expr_node * pSwIsExpr = pSwIsAttr->GetExpr();
  2935. pSwIsExpr->ExprAnalyze( &SwCtxt );
  2936. if ( SwCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  2937. {
  2938. TypeSemError( this,
  2939. MyContext,
  2940. ATTRIBUTE_ID_UNRESOLVED,
  2941. pSwIsAttr->GetNodeNameString() );
  2942. HasBadExpr = TRUE;
  2943. }
  2944. if ( !SwCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  2945. {
  2946. TypeSemError( this,
  2947. MyContext,
  2948. ATTRIBUTE_ID_MUST_BE_VAR,
  2949. pSwIsAttr->GetNodeNameString() );
  2950. HasBadExpr = TRUE;
  2951. }
  2952. }
  2953. // if they left off the switch_type, take it from the switch_is type
  2954. if ( !pSwTypeAttr && !fEncap && pSwIsAttr && !HasBadExpr )
  2955. {
  2956. node_skl * pSwIsType = pSwIsAttr->GetSwitchIsType();
  2957. MIDL_ASSERT( pSwIsType || !"no type for switch_is expr");
  2958. if ( ( pSwIsType->NodeKind() == NODE_FIELD ) ||
  2959. ( pSwIsType->NodeKind() == NODE_PARAM ) )
  2960. pSwIsType = pSwIsType->GetChild();
  2961. pSwTypeAttr = new node_switch_type( pSwIsType );
  2962. SetAttribute( pSwTypeAttr );
  2963. }
  2964. if ( pSwIsAttr && pSwTypeAttr && !HasBadExpr )
  2965. {
  2966. node_skl * pSwIsType = pSwIsAttr->GetSwitchIsType();
  2967. node_skl * pSwType = pSwTypeAttr->GetType();
  2968. pSwIsType = pSwIsType->GetBasicType();
  2969. if ( pSwIsType && pSwIsType->IsBasicType() && pSwType->IsBasicType() )
  2970. {
  2971. if ( !((node_base_type *)pSwType)
  2972. ->IsAssignmentCompatible( (node_base_type *) pSwIsType ) )
  2973. TypeSemError( this, MyContext, SWITCH_TYPE_MISMATCH, NULL );
  2974. }
  2975. if ( !pSwType || !Xxx_Is_Type_OK( pSwType ) )
  2976. {
  2977. TypeSemError( this,
  2978. MyContext,
  2979. SWITCH_IS_TYPE_IS_WRONG,
  2980. pSwType ? pSwType->GetSymName() : NULL );
  2981. }
  2982. if ( !pSwIsType || !Xxx_Is_Type_OK( pSwIsType ) )
  2983. {
  2984. TypeSemError( this,
  2985. MyContext,
  2986. SWITCH_IS_TYPE_IS_WRONG,
  2987. pSwIsType ? pSwIsType->GetSymName() : NULL );
  2988. }
  2989. }
  2990. // We don't care about local: it can be anything.
  2991. if ( MyContext.AnyAncestorBits( IN_RPC ) )
  2992. {
  2993. if ( !fEncap && !pSwTypeAttr && !pSwIsAttr )
  2994. {
  2995. if ( MyContext.AnyAncestorBits( IN_PARAM_LIST ) )
  2996. RpcSemError( this, MyContext, NON_RPC_UNION, NULL );
  2997. else
  2998. RpcSemError( this, MyContext, NON_RPC_RTYPE_UNION, NULL );
  2999. }
  3000. if ( !fEncap &&
  3001. MyContext.AnyAncestorBits( IN_FUNCTION_RESULT ) &&
  3002. !MyContext.AnyAncestorBits( IN_STRUCT | IN_UNION ) )
  3003. RpcSemError( this, MyContext, RETURN_OF_UNIONS_ILLEGAL, NULL );
  3004. if ( pSwTypeAttr && !pSwIsAttr )
  3005. RpcSemError( this, MyContext, NO_SWITCH_IS, NULL );
  3006. }
  3007. // See if context_handle applied to param reached us
  3008. if ( CheckContextHandle( MyContext ) )
  3009. {
  3010. MyContext.SetDescendantBits( HAS_HANDLE | HAS_CONTEXT_HANDLE );
  3011. }
  3012. MyContext.MarkImportantPosition();
  3013. if ( MyContext.AllAncestorBits( IN_INTERFACE | IN_NE_UNION ) )
  3014. {
  3015. RpcSemError( this, MyContext, NE_UNION_FIELD_NE_UNION, NULL );
  3016. }
  3017. if ( ( MyContext.FindNonDefAncestorContext()->GetParent()
  3018. ->NodeKind() == NODE_UNION ) &&
  3019. MyContext.AnyAncestorBits( IN_INTERFACE ) )
  3020. {
  3021. RpcSemError( this, MyContext, ARRAY_OF_UNIONS_ILLEGAL, NULL );
  3022. }
  3023. MyContext.SetAncestorBits( IN_UNION | IN_NE_UNION );
  3024. MyContext.SetDescendantBits( HAS_UNION );
  3025. // eat the union flavor determiner
  3026. MyContext.ExtractAttribute( ATTR_MS_UNION );
  3027. while ( ( pN = (node_field *) MemIter.GetNext() ) != 0 )
  3028. {
  3029. // tbd - put cases into case database...
  3030. // tbd - check type, range, and duplication
  3031. pN->SemanticAnalysis( &MyContext );
  3032. if ( !NonEmptyArm && !pN->IsEmptyArm() )
  3033. NonEmptyArm = TRUE;
  3034. if ( !HasCases && (pN->FInSummary( ATTR_CASE ) || pN->FInSummary( ATTR_DEFAULT ) ) )
  3035. HasCases = TRUE;
  3036. }
  3037. // at least one arm should be non-empty
  3038. if ( !NonEmptyArm )
  3039. SemError( this, MyContext, UNION_NO_FIELDS, NULL );
  3040. if ( !fEncap && !pSwTypeAttr && !HasCases )
  3041. RpcSemError( this, MyContext, BAD_CON_NON_RPC_UNION, NULL );
  3042. // disallow forward references as union members
  3043. if ( MyContext.AnyDescendantBits( HAS_INCOMPLETE_TYPE ) )
  3044. {
  3045. if (! MyContext.AnyAncestorBits( IN_LIBRARY ))
  3046. SemError( this, MyContext, UNDEFINED_SYMBOL, NULL );
  3047. MyContext.ClearDescendantBits( HAS_INCOMPLETE_TYPE );
  3048. }
  3049. MyContext.ClearDescendantBits( HAS_RECURSIVE_DEF );
  3050. if ( MyContext.AnyDescendantBits( HAS_POINTER ) )
  3051. SetHasAtLeastOnePointer( TRUE );
  3052. if ( MyContext.AnyDescendantBits( HAS_CONF_ARRAY | HAS_CONF_VAR_ARRAY ) )
  3053. {
  3054. RpcSemError( this, MyContext, BAD_CON_UNION_FIELD_CONF , NULL );
  3055. }
  3056. if ( pCommand->NeedsNDR64Run() )
  3057. {
  3058. if ( MyContext.AnyDescendantBits( HAS_UNSAT_REP_AS ) )
  3059. {
  3060. RpcSemError( this, MyContext, UNSPECIFIED_EMBEDDED_REPRESENT_AS_NOT_SUPPORTED, NULL );
  3061. }
  3062. }
  3063. // clear flags not affecting complexity above
  3064. MyContext.ClearDescendantBits( HAS_POINTER |
  3065. HAS_CONF_PTR |
  3066. HAS_VAR_PTR |
  3067. HAS_CONF_VAR_PTR |
  3068. HAS_MULTIDIM_SIZING |
  3069. HAS_MULTIDIM_VECTOR |
  3070. HAS_ARRAY_OF_REF |
  3071. HAS_ENUM |
  3072. HAS_DIRECT_CONF_OR_VAR |
  3073. HAS_ARRAY |
  3074. HAS_REPRESENT_AS |
  3075. HAS_TRANSMIT_AS |
  3076. HAS_CONF_VAR_ARRAY |
  3077. HAS_CONF_ARRAY |
  3078. HAS_VAR_ARRAY );
  3079. pParentCtxt->ReturnValues( MyContext );
  3080. fBeingAnalyzed = FALSE;
  3081. }
  3082. void
  3083. node_en_union::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  3084. {
  3085. MEM_ITER MemIter( this );
  3086. node_field * pN;
  3087. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  3088. node_switch_type* pSwTypeAttr = ( node_switch_type* ) MyContext.ExtractAttribute( ATTR_SWITCH_TYPE );
  3089. node_skl * pSwType;
  3090. node_switch_is* pSwIsAttr = ( node_switch_is* ) MyContext.ExtractAttribute( ATTR_SWITCH_IS );
  3091. BOOL NonEmptyArm = FALSE;
  3092. if ( HasCorrelation( this ) )
  3093. {
  3094. MyContext.IncCorrelationCount();
  3095. }
  3096. // gaj - tbd do semantic checks on these attributes
  3097. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  3098. MyContext.ExtractAttribute( ATTR_HELPSTRINGCONTEXT );
  3099. MyContext.ExtractAttribute( ATTR_HELPCONTEXT );
  3100. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  3101. {
  3102. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  3103. }
  3104. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  3105. // make sure the UUID is unique
  3106. if ( pGuid )
  3107. {
  3108. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  3109. if ( pDuplicate )
  3110. {
  3111. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  3112. }
  3113. }
  3114. if ( fBeingAnalyzed )
  3115. {
  3116. // if we hit the same node more than once (it can only be through a ptr),
  3117. // and the ptr type is ref, we flag an error; recursive defn. through a ref ptr.
  3118. if ( !MyContext.AnyAncestorBits( IN_NON_REF_PTR ) &&
  3119. MyContext.AnyAncestorBits( IN_RPC ) )
  3120. {
  3121. TypeSemError( this, MyContext, RECURSION_THRU_REF, NULL );
  3122. }
  3123. return;
  3124. }
  3125. fBeingAnalyzed = TRUE;
  3126. CheckDeclspecAlign( MyContext );
  3127. if ( pSwTypeAttr )
  3128. {
  3129. pSwType = pSwTypeAttr->GetSwitchType();
  3130. if ( !pSwType ||
  3131. !Xxx_Is_Type_OK( pSwType ) ||
  3132. pSwType->NodeKind() == NODE_BYTE )
  3133. {
  3134. TypeSemError( this,
  3135. MyContext,
  3136. SWITCH_IS_TYPE_IS_WRONG,
  3137. pSwType ? pSwType->GetSymName() : NULL );
  3138. }
  3139. }
  3140. if ( pSwIsAttr )
  3141. {
  3142. EXPR_CTXT SwCtxt( &MyContext );
  3143. expr_node * pSwIsExpr = pSwIsAttr->GetExpr();
  3144. pSwIsExpr->ExprAnalyze( &SwCtxt );
  3145. if ( SwCtxt.AnyUpFlags( EX_UNSAT_FWD ) )
  3146. TypeSemError( this,
  3147. MyContext,
  3148. ATTRIBUTE_ID_UNRESOLVED,
  3149. pSwIsAttr->GetNodeNameString() );
  3150. if ( !SwCtxt.AnyUpFlags( EX_VALUE_INVALID ) )
  3151. TypeSemError( this,
  3152. MyContext,
  3153. ATTRIBUTE_ID_MUST_BE_VAR,
  3154. pSwIsAttr->GetNodeNameString() );
  3155. }
  3156. MyContext.MarkImportantPosition();
  3157. MyContext.SetAncestorBits( IN_UNION );
  3158. MyContext.SetDescendantBits( HAS_UNION );
  3159. while ( ( pN = (node_field *) MemIter.GetNext() ) != 0 )
  3160. {
  3161. // tbd - put cases into case database...
  3162. // tbd - check type, range, and duplication
  3163. pN->SemanticAnalysis( &MyContext );
  3164. if ( !pN->IsEmptyArm() )
  3165. NonEmptyArm = TRUE;
  3166. }
  3167. // at least one arm should be non-empty
  3168. if ( !NonEmptyArm )
  3169. SemError( this, MyContext, UNION_NO_FIELDS, NULL );
  3170. // remember if we have a pointer
  3171. if ( MyContext.AnyDescendantBits( HAS_POINTER ) )
  3172. SetHasAtLeastOnePointer( TRUE );
  3173. if ( MyContext.AnyDescendantBits( HAS_CONF_ARRAY | HAS_CONF_VAR_ARRAY ) )
  3174. {
  3175. RpcSemError( this, MyContext, BAD_CON_UNION_FIELD_CONF , NULL );
  3176. }
  3177. // clear flags not affecting complexity above
  3178. MyContext.ClearDescendantBits( HAS_POINTER |
  3179. HAS_CONF_PTR |
  3180. HAS_VAR_PTR |
  3181. HAS_CONF_VAR_PTR |
  3182. HAS_MULTIDIM_SIZING |
  3183. HAS_MULTIDIM_VECTOR |
  3184. HAS_ARRAY_OF_REF |
  3185. HAS_ENUM |
  3186. HAS_DIRECT_CONF_OR_VAR |
  3187. HAS_ARRAY |
  3188. HAS_REPRESENT_AS |
  3189. HAS_TRANSMIT_AS |
  3190. HAS_CONF_VAR_ARRAY |
  3191. HAS_CONF_ARRAY |
  3192. HAS_VAR_ARRAY );
  3193. pParentCtxt->ReturnValues( MyContext );
  3194. fBeingAnalyzed = FALSE;
  3195. }
  3196. void
  3197. node_def::SemanticAnalysisForTransmit(
  3198. SEM_ANALYSIS_CTXT * pMyContext,
  3199. BOOL fPresented )
  3200. {
  3201. if ( fPresented )
  3202. {
  3203. // the presented type may not be conformant.
  3204. if ( pMyContext->AnyDescendantBits( HAS_VAR_ARRAY
  3205. | HAS_CONF_ARRAY
  3206. | HAS_CONF_VAR_ARRAY ) )
  3207. TypeSemError( this, *pMyContext, TRANSMIT_TYPE_CONF, NULL );
  3208. }
  3209. else
  3210. {
  3211. // transmitted type may not have a pointer.
  3212. if ( pMyContext->AnyDescendantBits( HAS_POINTER | HAS_INTERFACE_PTR ) )
  3213. TypeSemError( this,*pMyContext, TRANSMIT_AS_POINTER, NULL );
  3214. // transmitted type may not derive from void
  3215. if ( pMyContext->AnyDescendantBits( DERIVES_FROM_VOID ) )
  3216. TypeSemError( this, *pMyContext, TRANSMIT_AS_VOID, NULL );
  3217. }
  3218. }
  3219. void
  3220. node_def::SemanticAnalysisForWireMarshal(
  3221. SEM_ANALYSIS_CTXT * pMyContext,
  3222. BOOL fPresented )
  3223. {
  3224. if ( fPresented )
  3225. {
  3226. // We need to check if the presented type is not void; note, void * is ok.
  3227. }
  3228. else
  3229. {
  3230. // We check only the transmitted type for wire_marshal, user marshal.
  3231. //
  3232. // The transmitted type must not have full pointers, since
  3233. // the app has no mechanism to generate the full pointer ids.
  3234. // BUG, BUG semantic analysis treats arrays in structures
  3235. // as pointers. Change to error once the bug is fixed.
  3236. if ( pMyContext->AnyDescendantBits( HAS_FULL_PTR ) )
  3237. TypeSemError( this, *pMyContext, WIRE_HAS_FULL_PTR, NULL);
  3238. // The wire type must have a fully defined memory size. It cannot be
  3239. // conformant or conformant varying. Arrays have a problem
  3240. // in that the app can't marshal the MaxCount, Actual Count, or Offset properly.
  3241. if ( pMyContext->AnyDescendantBits( HAS_CONF_ARRAY
  3242. | HAS_CONF_VAR_ARRAY ) )
  3243. TypeSemError( this, *pMyContext, WIRE_NOT_DEFINED_SIZE, NULL);
  3244. // transmitted type may not derive from void
  3245. if ( pMyContext->AnyDescendantBits( DERIVES_FROM_VOID ) )
  3246. TypeSemError( this, *pMyContext, TRANSMIT_AS_VOID, NULL );
  3247. }
  3248. }
  3249. void
  3250. node_def::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  3251. {
  3252. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  3253. BOOL fInRpc = MyContext.AnyAncestorBits( IN_RPC );
  3254. BOOL fInPresented = MyContext.AnyAncestorBits( IN_PRESENTED_TYPE );
  3255. SEM_ANALYSIS_CTXT * pIntfCtxt = (SEM_ANALYSIS_CTXT *)
  3256. MyContext.GetInterfaceContext();
  3257. node_represent_as * pRepresent = (node_represent_as *)
  3258. MyContext.ExtractAttribute( ATTR_REPRESENT_AS );
  3259. node_transmit * pTransmit = (node_transmit *)
  3260. MyContext.ExtractAttribute( ATTR_TRANSMIT );
  3261. node_user_marshal * pUserMarshal = (node_user_marshal *)
  3262. MyContext.ExtractAttribute( ATTR_USER_MARSHAL );
  3263. node_wire_marshal * pWireMarshal = (node_wire_marshal *)
  3264. MyContext.ExtractAttribute( ATTR_WIRE_MARSHAL );
  3265. BOOL fRepMarshal = pRepresent || pUserMarshal;
  3266. BOOL fXmitMarshal = pTransmit || pWireMarshal;
  3267. BOOL fEncodeDecode = (NULL != MyContext.ExtractAttribute( ATTR_ENCODE ));
  3268. MyContext.ExtractAttribute(ATTR_HELPSTRING);
  3269. MyContext.ExtractAttribute( ATTR_HELPCONTEXT );
  3270. MyContext.ExtractAttribute( ATTR_HELPSTRINGCONTEXT );
  3271. // Partial ignore may not be used directly on an xmit or rep as.
  3272. if (MyContext.AnyAncestorBits( UNDER_PARTIAL_IGNORE_PARAM ) &&
  3273. ( fRepMarshal || fXmitMarshal ) )
  3274. {
  3275. SemError( this, MyContext, PARTIAL_IGNORE_UNIQUE, 0 );
  3276. }
  3277. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  3278. {
  3279. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  3280. }
  3281. if ( HasCorrelation( this ) )
  3282. {
  3283. MyContext.IncCorrelationCount();
  3284. }
  3285. CheckDeclspecAlign( MyContext );
  3286. node_range_attr* pRange = ( node_range_attr* ) MyContext.GetAttribute(ATTR_RANGE);
  3287. if ( pRange )
  3288. {
  3289. if ( pRange->GetMinExpr()->GetValue() > pRange->GetMaxExpr()->GetValue() )
  3290. {
  3291. SemError(this, MyContext, INCORRECT_RANGE_DEFN, 0);
  3292. }
  3293. }
  3294. BOOL fPropogateChild = TRUE; // propogate direct child info
  3295. unsigned long ulHandleKind;
  3296. // check for illegal type attributes
  3297. node_type_attr * pTA;
  3298. while ( ( pTA = (node_type_attr *)MyContext.ExtractAttribute(ATTR_TYPE) ) != 0 )
  3299. {
  3300. switch (pTA->GetAttr())
  3301. {
  3302. // acceptable attributes
  3303. case TATTR_PUBLIC:
  3304. {
  3305. break;
  3306. }
  3307. // unacceptable attributes
  3308. case TATTR_LICENSED:
  3309. case TATTR_OLEAUTOMATION:
  3310. case TATTR_APPOBJECT:
  3311. case TATTR_CONTROL:
  3312. case TATTR_PROXY:
  3313. case TATTR_DUAL:
  3314. case TATTR_NONEXTENSIBLE:
  3315. case TATTR_NONCREATABLE:
  3316. case TATTR_AGGREGATABLE:
  3317. {
  3318. char * pAttrName = pTA->GetNodeNameString();
  3319. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  3320. break;
  3321. }
  3322. }
  3323. }
  3324. // check for illegal member attributes
  3325. node_member_attr * pMA;
  3326. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  3327. {
  3328. switch (pMA->GetAttr())
  3329. {
  3330. case MATTR_RESTRICTED:
  3331. break;
  3332. case MATTR_OPTIONAL:
  3333. case MATTR_RETVAL:
  3334. case MATTR_BINDABLE:
  3335. case MATTR_DISPLAYBIND:
  3336. case MATTR_DEFAULTBIND:
  3337. case MATTR_REQUESTEDIT:
  3338. case MATTR_PROPGET:
  3339. case MATTR_PROPPUT:
  3340. case MATTR_PROPPUTREF:
  3341. case MATTR_VARARG:
  3342. case MATTR_SOURCE:
  3343. case MATTR_DEFAULTVTABLE:
  3344. case MATTR_PREDECLID:
  3345. case MATTR_UIDEFAULT:
  3346. case MATTR_NONBROWSABLE:
  3347. case MATTR_DEFAULTCOLLELEM:
  3348. case MATTR_USESGETLASTERROR:
  3349. case MATTR_IMMEDIATEBIND:
  3350. case MATTR_REPLACEABLE:
  3351. default:
  3352. {
  3353. char * pAttrName = pMA->GetNodeNameString();
  3354. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  3355. break;
  3356. }
  3357. }
  3358. }
  3359. #if defined(TARGET_RKK)
  3360. // Checking the release compatibility
  3361. if ( pCommand->GetTargetSystem() < NT40 )
  3362. {
  3363. if ( pWireMarshal )
  3364. SemError( this, MyContext, REQUIRES_NT40, "[wire_marshal]" );
  3365. if ( pUserMarshal )
  3366. SemError( this, MyContext, REQUIRES_NT40, "[user_marshal]" );
  3367. }
  3368. if ( pCommand->GetTargetSystem() < NT351 )
  3369. {
  3370. if ( fEncodeDecode )
  3371. SemError( this, MyContext, REQUIRES_NT351, "[encode,decode]" );
  3372. }
  3373. #endif
  3374. MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
  3375. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  3376. // clear the GUID, VERSION and HIDDEN attributes if set
  3377. MyContext.ExtractAttribute( ATTR_HIDDEN );
  3378. MyContext.ExtractAttribute( ATTR_VERSION );
  3379. MyContext.ExtractAttribute( ATTR_HELPCONTEXT);
  3380. MyContext.ExtractAttribute( ATTR_HELPSTRINGCONTEXT);
  3381. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  3382. // make sure the UUID is unique
  3383. if ( pGuid )
  3384. {
  3385. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  3386. if ( pDuplicate )
  3387. {
  3388. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  3389. }
  3390. }
  3391. // get the encode and decode attributes
  3392. fEncodeDecode |= (NULL != MyContext.ExtractAttribute( ATTR_DECODE ));
  3393. fEncodeDecode |= pIntfCtxt->FInSummary( ATTR_ENCODE );
  3394. fEncodeDecode |= pIntfCtxt->FInSummary( ATTR_DECODE );
  3395. if ( fEncodeDecode )
  3396. {
  3397. // only direct children of the interface get these bits
  3398. if ( !pParentCtxt->GetParent()->IsInterfaceOrObject() )
  3399. {
  3400. fEncodeDecode = FALSE;
  3401. }
  3402. else if (MyContext.AnyAncestorBits( IN_OBJECT_INTF ) )
  3403. {
  3404. fEncodeDecode = FALSE;
  3405. TypeSemError( this, MyContext, PICKLING_INVALID_IN_OBJECT, NULL );
  3406. }
  3407. else
  3408. {
  3409. // note that this is an rpc-able interface
  3410. GetMyInterfaceNode()->SetPickleInterface();
  3411. MyContext.SetAncestorBits( IN_RPC );
  3412. }
  3413. SemError( this, MyContext, TYPE_PICKLING_INVALID_IN_OSF, NULL );
  3414. BOOL HasV2Optimize = pCommand->GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2;
  3415. if ( pCommand->IsSwitchDefined( SWITCH_ROBUST ) )
  3416. {
  3417. if ( HasV2Optimize )
  3418. {
  3419. pCommand->GetNdrVersionControl().SetHasOicfPickling();
  3420. if ( pCommand->GetTargetSystem() == NT40 )
  3421. SemError( this, MyContext, INVALID_FEATURE_FOR_TARGET, ":oicf pickling" );
  3422. }
  3423. else
  3424. {
  3425. SemError( this, MyContext, ROBUST_PICKLING_NO_OICF, 0 );
  3426. }
  3427. }
  3428. BOOL HasCommFault = MyContext.FInSummary( ATTR_COMMSTAT )
  3429. || MyContext.FInSummary( ATTR_FAULTSTAT );
  3430. if ( HasCommFault && !HasV2Optimize)
  3431. {
  3432. SemError( this, MyContext, COMMFAULT_PICKLING_NO_OICF, 0 );
  3433. }
  3434. }
  3435. // kind of handle applied right now (HandleKind only set for ones on this
  3436. // typedef node)
  3437. if ( FInSummary(ATTR_HANDLE) )
  3438. {
  3439. MyContext.ExtractAttribute( ATTR_HANDLE );
  3440. SetHandleKind( HDL_GEN );
  3441. }
  3442. bool fSerialize = MyContext.ExtractAttribute( ATTR_SERIALIZE ) != 0;
  3443. bool fNoSerialize = MyContext.ExtractAttribute( ATTR_NOSERIALIZE ) != 0;
  3444. // See if context_handle applied to param reached us
  3445. if ( FInSummary(ATTR_CONTEXT) )
  3446. {
  3447. if ( ( GetHandleKind() != HDL_NONE ) &&
  3448. ( GetHandleKind() != HDL_CTXT ) )
  3449. TypeSemError( this, MyContext, CTXT_HDL_GENERIC_HDL, NULL );
  3450. MyContext.ExtractAttribute( ATTR_CONTEXT );
  3451. if ( fSerialize && fNoSerialize )
  3452. {
  3453. SemError( this, MyContext, CONFLICTING_ATTRIBUTES, GetSymName() );
  3454. }
  3455. SetHandleKind( HDL_CTXT );
  3456. // since the base type is not transmitted, we aren't really
  3457. // in an rpc after here
  3458. MyContext.ClearAncestorBits( IN_RPC );
  3459. }
  3460. else
  3461. {
  3462. if ( fSerialize || fNoSerialize )
  3463. {
  3464. SemError( this, MyContext, NO_CONTEXT_HANDLE, GetSymName() );
  3465. }
  3466. }
  3467. ulHandleKind = GetHandleKind();
  3468. if ( ulHandleKind != HDL_NONE )
  3469. {
  3470. MyContext.SetAncestorBits( IN_HANDLE );
  3471. }
  3472. // effectively, the presented type is NOT involved in an RPC
  3473. if ( fXmitMarshal )
  3474. {
  3475. MyContext.ClearAncestorBits( IN_RPC );
  3476. MyContext.SetAncestorBits( IN_PRESENTED_TYPE );
  3477. if ( MyContext.FInSummary( ATTR_ALLOCATE ) )
  3478. AcfError( (acf_attr *) MyContext.ExtractAttribute( ATTR_ALLOCATE ),
  3479. this,
  3480. MyContext,
  3481. ALLOCATE_ON_TRANSMIT_AS,
  3482. NULL );
  3483. if ( GetHandleKind() == HDL_CTXT )
  3484. TypeSemError( this, MyContext, TRANSMIT_AS_CTXT_HANDLE, NULL );
  3485. }
  3486. if ( MyContext.ExtractAttribute( ATTR_CSCHAR ) )
  3487. {
  3488. if ( MyContext.AnyAncestorBits( UNDER_IN_PARAM ) )
  3489. MyContext.SetDescendantBits( HAS_IN_CSTYPE );
  3490. if ( MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) )
  3491. MyContext.SetDescendantBits( HAS_OUT_CSTYPE );
  3492. }
  3493. // process the child
  3494. GetChild()->SemanticAnalysis( &MyContext );
  3495. if (pCommand->IsSwitchDefined(SWITCH_MKTYPLIB))
  3496. {
  3497. switch (GetChild()->NodeKind())
  3498. {
  3499. case NODE_STRUCT:
  3500. case NODE_UNION:
  3501. case NODE_ENUM:
  3502. {
  3503. // This is the 'typedef' part of a 'typedef struct',
  3504. // 'typedef union', or 'typedef enum' declaration.
  3505. // Make sure that the type info name is set to the name of the
  3506. // typedef and not the child.
  3507. ((node_su_base *)GetChild())->SetTypeInfoName(GetSymName());
  3508. }
  3509. break;
  3510. }
  3511. }
  3512. else
  3513. {
  3514. if (GetChild()->GetSymName() && IsTempName(GetChild()->GetSymName()))
  3515. {
  3516. // Make sure that at least the [public] attribute is
  3517. // set on this typedef, forcing this typedef to be put
  3518. // in a type library if it is referenced from within one.
  3519. SetAttribute(new node_type_attr(TATTR_PUBLIC));
  3520. }
  3521. }
  3522. /* yongqu: don't enable this before we read custom data.
  3523. if ( GetChild()->NodeKind() == NODE_INT3264 )
  3524. {
  3525. SetAttribute( GetCustomAttrINT3264() );
  3526. }
  3527. */
  3528. // process all the nasties of transmit_as and wire_marshal
  3529. if ( fXmitMarshal && !fInPresented && fInRpc )
  3530. {
  3531. SEM_ANALYSIS_CTXT TransmitContext( &MyContext );
  3532. // eat the attributes added by the above constructor
  3533. TransmitContext.ClearAttributes();
  3534. // process the transmitted type
  3535. TransmitContext.SetAncestorBits( IN_TRANSMIT_AS );
  3536. if ( pWireMarshal )
  3537. TransmitContext.SetAncestorBits( IN_USER_MARSHAL );
  3538. TransmitContext.ClearAncestorBits( IN_PRESENTED_TYPE );
  3539. if ( fInRpc)
  3540. TransmitContext.SetAncestorBits( IN_RPC );
  3541. if ( pTransmit )
  3542. pTransmit->GetType()->SemanticAnalysis( &TransmitContext );
  3543. else if ( pWireMarshal )
  3544. pWireMarshal->GetType()->SemanticAnalysis( &TransmitContext );
  3545. else
  3546. MIDL_ASSERT(0);
  3547. if ( pTransmit )
  3548. {
  3549. // check the transmitted type.
  3550. SemanticAnalysisForTransmit( &TransmitContext, FALSE );
  3551. // Check the presented type.
  3552. SemanticAnalysisForTransmit( &MyContext, TRUE );
  3553. }
  3554. else if ( pWireMarshal )
  3555. {
  3556. // check the transmitted type
  3557. SemanticAnalysisForWireMarshal( &TransmitContext, FALSE );
  3558. // check the presented type
  3559. SemanticAnalysisForWireMarshal( &MyContext, TRUE );
  3560. }
  3561. else {
  3562. MIDL_ASSERT(0);
  3563. }
  3564. if ( TransmitContext.AnyDescendantBits( HAS_HANDLE ) )
  3565. {
  3566. //gaj TypeSemError( this, MyContext, HANDLE_T_XMIT, NULL );
  3567. }
  3568. if ( TransmitContext.AnyDescendantBits( HAS_TRANSMIT_AS ) )
  3569. {
  3570. TypeSemError( this, MyContext, TRANSMIT_AS_NON_RPCABLE, NULL );
  3571. }
  3572. TransmitContext.SetDescendantBits( HAS_TRANSMIT_AS );
  3573. // since the base type is not transmitted, we aren't really
  3574. // in an rpc after here
  3575. pParentCtxt->ReturnValues( TransmitContext );
  3576. fPropogateChild = FALSE;
  3577. }
  3578. // process all the nasties of represent_as and user_marshal
  3579. if ( fRepMarshal )
  3580. {
  3581. node_represent_as * pRepUser = (pRepresent) ? pRepresent
  3582. : pUserMarshal ;
  3583. if ( ulHandleKind == HDL_CTXT )
  3584. AcfError( pRepUser, this, MyContext, TRANSMIT_AS_CTXT_HANDLE, NULL );
  3585. // process the transmitted type
  3586. MyContext.SetAncestorBits( IN_REPRESENT_AS );
  3587. if ( pUserMarshal )
  3588. MyContext.SetAncestorBits( IN_USER_MARSHAL );
  3589. pParentCtxt->SetDescendantBits( HAS_REPRESENT_AS );
  3590. if ( !pRepUser->GetRepresentationType() )
  3591. {
  3592. pParentCtxt->SetDescendantBits( HAS_UNSAT_REP_AS );
  3593. if ( pCommand->NeedsNDR64Run() )
  3594. {
  3595. AcfError( pRepUser, this, MyContext, UNSPECIFIED_REP_OR_UMRSHL_IN_NDR64, NULL );
  3596. }
  3597. }
  3598. if ( pUserMarshal )
  3599. {
  3600. // Check the transmitted type.
  3601. SemanticAnalysisForWireMarshal( &MyContext, FALSE );
  3602. }
  3603. else if ( pRepresent )
  3604. {
  3605. // Check the transmitted type.
  3606. SemanticAnalysisForTransmit( &MyContext, FALSE );
  3607. }
  3608. // since the base type is not transmitted, we aren't really
  3609. // in an rpc after here
  3610. }
  3611. // make checks for encode/decode
  3612. if ( fEncodeDecode )
  3613. {
  3614. if ( MyContext.AnyDescendantBits( HAS_DIRECT_CONF_OR_VAR ) )
  3615. TypeSemError( this, MyContext, ENCODE_CONF_OR_VAR, NULL );
  3616. }
  3617. // process handles
  3618. if ( ulHandleKind != HDL_NONE)
  3619. {
  3620. if ( ulHandleKind == HDL_GEN )
  3621. {
  3622. if ( MyContext.AnyDescendantBits( DERIVES_FROM_VOID ) )
  3623. TypeSemError( this, MyContext, GENERIC_HDL_VOID, NULL );
  3624. if ( MyContext.AnyDescendantBits( HAS_TRANSMIT_AS ) )
  3625. TypeSemError( this, MyContext, GENERIC_HANDLE_XMIT_AS, NULL );
  3626. if ( MyContext.AnyAncestorBits( IN_INTERPRET ) &&
  3627. ( GetChild()->GetSize() > (unsigned long)(SIZEOF_MEM_PTR()) ) )
  3628. {
  3629. if ( pCommand->NeedsNDR64Run() )
  3630. TypeSemError( this, MyContext, UNSUPPORTED_LARGE_GENERIC_HANDLE, NULL );
  3631. else
  3632. MyContext.SetDescendantBits( HAS_TOO_BIG_HDL );
  3633. }
  3634. }
  3635. if ( ulHandleKind == HDL_CTXT )
  3636. {
  3637. MyContext.SetDescendantBits( HAS_CONTEXT_HANDLE );
  3638. if ( GetBasicType()->NodeKind() != NODE_POINTER )
  3639. TypeSemError( this, MyContext, CTXT_HDL_NON_PTR, NULL );
  3640. }
  3641. MyContext.SetDescendantBits( HAS_HANDLE );
  3642. WALK_CTXT * pParamCtxt = (SEM_ANALYSIS_CTXT *)
  3643. MyContext.GetParentContext();
  3644. node_param * pParamNode;
  3645. node_skl * pCurNode;
  3646. short PtrDepth = 0;
  3647. // this returns NULL if no appropriate ancestor found
  3648. while ( pParamCtxt )
  3649. {
  3650. pCurNode = pParamCtxt->GetParent();
  3651. if ( pCurNode->NodeKind() == NODE_PARAM )
  3652. break;
  3653. if ( ( pCurNode->NodeKind() == NODE_DEF ) &&
  3654. pCurNode->FInSummary( ATTR_TRANSMIT ) )
  3655. {
  3656. pParamCtxt = NULL;
  3657. break;
  3658. }
  3659. if ( pCurNode->NodeKind() == NODE_POINTER )
  3660. {
  3661. PtrDepth ++;
  3662. if ( MyContext.AllAncestorBits( IN_RPC | IN_FUNCTION_RESULT ) )
  3663. {
  3664. SemError( this, MyContext, CTXT_HDL_MUST_BE_DIRECT_RETURN, NULL );
  3665. pParamCtxt = NULL;
  3666. break;
  3667. }
  3668. }
  3669. pParamCtxt = (SEM_ANALYSIS_CTXT *)pParamCtxt->GetParentContext();
  3670. }
  3671. pParamNode = (pParamCtxt) ? (node_param *) pParamCtxt->GetParent() : NULL;
  3672. // stuff handle info into our param node
  3673. if ( pParamNode )
  3674. pParamNode->HandleKind = ulHandleKind;
  3675. // out context/generic handles must be two levels deep
  3676. if ( pParamCtxt &&
  3677. MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) &&
  3678. ( PtrDepth < 1 ) )
  3679. TypeSemError( this, MyContext, OUT_CONTEXT_GENERIC_HANDLE, NULL );
  3680. }
  3681. if ( IsHResultOrSCode() )
  3682. {
  3683. MyContext.SetDescendantBits( HAS_HRESULT );
  3684. }
  3685. // don't propogate info here from below if we had transmit_as,
  3686. // it is propogated above...
  3687. if ( fPropogateChild )
  3688. {
  3689. pParentCtxt->ReturnValues( MyContext );
  3690. }
  3691. // set the DontCallFreeInst flag on the param
  3692. if ( ( pTransmit || pRepresent ) &&
  3693. fInRpc &&
  3694. MyContext.AllAncestorBits( IN_PARAM_LIST ) &&
  3695. !MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) )
  3696. {
  3697. // look up the context stack. If any non-pointer, non-def found,
  3698. // set the fDontCallFreeInst flag on the param
  3699. MarkDontCallFreeInst( &MyContext );
  3700. }
  3701. }
  3702. // look up the context stack. If any non-pointer, non-def found,
  3703. // set the fDontCallFreeInst flag on the param
  3704. void
  3705. node_def::MarkDontCallFreeInst( SEM_ANALYSIS_CTXT * pCtxt )
  3706. {
  3707. SEM_ANALYSIS_CTXT * pCurCtxt = pCtxt;
  3708. node_skl * pCurNode;
  3709. NODE_T Kind;
  3710. unsigned long MarkIt = 2;
  3711. for(;;)
  3712. {
  3713. pCurCtxt = (SEM_ANALYSIS_CTXT *) pCurCtxt->GetParentContext();
  3714. pCurNode = pCurCtxt->GetParent();
  3715. Kind = pCurNode->NodeKind();
  3716. switch ( Kind )
  3717. {
  3718. case NODE_DEF:
  3719. case NODE_POINTER:
  3720. break;
  3721. case NODE_PARAM:
  3722. // if we only found defs and pointers, this will
  3723. // leave it unchanged
  3724. ((node_param *)pCurNode)->fDontCallFreeInst |= MarkIt;
  3725. return;
  3726. default:
  3727. MarkIt = 1;
  3728. break;
  3729. }
  3730. }
  3731. }
  3732. // interface nodes have two entries on the context stack;
  3733. // one for the interface node, and one for info to pass to
  3734. // the children
  3735. void
  3736. node_interface::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  3737. {
  3738. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  3739. MEM_ITER MemList( this );
  3740. named_node* pN;
  3741. SEM_ANALYSIS_CTXT ChildCtxt( &MyContext );
  3742. BOOL IsLocal = MyContext.FInSummary( ATTR_LOCAL );
  3743. BOOL HasGuid = MyContext.FInSummary( ATTR_GUID );
  3744. BOOL IsObject = MyContext.FInSummary( ATTR_OBJECT );
  3745. BOOL fEncode = MyContext.FInSummary( ATTR_ENCODE );
  3746. BOOL fDecode = MyContext.FInSummary( ATTR_DECODE );
  3747. BOOL IsPickle = fEncode || fDecode;
  3748. BOOL HasVersion = MyContext.FInSummary( ATTR_VERSION );
  3749. BOOL IsIUnknown = FALSE;
  3750. BOOL fAuto = MyContext.FInSummary( ATTR_AUTO );
  3751. BOOL fCode = MyContext.FInSummary( ATTR_CODE );
  3752. BOOL fNoCode = MyContext.FInSummary( ATTR_NOCODE );
  3753. fHasMSConfStructAttr = fHasMSConfStructAttr || MyContext.ExtractAttribute( ATTR_MS_CONF_STRUCT ) != 0;
  3754. node_implicit* pImplicit = ( node_implicit* ) MyContext.GetAttribute( ATTR_IMPLICIT );
  3755. acf_attr* pExplicit = ( acf_attr* ) MyContext.GetAttribute( ATTR_EXPLICIT );
  3756. node_optimize* pOptAttr = 0;
  3757. bool fAnalizeAsyncIf = false;
  3758. node_cs_tag_rtn* pCSTagAttr = 0;
  3759. // [message] only allowed in ORPC interfaces and RPC procs.
  3760. node_base_attr* pTemp = MyContext.GetAttribute( ATTR_MESSAGE );
  3761. if ( pTemp )
  3762. {
  3763. if ( !IsObject )
  3764. {
  3765. SemError(
  3766. this,
  3767. MyContext,
  3768. INAPPLICABLE_ATTRIBUTE,
  3769. pTemp->GetNodeNameString()
  3770. );
  3771. }
  3772. ChildCtxt.SetAncestorBits( HAS_MESSAGE );
  3773. }
  3774. // process async_uuid before doing anything
  3775. if ( !IsAsyncClone() )
  3776. {
  3777. node_guid* pAsyncGuid = (node_guid*) MyContext.GetAttribute( ATTR_ASYNCUUID );
  3778. if ( pAsyncGuid )
  3779. {
  3780. if ( GetDefiningFile()->GetImportLevel() == 0 )
  3781. {
  3782. pCommand->GetNdrVersionControl().SetHasAsyncUUID();
  3783. }
  3784. ChildCtxt.SetAncestorBits( HAS_ASYNC_UUID );
  3785. // async_uuid can only be applied to an object interface.
  3786. if ( !IsObject || !pBaseIntf )
  3787. {
  3788. SemError(
  3789. this,
  3790. MyContext,
  3791. INAPPLICABLE_ATTRIBUTE,
  3792. pAsyncGuid->GetNodeNameString()
  3793. );
  3794. }
  3795. if ( !GetAsyncInterface() )
  3796. {
  3797. // duplicate this interface and split its methods
  3798. SetAsyncInterface( CloneIFAndSplitMethods( this ) );
  3799. if ( GetAsyncInterface() )
  3800. {
  3801. fAnalizeAsyncIf = true;
  3802. GetAsyncInterface()->SetIsAsyncClone();
  3803. }
  3804. }
  3805. }
  3806. }
  3807. else
  3808. {
  3809. // This is the cloned interface, don't clone it again.
  3810. ChildCtxt.SetAncestorBits( HAS_ASYNC_UUID );
  3811. }
  3812. while( MyContext.ExtractAttribute(ATTR_CUSTOM) )
  3813. ;
  3814. MyContext.ExtractAttribute( ATTR_TYPEDESCATTR );
  3815. MyContext.ExtractAttribute( ATTR_HIDDEN );
  3816. MyContext.ExtractAttribute( ATTR_VERSION );
  3817. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  3818. MyContext.ExtractAttribute( ATTR_HELPSTRINGCONTEXT );
  3819. MyContext.ExtractAttribute( ATTR_HELPCONTEXT );
  3820. MyContext.ExtractAttribute( ATTR_LCID );
  3821. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  3822. {
  3823. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  3824. }
  3825. // don't pass the interface attributes down directly...
  3826. // pass them down elsewhere
  3827. ChildCtxt.SetInterfaceContext( &MyContext );
  3828. //
  3829. // check the interface attributes
  3830. //
  3831. // make sure we only get analyzed once when object interfaces
  3832. // check their inherited info
  3833. if ( fSemAnalyzed )
  3834. return;
  3835. fSemAnalyzed = TRUE;
  3836. #ifdef gajgaj
  3837. // look for pointer default
  3838. if ( !FInSummary( ATTR_PTR_KIND ) &&
  3839. MyContext.AnyAncestorBits( IN_INTERFACE ) )
  3840. {
  3841. RpcSemError(this, MyContext, NO_PTR_DEFAULT_ON_INTERFACE, NULL );
  3842. }
  3843. #endif // gajgaj
  3844. // must have exactly one of [local] or [UUID]
  3845. if (IsLocal && HasGuid && !IsObject )
  3846. {
  3847. SemError( this, MyContext, UUID_LOCAL_BOTH_SPECIFIED, NULL );
  3848. }
  3849. // object interface error checking
  3850. if ( IsObject )
  3851. {
  3852. MyContext.SetAncestorBits( IN_OBJECT_INTF );
  3853. ChildCtxt.SetAncestorBits( IN_OBJECT_INTF );
  3854. if ( HasVersion )
  3855. {
  3856. SemError( this, MyContext, OBJECT_WITH_VERSION, NULL );
  3857. }
  3858. }
  3859. // make sure the uuid is unique
  3860. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  3861. // make sure the UUID is unique
  3862. if ( pGuid )
  3863. {
  3864. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  3865. if ( pDuplicate )
  3866. {
  3867. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  3868. }
  3869. }
  3870. /////////////////////////////////////////////////////////////////////
  3871. //Check the base interface
  3872. if (pBaseIntf)
  3873. {
  3874. if ( !IsObject && !MyContext.AnyAncestorBits(IN_LIBRARY))
  3875. {
  3876. SemError( this, MyContext, ILLEGAL_INTERFACE_DERIVATION, NULL );
  3877. }
  3878. ChildCtxt.SetAncestorBits( IN_BASE_CLASS );
  3879. pBaseIntf->SemanticAnalysis( &ChildCtxt );
  3880. if ( ChildCtxt.AnyDescendantBits( HAS_INCOMPLETE_TYPE ) )
  3881. {
  3882. SemError( pBaseIntf, ChildCtxt, UNRESOLVED_TYPE, pBaseIntf->GetSymName() );
  3883. }
  3884. else
  3885. {
  3886. if ( pBaseIntf->NodeKind() != NODE_INTERFACE_REFERENCE && pBaseIntf->NodeKind() != NODE_HREF )
  3887. {
  3888. SemError( this, MyContext, ILLEGAL_BASE_INTERFACE, NULL );
  3889. }
  3890. node_interface* pRealBaseIf = ( ( node_interface_reference* ) pBaseIntf )->GetRealInterface();
  3891. // verify the base interface is really an interface.
  3892. if ( pRealBaseIf == NULL || ( pRealBaseIf->NodeKind() != NODE_INTERFACE &&
  3893. pRealBaseIf->NodeKind() != NODE_DISPINTERFACE ) )
  3894. {
  3895. SemError( this, MyContext, ILLEGAL_BASE_INTERFACE, NULL );
  3896. }
  3897. if ( fAnalizeAsyncIf )
  3898. {
  3899. if ( pBaseIntf->NodeKind() != NODE_INTERFACE_REFERENCE )
  3900. {
  3901. SemError( this, MyContext, ILLEGAL_BASE_INTERFACE, NULL );
  3902. }
  3903. else
  3904. {
  3905. node_interface* pRealBaseIf = ( ( node_interface_reference* ) pBaseIntf )->GetRealInterface();
  3906. if ( !pRealBaseIf->GetAsyncInterface() && strcmp( pRealBaseIf->GetSymName(), "IUnknown" ) )
  3907. {
  3908. SemError( this, MyContext, ILLEGAL_BASE_INTERFACE, NULL );
  3909. }
  3910. }
  3911. }
  3912. if ( pBaseIntf->NodeKind() == NODE_INTERFACE_REFERENCE && HasGuid )
  3913. {
  3914. node_interface* pRealBaseIf = ( ( node_interface_reference* ) pBaseIntf )->GetRealInterface();
  3915. if ( pRealBaseIf )
  3916. {
  3917. node_guid * pNodeGuid = (node_guid *) pRealBaseIf->GetAttribute( ATTR_GUID );
  3918. if ( pNodeGuid )
  3919. {
  3920. GUID thisGuid;
  3921. pGuid->GetGuid( thisGuid );
  3922. GUID baseIFGuid;
  3923. pNodeGuid->GetGuid( baseIFGuid );
  3924. if ( !IsAnyIAdviseSinkIID( thisGuid ) )
  3925. {
  3926. if ( IsAnyIAdviseSinkIID( baseIFGuid ) )
  3927. {
  3928. SemError( this, MyContext, CANNOT_INHERIT_IADVISESINK, pBaseIntf->GetSymName() );
  3929. }
  3930. }
  3931. else
  3932. {
  3933. ChildCtxt.SetAncestorBits( IN_IADVISESINK );
  3934. }
  3935. }
  3936. }
  3937. }
  3938. }
  3939. // note that the above deletes intervening forwards
  3940. ChildCtxt.ClearAncestorBits( IN_BASE_CLASS );
  3941. }
  3942. if ( IsValidRootInterface() )
  3943. {
  3944. ChildCtxt.SetAncestorBits( IN_ROOT_CLASS );
  3945. IsIUnknown = TRUE;
  3946. }
  3947. if ( IsObject && !pBaseIntf && !IsIUnknown && !MyContext.AnyAncestorBits(IN_LIBRARY))
  3948. {
  3949. SemError( pBaseIntf, MyContext, ILLEGAL_INTERFACE_DERIVATION, NULL );
  3950. }
  3951. // our optimization is controlled either here or for the whole compile
  3952. if ( IsAsyncClone() )
  3953. {
  3954. SetOptimizationFlags( OPTIMIZE_ALL_I2_FLAGS );
  3955. }
  3956. else
  3957. {
  3958. if ( ( pOptAttr = (node_optimize *) GetAttribute( ATTR_OPTIMIZE ) ) != 0 )
  3959. {
  3960. SetOptimizationFlags( pOptAttr->GetOptimizationFlags() );
  3961. SetOptimizationLevel( pOptAttr->GetOptimizationLevel() );
  3962. }
  3963. else
  3964. {
  3965. SetOptimizationFlags( pCommand->GetOptimizationFlags() );
  3966. SetOptimizationLevel( pCommand->GetOptimizationLevel() );
  3967. }
  3968. }
  3969. if ( MyContext.FInSummary( ATTR_NOCODE ) &&
  3970. pCommand->GenerateSStub() &&
  3971. !pCommand->IsSwitchDefined( SWITCH_MS_EXT ) )
  3972. {
  3973. SemError( this, MyContext, NOCODE_WITH_SERVER_STUBS, NULL );
  3974. }
  3975. if ( IsPickle && pCommand->IsSwitchDefined( SWITCH_ROBUST ) )
  3976. {
  3977. if ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 )
  3978. {
  3979. pCommand->GetNdrVersionControl().SetHasOicfPickling();
  3980. }
  3981. else
  3982. {
  3983. SemError(this, MyContext, ROBUST_PICKLING_NO_OICF, 0);
  3984. }
  3985. }
  3986. BOOL HasCommFault = MyContext.FInSummary( ATTR_COMMSTAT )
  3987. || MyContext.FInSummary( ATTR_FAULTSTAT );
  3988. if ( HasCommFault )
  3989. {
  3990. if ( ! ( GetOptimizationFlags() & OPTIMIZE_INTERPRETER_V2 ) )
  3991. {
  3992. SemError( this, MyContext, COMMFAULT_PICKLING_NO_OICF, 0 );
  3993. if ( pCommand->GetTargetSystem() == NT40 )
  3994. SemError( this, MyContext, INVALID_FEATURE_FOR_TARGET, ":oicf pickling" );
  3995. }
  3996. }
  3997. // mark the interface as a pickle interface
  3998. if ( IsPickle )
  3999. SetPickleInterface();
  4000. // default the handle type, if needed
  4001. if ( !IsObject && !pImplicit && !pExplicit && !fAuto && !IsLocal )
  4002. {
  4003. if ( IsPickleInterface() )
  4004. {
  4005. pExplicit = new acf_attr( ATTR_EXPLICIT );
  4006. SetAttribute( pExplicit );
  4007. }
  4008. else
  4009. {
  4010. fAuto = TRUE;
  4011. SetAttribute( new acf_attr( ATTR_AUTO ) );
  4012. }
  4013. }
  4014. // make sure no pickle w/ auto handle
  4015. if ( IsPickleInterface() )
  4016. {
  4017. ChildCtxt.SetAncestorBits( IN_ENCODE_INTF );
  4018. if ( fAuto )
  4019. SemError( this, MyContext, ENCODE_AUTO_HANDLE, NULL );
  4020. }
  4021. // check for handle conflicts
  4022. if ( ( fAuto && pImplicit ) ||
  4023. ( fAuto && pExplicit ) ||
  4024. ( pImplicit && pExplicit ) )
  4025. SemError( this, MyContext, CONFLICTING_INTF_HANDLES, NULL );
  4026. if ( pImplicit )
  4027. {
  4028. node_id * pID;
  4029. node_skl * pType;
  4030. pImplicit->ImplicitHandleDetails( &pType, &pID );
  4031. char* szName = pType->GetNonDefSelf()->GetSymName();
  4032. if ( pImplicit->IsHandleTypeDefined() )
  4033. {
  4034. if ( !pType->FInSummary( ATTR_HANDLE ) &&
  4035. strcmp( szName, "handle_t" ) &&
  4036. !pID->FInSummary( ATTR_HANDLE ) )
  4037. {
  4038. SemError( this, MyContext, IMPLICIT_HANDLE_NON_HANDLE, NULL );
  4039. }
  4040. }
  4041. else
  4042. {
  4043. if ( !pID->FInSummary( ATTR_HANDLE ) )
  4044. SemError( this, MyContext, IMPLICIT_HDL_ASSUMED_GENERIC, NULL );
  4045. }
  4046. }
  4047. if ( fAuto )
  4048. {
  4049. ChildCtxt.SetAncestorBits( HAS_AUTO_HANDLE );
  4050. }
  4051. else if ( pExplicit )
  4052. {
  4053. ChildCtxt.SetAncestorBits( HAS_EXPLICIT_HANDLE );
  4054. }
  4055. else if ( pImplicit )
  4056. {
  4057. ChildCtxt.SetAncestorBits( HAS_IMPLICIT_HANDLE );
  4058. }
  4059. // check for illegal type attributes
  4060. node_type_attr * pTA;
  4061. BOOL fIsDual = FALSE;
  4062. while ( ( pTA = (node_type_attr *)MyContext.ExtractAttribute(ATTR_TYPE) ) != 0 )
  4063. {
  4064. switch (pTA->GetAttr())
  4065. {
  4066. // acceptable attributes
  4067. case TATTR_DUAL:
  4068. fIsDual = TRUE;
  4069. // fall through
  4070. case TATTR_OLEAUTOMATION:
  4071. HasOLEAutomation(TRUE);
  4072. break;
  4073. case TATTR_PROXY:
  4074. case TATTR_PUBLIC:
  4075. case TATTR_NONEXTENSIBLE:
  4076. break;
  4077. // unacceptable attributes
  4078. case TATTR_CONTROL:
  4079. case TATTR_LICENSED:
  4080. {
  4081. char * pAttrName = pTA->GetNodeNameString();
  4082. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  4083. break;
  4084. }
  4085. case TATTR_APPOBJECT:
  4086. case TATTR_NONCREATABLE:
  4087. case TATTR_AGGREGATABLE:
  4088. {
  4089. char * pAttrName = pTA->GetNodeNameString();
  4090. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  4091. break;
  4092. }
  4093. }
  4094. }
  4095. if (HasOLEAutomation())
  4096. {
  4097. node_interface* pUltimate = 0;
  4098. node_interface* pIntf = this;
  4099. STATUS_T ErrorCode = NOT_OLEAUTOMATION_INTERFACE;
  4100. while ( pIntf )
  4101. {
  4102. pUltimate = pIntf;
  4103. pIntf = pIntf->GetMyBaseInterface();
  4104. if ( !pUltimate->IsValidRootInterface() )
  4105. {
  4106. // pUltimate is not IUnknown. If it is not a IDispatch either, it is not
  4107. // an oleautomation compliant interface.
  4108. char* szName = pUltimate->GetSymName();
  4109. if ( _stricmp(szName, "IDispatch") == 0 )
  4110. {
  4111. ErrorCode = STATUS_OK;
  4112. break;
  4113. }
  4114. }
  4115. else
  4116. {
  4117. // IUnknown could be OLEAUTOMATION compatible, but not DUAL
  4118. if ( fIsDual )
  4119. ErrorCode = NOT_DUAL_INTERFACE;
  4120. else
  4121. ErrorCode = STATUS_OK;
  4122. break;
  4123. }
  4124. }
  4125. if ( ErrorCode != STATUS_OK )
  4126. SemError( this, MyContext, ErrorCode, GetSymName() );
  4127. ChildCtxt.SetAncestorBits( HAS_OLEAUTOMATION );
  4128. }
  4129. // check for illegal member attributes
  4130. node_member_attr * pMA;
  4131. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  4132. {
  4133. switch (pMA->GetAttr())
  4134. {
  4135. case MATTR_RESTRICTED:
  4136. break;
  4137. case MATTR_DEFAULTVTABLE:
  4138. case MATTR_SOURCE:
  4139. {
  4140. if ( MyContext.AnyAncestorBits( IN_COCLASS ) )
  4141. // [source] and [defaultvtable] are only allowed on
  4142. // interface's defined as members of coclasses.
  4143. break;
  4144. // illegal attribute, so fall through
  4145. }
  4146. case MATTR_READONLY:
  4147. {
  4148. char * pAttrName = pMA->GetNodeNameString();
  4149. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  4150. break;
  4151. }
  4152. case MATTR_BINDABLE:
  4153. case MATTR_DISPLAYBIND:
  4154. case MATTR_DEFAULTBIND:
  4155. case MATTR_REQUESTEDIT:
  4156. case MATTR_PROPGET:
  4157. case MATTR_PROPPUT:
  4158. case MATTR_PROPPUTREF:
  4159. case MATTR_OPTIONAL:
  4160. case MATTR_RETVAL:
  4161. case MATTR_VARARG:
  4162. case MATTR_PREDECLID:
  4163. case MATTR_UIDEFAULT:
  4164. case MATTR_NONBROWSABLE:
  4165. case MATTR_DEFAULTCOLLELEM:
  4166. case MATTR_IMMEDIATEBIND:
  4167. case MATTR_USESGETLASTERROR:
  4168. case MATTR_REPLACEABLE:
  4169. {
  4170. char * pAttrName = pMA->GetNodeNameString();
  4171. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  4172. break;
  4173. }
  4174. }
  4175. }
  4176. node_base_attr* pAttrAsync = MyContext.ExtractAttribute( ATTR_ASYNC );
  4177. if ( pAttrAsync )
  4178. {
  4179. if ( !pAttrAsync->IsAcfAttr() )
  4180. {
  4181. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  4182. }
  4183. if ( fCode || fNoCode || IsLocal || pOptAttr || IsObject || HasOLEAutomation() )
  4184. {
  4185. SemError( this, MyContext, ILLEGAL_COMBINATION_OF_ATTRIBUTES, 0 );
  4186. }
  4187. ChildCtxt.SetAncestorBits( HAS_ASYNCHANDLE );
  4188. }
  4189. pCSTagAttr = ( node_cs_tag_rtn *) MyContext.ExtractAttribute( ATTR_CSTAGRTN );
  4190. ////////////////////////////////////////////////////////////////////////
  4191. // process all the children of the interface
  4192. //
  4193. while ( ( pN = MemList.GetNext() ) != 0 )
  4194. {
  4195. pN->SemanticAnalysis( &ChildCtxt );
  4196. // Set the cs tag routine for the proc if it needs one and doesn't
  4197. // have one yet
  4198. if ( NODE_PROC == pN->NodeKind() )
  4199. {
  4200. node_proc *pProc = ( node_proc * ) pN;
  4201. if ( ChildCtxt.AnyDescendantBits( HAS_IN_CSTYPE | HAS_OUT_CSTYPE )
  4202. && ( NULL == pProc->GetCSTagRoutine() )
  4203. && ( NULL != pCSTagAttr ) )
  4204. {
  4205. pProc->SetCSTagRoutine( pCSTagAttr->GetCSTagRoutine() );
  4206. }
  4207. }
  4208. }
  4209. // make sure we had some rpc-able routines
  4210. if ( IsObject )
  4211. {
  4212. //UUID must be specified on object procs.
  4213. if( !HasGuid )
  4214. {
  4215. SemError( this, MyContext, NO_UUID_SPECIFIED, NULL );
  4216. }
  4217. }
  4218. else if( MyContext.AnyAncestorBits( IN_INTERFACE ) &&
  4219. pCommand->GenerateStubs() &&
  4220. !IsLocal )
  4221. {
  4222. if ( ProcCount == 0 )
  4223. {
  4224. if ( !IsPickleInterface() &&
  4225. !IsObject )
  4226. {
  4227. if (CallBackProcCount == 0 )
  4228. {
  4229. SemError( this, MyContext, NO_REMOTE_PROCS_NO_STUBS, NULL );
  4230. }
  4231. else
  4232. {
  4233. SemError( this, MyContext, INTERFACE_ONLY_CALLBACKS, NULL );
  4234. }
  4235. }
  4236. }
  4237. else
  4238. {
  4239. //UUID must be specified when interface has remote procs.
  4240. if( !HasGuid )
  4241. {
  4242. SemError( this, MyContext, NO_UUID_SPECIFIED, NULL );
  4243. }
  4244. }
  4245. }
  4246. if (pExplicit && MyContext.AnyAncestorBits( IN_LIBRARY ))
  4247. {
  4248. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, NULL);
  4249. }
  4250. if (fCode && fNoCode)
  4251. {
  4252. SemError(this, MyContext, CODE_NOCODE_CONFLICT, NULL);
  4253. }
  4254. if ( IsObject )
  4255. {
  4256. unsigned short uProcCount = GetProcCount();
  4257. if ( GetFileNode() && GetFileNode()->GetImportLevel() > 0 )
  4258. {
  4259. if ( uProcCount > 64 && uProcCount <= 256 )
  4260. {
  4261. pCommand->GetNdrVersionControl().SetHasMoreThan64DelegatedProcs();
  4262. }
  4263. else if ( uProcCount > 256 )
  4264. {
  4265. SemError(this, MyContext, TOO_MANY_DELEGATED_PROCS, NULL);
  4266. }
  4267. }
  4268. // method limits apply only to stubless proxies. /Oicf not /Oi or /Os
  4269. /*
  4270. < 32 Windows NT 3.51-
  4271. 32 - 110 Windows NT 4.0
  4272. 110 - 512 Windows NT 4.0 SP3
  4273. > 512 Windows 2000
  4274. */
  4275. unsigned short uOpt = GetOptimizationFlags();
  4276. if ( GetFileNode() && GetFileNode()->GetImportLevel() == 0 && ( uOpt & OPTIMIZE_STUBLESS_CLIENT ) )
  4277. {
  4278. if ( (uProcCount > 512) && MyContext.AnyAncestorBits(IN_LIBRARY))
  4279. {
  4280. SemError(this, MyContext, TOO_MANY_PROCS, 0);
  4281. pCommand->GetNdrVersionControl().SetHasNT5VTableSize();
  4282. }
  4283. else if ( (uProcCount > 110) && (uProcCount <= 512) && MyContext.AnyAncestorBits(IN_LIBRARY))
  4284. {
  4285. SemError(this, MyContext, TOO_MANY_PROCS_FOR_NT4, 0);
  4286. pCommand->GetNdrVersionControl().SetHasNT43VTableSize();
  4287. }
  4288. else if ( uProcCount > 32 && uProcCount <= 110 )
  4289. {
  4290. pCommand->GetNdrVersionControl().SetHasNT4VTableSize();
  4291. }
  4292. }
  4293. }
  4294. if ( GetAsyncInterface() && fAnalizeAsyncIf )
  4295. {
  4296. GetAsyncInterface()->SemanticAnalysis( pParentCtxt );
  4297. }
  4298. MyContext.ReturnValues(ChildCtxt);
  4299. // consume all the interface attributes
  4300. MyContext.ClearAttributes();
  4301. pParentCtxt->ReturnValues( MyContext );
  4302. }
  4303. // a reference to an interface...
  4304. //Check for ms_ext mode.
  4305. //Check if the interface has the [object] attribute
  4306. //if used in an RPC, the parent must be a pointer.
  4307. void
  4308. node_interface_reference::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  4309. {
  4310. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  4311. CheckDeclspecAlign( MyContext );
  4312. // see if we are detecting class dependencies
  4313. if ( MyContext.AnyAncestorBits( IN_BASE_CLASS ) )
  4314. {
  4315. if ( !GetRealInterface()->FInSummary( ATTR_OBJECT ) && !MyContext.AnyAncestorBits(IN_LIBRARY))
  4316. {
  4317. SemError( this, MyContext, ILLEGAL_INTERFACE_DERIVATION, NULL );
  4318. }
  4319. // fetch my interface's BaseInteraceReference
  4320. named_node * pBaseClass = GetMyBaseInterfaceReference();
  4321. if ( pBaseClass )
  4322. {
  4323. if ( MyContext.FindRecursiveContext( pBaseClass ) )
  4324. SemError( this, MyContext, CIRCULAR_INTERFACE_DEPENDENCY, NULL);
  4325. else
  4326. {
  4327. // make sure our base class got analyzed
  4328. SEM_ANALYSIS_CTXT BaseContext( this, &MyContext );
  4329. BaseContext.ClearAncestorBits( IN_BASE_CLASS | IN_INTERFACE );
  4330. BaseContext.SetInterfaceContext( &BaseContext );
  4331. GetRealInterface()->SemanticAnalysis( &BaseContext );
  4332. pBaseClass->SemanticAnalysis( &MyContext );
  4333. }
  4334. }
  4335. else // root base class
  4336. {
  4337. if ( !GetRealInterface()->IsValidRootInterface() && !MyContext.AnyAncestorBits(IN_LIBRARY))
  4338. SemError( this, MyContext, NOT_VALID_AS_BASE_INTF, NULL );
  4339. }
  4340. }
  4341. else if ( ( pParentCtxt->GetParent()->NodeKind() == NODE_FORWARD ) &&
  4342. ( pParentCtxt->GetParentContext()->GetParent()->IsInterfaceOrObject() ) )
  4343. {
  4344. // we are an interface forward decl
  4345. }
  4346. else // we are at an interface pointer
  4347. {
  4348. node_interface * pIntf = GetRealInterface();
  4349. if ( !MyContext.AnyAncestorBits( IN_POINTER ) && !MyContext.AnyAncestorBits( IN_LIBRARY ))
  4350. {
  4351. SemError( this, MyContext, INTF_NON_POINTER, NULL );
  4352. }
  4353. if ( !pIntf->FInSummary( ATTR_GUID ) )
  4354. {
  4355. SemError( this, MyContext, PTR_INTF_NO_GUID, NULL );
  4356. }
  4357. MyContext.SetDescendantBits( HAS_INTERFACE_PTR );
  4358. }
  4359. pParentCtxt->ReturnValues( MyContext );
  4360. return;
  4361. };
  4362. void
  4363. node_source::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  4364. {
  4365. MEM_ITER MemIter( this );
  4366. node_skl * pN;
  4367. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  4368. while ( ( pN = MemIter.GetNext() ) != 0 )
  4369. {
  4370. pN->SemanticAnalysis( &MyContext );
  4371. }
  4372. pParentCtxt->ReturnValues( MyContext );
  4373. };
  4374. void
  4375. node_pointer::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  4376. {
  4377. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  4378. PTRTYPE PtrKind = PTR_UNKNOWN;
  4379. FIELD_ATTR_INFO FAInfo;
  4380. node_ptr_attr * pPAttr; // pointer attribute
  4381. node_byte_count * pCountAttr;
  4382. node_allocate * pAlloc;
  4383. BOOL fInterfacePtr = FALSE;
  4384. BOOL fUnderAPtr = MyContext.AnyAncestorBits( IN_POINTER | IN_ARRAY );
  4385. BOOL fIgnore;
  4386. BOOL fIsSizedPtr = FALSE;
  4387. if ( (GetChild()->NodeKind() == NODE_INTERFACE_REFERENCE ) ||
  4388. (GetChild()->NodeKind() == NODE_FORWARD &&
  4389. GetChild()->GetChild() &&
  4390. GetChild()->GetChild()->NodeKind() == NODE_INTERFACE_REFERENCE ) )
  4391. fInterfacePtr = TRUE;
  4392. // see if we have allocate
  4393. pAlloc = (node_allocate *) MyContext.ExtractAttribute( ATTR_ALLOCATE );
  4394. if ( HasCorrelation( this ) )
  4395. {
  4396. MyContext.IncCorrelationCount();
  4397. }
  4398. CheckDeclspecAlign( MyContext );
  4399. ////////////////////////////////////////////////////////////////////////
  4400. // process pointer attributes
  4401. BOOL fExplicitPtrAttr = FALSE;
  4402. PtrKind = MyContext.GetPtrKind( &fExplicitPtrAttr );
  4403. if ( PtrKind == PTR_FULL )
  4404. {
  4405. MyContext.SetDescendantBits( HAS_FULL_PTR );
  4406. }
  4407. if ( ( pPAttr = (node_ptr_attr *)MyContext.ExtractAttribute( ATTR_PTR_KIND) ) != 0 )
  4408. {
  4409. TypeSemError( this, MyContext, MORE_THAN_ONE_PTR_ATTR, NULL );
  4410. }
  4411. if ( MyContext.AnyAncestorBits( UNDER_PARTIAL_IGNORE_PARAM ) &&
  4412. ( PtrKind != PTR_UNIQUE ) )
  4413. {
  4414. TypeSemError( this, MyContext, PARTIAL_IGNORE_UNIQUE, NULL );
  4415. }
  4416. MyContext.ClearAncestorBits( UNDER_PARTIAL_IGNORE_PARAM );
  4417. // mark this pointer as ref or non-ref. This flag is only valid for the
  4418. // pointer nodes themselves.
  4419. if ( PtrKind == PTR_REF )
  4420. MyContext.ClearAncestorBits( IN_NON_REF_PTR );
  4421. else
  4422. MyContext.SetAncestorBits( IN_NON_REF_PTR );
  4423. // detect top level ref pointer on return type
  4424. if ( ( PtrKind == PTR_REF ) &&
  4425. MyContext.AllAncestorBits( IN_RPC | IN_FUNCTION_RESULT ) )
  4426. {
  4427. if (MyContext.FindNonDefAncestorContext()->GetParent()->NodeKind()
  4428. == NODE_PROC )
  4429. TypeSemError( this, MyContext, BAD_CON_REF_RT, NULL );
  4430. }
  4431. // unique or full pointer may not be out only
  4432. if ( ( PtrKind != PTR_REF ) &&
  4433. MyContext.AllAncestorBits( IN_RPC | IN_PARAM_LIST ) &&
  4434. !fUnderAPtr &&
  4435. !MyContext.AnyAncestorBits( UNDER_IN_PARAM |
  4436. IN_STRUCT | IN_UNION ))
  4437. TypeSemError( this, MyContext, UNIQUE_FULL_PTR_OUT_ONLY, NULL );
  4438. MyContext.SetAncestorBits( IN_POINTER );
  4439. // warn about OUT const things
  4440. if ( FInSummary( ATTR_CONST ) )
  4441. {
  4442. if ( MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) )
  4443. RpcSemError( this, MyContext, CONST_ON_OUT_PARAM, NULL );
  4444. else if ( MyContext.AnyAncestorBits( IN_FUNCTION_RESULT ) )
  4445. RpcSemError( this, MyContext, CONST_ON_RETVAL, NULL );
  4446. }
  4447. // ignore pointers do not need to be rpc-able
  4448. fIgnore = (NULL != MyContext.ExtractAttribute( ATTR_IGNORE ));
  4449. if ( fIgnore )
  4450. {
  4451. MyContext.ClearAncestorBits( IN_RPC );
  4452. }
  4453. ////////////////////////////////////////////////////////////////////////
  4454. // process field attributes
  4455. // see if we have any field attributes (are conformant or varying)
  4456. FAInfo.SetControl( TRUE, GetBasicType()->IsPtrOrArray() );
  4457. MyContext.ExtractFieldAttributes( &FAInfo );
  4458. FAInfo.Validate( &MyContext );
  4459. // ptr is conf or varying or conf/varying
  4460. if ( FAInfo.Kind & FA_CONFORMANT_VARYING )
  4461. {
  4462. fIsSizedPtr = TRUE;
  4463. }
  4464. switch ( FAInfo.Kind )
  4465. {
  4466. case FA_NONE:
  4467. {
  4468. break;
  4469. }
  4470. case FA_STRING:
  4471. {
  4472. // string attributes only allowed on char and wchar_t
  4473. if ( !GetBasicType()->IsStringableType() )
  4474. TypeSemError( this, MyContext, STRING_NOT_ON_BYTE_CHAR, NULL );
  4475. if ( MyContext.AllAncestorBits( UNDER_OUT_PARAM |
  4476. IN_PARAM_LIST | IN_RPC ) &&
  4477. !fUnderAPtr &&
  4478. !MyContext.AnyAncestorBits( IN_STRUCT | IN_UNION |
  4479. UNDER_IN_PARAM ) )
  4480. TypeSemError( this, MyContext, DERIVES_FROM_UNSIZED_STRING, NULL );
  4481. MyContext.SetDescendantBits( HAS_STRING );
  4482. // break; deliberate fall through to case below
  4483. }
  4484. case FA_VARYING:
  4485. {
  4486. MyContext.SetDescendantBits( HAS_VAR_PTR );
  4487. break;
  4488. }
  4489. case FA_CONFORMANT:
  4490. {
  4491. MyContext.SetDescendantBits( HAS_CONF_PTR );
  4492. break;
  4493. }
  4494. case FA_CONFORMANT_STRING:
  4495. {
  4496. // string attributes only allowed on char and wchar_t
  4497. if ( !GetBasicType()->IsStringableType() )
  4498. TypeSemError( this, MyContext, STRING_NOT_ON_BYTE_CHAR, NULL );
  4499. if ( FAInfo.StringKind == STR_BSTRING )
  4500. TypeSemError( this, MyContext, BSTRING_NOT_ON_PLAIN_PTR, NULL );
  4501. // break; deliberate fall through to case below
  4502. }
  4503. case FA_CONFORMANT_VARYING:
  4504. {
  4505. MyContext.SetDescendantBits( HAS_CONF_VAR_PTR );
  4506. break;
  4507. }
  4508. case FA_INTERFACE:
  4509. {
  4510. if ( !fInterfacePtr && (GetBasicType()->NodeKind() != NODE_VOID ) )
  4511. {
  4512. TypeSemError( this, MyContext, IID_IS_NON_POINTER, NULL );
  4513. }
  4514. fInterfacePtr = TRUE;
  4515. break;
  4516. }
  4517. default: // string + varying combinations
  4518. {
  4519. TypeSemError( this, MyContext, INVALID_SIZE_ATTR_ON_STRING, NULL );
  4520. break;
  4521. }
  4522. }
  4523. // tell our children we are constructing an interface pointer
  4524. if (fInterfacePtr)
  4525. MyContext.SetAncestorBits( IN_INTERFACE_PTR );
  4526. // interface pointer shouldn't have explicit pointer attributes
  4527. if ( fInterfacePtr && fExplicitPtrAttr &&
  4528. (PtrKind == PTR_FULL || PtrKind == PTR_REF ) )
  4529. {
  4530. TypeSemError( this, MyContext, INTF_EXPLICIT_PTR_ATTR, NULL );
  4531. }
  4532. // Non pipe [out] interface pointers must use double indirection.
  4533. // However, pipe interface pointers can use only a single indirection.
  4534. // Note that fInterfacePtr may be true for a void *.
  4535. if ( fInterfacePtr && MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) &&
  4536. !fUnderAPtr )
  4537. {
  4538. if ( GetChild()->NodeKind() == NODE_INTERFACE_REFERENCE )
  4539. TypeSemError( this, MyContext, NON_INTF_PTR_PTR_OUT, NULL );
  4540. }
  4541. if ( MyContext.FInSummary( ATTR_SWITCH_IS ) &&
  4542. ( FAInfo.Kind != FA_NONE) )
  4543. TypeSemError( this, MyContext, ARRAY_OF_UNIONS_ILLEGAL, NULL );
  4544. // see if a param or return type context attr reached us...
  4545. bool fSerialize = MyContext.ExtractAttribute( ATTR_SERIALIZE ) != 0;
  4546. bool fNoSerialize = MyContext.ExtractAttribute( ATTR_NOSERIALIZE ) != 0;
  4547. if ( MyContext.FInSummary( ATTR_CONTEXT ) )
  4548. {
  4549. if (GetBasicType()->NodeKind() != NODE_POINTER )
  4550. {
  4551. if ( fSerialize && fNoSerialize )
  4552. {
  4553. SemError( this, MyContext, CONFLICTING_ATTRIBUTES, GetSymName() );
  4554. }
  4555. MyContext.ExtractAttribute( ATTR_CONTEXT );
  4556. MyContext.SetDescendantBits( HAS_HANDLE | HAS_CONTEXT_HANDLE );
  4557. pParentCtxt->SetDescendantBits( HAS_HANDLE | HAS_CONTEXT_HANDLE );
  4558. MyContext.ClearAncestorBits( IN_RPC );
  4559. if (GetBasicType()->NodeKind() != NODE_VOID )
  4560. {
  4561. TypeSemError( this, MyContext, CONTEXT_HANDLE_VOID_PTR, NULL );
  4562. }
  4563. }
  4564. }
  4565. else
  4566. {
  4567. if ( fSerialize || fNoSerialize )
  4568. {
  4569. SemError( this, MyContext, NO_CONTEXT_HANDLE, GetSymName() );
  4570. }
  4571. }
  4572. // see if a byte_count reached us...
  4573. pCountAttr = (node_byte_count *)
  4574. MyContext.ExtractAttribute( ATTR_BYTE_COUNT );
  4575. if (pCountAttr)
  4576. {
  4577. // byte count error checking
  4578. if ( pCommand->NeedsNDR64Run() )
  4579. TypeSemError( this, MyContext, BYTE_COUNT_IN_NDR64, 0 );
  4580. node_param * pParam = pCountAttr->GetByteCountParam();
  4581. if ( !MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) ||
  4582. MyContext.AnyAncestorBits( UNDER_IN_PARAM ) )
  4583. {
  4584. TypeSemError( this, MyContext, BYTE_COUNT_NOT_OUT_PTR, 0 );
  4585. }
  4586. if ( !pParam || !pParam->FInSummary( ATTR_IN ) || pParam->FInSummary( ATTR_OUT ) )
  4587. TypeSemError( this, MyContext, BYTE_COUNT_PARAM_NOT_IN, 0 );
  4588. if ( pParam )
  4589. {
  4590. NODE_T nodeKind = pParam->GetBasicType()->NodeKind();
  4591. if ( nodeKind < NODE_HYPER || nodeKind > NODE_BYTE )
  4592. {
  4593. SemError( this, MyContext, BYTE_COUNT_PARAM_NOT_INTEGRAL, 0 );
  4594. }
  4595. }
  4596. if ( !pCommand->IsSwitchDefined( SWITCH_MS_EXT ) )
  4597. {
  4598. SemError( this, MyContext, BYTE_COUNT_INVALID, 0 );
  4599. }
  4600. if ( MyContext.AnyDescendantBits( HAS_CONF_VAR_PTR | HAS_VAR_PTR | HAS_CONF_PTR ) )
  4601. {
  4602. SemError( this, MyContext, BYTE_COUNT_INVALID, 0 );
  4603. }
  4604. }
  4605. if ( PtrKind == PTR_REF )
  4606. {
  4607. SEM_ANALYSIS_CTXT * pCtxt = (SEM_ANALYSIS_CTXT *)
  4608. MyContext.FindNonDefAncestorContext();
  4609. if ( ( pCtxt->GetParent()->NodeKind() == NODE_FIELD ) &&
  4610. ( pCtxt->GetParentContext()->GetParent()->NodeKind() == NODE_UNION ) )
  4611. TypeSemError( this, MyContext, REF_PTR_IN_UNION, NULL );
  4612. }
  4613. MyContext.ClearAncestorBits( IN_UNION | IN_NE_UNION | IN_ARRAY );
  4614. ////////////////////////////////////////////////////////////////////////
  4615. // finally, process the child
  4616. GetChild()->SemanticAnalysis( &MyContext );
  4617. // if the child and this node is a conf and/or varying pointer
  4618. if ( fIsSizedPtr )
  4619. {
  4620. if ( MyContext.AnyDescendantBits( HAS_SIZED_PTR ) )
  4621. {
  4622. MyContext.SetDescendantBits( HAS_MULTIDIM_VECTOR );
  4623. }
  4624. else
  4625. {
  4626. MyContext.SetDescendantBits( HAS_SIZED_PTR );
  4627. }
  4628. }
  4629. // allocate error checking
  4630. if ( pAlloc )
  4631. {
  4632. if ( MyContext.AnyDescendantBits( HAS_TRANSMIT_AS | HAS_REPRESENT_AS ) )
  4633. {
  4634. if ( MyContext.AnyAncestorBits( IN_RPC ) )
  4635. SemError( this, MyContext, ALLOCATE_ON_TRANSMIT_AS, NULL );
  4636. else
  4637. AcfError( pAlloc, this, MyContext, ALLOCATE_ON_TRANSMIT_AS, NULL );
  4638. }
  4639. if ( MyContext.AnyDescendantBits( HAS_HANDLE ) )
  4640. {
  4641. if ( MyContext.AnyAncestorBits( IN_RPC ) )
  4642. SemError( this, MyContext, ALLOCATE_ON_HANDLE, NULL );
  4643. else
  4644. AcfError( pAlloc, this, MyContext, ALLOCATE_ON_HANDLE, NULL );
  4645. }
  4646. // warn about allocate(all_nodes) with [in,out] parameter
  4647. if ( MyContext.AllAncestorBits( IN_RPC |
  4648. IN_PARAM_LIST |
  4649. UNDER_IN_PARAM |
  4650. UNDER_OUT_PARAM ) &&
  4651. ( pAlloc->GetAllocateDetails() & ALLOCATE_ALL_NODES ) )
  4652. {
  4653. SemError( this, MyContext, ALLOCATE_IN_OUT_PTR, NULL );
  4654. }
  4655. }
  4656. if ( fInterfacePtr )
  4657. MyContext.SetAncestorBits( IN_INTERFACE_PTR );
  4658. if ( MyContext.AnyDescendantBits( HAS_CONF_ARRAY |
  4659. HAS_CONF_VAR_ARRAY ) &&
  4660. !MyContext.AnyDescendantBits( HAS_ARRAY |
  4661. HAS_TRANSMIT_AS ) &&
  4662. MyContext.AllAncestorBits( IN_RPC | UNDER_OUT_PARAM ) &&
  4663. !MyContext.AnyAncestorBits( UNDER_IN_PARAM |
  4664. IN_ARRAY |
  4665. IN_STRUCT |
  4666. IN_UNION |
  4667. IN_TRANSMIT_AS |
  4668. IN_REPRESENT_AS ) &&
  4669. ( PtrKind == PTR_REF ) )
  4670. TypeSemError( this, MyContext, DERIVES_FROM_PTR_TO_CONF, NULL );
  4671. #if 0
  4672. if ( MyContext.AnyDescendantBits( HAS_DIRECT_CONF_OR_VAR ) )
  4673. {
  4674. TypeSemError( this, MyContext, ILLEGAL_CONFORMANT_ARRAY, NULL );
  4675. }
  4676. #endif
  4677. // incomplete types are OK below a pointer
  4678. // array characteristics blocked by pointer
  4679. MyContext.ClearDescendantBits( HAS_INCOMPLETE_TYPE
  4680. | HAS_RECURSIVE_DEF
  4681. | HAS_ARRAY
  4682. | HAS_VAR_ARRAY
  4683. | HAS_CONF_ARRAY
  4684. | HAS_CONF_VAR_ARRAY
  4685. | HAS_MULTIDIM_SIZING
  4686. | HAS_UNION
  4687. | HAS_STRUCT
  4688. | HAS_TRANSMIT_AS
  4689. | HAS_REPRESENT_AS
  4690. | HAS_UNSAT_REP_AS
  4691. | HAS_DIRECT_CONF_OR_VAR
  4692. | HAS_ENUM
  4693. | HAS_ARRAY_OF_REF
  4694. | HAS_CONTEXT_HANDLE
  4695. | HAS_HRESULT );
  4696. if ( !fInterfacePtr && !fIgnore )
  4697. MyContext.SetDescendantBits( HAS_POINTER );
  4698. if ( ( FAInfo.Kind != FA_NONE ) &&
  4699. ( FAInfo.Kind != FA_STRING ) &&
  4700. ( FAInfo.Kind != FA_INTERFACE ) )
  4701. MyContext.SetDescendantBits( HAS_DIRECT_CONF_OR_VAR );
  4702. if ( ( PtrKind == PTR_REF ) &&
  4703. ( MyContext.FindNonDefAncestorContext()
  4704. ->GetParent()->NodeKind() == NODE_ARRAY ) )
  4705. {
  4706. MyContext.SetDescendantBits( HAS_ARRAY_OF_REF );
  4707. }
  4708. #ifdef gajgaj
  4709. if ( (PtrKind != PTR_REF ) &&
  4710. MyContext.AnyDescendantBits( HAS_HANDLE ) &&
  4711. MyContext.AnyAncestorBits( IN_RPC ) )
  4712. TypeSemError( this, MyContext, PTR_TO_HDL_UNIQUE_OR_FULL, NULL );
  4713. #endif //gajgaj
  4714. if ( MyContext.AnyDescendantBits( HAS_IN_CSTYPE | HAS_OUT_CSTYPE ) )
  4715. {
  4716. if ( !FAInfo.VerifyOnlySimpleExpression() )
  4717. SemError( this, MyContext, CSCHAR_EXPR_MUST_BE_SIMPLE, NULL );
  4718. if ( FA_CONFORMANT == FAInfo.Kind )
  4719. SemError( this, MyContext, NO_CONFORMANT_CSCHAR, NULL );
  4720. if ( MyContext.AnyDescendantBits( HAS_MULTIDIM_SIZING
  4721. | HAS_MULTIDIM_VECTOR ) )
  4722. {
  4723. SemError( this, MyContext, NO_MULTIDIM_CSCHAR, NULL );
  4724. }
  4725. // We want to propagate the the descendant bits up so that the proc
  4726. // and interface know the cs stuff is around but we only want to set
  4727. // the "this is a cs array" flag if it's actually a cs array
  4728. if ( GetChild()->FInSummary( ATTR_CSCHAR ) )
  4729. SetHasCSType();
  4730. }
  4731. SIZE_LENGTH_USAGE usage;
  4732. if ( HasCSType() )
  4733. usage = CSSizeLengthUsage;
  4734. else
  4735. usage = NonCSSizeLengthUsage;
  4736. if ( ! FAInfo.SetExpressionVariableUsage( usage ) )
  4737. SemError( this, MyContext, SHARED_CSCHAR_EXPR_VAR, NULL );
  4738. pParentCtxt->ReturnValues( MyContext );
  4739. }
  4740. void
  4741. node_array::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  4742. {
  4743. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  4744. FIELD_ATTR_INFO FAInfo;
  4745. PTRTYPE PtrKind = PTR_UNKNOWN;
  4746. BOOL fArrayParent = MyContext.AnyAncestorBits( IN_ARRAY );
  4747. if ( HasCorrelation( this ) )
  4748. {
  4749. MyContext.IncCorrelationCount();
  4750. }
  4751. CheckDeclspecAlign( MyContext );
  4752. // See if context_handle applied to param reached us
  4753. if ( CheckContextHandle( MyContext ) )
  4754. {
  4755. MyContext.SetDescendantBits( HAS_HANDLE | HAS_CONTEXT_HANDLE );
  4756. }
  4757. if ( MyContext.FInSummary( ATTR_SWITCH_IS ) )
  4758. TypeSemError( this, MyContext, ARRAY_OF_UNIONS_ILLEGAL, NULL );
  4759. ////////////////////////////////////////////////////////////////////////
  4760. // process pointer attributes
  4761. PtrKind = MyContext.GetPtrKind();
  4762. MIDL_ASSERT( PtrKind != PTR_UNKNOWN );
  4763. if ( PtrKind == PTR_FULL )
  4764. {
  4765. MyContext.SetDescendantBits( HAS_FULL_PTR );
  4766. }
  4767. if ( MyContext.ExtractAttribute( ATTR_PTR_KIND) )
  4768. TypeSemError( this, MyContext, MORE_THAN_ONE_PTR_ATTR, NULL );
  4769. // ref pointer may not be returned
  4770. if ( ( PtrKind == PTR_REF ) &&
  4771. MyContext.AllAncestorBits( IN_RPC | IN_FUNCTION_RESULT ) )
  4772. {
  4773. if (MyContext.FindNonDefAncestorContext()->GetParent()->NodeKind()
  4774. == NODE_PROC )
  4775. TypeSemError( this, MyContext, BAD_CON_REF_RT, NULL );
  4776. }
  4777. // unique or full pointer may not be out only
  4778. if ( ( PtrKind != PTR_REF ) &&
  4779. MyContext.AllAncestorBits( IN_RPC | IN_PARAM_LIST ) &&
  4780. !MyContext.AnyAncestorBits( UNDER_IN_PARAM |
  4781. IN_STRUCT |
  4782. IN_UNION |
  4783. IN_ARRAY |
  4784. IN_POINTER ) )
  4785. TypeSemError( this, MyContext, UNIQUE_FULL_PTR_OUT_ONLY, NULL );
  4786. MyContext.SetAncestorBits( IN_ARRAY );
  4787. // warn about OUT const things
  4788. if ( FInSummary( ATTR_CONST ) )
  4789. {
  4790. if ( MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) )
  4791. RpcSemError( this, MyContext, CONST_ON_OUT_PARAM, NULL );
  4792. else if ( MyContext.AnyAncestorBits( IN_FUNCTION_RESULT ) )
  4793. RpcSemError( this, MyContext, CONST_ON_RETVAL, NULL );
  4794. }
  4795. /////////////////////////////////////////////////////////////////////////
  4796. // process field attributes
  4797. FAInfo.SetControl( FALSE, GetBasicType()->IsPtrOrArray() );
  4798. MyContext.ExtractFieldAttributes( &FAInfo );
  4799. FAInfo.Validate( &MyContext, pLowerBound, pUpperBound );
  4800. if (MyContext.AnyAncestorBits( IN_LIBRARY ))
  4801. {
  4802. if ( FA_NONE != FAInfo.Kind && FA_CONFORMANT != FAInfo.Kind)
  4803. {
  4804. // only Fixed size arrays and SAFEARRAYs are allowed in Type Libraries
  4805. SemError( this, MyContext, NOT_FIXED_ARRAY, NULL );
  4806. }
  4807. }
  4808. switch ( FAInfo.Kind )
  4809. {
  4810. case FA_NONE:
  4811. {
  4812. break;
  4813. }
  4814. case FA_STRING:
  4815. {
  4816. // string attributes only allowed on char and wchar_t
  4817. if ( !GetBasicType()->IsStringableType() )
  4818. TypeSemError( this, MyContext, STRING_NOT_ON_BYTE_CHAR, NULL );
  4819. if ( MyContext.AllAncestorBits( UNDER_OUT_PARAM |
  4820. IN_PARAM_LIST |
  4821. IN_RPC ) &&
  4822. !MyContext.AnyAncestorBits( IN_STRUCT |
  4823. IN_UNION |
  4824. IN_POINTER |
  4825. IN_ARRAY |
  4826. UNDER_IN_PARAM ) )
  4827. TypeSemError( this, MyContext, DERIVES_FROM_UNSIZED_STRING, NULL );
  4828. if ( FAInfo.StringKind == STR_BSTRING )
  4829. TypeSemError( this, MyContext, BSTRING_NOT_ON_PLAIN_PTR, NULL );
  4830. // break; deliberate fall through to case below
  4831. }
  4832. case FA_VARYING:
  4833. {
  4834. MyContext.SetDescendantBits( HAS_VAR_ARRAY );
  4835. break;
  4836. }
  4837. case FA_CONFORMANT:
  4838. {
  4839. MyContext.SetDescendantBits( HAS_CONF_ARRAY );
  4840. break;
  4841. }
  4842. case FA_CONFORMANT_STRING:
  4843. {
  4844. // string attributes only allowed on char and wchar_t
  4845. if ( !GetBasicType()->IsStringableType() )
  4846. TypeSemError( this, MyContext, STRING_NOT_ON_BYTE_CHAR, NULL );
  4847. if ( FAInfo.StringKind == STR_BSTRING )
  4848. TypeSemError( this, MyContext, BSTRING_NOT_ON_PLAIN_PTR, NULL );
  4849. MyContext.SetDescendantBits( HAS_STRING );
  4850. // break; deliberate fall through to case below
  4851. }
  4852. case FA_CONFORMANT_VARYING:
  4853. {
  4854. MyContext.SetDescendantBits( HAS_CONF_VAR_ARRAY );
  4855. break;
  4856. }
  4857. case FA_INTERFACE:
  4858. {
  4859. // gaj - tbd
  4860. break;
  4861. }
  4862. default: // string + varying combinations
  4863. {
  4864. TypeSemError( this, MyContext, INVALID_SIZE_ATTR_ON_STRING, NULL );
  4865. break;
  4866. }
  4867. }
  4868. // detect things like arrays of conf structs...
  4869. // if we have an array as an ancestor, and we have conformance, then complain
  4870. if ( MyContext.AnyDescendantBits( HAS_CONF_ARRAY | HAS_CONF_VAR_ARRAY ) &&
  4871. fArrayParent )
  4872. {
  4873. // see if there are any bad things between us and our parent array
  4874. SEM_ANALYSIS_CTXT * pCtxt = (SEM_ANALYSIS_CTXT *) pParentCtxt;
  4875. node_skl * pCur = pCtxt->GetParent();
  4876. // check up for anything other than def below proc
  4877. // make sure the proc only has one param
  4878. while ( pCur->NodeKind() != NODE_ARRAY )
  4879. {
  4880. if ( pCur->NodeKind() != NODE_DEF )
  4881. {
  4882. SemError( this, MyContext, ILLEGAL_CONFORMANT_ARRAY, NULL );
  4883. break;
  4884. }
  4885. pCtxt = (SEM_ANALYSIS_CTXT *) pCtxt->GetParentContext();
  4886. pCur = pCtxt->GetParent();
  4887. }
  4888. }
  4889. //////////////////////////////////////////////////////////////
  4890. // process the array element
  4891. GetChild()->SemanticAnalysis( &MyContext );
  4892. if ( MyContext.AnyDescendantBits( HAS_PIPE ) )
  4893. {
  4894. SemError( this, MyContext, INVALID_ARRAY_ELEMENT, 0 );
  4895. }
  4896. BOOL IsMultiDim = MyContext.AnyDescendantBits( HAS_ARRAY );
  4897. if ( MyContext.AnyDescendantBits( HAS_ARRAY ) &&
  4898. MyContext.AnyDescendantBits( HAS_CONF_ARRAY |
  4899. HAS_CONF_VAR_ARRAY |
  4900. HAS_VAR_ARRAY ) )
  4901. {
  4902. MyContext.SetDescendantBits( HAS_MULTIDIM_SIZING );
  4903. MyContext.SetDescendantBits( HAS_MULTIDIM_VECTOR );
  4904. }
  4905. MyContext.SetDescendantBits( HAS_ARRAY );
  4906. MIDL_ASSERT( GetNonDefChild != NULL );
  4907. if ( NODE_POINTER == GetNonDefChild()->NodeKind() )
  4908. MyContext.SetDescendantBits( HAS_ARRAYOFPOINTERS );
  4909. // disallow forward references as array elements
  4910. if ( MyContext.AnyDescendantBits( HAS_INCOMPLETE_TYPE ) )
  4911. {
  4912. if (! MyContext.AnyAncestorBits( IN_LIBRARY ))
  4913. SemError( this, MyContext, UNDEFINED_SYMBOL, NULL );
  4914. MyContext.ClearDescendantBits( HAS_INCOMPLETE_TYPE );
  4915. }
  4916. MyContext.ClearDescendantBits( HAS_RECURSIVE_DEF );
  4917. if ( MyContext.AllDescendantBits( HAS_DIRECT_CONF_OR_VAR |
  4918. HAS_MULTIDIM_SIZING ) &&
  4919. MyContext.AnyDescendantBits( HAS_CONF_ARRAY | HAS_CONF_VAR_ARRAY ) &&
  4920. ( GetChild()->NodeKind() == NODE_DEF ) )
  4921. {
  4922. SemError( this, MyContext, NON_ANSI_MULTI_CONF_ARRAY, NULL );
  4923. }
  4924. MyContext.ClearDescendantBits( HAS_DIRECT_CONF_OR_VAR );
  4925. if ( ( FAInfo.Kind != FA_NONE ) &&
  4926. ( FAInfo.Kind != FA_STRING ) &&
  4927. ( FAInfo.Kind != FA_INTERFACE ) )
  4928. MyContext.SetDescendantBits( HAS_DIRECT_CONF_OR_VAR );
  4929. if ( MyContext.AnyDescendantBits( HAS_POINTER ) )
  4930. fHasPointer = TRUE;
  4931. if ( MyContext.AnyDescendantBits( HAS_HANDLE ) )
  4932. TypeSemError( this, MyContext, BAD_CON_CTXT_HDL_ARRAY, NULL );
  4933. // don't allow functions as elements
  4934. if ( MyContext.AnyDescendantBits( HAS_FUNC ) &&
  4935. MyContext.AllAncestorBits( IN_INTERFACE | IN_RPC ) )
  4936. TypeSemError( this, MyContext, BAD_CON_ARRAY_FUNC, NULL );
  4937. if ( MyContext.AnyDescendantBits( HAS_IN_CSTYPE | HAS_OUT_CSTYPE ) )
  4938. {
  4939. if ( FA_CONFORMANT == FAInfo.Kind )
  4940. SemError( this, MyContext, NO_CONFORMANT_CSCHAR, NULL );
  4941. if ( IsMultiDim )
  4942. SemError( this, MyContext, NO_MULTIDIM_CSCHAR, NULL );
  4943. SetHasCSType();
  4944. }
  4945. SIZE_LENGTH_USAGE usage;
  4946. if ( HasCSType() )
  4947. usage = CSSizeLengthUsage;
  4948. else
  4949. usage = NonCSSizeLengthUsage;
  4950. if ( ! FAInfo.SetExpressionVariableUsage( usage ) )
  4951. SemError( this, MyContext, SHARED_CSCHAR_EXPR_VAR, NULL );
  4952. MyContext.ClearDescendantBits( HAS_STRUCT );
  4953. pParentCtxt->ReturnValues( MyContext );
  4954. }
  4955. void
  4956. node_echo_string::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  4957. {
  4958. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  4959. pParentCtxt->ReturnValues( MyContext );
  4960. };
  4961. void
  4962. node_e_status_t::VerifyParamUsage( SEM_ANALYSIS_CTXT * pCtxt )
  4963. {
  4964. // verify that we are under an OUT-only pointer
  4965. // or a "hidden" status parameter (only specified in the acf file)
  4966. if ( pCtxt->AnyAncestorBits( UNDER_IN_PARAM ) ||
  4967. !pCtxt->AnyAncestorBits( UNDER_OUT_PARAM ) )
  4968. {
  4969. if ( !pCtxt->AnyAncestorBits( UNDER_HIDDEN_STATUS ) )
  4970. {
  4971. TypeSemError( this, *pCtxt, E_STAT_T_MUST_BE_PTR_TO_E, NULL );
  4972. return;
  4973. }
  4974. }
  4975. SEM_ANALYSIS_CTXT * pCurCtxt = (SEM_ANALYSIS_CTXT *)pCtxt->GetParentContext();
  4976. node_skl * pPar = pCurCtxt->GetParent();
  4977. unsigned short PtrSeen = 0;
  4978. NODE_T Kind;
  4979. while ( ( Kind = pPar->NodeKind() ) != NODE_PARAM )
  4980. {
  4981. switch ( Kind )
  4982. {
  4983. case NODE_POINTER: // count pointers (must see just 1 )
  4984. PtrSeen++;
  4985. break;
  4986. case NODE_DEF: // skip DEF nodes
  4987. case NODE_E_STATUS_T: // and the error_status_t node
  4988. break;
  4989. default: // error on anything else
  4990. TypeSemError( this, *pCtxt, E_STAT_T_MUST_BE_PTR_TO_E, NULL );
  4991. return;
  4992. }
  4993. // advance up the stack
  4994. pCurCtxt = (SEM_ANALYSIS_CTXT *) pCurCtxt->GetParentContext();
  4995. pPar = pCurCtxt->GetParent();
  4996. }
  4997. // complain about wrong number of pointers
  4998. if ( PtrSeen != 1 )
  4999. TypeSemError( this, *pCtxt, E_STAT_T_MUST_BE_PTR_TO_E, NULL );
  5000. }
  5001. void
  5002. node_e_status_t::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  5003. {
  5004. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  5005. BOOL fFaultstat = (NULL != MyContext.ExtractAttribute( ATTR_FAULTSTAT ));
  5006. BOOL fCommstat = (NULL != MyContext.ExtractAttribute( ATTR_COMMSTAT ));
  5007. MyContext.SetDescendantBits( HAS_E_STAT_T );
  5008. CheckDeclspecAlign( MyContext );
  5009. // an error status_t can only be:
  5010. // 1: a parameter return type, or
  5011. // 2: an [out] only pointer parameter
  5012. // and it must have at least one of [comm_status] or
  5013. // [fault_status] applied
  5014. // make sure parameter is an OUT-only pointer if it has comm/fault_status
  5015. if ( fFaultstat || fCommstat )
  5016. {
  5017. if ( MyContext.AnyAncestorBits( IN_RPC ) )
  5018. {
  5019. // A proc in an actual remote interface.
  5020. // Then it must be an appropriate parameter
  5021. if ( MyContext.AnyAncestorBits( IN_PARAM_LIST ) )
  5022. {
  5023. VerifyParamUsage( &MyContext );
  5024. }
  5025. // or on a return type.
  5026. else if ( !MyContext.AnyAncestorBits( IN_FUNCTION_RESULT ) )
  5027. {
  5028. TypeSemError( this, MyContext, E_STAT_T_MUST_BE_PTR_TO_E , NULL );
  5029. }
  5030. }
  5031. if ( MyContext.AnyAncestorBits( IN_ARRAY ) )
  5032. TypeSemError( this, MyContext, E_STAT_T_ARRAY_ELEMENT, NULL );
  5033. if ( MyContext.AnyAncestorBits( IN_TRANSMIT_AS | IN_REPRESENT_AS ) )
  5034. TypeSemError( this, MyContext, TRANSMIT_AS_ON_E_STAT_T, NULL );
  5035. if ( MyContext.AnyAncestorBits( IN_STRUCT | IN_UNION ) )
  5036. TypeSemError( this, MyContext, BAD_CON_E_STAT_T_FIELD, NULL );
  5037. if ( MyContext.AnyAncestorBits( IN_USER_MARSHAL ) )
  5038. TypeSemError( this, MyContext, TRANSMIT_AS_ON_E_STAT_T, NULL );
  5039. }
  5040. MyContext.RejectAttributes();
  5041. pParentCtxt->ReturnValues( MyContext );
  5042. };
  5043. void
  5044. node_error::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  5045. {
  5046. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  5047. MyContext.RejectAttributes();
  5048. CheckDeclspecAlign( MyContext );
  5049. pParentCtxt->ReturnValues( MyContext );
  5050. };
  5051. void
  5052. node_wchar_t::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  5053. {
  5054. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  5055. CheckDeclspecAlign( MyContext );
  5056. TypeSemError( this, MyContext, WCHAR_T_INVALID_OSF, NULL );
  5057. if ( MyContext.AllAncestorBits( IN_PARAM_LIST | IN_RPC ) )
  5058. SemError( this, MyContext, WCHAR_T_NEEDS_MS_EXT_TO_RPC, NULL );
  5059. MyContext.RejectAttributes();
  5060. pParentCtxt->ReturnValues( MyContext );
  5061. };
  5062. void
  5063. node_library::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt)
  5064. {
  5065. MEM_ITER MemIter(this);
  5066. SEM_ANALYSIS_CTXT MyContext(this, pParentCtxt);
  5067. BOOL HasGuid = MyContext.FInSummary( ATTR_GUID );
  5068. MyContext.ExtractAttribute(ATTR_HELPSTRING);
  5069. MyContext.ExtractAttribute(ATTR_HELPCONTEXT);
  5070. MyContext.ExtractAttribute(ATTR_HELPSTRINGCONTEXT);
  5071. MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL);
  5072. gfCaseSensitive=FALSE;
  5073. // check for illegal attributes
  5074. node_member_attr * pMA;
  5075. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  5076. {
  5077. switch (pMA->GetAttr())
  5078. {
  5079. // acceptable attributes
  5080. case MATTR_RESTRICTED:
  5081. break;
  5082. // unacceptable attributes
  5083. case MATTR_READONLY:
  5084. case MATTR_SOURCE:
  5085. case MATTR_DEFAULTVTABLE:
  5086. case MATTR_BINDABLE:
  5087. case MATTR_DISPLAYBIND:
  5088. case MATTR_DEFAULTBIND:
  5089. case MATTR_REQUESTEDIT:
  5090. case MATTR_PROPGET:
  5091. case MATTR_PROPPUT:
  5092. case MATTR_PROPPUTREF:
  5093. case MATTR_OPTIONAL:
  5094. case MATTR_RETVAL:
  5095. case MATTR_VARARG:
  5096. case MATTR_PREDECLID:
  5097. case MATTR_UIDEFAULT:
  5098. case MATTR_NONBROWSABLE:
  5099. case MATTR_DEFAULTCOLLELEM:
  5100. case MATTR_IMMEDIATEBIND:
  5101. case MATTR_USESGETLASTERROR:
  5102. case MATTR_REPLACEABLE:
  5103. {
  5104. char * pAttrName = pMA->GetNodeNameString();
  5105. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  5106. break;
  5107. }
  5108. }
  5109. }
  5110. node_type_attr * pTA;
  5111. while ( ( pTA = (node_type_attr *)MyContext.ExtractAttribute(ATTR_TYPE) ) != 0 )
  5112. {
  5113. switch (pTA->GetAttr())
  5114. {
  5115. // acceptable attributes
  5116. case TATTR_CONTROL:
  5117. break;
  5118. // unacceptable attributes
  5119. case TATTR_LICENSED:
  5120. case TATTR_APPOBJECT:
  5121. case TATTR_PUBLIC:
  5122. case TATTR_DUAL:
  5123. case TATTR_PROXY:
  5124. case TATTR_NONEXTENSIBLE:
  5125. case TATTR_OLEAUTOMATION:
  5126. case TATTR_NONCREATABLE:
  5127. case TATTR_AGGREGATABLE:
  5128. {
  5129. char * pAttrName = pTA->GetNodeNameString();
  5130. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  5131. break;
  5132. }
  5133. }
  5134. }
  5135. // make sure the UUID is unique
  5136. if ( HasGuid )
  5137. {
  5138. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  5139. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  5140. if ( pDuplicate )
  5141. {
  5142. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  5143. }
  5144. }
  5145. else
  5146. {
  5147. SemError(this, MyContext, NO_UUID_SPECIFIED, NULL);
  5148. }
  5149. node_skl * pN;
  5150. NODE_T nodeKind;
  5151. while ( ( pN = MemIter.GetNext() ) != 0 )
  5152. {
  5153. SEM_ANALYSIS_CTXT ChildContext(MyContext);
  5154. ChildContext.SetInterfaceContext( &MyContext );
  5155. ChildContext.SetAncestorBits(IN_LIBRARY);
  5156. nodeKind = pN->NodeKind();
  5157. if ( nodeKind == NODE_PROC )
  5158. {
  5159. SemError( this, MyContext, INVALID_MEMBER, pN->GetSymName() );
  5160. }
  5161. else if (
  5162. nodeKind != NODE_MODULE &&
  5163. nodeKind != NODE_DISPINTERFACE &&
  5164. nodeKind != NODE_COCLASS &&
  5165. nodeKind != NODE_INTERFACE &&
  5166. nodeKind != NODE_STRUCT &&
  5167. nodeKind != NODE_UNION &&
  5168. nodeKind != NODE_ENUM &&
  5169. nodeKind != NODE_LABEL &&
  5170. nodeKind != NODE_DEF &&
  5171. nodeKind != NODE_INTERFACE_REFERENCE &&
  5172. nodeKind != NODE_ID &&
  5173. nodeKind != NODE_ECHO_STRING &&
  5174. nodeKind != NODE_FORWARD &&
  5175. nodeKind != NODE_MIDL_PRAGMA
  5176. )
  5177. {
  5178. SemError(this, MyContext, POSSIBLE_INVALID_MEMBER, pN->GetSymName());
  5179. }
  5180. pN->SemanticAnalysis(&ChildContext);
  5181. }
  5182. // consume all the library attributes
  5183. MyContext.CheckAttributes( );
  5184. // MyContext.ReturnValues(ChildContext);
  5185. pParentCtxt->ReturnValues( MyContext );
  5186. gfCaseSensitive=TRUE;
  5187. }
  5188. void
  5189. node_coclass::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt)
  5190. {
  5191. // make sure each coclass only gets analyzed once
  5192. if (fSemAnalyzed)
  5193. return;
  5194. fSemAnalyzed = TRUE;
  5195. MEM_ITER MemIter(this);
  5196. SEM_ANALYSIS_CTXT MyContext(this, pParentCtxt);
  5197. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  5198. MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
  5199. MyContext.ExtractAttribute( ATTR_HIDDEN );
  5200. MyContext.ExtractAttribute( ATTR_VERSION );
  5201. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  5202. MyContext.ExtractAttribute( ATTR_HELPSTRINGCONTEXT );
  5203. MyContext.ExtractAttribute( ATTR_HELPCONTEXT );
  5204. MyContext.ExtractAttribute( ATTR_LCID );
  5205. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  5206. {
  5207. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  5208. }
  5209. SEM_ANALYSIS_CTXT ChildContext(MyContext);
  5210. ChildContext.SetInterfaceContext( &MyContext );
  5211. // check for illegal attributes
  5212. node_type_attr * pTA;
  5213. while ( ( pTA = (node_type_attr *)MyContext.ExtractAttribute(ATTR_TYPE) ) != 0 )
  5214. {
  5215. switch (pTA->GetAttr())
  5216. {
  5217. // acceptable attributes
  5218. case TATTR_NONCREATABLE:
  5219. SetNotCreatable(TRUE);
  5220. break;
  5221. case TATTR_LICENSED:
  5222. case TATTR_APPOBJECT:
  5223. case TATTR_CONTROL:
  5224. case TATTR_AGGREGATABLE:
  5225. break;
  5226. // unacceptable attributes
  5227. case TATTR_PUBLIC:
  5228. {
  5229. char * pAttrName = pTA->GetNodeNameString();
  5230. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  5231. break;
  5232. }
  5233. case TATTR_DUAL:
  5234. case TATTR_PROXY:
  5235. case TATTR_NONEXTENSIBLE:
  5236. case TATTR_OLEAUTOMATION:
  5237. {
  5238. char * pAttrName = pTA->GetNodeNameString();
  5239. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  5240. break;
  5241. }
  5242. }
  5243. }
  5244. // check for illegal attributes
  5245. node_member_attr * pMA;
  5246. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  5247. {
  5248. switch (pMA->GetAttr())
  5249. {
  5250. // acceptable attributes
  5251. case MATTR_RESTRICTED:
  5252. break;
  5253. // unacceptable attributes
  5254. case MATTR_READONLY:
  5255. case MATTR_SOURCE:
  5256. case MATTR_DEFAULTVTABLE:
  5257. case MATTR_BINDABLE:
  5258. case MATTR_DISPLAYBIND:
  5259. case MATTR_DEFAULTBIND:
  5260. case MATTR_REQUESTEDIT:
  5261. case MATTR_PROPGET:
  5262. case MATTR_PROPPUT:
  5263. case MATTR_PROPPUTREF:
  5264. case MATTR_OPTIONAL:
  5265. case MATTR_RETVAL:
  5266. case MATTR_VARARG:
  5267. case MATTR_UIDEFAULT:
  5268. case MATTR_NONBROWSABLE:
  5269. case MATTR_DEFAULTCOLLELEM:
  5270. case MATTR_IMMEDIATEBIND:
  5271. case MATTR_USESGETLASTERROR:
  5272. case MATTR_REPLACEABLE:
  5273. {
  5274. char * pAttrName = pMA->GetNodeNameString();
  5275. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  5276. break;
  5277. }
  5278. }
  5279. }
  5280. BOOL HasGuid = MyContext.FInSummary( ATTR_GUID );
  5281. // make sure the UUID is unique
  5282. if ( HasGuid )
  5283. {
  5284. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  5285. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  5286. if ( pDuplicate )
  5287. {
  5288. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  5289. }
  5290. }
  5291. else
  5292. {
  5293. SemError(this, MyContext, NO_UUID_SPECIFIED, NULL);
  5294. }
  5295. ChildContext.SetAncestorBits(IN_COCLASS);
  5296. BOOL fHasDefaultSource = FALSE;
  5297. BOOL fHasDefaultSink = FALSE;
  5298. named_node * pN = (named_node *)MemIter.GetNext();
  5299. named_node * pNFirstSource = NULL;
  5300. named_node * pNFirstSink = NULL;
  5301. while (pN)
  5302. {
  5303. BOOL fSource = pN->FMATTRInSummary(MATTR_SOURCE);
  5304. BOOL fDefaultVtable = pN->FMATTRInSummary(MATTR_DEFAULTVTABLE);
  5305. if (fSource)
  5306. {
  5307. if (NULL == pNFirstSource && !pN->FMATTRInSummary(MATTR_RESTRICTED))
  5308. pNFirstSource = pN;
  5309. }
  5310. else
  5311. {
  5312. if (NULL == pNFirstSink && !pN->FMATTRInSummary(MATTR_RESTRICTED))
  5313. pNFirstSink = pN;
  5314. }
  5315. if (fDefaultVtable)
  5316. {
  5317. if (!fSource)
  5318. {
  5319. SemError(this, MyContext, DEFAULTVTABLE_REQUIRES_SOURCE, pN->GetSymName());
  5320. }
  5321. }
  5322. if (pN->GetAttribute(ATTR_DEFAULT))
  5323. {
  5324. if (fSource)
  5325. {
  5326. if (fHasDefaultSource)
  5327. {
  5328. SemError(this, MyContext, TWO_DEFAULT_INTERFACES, pN->GetSymName());
  5329. }
  5330. fHasDefaultSource = TRUE;
  5331. }
  5332. else
  5333. {
  5334. if (fHasDefaultSink)
  5335. {
  5336. SemError(this, MyContext, TWO_DEFAULT_INTERFACES, pN->GetSymName());
  5337. }
  5338. fHasDefaultSink = TRUE;
  5339. }
  5340. }
  5341. pN->SemanticAnalysis(&ChildContext);
  5342. pN = MemIter.GetNext();
  5343. }
  5344. if (!fHasDefaultSink)
  5345. {
  5346. if (pNFirstSink)
  5347. pNFirstSink->SetAttribute(ATTR_DEFAULT);
  5348. }
  5349. if (!fHasDefaultSource)
  5350. {
  5351. if (pNFirstSource)
  5352. pNFirstSource->SetAttribute(ATTR_DEFAULT);
  5353. }
  5354. MyContext.CheckAttributes( );
  5355. MyContext.ReturnValues(ChildContext);
  5356. pParentCtxt->ReturnValues( MyContext );
  5357. }
  5358. void
  5359. node_dispinterface::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt)
  5360. {
  5361. // make sure each dispinterface gets analyzed only once
  5362. if (fSemAnalyzed)
  5363. return;
  5364. fSemAnalyzed = TRUE;
  5365. MEM_ITER MemIter(this);
  5366. SEM_ANALYSIS_CTXT MyContext(this, pParentCtxt);
  5367. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  5368. MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
  5369. MyContext.ExtractAttribute( ATTR_HIDDEN );
  5370. MyContext.ExtractAttribute( ATTR_VERSION );
  5371. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  5372. MyContext.ExtractAttribute( ATTR_HELPSTRINGCONTEXT );
  5373. MyContext.ExtractAttribute( ATTR_HELPCONTEXT );
  5374. MyContext.ExtractAttribute( ATTR_LCID );
  5375. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  5376. {
  5377. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  5378. }
  5379. SEM_ANALYSIS_CTXT ChildContext(MyContext);
  5380. ChildContext.SetInterfaceContext( &MyContext );
  5381. // check for illegal attributes
  5382. node_type_attr * pTA;
  5383. while ( ( pTA = (node_type_attr *)MyContext.ExtractAttribute(ATTR_TYPE) ) != 0 )
  5384. {
  5385. switch (pTA->GetAttr())
  5386. {
  5387. // acceptable attributes
  5388. case TATTR_NONEXTENSIBLE:
  5389. break;
  5390. // unacceptable attributes
  5391. case TATTR_OLEAUTOMATION:
  5392. case TATTR_PUBLIC:
  5393. {
  5394. char * pAttrName = pTA->GetNodeNameString();
  5395. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  5396. break;
  5397. }
  5398. case TATTR_PROXY:
  5399. case TATTR_DUAL:
  5400. case TATTR_LICENSED:
  5401. case TATTR_APPOBJECT:
  5402. case TATTR_CONTROL:
  5403. case TATTR_NONCREATABLE:
  5404. case TATTR_AGGREGATABLE:
  5405. {
  5406. char * pAttrName = pTA->GetNodeNameString();
  5407. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  5408. break;
  5409. }
  5410. }
  5411. }
  5412. node_member_attr * pMA;
  5413. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  5414. {
  5415. switch (pMA->GetAttr())
  5416. {
  5417. // acceptable attributes
  5418. case MATTR_RESTRICTED:
  5419. break;
  5420. // unacceptable attributes
  5421. case MATTR_READONLY:
  5422. case MATTR_SOURCE:
  5423. case MATTR_DEFAULTVTABLE:
  5424. case MATTR_BINDABLE:
  5425. case MATTR_DISPLAYBIND:
  5426. case MATTR_DEFAULTBIND:
  5427. case MATTR_REQUESTEDIT:
  5428. case MATTR_PROPGET:
  5429. case MATTR_PROPPUT:
  5430. case MATTR_PROPPUTREF:
  5431. case MATTR_OPTIONAL:
  5432. case MATTR_RETVAL:
  5433. case MATTR_VARARG:
  5434. case MATTR_PREDECLID:
  5435. case MATTR_UIDEFAULT:
  5436. case MATTR_NONBROWSABLE:
  5437. case MATTR_DEFAULTCOLLELEM:
  5438. case MATTR_IMMEDIATEBIND:
  5439. case MATTR_USESGETLASTERROR:
  5440. case MATTR_REPLACEABLE:
  5441. {
  5442. char * pAttrName = pMA->GetNodeNameString();
  5443. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  5444. break;
  5445. }
  5446. }
  5447. }
  5448. BOOL HasGuid = MyContext.FInSummary( ATTR_GUID );
  5449. // make sure the UUID is unique
  5450. if ( HasGuid )
  5451. {
  5452. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  5453. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  5454. if ( pDuplicate )
  5455. {
  5456. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  5457. }
  5458. }
  5459. else
  5460. {
  5461. SemError(this, MyContext, NO_UUID_SPECIFIED, NULL);
  5462. }
  5463. // make sure IDispatch is defined.
  5464. SymKey SKey("IDispatch", NAME_DEF);
  5465. pDispatch = pBaseSymTbl->SymSearch(SKey);
  5466. if (!pDispatch)
  5467. {
  5468. // IDispatch is not defined: generate error.
  5469. SemError(this, MyContext, NO_IDISPATCH, GetSymName());
  5470. }
  5471. else
  5472. {
  5473. if (pDispatch->NodeKind() == NODE_INTERFACE_REFERENCE)
  5474. pDispatch = ((node_interface_reference *)pDispatch)->GetRealInterface();
  5475. }
  5476. ChildContext.SetAncestorBits((ANCESTOR_FLAGS) IN_DISPINTERFACE);
  5477. node_skl * pN;
  5478. while ( ( pN = MemIter.GetNext() ) != 0 )
  5479. {
  5480. pN->SemanticAnalysis(&ChildContext);
  5481. }
  5482. MyContext.CheckAttributes( );
  5483. MyContext.ReturnValues(ChildContext);
  5484. pParentCtxt->ReturnValues( MyContext );
  5485. }
  5486. void
  5487. node_module::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt)
  5488. {
  5489. // make sure each module gets analyzed only once
  5490. if (fSemAnalyzed)
  5491. return;
  5492. fSemAnalyzed = TRUE;
  5493. MEM_ITER MemIter(this);
  5494. SEM_ANALYSIS_CTXT MyContext(this, pParentCtxt);
  5495. BOOL HasGuid = MyContext.FInSummary( ATTR_GUID );
  5496. MyContext.ExtractAttribute(ATTR_DLLNAME);
  5497. while(MyContext.ExtractAttribute(ATTR_CUSTOM));
  5498. MyContext.ExtractAttribute(ATTR_TYPEDESCATTR);
  5499. MyContext.ExtractAttribute( ATTR_HIDDEN );
  5500. MyContext.ExtractAttribute( ATTR_VERSION );
  5501. MyContext.ExtractAttribute( ATTR_HELPSTRING );
  5502. MyContext.ExtractAttribute( ATTR_HELPSTRINGCONTEXT );
  5503. MyContext.ExtractAttribute( ATTR_HELPCONTEXT );
  5504. MyContext.ExtractAttribute( ATTR_LCID );
  5505. if (MyContext.ExtractAttribute(ATTR_HELPSTRINGDLL))
  5506. {
  5507. SemError(this, MyContext, INAPPLICABLE_ATTRIBUTE, 0);
  5508. }
  5509. if ( !MyContext.AnyAncestorBits( IN_LIBRARY ) )
  5510. {
  5511. SemError(this, MyContext, NO_LIBRARY, 0);
  5512. }
  5513. SEM_ANALYSIS_CTXT ChildContext(MyContext);
  5514. ChildContext.SetInterfaceContext( &MyContext );
  5515. // make sure the UUID is unique
  5516. if ( HasGuid )
  5517. {
  5518. node_guid * pGuid = (node_guid *) MyContext.ExtractAttribute( ATTR_GUID );
  5519. node_skl* pDuplicate = GetDuplicateGuid( pGuid, pUUIDTable );
  5520. if ( pDuplicate )
  5521. {
  5522. SemError(this, MyContext, DUPLICATE_UUID, pDuplicate->GetSymName());
  5523. }
  5524. }
  5525. // check for illegal attributes
  5526. node_type_attr * pTA;
  5527. while ( ( pTA = (node_type_attr *)MyContext.ExtractAttribute(ATTR_TYPE) ) != 0 )
  5528. {
  5529. switch (pTA->GetAttr())
  5530. {
  5531. // acceptable attributes
  5532. case TATTR_PUBLIC:
  5533. {
  5534. char * pAttrName = pTA->GetNodeNameString();
  5535. SemError( this, MyContext, NEWLYFOUND_INAPPLICABLE_ATTRIBUTE, pAttrName);
  5536. break;
  5537. }
  5538. break;
  5539. // unacceptable attributes
  5540. case TATTR_OLEAUTOMATION:
  5541. case TATTR_LICENSED:
  5542. case TATTR_APPOBJECT:
  5543. case TATTR_CONTROL:
  5544. case TATTR_PROXY:
  5545. case TATTR_DUAL:
  5546. case TATTR_NONEXTENSIBLE:
  5547. case TATTR_NONCREATABLE:
  5548. case TATTR_AGGREGATABLE:
  5549. {
  5550. char * pAttrName = pTA->GetNodeNameString();
  5551. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  5552. break;
  5553. }
  5554. }
  5555. }
  5556. node_member_attr * pMA;
  5557. node_member_attr * pUsesGetLastErrorAttr = 0;
  5558. while ( ( pMA = (node_member_attr *)MyContext.ExtractAttribute(ATTR_MEMBER) ) != 0 )
  5559. {
  5560. switch (pMA->GetAttr())
  5561. {
  5562. // acceptable attributes
  5563. case MATTR_RESTRICTED:
  5564. break;
  5565. case MATTR_USESGETLASTERROR:
  5566. pUsesGetLastErrorAttr = pMA;
  5567. break;
  5568. // unacceptable attributes
  5569. case MATTR_READONLY:
  5570. case MATTR_SOURCE:
  5571. case MATTR_DEFAULTVTABLE:
  5572. case MATTR_BINDABLE:
  5573. case MATTR_DISPLAYBIND:
  5574. case MATTR_DEFAULTBIND:
  5575. case MATTR_REQUESTEDIT:
  5576. case MATTR_PROPGET:
  5577. case MATTR_PROPPUT:
  5578. case MATTR_PROPPUTREF:
  5579. case MATTR_OPTIONAL:
  5580. case MATTR_RETVAL:
  5581. case MATTR_VARARG:
  5582. case MATTR_PREDECLID:
  5583. case MATTR_UIDEFAULT:
  5584. case MATTR_NONBROWSABLE:
  5585. case MATTR_DEFAULTCOLLELEM:
  5586. case MATTR_IMMEDIATEBIND:
  5587. case MATTR_REPLACEABLE:
  5588. {
  5589. char * pAttrName = pMA->GetNodeNameString();
  5590. SemError( this, MyContext, INAPPLICABLE_ATTRIBUTE, pAttrName);
  5591. break;
  5592. }
  5593. }
  5594. }
  5595. if (pUsesGetLastErrorAttr != 0)
  5596. {
  5597. MyContext.Add(pUsesGetLastErrorAttr);
  5598. }
  5599. ChildContext.SetAncestorBits(IN_MODULE);
  5600. node_skl * pN;
  5601. while ( (pN = MemIter.GetNext() ) != 0 )
  5602. {
  5603. pN->SemanticAnalysis(&ChildContext);
  5604. }
  5605. MyContext.CheckAttributes( );
  5606. MyContext.ReturnValues(ChildContext);
  5607. pParentCtxt->ReturnValues( MyContext );
  5608. }
  5609. void
  5610. node_pipe::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  5611. {
  5612. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  5613. if (!GetSymName())
  5614. {
  5615. char * pParentName = pParentCtxt->GetParent()->GetSymName();
  5616. char * pName = new char [strlen(pParentName) + 6]; // the length of "pipe_" plus terminating null
  5617. strcpy(pName, "pipe_");
  5618. strcat(pName,pParentName);
  5619. SetSymName(pName);
  5620. }
  5621. if ( MyContext.AnyAncestorBits( HAS_ASYNCHANDLE ) &&
  5622. !MyContext.AnyAncestorBits( IN_OBJECT_INTF ) )
  5623. {
  5624. SetGenAsyncPipeFlavor();
  5625. }
  5626. GetChild()->SemanticAnalysis(&MyContext);
  5627. CheckDeclspecAlign( MyContext );
  5628. // Remove the following statement once support for UNIONS within PIPES is provided by the interpreter.
  5629. if (MyContext.AnyDescendantBits( HAS_UNION ))
  5630. {
  5631. // pipe with a UNION
  5632. RpcSemError(this , MyContext, UNIMPLEMENTED_FEATURE, "pipes can't contain unions" );
  5633. }
  5634. if (MyContext.AnyDescendantBits( HAS_HANDLE
  5635. | HAS_POINTER
  5636. | HAS_VAR_ARRAY
  5637. | HAS_CONF_ARRAY
  5638. | HAS_CONF_VAR_ARRAY
  5639. | HAS_CONTEXT_HANDLE
  5640. | HAS_CONF_PTR
  5641. | HAS_VAR_PTR
  5642. | HAS_CONF_VAR_PTR
  5643. | HAS_TRANSMIT_AS
  5644. | HAS_REPRESENT_AS
  5645. | HAS_INTERFACE_PTR
  5646. | HAS_DIRECT_CONF_OR_VAR ))
  5647. {
  5648. // All the above are illegal types within a pipe
  5649. RpcSemError(this, MyContext, ILLEGAL_PIPE_TYPE, NULL );
  5650. }
  5651. MyContext.ClearAncestorBits( IN_UNION | IN_NE_UNION | IN_ARRAY );
  5652. if ( MyContext.AnyAncestorBits( IN_ARRAY |
  5653. IN_UNION |
  5654. IN_NE_UNION |
  5655. IN_STRUCT ))
  5656. TypeSemError( this, MyContext, ILLEGAL_PIPE_EMBEDDING, NULL );
  5657. if ( MyContext.AnyAncestorBits( IN_TRANSMIT_AS |
  5658. IN_REPRESENT_AS |
  5659. IN_USER_MARSHAL |
  5660. IN_FUNCTION_RESULT ))
  5661. TypeSemError( this, MyContext, ILLEGAL_PIPE_CONTEXT, NULL );
  5662. if ( MyContext.AnyAncestorBits( IN_ENCODE_INTF ))
  5663. TypeSemError( this, MyContext, PIPES_WITH_PICKLING, NULL );
  5664. if ( MyContext.AnyAncestorBits( IN_OBJECT_INTF ) )
  5665. {
  5666. node_skl* pType = pParentCtxt->GetParent();
  5667. if ( pType->GetChild() )
  5668. {
  5669. pType = pType->GetChild();
  5670. }
  5671. }
  5672. // BUGBUG UNDONE
  5673. // Basically, a pipe can only be used as a parameter.
  5674. // Pipe parameters may only be passed by value or by reference.
  5675. // Need to make sure that /-Os mode isn't enabled (until support
  5676. // for it has been implemented).
  5677. // Need to enable /-Oi2 mode for the containing proc if we decide not
  5678. // to implement /-Oi mode.
  5679. MyContext.SetDescendantBits( (DESCENDANT_FLAGS) HAS_PIPE );
  5680. pParentCtxt->ReturnValues( MyContext );
  5681. }
  5682. void
  5683. node_safearray::SemanticAnalysis( SEM_ANALYSIS_CTXT * pParentCtxt )
  5684. {
  5685. SEM_ANALYSIS_CTXT MyContext( this, pParentCtxt );
  5686. FIELD_ATTR_INFO FAInfo;
  5687. PTRTYPE PtrKind = PTR_UNKNOWN;
  5688. BOOL fArrayParent = MyContext.AnyAncestorBits( IN_ARRAY );
  5689. // this maintains a reference to LPSAFEARRAY. This is
  5690. // necessary to generate the appropriate code when
  5691. // SAFEARRAY(type) construct is used outside the library block
  5692. char* szSafeArray = "LPSAFEARRAY";
  5693. SymKey SKey( szSafeArray, NAME_DEF );
  5694. named_node* pSafeArrayNode = pBaseSymTbl->SymSearch( SKey );
  5695. if ( pSafeArrayNode == 0 )
  5696. {
  5697. SemError( this, MyContext, UNDEFINED_SYMBOL, szSafeArray );
  5698. }
  5699. else
  5700. {
  5701. SetTypeAlias( pSafeArrayNode );
  5702. }
  5703. CheckDeclspecAlign( MyContext );
  5704. // See if context_handle applied to param reached us
  5705. if ( CheckContextHandle( MyContext ) )
  5706. {
  5707. MyContext.SetDescendantBits( HAS_HANDLE | HAS_CONTEXT_HANDLE );
  5708. }
  5709. if ( MyContext.FInSummary( ATTR_SWITCH_IS ) )
  5710. TypeSemError( this, MyContext, ARRAY_OF_UNIONS_ILLEGAL, NULL );
  5711. // if ( !MyContext.AnyAncestorBits( IN_LIBRARY ) )
  5712. // {
  5713. // SemError(this, MyContext, SAFEARRAY_NOT_SUPPORT_OUTSIDE_TLB, 0);
  5714. // }
  5715. ////////////////////////////////////////////////////////////////////////
  5716. // process pointer attributes
  5717. PtrKind = MyContext.GetPtrKind();
  5718. MIDL_ASSERT( PtrKind != PTR_UNKNOWN );
  5719. if ( PtrKind == PTR_FULL )
  5720. {
  5721. MyContext.SetDescendantBits( HAS_FULL_PTR );
  5722. }
  5723. if ( MyContext.ExtractAttribute( ATTR_PTR_KIND) )
  5724. TypeSemError( this, MyContext, MORE_THAN_ONE_PTR_ATTR, NULL );
  5725. // ref pointer may not be returned
  5726. if ( ( PtrKind == PTR_REF ) &&
  5727. MyContext.AllAncestorBits( IN_RPC | IN_FUNCTION_RESULT ) )
  5728. {
  5729. if (MyContext.FindNonDefAncestorContext()->GetParent()->NodeKind()
  5730. == NODE_PROC )
  5731. TypeSemError( this, MyContext, BAD_CON_REF_RT, NULL );
  5732. }
  5733. // unique or full pointer may not be out only
  5734. if ( ( PtrKind != PTR_REF ) &&
  5735. MyContext.AllAncestorBits( IN_RPC | IN_PARAM_LIST ) &&
  5736. !MyContext.AnyAncestorBits( UNDER_IN_PARAM |
  5737. IN_STRUCT |
  5738. IN_UNION |
  5739. IN_ARRAY |
  5740. IN_POINTER ) )
  5741. TypeSemError( this, MyContext, UNIQUE_FULL_PTR_OUT_ONLY, NULL );
  5742. MyContext.SetAncestorBits( IN_ARRAY );
  5743. // warn about OUT const things
  5744. if ( FInSummary( ATTR_CONST ) )
  5745. {
  5746. if ( MyContext.AnyAncestorBits( UNDER_OUT_PARAM ) )
  5747. RpcSemError( this, MyContext, CONST_ON_OUT_PARAM, NULL );
  5748. else if ( MyContext.AnyAncestorBits( IN_FUNCTION_RESULT ) )
  5749. RpcSemError( this, MyContext, CONST_ON_RETVAL, NULL );
  5750. }
  5751. /////////////////////////////////////////////////////////////////////////
  5752. // process field attributes
  5753. FAInfo.SetControl( FALSE, GetBasicType()->IsPtrOrArray() );
  5754. MyContext.ExtractFieldAttributes( &FAInfo );
  5755. switch ( FAInfo.Kind )
  5756. {
  5757. case FA_NONE:
  5758. {
  5759. break;
  5760. }
  5761. case FA_STRING:
  5762. {
  5763. // string attributes only allowed on char and wchar_t
  5764. if ( !GetBasicType()->IsStringableType() )
  5765. TypeSemError( this, MyContext, STRING_NOT_ON_BYTE_CHAR, NULL );
  5766. if ( MyContext.AllAncestorBits( UNDER_OUT_PARAM |
  5767. IN_PARAM_LIST |
  5768. IN_RPC ) &&
  5769. !MyContext.AnyAncestorBits( IN_STRUCT |
  5770. IN_UNION |
  5771. IN_POINTER |
  5772. IN_ARRAY |
  5773. UNDER_IN_PARAM ) )
  5774. TypeSemError( this, MyContext, DERIVES_FROM_UNSIZED_STRING, NULL );
  5775. if ( FAInfo.StringKind == STR_BSTRING )
  5776. TypeSemError( this, MyContext, BSTRING_NOT_ON_PLAIN_PTR, NULL );
  5777. // break; deliberate fall through to case below
  5778. }
  5779. case FA_VARYING:
  5780. {
  5781. MyContext.SetDescendantBits( HAS_VAR_ARRAY );
  5782. break;
  5783. }
  5784. case FA_CONFORMANT:
  5785. {
  5786. MyContext.SetDescendantBits( HAS_CONF_ARRAY );
  5787. break;
  5788. }
  5789. case FA_CONFORMANT_STRING:
  5790. {
  5791. // string attributes only allowed on char and wchar_t
  5792. if ( !GetBasicType()->IsStringableType() )
  5793. TypeSemError( this, MyContext, STRING_NOT_ON_BYTE_CHAR, NULL );
  5794. if ( FAInfo.StringKind == STR_BSTRING )
  5795. TypeSemError( this, MyContext, BSTRING_NOT_ON_PLAIN_PTR, NULL );
  5796. // break; deliberate fall through to case below
  5797. }
  5798. case FA_CONFORMANT_VARYING:
  5799. {
  5800. MyContext.SetDescendantBits( HAS_CONF_VAR_ARRAY );
  5801. break;
  5802. }
  5803. case FA_INTERFACE:
  5804. {
  5805. // gaj - tbd
  5806. break;
  5807. }
  5808. default: // string + varying combinations
  5809. {
  5810. TypeSemError( this, MyContext, INVALID_SIZE_ATTR_ON_STRING, NULL );
  5811. break;
  5812. }
  5813. }
  5814. // detect things like arrays of conf structs...
  5815. // if we have an array as an ancestor, and we have conformance, then complain
  5816. if ( MyContext.AnyDescendantBits( HAS_CONF_ARRAY | HAS_CONF_VAR_ARRAY ) &&
  5817. fArrayParent )
  5818. {
  5819. // see if there are any bad things between us and our parent array
  5820. SEM_ANALYSIS_CTXT * pCtxt = (SEM_ANALYSIS_CTXT *) pParentCtxt;
  5821. node_skl * pCur = pCtxt->GetParent();
  5822. // check up for anything other than def below proc
  5823. // make sure the proc only has one param
  5824. while ( pCur->NodeKind() != NODE_ARRAY )
  5825. {
  5826. if ( pCur->NodeKind() != NODE_DEF )
  5827. {
  5828. SemError( this, MyContext, ILLEGAL_CONFORMANT_ARRAY, NULL );
  5829. break;
  5830. }
  5831. pCtxt = (SEM_ANALYSIS_CTXT *) pCtxt->GetParentContext();
  5832. pCur = pCtxt->GetParent();
  5833. }
  5834. }
  5835. //////////////////////////////////////////////////////////////
  5836. // process the array element
  5837. GetChild()->SemanticAnalysis( &MyContext );
  5838. /*
  5839. // BSTR has sizeis_ptr, eventhough under variant, and it would be ugly to
  5840. // hardcode checking variant here. well...
  5841. if ( MyContext.AnyDescendantBits( HAS_CONF_ARRAY |
  5842. HAS_CONF_VAR_ARRAY |
  5843. HAS_VAR_ARRAY |
  5844. HAS_UNSAT_REP_AS |
  5845. HAS_CONTEXT_HANDLE |
  5846. HAS_CONF_PTR |
  5847. HAS_VAR_PTR |
  5848. HAS_CONF_VAR_PTR |
  5849. HAS_DIRECT_CONF_OR_VAR |
  5850. HAS_FUNC |
  5851. HAS_FULL_PTR |
  5852. HAS_TOO_BIG_HDL |
  5853. HAS_MULTIDIM_SIZING |
  5854. HAS_PIPE |
  5855. HAS_MULTIDIM_VECTOR |
  5856. HAS_SIZED_ARRAY |
  5857. HAS_SIZED_PTR ) )
  5858. TypeSemError( this, MyContext, INVALID_SAFEARRAY_ATTRIBUTE, NULL );
  5859. */
  5860. MyContext.SetDescendantBits( HAS_ARRAY );
  5861. // early binding of safearray(interface pointer) doesn't work
  5862. node_skl * pChild = GetChild()->GetBasicType();
  5863. SEM_ANALYSIS_CTXT * pIntfCtxt = (SEM_ANALYSIS_CTXT *)
  5864. MyContext.GetInterfaceContext();
  5865. BOOL fLocal = pIntfCtxt->FInSummary( ATTR_LOCAL );
  5866. fLocal |= MyContext.AnyAncestorBits( IN_LOCAL_PROC );
  5867. if ( pChild->NodeKind() == NODE_POINTER )
  5868. pChild = pChild->GetChild();
  5869. if ( IsInterfaceKind( pChild->NodeKind() ) &&
  5870. !MyContext.AnyAncestorBits( IN_LIBRARY ) &&
  5871. !fLocal )
  5872. SemError( this, MyContext, SAFEARRAY_IF_OUTSIDE_LIBRARY, NULL );
  5873. // disallow forward references as array elements
  5874. // NOTE- all safearray elements are VARIANTS, we don't really need
  5875. // to enforce this restriction for safearrays. Besides, enforcing
  5876. // this restriction breaks some of our test cases.
  5877. if ( MyContext.AnyDescendantBits( HAS_INCOMPLETE_TYPE ) )
  5878. {
  5879. MyContext.ClearDescendantBits( HAS_INCOMPLETE_TYPE );
  5880. }
  5881. MyContext.ClearDescendantBits( HAS_RECURSIVE_DEF );
  5882. if ( MyContext.AllDescendantBits( HAS_DIRECT_CONF_OR_VAR |
  5883. HAS_MULTIDIM_SIZING ) &&
  5884. MyContext.AnyDescendantBits( HAS_CONF_ARRAY | HAS_CONF_VAR_ARRAY ) &&
  5885. ( GetChild()->NodeKind() == NODE_DEF ) )
  5886. {
  5887. SemError( this, MyContext, NON_ANSI_MULTI_CONF_ARRAY, NULL );
  5888. }
  5889. MyContext.ClearDescendantBits( HAS_DIRECT_CONF_OR_VAR );
  5890. if ( ( FAInfo.Kind != FA_NONE ) &&
  5891. ( FAInfo.Kind != FA_STRING ) &&
  5892. ( FAInfo.Kind != FA_INTERFACE ) )
  5893. MyContext.SetDescendantBits( HAS_DIRECT_CONF_OR_VAR );
  5894. if ( MyContext.AnyDescendantBits( HAS_HANDLE ) )
  5895. TypeSemError( this, MyContext, BAD_CON_CTXT_HDL_ARRAY, NULL );
  5896. // don't allow functions as elements
  5897. if ( MyContext.AnyDescendantBits( HAS_FUNC ) &&
  5898. MyContext.AllAncestorBits( IN_INTERFACE | IN_RPC ) )
  5899. TypeSemError( this, MyContext, BAD_CON_ARRAY_FUNC, NULL );
  5900. // This is a hack to propagate the correct attributes up to the next level.
  5901. // Unfortunately, semantic analysis does more then just determine
  5902. // if the *.idl file is legal. It also catches known limitations of the
  5903. // engine, aids in determining the complexity of the marshaling problem,
  5904. // and other checks that change the state of the front end which directly
  5905. // affect the backend.
  5906. // gracelly handle the error case and the library case.
  5907. if ( ! pSafeArrayNode || MyContext.AnyAncestorBits( IN_LIBRARY ) )
  5908. {
  5909. // Is this class was used in a proxy, continue to pass up the proxy bits.
  5910. if ( fInProxy )
  5911. {
  5912. pSafeArrayNode->SemanticAnalysis( pParentCtxt );
  5913. return;
  5914. }
  5915. MyContext.ClearDescendantBits( HAS_STRUCT );
  5916. pParentCtxt->ReturnValues( MyContext );
  5917. return;
  5918. }
  5919. fInProxy = TRUE;
  5920. pSafeArrayNode->SemanticAnalysis( pParentCtxt );
  5921. };
  5922. void
  5923. node_async_handle::SemanticAnalysis( SEM_ANALYSIS_CTXT* )
  5924. {
  5925. }
  5926. BOOL IsOLEAutomationType( char* szTypeName )
  5927. {
  5928. BOOL fRet = FALSE;
  5929. // keep this list sorted!
  5930. static char* szOLEAutomationTypes[] =
  5931. {
  5932. "BSTR", // wchar_t
  5933. "CURRENCY", // struct
  5934. "DATE", // double
  5935. "SCODE", // long
  5936. "VARIANT",
  5937. "VARIANT_BOOL",
  5938. };
  5939. int uFirst = 0;
  5940. int uLast = (sizeof(szOLEAutomationTypes) - 1) / sizeof(char*);
  5941. int uMid = (uFirst + uLast) / 2;
  5942. while (uLast >= uFirst && uLast >= 0 && uFirst <= (sizeof(szOLEAutomationTypes) - 1) / sizeof(char*))
  5943. {
  5944. int nCmp = strcmp(szOLEAutomationTypes[uMid], szTypeName);
  5945. if (nCmp == 0)
  5946. {
  5947. fRet = TRUE;
  5948. break;
  5949. }
  5950. else if (nCmp > 0)
  5951. {
  5952. uLast = uMid - 1;
  5953. }
  5954. else
  5955. {
  5956. uFirst = uMid + 1;
  5957. }
  5958. uMid = (uFirst + uLast) / 2;
  5959. }
  5960. return fRet;
  5961. }
  5962. BOOL IsBasicOleAutoKind( NODE_T x)
  5963. {
  5964. // NODE_INT128, NODE_FLOAT80, NODE_FLOAT128 is not supported.
  5965. return ( (x) == NODE_DOUBLE || (x) == NODE_FLOAT || (x) == NODE_INT ||
  5966. (x) == NODE_SHORT || (x) == NODE_LONG || (x) == NODE_CHAR ||
  5967. (x) == NODE_INT32 ||
  5968. (x) == NODE_HYPER || (x) == NODE_INT64 || (x) == NODE_INT3264 ||
  5969. (x) == NODE_BOOLEAN || (x) == NODE_WCHAR_T
  5970. );
  5971. }
  5972. BOOL IsOLEAutoBasicType ( node_base_type* pNBT )
  5973. {
  5974. NODE_T nodeKind = pNBT->NodeKind();
  5975. if ( nodeKind == NODE_CHAR )
  5976. {
  5977. return ( (node_base_type*) pNBT )->IsUnsigned();
  5978. }
  5979. else
  5980. {
  5981. return TRUE;
  5982. }
  5983. }
  5984. BOOL IsOLEAutoInterface ( node_interface* pType )
  5985. {
  5986. node_interface* pNodeIf;
  5987. BOOL fRet = FALSE;
  5988. // pType may be a node_interface or a node_interaface_reference
  5989. // "normalize" it.
  5990. if ( pType->NodeKind() == NODE_INTERFACE_REFERENCE )
  5991. {
  5992. pNodeIf = (( node_interface_reference *) pType )->GetRealInterface();
  5993. }
  5994. else
  5995. {
  5996. pNodeIf = pType;
  5997. }
  5998. fRet = pNodeIf->HasOLEAutomation();
  5999. if ( !fRet )
  6000. {
  6001. // the interface is forward declared,
  6002. // and has not been analyzed for semantic errors,
  6003. // it does not have HasOleAutomation flag set.
  6004. fRet = pNodeIf->FTATTRInSummary( TATTR_OLEAUTOMATION ) ||
  6005. pNodeIf->FTATTRInSummary( TATTR_DUAL );
  6006. if ( !fRet )
  6007. {
  6008. // interface may be an IUnknown or an IDispatch and these do not
  6009. // have HasOleAutomation flag set.
  6010. fRet = pNodeIf->IsValidRootInterface();
  6011. if ( !fRet )
  6012. {
  6013. // It is not IUnknown. If it is not IFont or IDispatch, it is not
  6014. // an oleautomation compliant interface.
  6015. char* szIfName = pNodeIf->GetSymName();
  6016. fRet = !_stricmp(szIfName, "IDispatch") || !_stricmp(szIfName, "IFontDisp");
  6017. }
  6018. }
  6019. }
  6020. return fRet;
  6021. }
  6022. BOOL
  6023. IsOLEAutomationCompliant( node_skl* pParamType )
  6024. {
  6025. if ( pParamType == 0 )
  6026. {
  6027. return FALSE;
  6028. }
  6029. BOOL fConforms = FALSE;
  6030. NODE_T nKind = pParamType->NodeKind();
  6031. if ( nKind == NODE_SAFEARRAY || nKind == NODE_HREF || nKind == NODE_POINTER )
  6032. {
  6033. fConforms = IsOLEAutomationCompliant( pParamType->GetChild() );
  6034. }
  6035. else if ( IsInterfaceKind( nKind ) )
  6036. {
  6037. fConforms = IsOLEAutoInterface( (node_interface*) pParamType );
  6038. }
  6039. else if ( IsCoclassOrDispKind( nKind ) || nKind == NODE_ENUM || nKind == NODE_STRUCT ||
  6040. IsBasicOleAutoKind( nKind ) )
  6041. {
  6042. fConforms = TRUE;
  6043. }
  6044. else if ( nKind == NODE_DEF )
  6045. {
  6046. node_skl* pChild = pParamType->GetChild();
  6047. fConforms = IsOLEAutomationType( pParamType->GetSymName() ) ? TRUE : IsOLEAutomationCompliant( pChild );
  6048. }
  6049. else if ( nKind == NODE_FORWARD )
  6050. {
  6051. node_skl* pChild = ( (node_forward*) pParamType )->ResolveFDecl();
  6052. fConforms = ( pChild ) ? IsOLEAutomationCompliant( pChild ) : FALSE;
  6053. }
  6054. return fConforms;
  6055. }
  6056. bool
  6057. HasCorrelation( node_skl* pNode )
  6058. {
  6059. if (
  6060. pNode->FInSummary( ATTR_SIZE ) ||
  6061. pNode->FInSummary( ATTR_FIRST ) ||
  6062. pNode->FInSummary( ATTR_BYTE_COUNT ) ||
  6063. pNode->FInSummary( ATTR_LAST ) ||
  6064. pNode->FInSummary( ATTR_LENGTH ) ||
  6065. pNode->FInSummary( ATTR_MAX ) ||
  6066. pNode->FInSummary( ATTR_MIN ) ||
  6067. pNode->FInSummary( ATTR_SIZE ) ||
  6068. pNode->FInSummary( ATTR_IID_IS ) ||
  6069. pNode->FInSummary( ATTR_SWITCH_IS )
  6070. )
  6071. {
  6072. return true;
  6073. }
  6074. return false;
  6075. }
  6076. bool
  6077. node_skl::CheckContextHandle( SEM_ANALYSIS_CTXT& MyContext )
  6078. {
  6079. bool fSerialize = MyContext.ExtractAttribute( ATTR_SERIALIZE ) != 0;
  6080. bool fNoSerialize = MyContext.ExtractAttribute( ATTR_NOSERIALIZE ) != 0;
  6081. bool fContextHandle = MyContext.ExtractAttribute( ATTR_CONTEXT ) != 0;
  6082. // See if context_handle applied to param reached us
  6083. if ( fContextHandle )
  6084. {
  6085. // not allowed in DCE mode; context handle must be void *
  6086. TypeSemError( this, MyContext, CONTEXT_HANDLE_VOID_PTR, 0 );
  6087. TypeSemError( this, MyContext, CTXT_HDL_NON_PTR, 0 );
  6088. }
  6089. else
  6090. {
  6091. if ( fSerialize || fNoSerialize )
  6092. {
  6093. SemError( this, MyContext, NO_CONTEXT_HANDLE, GetSymName() );
  6094. }
  6095. }
  6096. if ( fSerialize && fNoSerialize )
  6097. {
  6098. SemError( this, MyContext, CONFLICTING_ATTRIBUTES, GetSymName() );
  6099. }
  6100. return fContextHandle;
  6101. }
  6102. extern CMessageNumberList GlobalMainMessageNumberList;
  6103. void
  6104. node_midl_pragma::SemanticAnalysis( SEM_ANALYSIS_CTXT* )
  6105. {
  6106. ProcessPragma();
  6107. }
  6108. void
  6109. node_midl_pragma::ProcessPragma()
  6110. {
  6111. LONG_PTR ulMsg = 0;
  6112. m_pMsgList->Init();
  6113. while ( m_pMsgList->GetNext( (void**) &ulMsg ) == STATUS_OK )
  6114. {
  6115. if ( m_PragmaType == mp_MessageDisable )
  6116. {
  6117. GlobalMainMessageNumberList.ResetMessageFlag( (long)ulMsg );
  6118. }
  6119. else
  6120. {
  6121. GlobalMainMessageNumberList.SetMessageFlag( (long)ulMsg );
  6122. }
  6123. }
  6124. }
  6125. void
  6126. node_decl_guid::SemanticAnalysis( SEM_ANALYSIS_CTXT* )
  6127. {
  6128. }