template.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,056 行 · 第 1/5 页
C
2,056 行
/****************************************************************************
*
* 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 "cgfront.h"
#include "errdefns.h"
#include "rewrite.h"
#include "preproc.h"
#include "ring.h"
#include "stack.h"
#include "memmgr.h"
#include "class.h"
#include "name.h"
#include "yydriver.h"
#include "fnovload.h"
#include "context.h"
#include "template.h"
#include "pcheader.h"
#include "initdefs.h"
#ifndef NDEBUG
#include "pragdefn.h"
#include "dbg.h"
#endif
#define BLOCK_TEMPLATE_INFO 16
#define BLOCK_TEMPLATE_SPECIALIZATION 16
#define BLOCK_CLASS_INST 32
#define BLOCK_TEMPLATE_MEMBER 32
#define BLOCK_FN_TEMPLATE_DEFN 16
static carve_t carveTEMPLATE_INFO;
static carve_t carveTEMPLATE_SPECIALIZATION;
static carve_t carveCLASS_INST;
static carve_t carveTEMPLATE_MEMBER;
static carve_t carveFN_TEMPLATE_DEFN;
static TEMPLATE_DATA *currentTemplate;
static TEMPLATE_INFO *allClassTemplates;
static FN_TEMPLATE_DEFN *allFunctionTemplates; // only ones with definitions
static struct {
unsigned max_depth;
unsigned curr_depth;
tc_fn_control fn_control;
SYMBOL translate_fn;
TYPE extra_member_class;
unsigned keep_going : 1;
unsigned extra_members : 1;
unsigned depth_diagnosed : 1;
} templateData;
static CNV_DIAG diagTempParm = // DIAGNOSIS FOR TEMPLATE ARGUMENT CONVERSION
{ ERR_PARM_IMPOSSIBLE
, ERR_PARM_AMBIGUOUS
, ERR_CALL_WATCOM
, ERR_PARM_PRIVATE
, ERR_PARM_PROTECTED
};
enum template_context_type {
TCTX_CLASS_DEFN = 1, // instantiating template class defn
TCTX_FN_DEFN = 2, // instantiating template function defn
TCTX_MEMBER_DEFN = 3, // instantiating template class member defn
TCTX_FN_BIND = 4, // binding a function template to arguments
TCTX_FN_BIND_AND_GEN= 5, // binding a function template to a fn sym
TCTX_NULL = 0
};
typedef struct template_context TEMPLATE_CONTEXT;
struct template_context {
TEMPLATE_CONTEXT *prev;
TOKEN_LOCN *locn;
union {
SYMBOL sym; // FN_DEFN, FN_BIND
SCOPE scope; // CLASS_DEFN
void *any;
} u;
enum template_context_type id;
};
static struct {
NESTED_POST_CONTEXT registration;
TEMPLATE_CONTEXT *inst_stack;
} activeInstantiations;
static SUICIDE_CALLBACK templateSuicide;
static void injectTemplateParm( SCOPE scope, PTREE parm, char *name );
static void templateSuicideHandler( void )
{
activeInstantiations.inst_stack = NULL;
templateData.curr_depth = 0;
}
static SYMBOL firstSymbol( SCOPE scope )
{
SYMBOL first;
first = ScopeOrderedFirst( scope );
DbgAssert( first != NULL );
return( first );
}
static void verifyOKToProceed( TOKEN_LOCN *locn )
{
templateData.curr_depth++;
if( templateData.curr_depth > templateData.max_depth ) {
if( ! templateData.depth_diagnosed ) {
templateData.depth_diagnosed = TRUE;
SetErrLoc( locn );
CErr2( ERR_TEMPLATE_DEPTH_EXHAUSTED, templateData.max_depth * 2 );
CSuicide();
}
}
}
static void pushInstContext( TEMPLATE_CONTEXT *ctx,
enum template_context_type id,
TOKEN_LOCN *locn, void *extra_info )
{
verifyOKToProceed( locn );
ctx->id = id;
ctx->locn = locn;
ctx->u.any = extra_info;
StackPush( &(activeInstantiations.inst_stack), ctx );
}
static void popInstContext( void )
{
templateData.curr_depth--;
StackPop( &(activeInstantiations.inst_stack) );
}
static TYPE extractTemplateClass( TEMPLATE_CONTEXT *ctx )
{
SYMBOL sym;
sym = firstSymbol( ctx->u.scope );
if( sym == NULL ) {
return( TypeError );
}
DbgAssert( sym->id == SC_TYPEDEF );
return( sym->sym_type );
}
static void displayActiveInstantiations( NESTED_POST_CONTEXT *blk )
{
TEMPLATE_CONTEXT *ctx;
#ifndef NDEBUG
if( blk != &(activeInstantiations.registration) ) {
CFatal( "registered call-back for template locations incorrect" );
}
#else
blk = blk;
#endif
Stack_forall( activeInstantiations.inst_stack, ctx ) {
if( ctx->locn != NULL ) {
switch( ctx->id ) {
case TCTX_CLASS_DEFN:
AddNoteMessage( INF_TEMPLATE_CLASS_DEFN_TRACEBACK,
extractTemplateClass( ctx ), ctx->locn );
break;
case TCTX_FN_DEFN:
AddNoteMessage( INF_TEMPLATE_FN_DEFN_TRACEBACK,
ctx->u.sym, ctx->locn );
break;
case TCTX_MEMBER_DEFN:
AddNoteMessage( INF_TEMPLATE_MEMBER_DEFN_TRACEBACK,
ctx->locn );
break;
case TCTX_FN_BIND:
AddNoteMessage( INF_TEMPLATE_FN_BIND_TRACEBACK,
ctx->u.sym, ctx->locn );
break;
case TCTX_FN_BIND_AND_GEN:
AddNoteMessage( INF_TEMPLATE_FN_BIND_AND_GEN_TRACEBACK,
ctx->u.sym, ctx->locn );
break;
}
}
}
}
void TemplateSetDepth( unsigned depth )
/*************************************/
{
if( depth < 2 ) {
/* we need at least 2 in order to bind a function */
depth = 2;
}
templateData.max_depth = depth;
}
static void templateInit( INITFINI* defn )
{
defn = defn;
if( CompFlags.dll_subsequent ) {
currentTemplate = NULL;
allClassTemplates = NULL;
allFunctionTemplates = NULL;
memset( &templateData, 0, sizeof( templateData ) );
}
templateData.max_depth = TEMPLATE_MAX_DEPTH;
activeInstantiations.registration.call_back = displayActiveInstantiations;
CtxRegisterPostContext( &(activeInstantiations.registration) );
templateSuicide.call_back = templateSuicideHandler;
RegisterSuicideCallback( &templateSuicide );
carveTEMPLATE_INFO = CarveCreate( sizeof( TEMPLATE_INFO ), BLOCK_TEMPLATE_INFO );
carveTEMPLATE_SPECIALIZATION = CarveCreate( sizeof( TEMPLATE_SPECIALIZATION ), BLOCK_TEMPLATE_SPECIALIZATION );
carveCLASS_INST = CarveCreate( sizeof( CLASS_INST ), BLOCK_CLASS_INST );
carveTEMPLATE_MEMBER = CarveCreate( sizeof( TEMPLATE_MEMBER ), BLOCK_TEMPLATE_MEMBER );
carveFN_TEMPLATE_DEFN = CarveCreate( sizeof( FN_TEMPLATE_DEFN ), BLOCK_FN_TEMPLATE_DEFN );
}
static void templateFini( INITFINI *defn )
{
defn = defn;
CarveDestroy( carveTEMPLATE_INFO );
CarveDestroy( carveTEMPLATE_SPECIALIZATION );
CarveDestroy( carveCLASS_INST );
CarveDestroy( carveTEMPLATE_MEMBER );
CarveDestroy( carveFN_TEMPLATE_DEFN );
}
INITDEFN( template, templateInit, templateFini )
static TYPE setArgIndex( SYMBOL sym, unsigned index )
{
TYPE type;
type = sym->sym_type;
DbgAssert( type->id == TYP_GENERIC );
DbgAssert( type->next == NULL );
type->u.g.index = index;
type = CheckDupType( type );
sym->sym_type = type;
return type;
}
void TemplateDeclInit( TEMPLATE_DATA *data )
/***********************************************************/
{
StackPush( ¤tTemplate, data );
CErrCheckpoint( &(data->errors) );
data->all_generic = TRUE;
data->args = NULL;
data->nr_args = 0;
data->spec_args = NULL;
data->unbound_type = NULL;
data->decl_scope = ScopeBegin( SCOPE_TEMPLATE_DECL );
data->defn = NULL;
data->member_defn = NULL;
data->template_name = NULL;
data->template_scope = NULL;
data->locn.src_file = NULL;
data->defn_found = FALSE;
data->member_found = FALSE;
data->defn_added = FALSE;
}
static void validateNonTypeParameterType( TYPE type )
{
TYPE trimmed_type;
trimmed_type = TypedefModifierRemoveOnly( type );
if( ( trimmed_type->id == TYP_POINTER ) // reference is also ok
|| ( trimmed_type->id == TYP_GENERIC ) ) {
return;
}
if( IntegralType( trimmed_type ) == NULL ) {
CErr2p( ERR_INVALID_TEMPLATE_ARG_TYPE, trimmed_type );
}
}
void TemplateDeclAddArgument( DECL_INFO *new_dinfo )
{
SYMBOL sym;
char *name;
currentTemplate->args = AddArgument( currentTemplate->args, new_dinfo );
currentTemplate->nr_args++;
name = new_dinfo->name;
sym = new_dinfo->generic_sym;
if( sym != NULL ) {
/* template type parameter */
new_dinfo->type = setArgIndex( sym, currentTemplate->nr_args );
DbgAssert( name != NULL );
sym = ScopeInsert( GetCurrScope(), sym, name );
} else if( ( new_dinfo->type != NULL ) ) {
/* template non-type parameter */
currentTemplate->all_generic = FALSE;
if( name != NULL ) {
sym = ScopeInsert( GetCurrScope(),
AllocTypedSymbol( new_dinfo->type ), name );
}
validateNonTypeParameterType( new_dinfo->type );
}
}
static unsigned getArgList( DECL_INFO *args, TYPE *type_list, char **names, REWRITE **defarg_list )
{
DECL_INFO *curr;
unsigned count;
count = 0;
RingIterBeg( args, curr ) {
if( type_list != NULL ) {
type_list[count] = curr->type;
}
if( names != NULL ) {
names[count] = curr->name;
}
if( defarg_list != NULL ) {
/*
// Ensure that we NULL out curr->defarg_rewrite or else
// when we delete the DECL_INFO, the rewrite element gets
// freed as well. The rewrite info will be freed when the
// the template info is freed.
*/
defarg_list[count] = curr->defarg_rewrite;
curr->defarg_rewrite = NULL;
}
++count;
} RingIterEnd( curr )
return( count );
}
static TEMPLATE_SPECIALIZATION *newTemplateSpecialization(
TEMPLATE_DATA *data, TEMPLATE_INFO *tinfo )
{
DECL_INFO *args;
TEMPLATE_SPECIALIZATION *tspec;
TEMPLATE_SPECIALIZATION *tprimary;
unsigned arg_count;
tinfo->nr_specs++;
args = data->args;
arg_count = getArgList( args, NULL, NULL, NULL );
tspec = RingCarveAlloc( carveTEMPLATE_SPECIALIZATION,
&tinfo->specializations );
tprimary = RingFirst( tinfo->specializations );
tspec->tinfo = tinfo;
tspec->instantiations = NULL;
tspec->member_defns = NULL;
tspec->decl_scope = ( arg_count > 0 ) ? data->decl_scope : NULL;
TokenLocnAssign( tspec->locn, data->locn );
tspec->num_args = arg_count;
tspec->type_list = CPermAlloc( arg_count * sizeof( TYPE ) );
tspec->arg_names = CPermAlloc( arg_count * sizeof( char * ) );
tspec->spec_args = data->spec_args;
data->spec_args = NULL;
tspec->ordering = NULL;
tspec->defn = NULL;
tspec->corrupted = FALSE;
tspec->defn_found = FALSE;
tspec->free = FALSE;
getArgList( args, tspec->type_list, tspec->arg_names, NULL );
return( tspec );
}
static TEMPLATE_INFO *newTemplateInfo( TEMPLATE_DATA *data )
{
DECL_INFO *args;
TEMPLATE_INFO *tinfo;
TEMPLATE_SPECIALIZATION *tprimary;
unsigned arg_count;
args = data->args;
arg_count = getArgList( args, NULL, NULL, NULL );
if( arg_count == 0 ) {
CErr1( ERR_TEMPLATE_MUST_HAVE_ARGS );
}
tinfo = RingCarveAlloc( carveTEMPLATE_INFO, &allClassTemplates );
tinfo->specializations = NULL;
tinfo->nr_specs = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?