namspace.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 471 行
C
471 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "plusplus.h"
#include "errdefns.h"
#include "memmgr.h"
#include "ptree.h"
#include "name.h"
#include "namspace.h"
#include "cgfront.h"
#include "template.h"
#include "ring.h"
#include "class.h"
typedef enum {
FNS_LEXICAL = 0x01,
FNS_NULL = 0x00
} find_ns;
static SYMBOL injectNameSpaceSym( SYMBOL sym
, NAME_SPACE *ns
, SCOPE scope
, char *name
, TOKEN_LOCN *locn )
{
SYMBOL ret_sym;
if( sym == NULL ) {
sym = AllocSymbol();
}
sym->id = SC_NAMESPACE;
sym->u.ns = ns;
sym->sym_type = MakeNamespaceType();
SymbolLocnDefine( locn, sym );
ret_sym = ScopeInsert( scope, sym, name );
DbgAssert(( ret_sym == sym )||( ret_sym == NULL )||( ret_sym->id != SC_NAMESPACE ));
return( ret_sym );
}
static SYMBOL previousNSSym( char *name, SCOPE host_scope, find_ns control )
{
SEARCH_RESULT *result;
SYMBOL_NAME sym_name;
SYMBOL sym;
if( control & FNS_LEXICAL ) {
result = ScopeFindLexicalNameSpace( host_scope, name );
} else {
result = ScopeContainsNaked( host_scope, name );
}
if( result != NULL ) {
sym_name = result->sym_name;
ScopeFreeResult( result );
sym = sym_name->name_type;
if( sym != NULL ) {
if( SymIsNameSpace( sym ) ) {
return( sym );
}
}
}
return( NULL );
}
static void openNameSpaceSym( char *name, TOKEN_LOCN *locn )
{
char *ns_name;
SCOPE inject_scope;
SCOPE scope;
SYMBOL ns_sym;
if( name == NULL ) {
ns_name = ScopeUnnamedNamespaceName( locn );
} else {
ns_name = name;
}
inject_scope = GetCurrScope();
if( ScopeId( inject_scope ) != SCOPE_FILE ) {
CErr1( ERR_NAMESPACE_MUST_BE_GLOBAL );
inject_scope = ScopeNearestFile( inject_scope );
}
ns_sym = previousNSSym( ns_name, inject_scope, FNS_NULL );
if( ns_sym != NULL ) {
SCOPE ns_scope = ns_sym->u.ns->scope;
ScopeOpen( ns_scope );
ScopeRestoreUsing( ns_scope );
} else {
ns_sym = AllocSymbol();
scope = ScopeOpenNameSpace( name, ns_sym );
injectNameSpaceSym( ns_sym, scope->owner.ns, inject_scope, ns_name, locn );
}
}
void NameSpaceUnnamed( TOKEN_LOCN *locn )
/***************************************/
{
SCOPE old_curr;
SCOPE save_curr;
old_curr = GetCurrScope();
openNameSpaceSym( NULL, locn );
save_curr = GetCurrScope();
SetCurrScope(old_curr);
ScopeAddUsing( save_curr, old_curr );
SetCurrScope(save_curr);
}
void NameSpaceNamed( PTREE id )
/*****************************/
{
char *name;
name = id->u.id.name;
openNameSpaceSym( name, &(id->locn) );
PTreeFree( id );
}
void NameSpaceClose( void )
/*************************/
{
ScopeEnd( SCOPE_FILE );
}
static SCOPE getSearchScope( PTREE id, PTREE *find_id, find_ns *pcontrol )
{
PTREE scope_tree;
SCOPE find_scope;
SCOPE test_scope;
find_ns control;
find_scope = GetCurrScope();
control = FNS_LEXICAL;
*find_id = id;
if( id->op == PT_BINARY ) {
DbgAssert( id->cgop == CO_STORAGE );
*find_id = id->u.subtree[1];
scope_tree = id->u.subtree[0];
DbgAssert( scope_tree != NULL );
scope_tree = scope_tree->u.subtree[1];
if( scope_tree != NULL ) {
DbgAssert( scope_tree->op == PT_ID );
test_scope = scope_tree->u.id.scope;
if( test_scope != NULL ) {
find_scope = test_scope;
}
} else {
find_scope = GetFileScope();
}
control = FNS_NULL;
}
*pcontrol = control;
DbgAssert( find_scope != NULL );
return( find_scope );
}
void NameSpaceAlias( PTREE to_id, PTREE from_id )
/***********************************************/
{
char *alias_name;
PTREE id;
SCOPE find_scope;
NAME_SPACE *ns;
NAME_SPACE *prev_ns;
SYMBOL ns_sym;
SYMBOL prev_ns_sym;
find_ns control;
find_scope = getSearchScope( from_id, &id, &control );
ns_sym = previousNSSym( id->u.id.name, find_scope, control );
if( ns_sym != NULL ) {
ns = ns_sym->u.ns;
alias_name = to_id->u.id.name;
prev_ns_sym = previousNSSym( alias_name, GetCurrScope(), FNS_NULL );
if( prev_ns_sym == NULL ) {
injectNameSpaceSym( NULL, ns, GetCurrScope(), alias_name, &(to_id->locn) );
} else {
prev_ns = prev_ns_sym->u.ns;
if( ns != prev_ns ) {
PTreeErrorExpr( from_id, ERR_NAMESPACE_ALIAS_DIFFERENT );
}
}
} else {
PTreeErrorExpr( from_id, ERR_NAME_DOESNT_REF_NAMESPACE );
}
PTreeFreeSubtrees( to_id );
PTreeFreeSubtrees( from_id );
}
void NameSpaceUsingDirective( PTREE ns_id )
/*****************************************/
{
PTREE id;
SCOPE find_scope;
SYMBOL ns_sym;
find_ns control;
find_scope = getSearchScope( ns_id, &id, &control );
ns_sym = previousNSSym( id->u.id.name, find_scope, control );
if( ns_sym != NULL ) {
ScopeAddUsing( ns_sym->u.ns->scope, NULL );
} else {
PTreeErrorExpr( ns_id, ERR_NAME_DOESNT_REF_NAMESPACE );
}
PTreeFreeSubtrees( ns_id );
}
static void nameSpaceUsingDecl( SYMBOL ns_sym, TOKEN_LOCN *locn )
{
injectNameSpaceSym( NULL
, ns_sym->u.ns
, GetCurrScope()
, ns_sym->name->name
, locn );
}
static SEARCH_RESULT *lookupUsingId( PTREE using_id )
{
SCOPE scope;
SCOPE disambig;
PTREE left;
PTREE right;
char *name;
SEARCH_RESULT *result;
if( NodeIsBinaryOp( using_id, CO_COLON_COLON ) ) {
left = using_id->u.subtree[0];
if( left == NULL ) {
scope = GetFileScope();
} else {
DbgAssert( left->op == PT_TYPE );
scope = left->u.type.scope;
DbgAssert( scope != NULL );
}
right = using_id->u.subtree[1];
} else {
DbgAssert( using_id->op == PT_ID );
right = using_id;
scope = GetFileScope();
}
disambig = scope;
DbgAssert( right != NULL && right->op == PT_ID );
name = right->u.id.name;
DbgAssert( scope != NULL && name != NULL );
if( ScopeId( scope ) == SCOPE_CLASS ) {
if( right->cgop == CO_NAME_CONVERT ) {
result = ScopeFindScopedMemberConversion( scope
, disambig
, right->type
, TF1_NULL );
} else {
result = ScopeFindScopedMember( scope, disambig, name );
}
} else {
DbgAssert( ScopeId( scope ) == SCOPE_FILE );
result = ScopeFindScopedNaked( scope, disambig, name );
}
if( result == NULL ) {
PTreeErrorExprName( using_id, ERR_UNDECLARED_SYM, name );
PTreeFreeSubtrees( using_id );
}
return( result );
}
static boolean verifyUsingDecl( SCOPE scope )
{
boolean error_occurred;
if( scope == NULL ) {
return( TRUE );
}
error_occurred = FALSE;
if( ScopeId( GetCurrScope() ) == SCOPE_CLASS ) {
if( ScopeId( scope ) != SCOPE_CLASS ) {
CErr1( ERR_MEMBER_USING_DECL_REFS_NON_MEMBER );
error_occurred = TRUE;
} else {
derived_status is_a_base = DERIVED_YES;
if( ScopeDerived( GetCurrScope(), scope ) == DERIVED_NO ) {
is_a_base = DERIVED_NO;
} else if( GetCurrScope() == scope ) {
is_a_base = DERIVED_NO;
}
if( is_a_base == DERIVED_NO ) {
CErr2p( ERR_USING_DECL_NOT_A_BASE_CLASS, ScopeClass( scope ) );
error_occurred = TRUE;
}
}
} else {
DbgAssert( ScopeId( GetCurrScope() ) == SCOPE_FILE || ScopeId( GetCurrScope() ) == SCOPE_BLOCK );
if( ScopeId( scope ) == SCOPE_CLASS ) {
CErr1( ERR_USING_DECL_REFS_MEMBER );
error_occurred = TRUE;
} else {
if( GetCurrScope() == scope ) {
CErr1( ERR_USING_DECL_NAME_SAME );
error_occurred = TRUE;
}
}
}
return( error_occurred );
}
static void injectNameSpaceFns( SYMBOL from, SYMBOL to, TOKEN_LOCN *locn )
{
SYMBOL curr;
RingIterBegFrom( from, curr ) {
SymMakeAlias( curr, locn );
} RingIterEndTo( curr, to )
}
static void functionUsingDecl( SEARCH_RESULT *result, SYMBOL name_syms, TOKEN_LOCN *locn )
{
SYM_REGION *head;
SYM_REGION *curr;
if( ScopeId( result->scope ) == SCOPE_CLASS ) {
DbgAssert( ScopeId( GetCurrScope() ) == SCOPE_CLASS );
return;
}
ScopeCheckSymbol( result, name_syms );
head = result->region;
if( head != NULL ) {
RingIterBeg( head, curr ) {
injectNameSpaceFns( curr->from, curr->to, locn );
} RingIterEnd( curr )
} else {
injectNameSpaceFns( RingFirst( name_syms ), RingLast( name_syms ), locn );
}
}
static void varUsingDecl( SEARCH_RESULT *result, SYMBOL name_syms, TOKEN_LOCN *locn )
{
if( ScopeId( result->scope ) == SCOPE_CLASS ) {
DbgAssert( ScopeId( GetCurrScope() ) == SCOPE_CLASS );
return;
}
if( ScopeCheckSymbol( result, name_syms ) ) {
return;
}
SymMakeAlias( name_syms, locn );
}
void NameSpaceUsingDeclId( PTREE using_id )
/*****************************************/
{
SCOPE sym_scope;
SYMBOL_NAME sym_name;
SEARCH_RESULT *result;
TOKEN_LOCN id_locn;
SYMBOL name_type;
SYMBOL name_syms;
result = lookupUsingId( using_id );
if( result == NULL ) {
/* using_id has been freed for this case */
return;
}
sym_scope = result->scope;
if( !verifyUsingDecl( sym_scope ) ) {
PTreeExtractLocn( using_id, &id_locn );
ScopeResultErrLocn( result, &id_locn );
sym_name = result->sym_name;
name_type = sym_name->name_type;
name_syms = sym_name->name_syms;
if( name_type != NULL ) {
switch( name_type->id ) {
case SC_NAMESPACE:
nameSpaceUsingDecl( name_type, &id_locn );
break;
case SC_CLASS_TEMPLATE:
TemplateUsingDecl( name_type, &id_locn );
break;
case SC_TYPEDEF:
TypedefUsingDecl( NULL, name_type, &id_locn );
break;
DbgDefault( "unexpected storage class" );
}
if( name_syms == NULL ) {
ScopeCheckSymbol( result, name_type );
}
}
if( name_syms != NULL ) {
if( ScopeId( result->scope ) == SCOPE_CLASS ) {
DbgAssert( ScopeId( GetCurrScope() ) == SCOPE_CLASS );
// NYI: full using-decl semantics within a class
ClassAccessDeclaration( using_id, &id_locn );
using_id = NULL;
} else {
if( SymIsFunction( name_syms ) ) {
functionUsingDecl( result, name_syms, &id_locn );
} else {
varUsingDecl( result, name_syms, &id_locn );
}
}
}
}
PTreeFreeSubtrees( using_id );
ScopeFreeResult( result );
}
void NameSpaceUsingDeclType( DECL_SPEC *dspec )
/*********************************************/
{
SCOPE type_scope;
type_scope = dspec->scope;
if( ! verifyUsingDecl( type_scope ) ) {
TypedefUsingDecl( dspec, NULL, NULL );
}
PTypeRelease( dspec );
}
void NameSpaceUsingDeclTemplateName( PTREE tid )
/**********************************************/
{
SYMBOL_NAME sym_name;
TOKEN_LOCN id_locn;
SYMBOL name_type;
SYMBOL name_syms;
PTREE right;
DbgAssert( NodeIsBinaryOp( tid, CO_STORAGE ) );
right = tid->u.subtree[1];
DbgAssert( ( right->op == PT_ID ) );
PTreeExtractLocn( tid, &id_locn );
sym_name = tid->sym_name;
name_type = sym_name->name_type;
name_syms = sym_name->name_syms;
if( name_type != NULL ) {
switch( name_type->id ) {
case SC_CLASS_TEMPLATE:
TemplateUsingDecl( name_type, &id_locn );
break;
DbgDefault( "unexpected storage class" );
}
}
PTreeFreeSubtrees( tid );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?