360 lines
9.4 KiB
C++
360 lines
9.4 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
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);
|
|
}
|
|
}
|
|
}
|