/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Copyright (c) 1989-1999 Microsoft Corporation Module Name: walkctxt.cxx Abstract: typegraph walk context block routines Notes: Author: GregJen Oct-27-1993 Created. Notes: ----------------------------------------------------------------------------*/ #pragma warning ( disable : 4514 4706 ) /**************************************************************************** * include files ***************************************************************************/ #include "allnodes.hxx" #include "walkctxt.hxx" #include "cmdana.hxx" #include "semantic.hxx" #include "control.hxx" /**************************************************************************** * local data ***************************************************************************/ /**************************************************************************** * externs ***************************************************************************/ extern ATTR_SUMMARY FieldAttrs; extern CMD_ARG * pCommand; extern ccontrol * pCompiler; extern ATTR_SUMMARY RedundantsOk; /**************************************************************************** * definitions ***************************************************************************/ // Extract a single attribute from the attribute list (and remove from // summary). node_base_attr * ATTR_ITERATOR::GetAttribute( ATTR_T Attr ) { return AllAttrs[ Attr ]; } // Extract a single attribute from the attribute list (and remove from // summary). node_base_attr * ATTR_ITERATOR::ExtractAttribute( ATTR_T Attr ) { node_base_attr * pResult = AllAttrs[ Attr ]; if ( !pResult ) { return pResult; } // if there were extras of a redundant attr, get the next one from the list if ( ( Attr <= REDUNDANT_ATTR_END ) && RedundantAttrExtras[ Attr ].NonNull() ) { RedundantAttrExtras[ Attr ].GetCurrent( (void **)&AllAttrs[Attr] ); RedundantAttrExtras[ Attr ].RemoveHead(); } else // no more of this attribute { AllAttrs[Attr] = NULL; RESET_ATTR( Summary, Attr ); } return pResult; } void ATTR_ITERATOR::ExtractFieldAttributes( FIELD_ATTR_INFO * FACtxt ) { node_base_attr * pAttrNode; expr_node * pExpr; if ( pAttrNode = ExtractAttribute( ATTR_FIRST ) ) { pExpr = pAttrNode->GetExpr(); if ( pExpr ) FACtxt->SetFirstIs( pExpr ); } if ( pAttrNode = ExtractAttribute( ATTR_LAST ) ) { pExpr = pAttrNode->GetExpr(); if ( pExpr ) FACtxt->SetLastIs( pExpr ); } if ( pAttrNode = ExtractAttribute( ATTR_LENGTH ) ) { pExpr = pAttrNode->GetExpr(); if ( pExpr ) FACtxt->SetLengthIs( pExpr ); } if ( pAttrNode = ExtractAttribute( ATTR_MIN ) ) { pExpr = pAttrNode->GetExpr(); if ( pExpr ) FACtxt->SetMinIs( pExpr ); } if ( pAttrNode = ExtractAttribute( ATTR_MAX ) ) { pExpr = pAttrNode->GetExpr(); if ( pExpr ) FACtxt->SetMaxIs( pExpr ); } if ( pAttrNode = ExtractAttribute( ATTR_SIZE ) ) { pExpr = pAttrNode->GetExpr(); if ( pExpr ) FACtxt->SetSizeIs( pExpr ); } // pass iid_is and string attrs on to child if ( (FACtxt->Control & FA_CHILD_IS_ARRAY_OR_PTR) == 0 ) { if ( pAttrNode = ExtractAttribute( ATTR_IID_IS ) ) { FACtxt->SetIIDIs( pAttrNode->GetExpr() ); } if ( pAttrNode = ExtractAttribute( ATTR_STRING ) ) { FACtxt->SetString(); } if ( pAttrNode = ExtractAttribute( ATTR_BSTRING ) ) { FACtxt->SetBString(); } } } // this routine searches up the context stack looking for a // matching node WALK_CTXT * WALK_CTXT::FindAncestorContext( NODE_T Kind ) { WALK_CTXT * pCur = this; while ( pCur ) { if ( (pCur->GetParent())->NodeKind() == Kind ) return pCur; pCur = pCur->GetParentContext(); } return NULL; } // this routine searches up the context stack looking for a // matching node WALK_CTXT * WALK_CTXT::FindRecursiveContext( node_skl * self ) { WALK_CTXT * pCur = this; while ( pCur ) { if ( pCur->GetParent() == self ) return pCur; pCur = pCur->GetParentContext(); } return NULL; } // this routine searches up the context stack looking for a // node other than a typedef WALK_CTXT * WALK_CTXT::FindNonDefAncestorContext( ) { WALK_CTXT * pCur = this->GetParentContext(); while ( pCur ) { if ( (pCur->GetParent())->NodeKind() != NODE_DEF ) return pCur; pCur = pCur->GetParentContext(); } return NULL; } // for my context, find the appropriate pointer kind ( and extract it if needed ) PTRTYPE WALK_CTXT::GetPtrKind( BOOL * pfExplicitPtrAttr ) { PTRTYPE PtrKind = PTR_UNKNOWN; node_ptr_attr * pPtrAttr; node_interface * pIntf; BOOL fMsExt = pCommand->IsSwitchDefined( SWITCH_MS_EXT ); WALK_CTXT * pImportantCtxt = ( fMsExt ) ? FindNonDefAncestorContext() : GetParentContext(); BOOL fBelowParam = (pImportantCtxt->GetParent()->NodeKind()) == NODE_PARAM; node_interface * pItsIntf = GetParent()->GetMyInterfaceNode(); //////////////////////////////////////////////////////////////////////// // process pointer attributes if ( pfExplicitPtrAttr ) *pfExplicitPtrAttr = FALSE; if ( FInSummary( ATTR_PTR_KIND ) ) { pPtrAttr = (node_ptr_attr *) ExtractAttribute( ATTR_PTR_KIND ); PtrKind = pPtrAttr->GetPtrKind(); if ( pfExplicitPtrAttr && ( PtrKind == PTR_REF || PtrKind == PTR_FULL ) ) { *pfExplicitPtrAttr = TRUE; } } // top level pointer under param is ref ptr unless explicitly changed else if ( fBelowParam ) { PtrKind = PTR_REF; } // pointer default on defining interface else if ( pItsIntf->FInSummary( ATTR_PTR_KIND ) ) { pPtrAttr = (node_ptr_attr *) pItsIntf->GetAttribute( ATTR_PTR_KIND ); PtrKind = pPtrAttr->GetPtrKind(); } // pointer default on using interface else if ( (pIntf=GetInterfaceNode()) ->FInSummary( ATTR_PTR_KIND ) ) { pPtrAttr = (node_ptr_attr *) pIntf->GetAttribute( ATTR_PTR_KIND ); // semantics verifies that there is exactly one here... // ...and adds REF if needed PtrKind = pPtrAttr->GetPtrKind(); } else // global default -- full for DCE, unique for MS_EXT { if ( fMsExt ) { PtrKind = PTR_UNIQUE; } else { PtrKind = PTR_FULL; } } return PtrKind; } // get all the operation bits (MAYBE, IDEMPOTENT, BROADCAST, etc. unsigned short WALK_CTXT::GetOperationBits() { unsigned short Bits = 0; if ( ExtractAttribute( ATTR_MAYBE )) Bits |= OPERATION_MAYBE; if ( ExtractAttribute( ATTR_BROADCAST )) Bits |= OPERATION_BROADCAST; if ( ExtractAttribute( ATTR_IDEMPOTENT )) Bits |= OPERATION_IDEMPOTENT; if ( ExtractAttribute( ATTR_MESSAGE )) Bits |= OPERATION_MESSAGE; if ( ExtractAttribute( ATTR_INPUTSYNC )) Bits |= OPERATION_INPUT_SYNC; return Bits; } // add all the attributes to the attribute list; for duplicates, report the duplicate void WALK_CTXT::AddAttributes( named_node * pNode ) { ATTRLIST MyAttrs; node_base_attr * pCurAttr; ATTR_T CurAttrKind; pNode->GetAttributeList( MyAttrs ); pCurAttr = MyAttrs.GetFirst(); while ( pCurAttr ) { CurAttrKind = pCurAttr->GetAttrID(); if ( ( pDownAttrList->FInSummary( CurAttrKind ) ) && ( !IS_ATTR( RedundantsOk , CurAttrKind ) ) ) { ProcessDuplicates( pCurAttr ); } else pDownAttrList->Add( pCurAttr ); pCurAttr = pCurAttr->GetNext(); } } void WALK_CTXT::ProcessDuplicates( node_base_attr * pAttr ) { if ( pCompiler->GetPassNumber() == SEMANTIC_PASS ) { STATUS_T errnum = ((pAttr->GetAttrID() > NO_DUPLICATES_END)? REDUNDANT_ATTRIBUTE : DUPLICATE_ATTR); // it is safe to use SemError on us, since it only uses parts of OUR // context that are ready, even though this is called during the constructor if ( pAttr->IsAcfAttr() ) { AcfError( (acf_attr *)pAttr, NULL, *((SEM_ANALYSIS_CTXT *)this), errnum, NULL); } else { char * pAttrName = pAttr->GetNodeNameString(); SemError( NULL, *((SEM_ANALYSIS_CTXT *)this), errnum ,pAttrName); } } }