class.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,168 行 · 第 1/5 页
C
2,168 行
/****************************************************************************
*
* 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: Handle processing of declarations within classes.
*
****************************************************************************/
#include "plusplus.h"
#include <malloc.h>
#include <limits.h>
#include "codegen.h"
#include "cgfront.h"
#include "errdefns.h"
#include "preproc.h"
#include "fnbody.h"
#include "ring.h"
#include "carve.h"
#include "vbuf.h"
#include "name.h"
#include "rewrite.h"
#include "yydriver.h"
#include "template.h"
#include "pcheader.h"
#include "decl.h"
#include "class.h"
#include "brinfo.h"
#include "pragdefn.h"
/*
Future object model changes:
- force vfptr to offset 0 (if possible)
- ensure that the following matches VC++ under -zp8
struct S {
char c;
double d;
void virtual foo( int );
};
- optimize more empty bases: when laying down a base class,
overlay an empty base class on top of it
(see notes\empty.c compiled with VC++)
- record padding, stuff empty base classes into the padding
*/
static CLASS_DATA *classDataStack;
#define BLOCK_BASE_CLASS 16
#define BLOCK_VF_HIDE 16
static carve_t carveBASE_CLASS;
static carve_t carveVF_HIDE;
struct vf_hide {
VF_HIDE *next;
SYMBOL_NAME derived;
SYMBOL_NAME base;
};
// new offset can equal old offset for zero sized array at end of struct
#if TARGET_UINT_MAX < 0x010000
#define _CLASS_CHECK_SIZE( n, o ) \
if( ((n) < (o)) || ((n) > TARGET_UINT_MAX) ) { \
CErr1( ERR_MAX_STRUCT_EXCEEDED ); \
}
#else
#define _CLASS_CHECK_SIZE( n, o ) \
if( (n) < (o) ) { \
CErr1( ERR_MAX_STRUCT_EXCEEDED ); \
}
#endif
#define _IS_DEFAULT_INLINE ( OptSize <= 50 )
enum {
CC_CONST = 0x01, /* first arg is const */
CC_REF = 0x02, /* first arg is a reference */
CC_NULL = 0x00
};
typedef enum {
PROP_BASE = 0x01, /* propagating from a base class */
PROP_STATIC = 0x02, /* propagating from a static member */
PROP_NULL = 0x00
} prop_type;
static uint_16 classIndex;
#ifndef NDEBUG
void DumpClasses( void )
{
CLASS_DATA *data;
printf( "---\n" );
for( data = classDataStack; data != NULL; data = data->next ) {
extern void DumpFullType( TYPE );
printf( "%p: ", data );
DumpFullType( data->type );
printf( "'%s' "
"inline_data %p "
"\n",
data->name,
data->inline_data,
0 );
}
}
#endif
void ClassInit( void )
/********************/
{
carveBASE_CLASS = CarveCreate( sizeof( BASE_CLASS ), BLOCK_BASE_CLASS );
carveVF_HIDE = CarveCreate( sizeof( VF_HIDE ), BLOCK_VF_HIDE );
classIndex = 0;
}
void ClassFini( void )
/********************/
{
#ifndef NDEBUG
CarveVerifyAllGone( carveVF_HIDE, "VF_HIDE" );
#endif
CarveDestroy( carveVF_HIDE );
CarveDestroy( carveBASE_CLASS );
}
target_offset_t PackAlignment( target_offset_t pack_amount, target_size_t size )
/******************************************************************************/
{
target_offset_t pack_adjustment;
if( pack_amount == 1 ) {
return( 1 );
}
pack_adjustment = pack_amount;
switch( size ) {
case 1:
pack_adjustment = 1;
break;
case 2:
if( pack_adjustment > 2 ) {
pack_adjustment = 2;
}
break;
case 4:
if( pack_adjustment > 4 ) {
pack_adjustment = 4;
}
break;
case 8:
if( pack_adjustment > 8 ) {
pack_adjustment = 8;
}
break;
}
return( pack_adjustment );
}
static target_offset_t packSize( CLASS_DATA *data, TYPE type )
{
target_size_t align_size;
align_size = CgMemorySize( AlignmentType( type ) );
return( PackAlignment( data->pack_amount, align_size ) );
}
static void doAlignment( CLASS_DATA *data, target_offset_t adjustment )
{
target_size_t old_offset;
target_size_t calc_offset;
if( adjustment != 1 ) {
old_offset = data->offset;
calc_offset = old_offset;
calc_offset += adjustment - 1;
calc_offset &= ~(((target_size_t) adjustment ) - 1 );
_CLASS_CHECK_SIZE( calc_offset, data->offset );
data->offset = calc_offset;
if( calc_offset != old_offset && CompFlags.warn_about_padding ) {
CErr2( WARN_PADDING_ADDED, ( calc_offset - old_offset ) );
}
}
}
static target_offset_t addField( CLASS_DATA *data, target_size_t size,
target_offset_t pack_amount )
{
target_size_t calc_offset;
target_offset_t start;
target_offset_t save_end;
if( pack_amount > data->max_align ) {
data->max_align = pack_amount;
}
save_end = data->offset;
if( data->is_union ) {
data->offset = data->start;
}
doAlignment( data, pack_amount );
start = data->offset;
calc_offset = start;
calc_offset += size;
_CLASS_CHECK_SIZE( calc_offset, start );
data->offset = calc_offset;
if( data->is_union ) {
if( save_end > data->offset ) {
data->offset = save_end;
}
}
return( start );
}
static target_offset_t addTypeField( CLASS_DATA *data, TYPE type )
{
return( addField( data, CgMemorySize( type ), packSize( data, type ) ) );
}
static target_offset_t addZeroSizedField( CLASS_DATA *data, TYPE type )
{
return( addField( data, 0, packSize( data, type ) ) );
}
void ClassInitState( type_flag class_variant, CLASS_INIT extra, TYPE class_mod_list )
/***********************************************************************************/
{
CLASS_DATA *data;
CLASS_DATA *prev_data;
unsigned packing;
TYPE class_mod_type;
packing = PackAmount;
if( extra & CLINIT_PACKED ) {
packing = TARGET_CHAR;
}
data = classDataStack;
data->sym = NULL;
data->type = NULL;
data->scope = NULL;
data->info = NULL;
data->bases = NULL;
data->base_vbptr = NULL;
data->base_vfptr = NULL;
data->name = NULL;
data->inlines = NULL;
data->defargs = NULL;
data->vf_hide_list = NULL;
data->offset = 0;
data->vb_offset = 0;
data->vf_offset = 0;
data->vf_index = 0;
data->vb_index = 0;
data->max_align = 0;
data->pack_amount = packing;
data->tflag = class_variant;
data->bitfield = FALSE;
data->defined = FALSE;
data->local_class = FALSE;
data->nested_class = FALSE;
data->allow_typedef = FALSE;
data->own_vfptr = FALSE;
data->nameless_OK = FALSE;
data->generic = FALSE;
data->specific_defn = FALSE;
data->is_explicit = TRUE;
data->is_union = FALSE;
data->zero_array_defd = FALSE;
data->member_mod_adjust = FALSE;
data->class_idiom = FALSE;
data->class_template = FALSE;
data->a_public = FALSE;
data->a_protected = FALSE;
data->a_private = FALSE;
data->a_const = FALSE;
data->a_reference = FALSE;
data->has_const_copy = FALSE;
data->has_nonconst_copy = FALSE;
data->has_const_opeq = FALSE;
data->has_nonconst_opeq = FALSE;
data->has_explicit_opeq = FALSE;
data->in_defn = FALSE;
class_mod_type = NULL;
if( class_mod_list != NULL ) {
class_mod_type = ProcessClassModifiers( class_mod_list, &(data->mod_flags), &(data->fn_flags), &(data->fn_pragma) );
data->member_mod_adjust = TRUE;
}
data->class_mod_type = class_mod_type;
if( extra & CLINIT_TEMPLATE_DECL ) {
data->class_template = TRUE;
}
prev_data = data->next;
if( prev_data != NULL ) {
if( ( prev_data->info != NULL ) && prev_data->info->defined ) {
data->inline_data = NULL;
} else {
/* our inline fns go where any previous class' inline fns
* go, but only if the previous class isn't already fully
* defined */
data->inline_data = prev_data->inline_data;
}
} else {
data->inline_data = NULL;
}
switch( ScopeId( GetCurrScope() ) ) {
case SCOPE_BLOCK:
data->local_class = TRUE;
break;
case SCOPE_CLASS:
data->nested_class = TRUE;
break;
case SCOPE_TEMPLATE_INST:
data->tflag |= TF1_INSTANTIATION;
break;
}
if( class_variant & (TF1_STRUCT|TF1_UNION) ) {
data->perm = SF_NULL;
if( class_variant & TF1_UNION ) {
data->is_union = TRUE;
}
} else {
data->perm = SF_PRIVATE;
}
CErrCheckpoint( &(data->errors) );
}
void ClassAddFunctionMods( TYPE fn_declarator )
/*********************************************/
{
CLASS_DATA *data;
data = classDataStack;
if( data != NULL && data->member_mod_adjust ) {
SetFnClassMods( fn_declarator, data->fn_flags, data->fn_pragma );
}
}
void ClassPermission( symbol_flag new_perm )
/******************************************/
{
classDataStack->perm = new_perm;
}
static void typeError( int msg, TYPE type )
{
CErr2p( msg, type );
}
static boolean verifyNoChangePerm( CLASS_DATA *data, symbol_flag perm, char *name )
{
if( perm != data->perm ) {
/* data->perm is 'protected' or 'public' */
if( data->perm & SF_PROTECTED ) {
if( perm & SF_PRIVATE ) {
CErr2p( ERR_ACCESS_DECL_INCREASE, name );
} else {
CErr2p( ERR_ACCESS_DECL_DECREASE, name );
}
} else {
CErr2p( ERR_ACCESS_DECL_INCREASE, name );
}
return( TRUE );
}
return( FALSE );
}
static boolean handleAccessDeclaration( PTREE id_tree )
{
PTREE scope_tree;
PTREE name_tree;
CLASS_DATA *data;
char *name;
TYPE type;
TYPE udc_return_type;
SCOPE scope;
SCOPE curr_scope;
SEARCH_RESULT *result;
SYMBOL_NAME sym_name;
SYMBOL sym;
SYMBOL curr_sym;
SYMBOL check_sym;
SYMBOL access_sym;
symbol_flag perm;
symbol_flag curr_perm;
boolean error_diagnosed;
auto TOKEN_LOCN name_locn;
error_diagnosed = FALSE;
data = classDataStack;
if( data->perm & SF_PRIVATE ) {
CErr1( ERR_ACCESS_DECL_IN_PRIVATE );
error_diagnosed = TRUE;
}
if( id_tree->op != PT_BINARY || id_tree->cgop != CO_COLON_COLON ) {
/* error occurred in the C part of C::id (ignore this declaration) */
return( error_diagnosed );
}
name_locn = id_tree->locn;
name_tree = id_tree->u.subtree[1];
name = name_tree->u.id.name;
udc_return_type = NULL;
if( name == CppConversionName() ) {
udc_return_type = name_tree->type;
}
type = NULL;
scope_tree = id_tree->u.subtree[0];
if( scope_tree != NULL ) {
type = scope_tree->type;
}
PTreeFreeSubtrees( id_tree );
if( type == NULL ) {
/* error occurred in the C part of C::id (ignore this declaration) */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?