decl.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,062 行 · 第 1/3 页
C
1,062 行
/****************************************************************************
*
* 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 <stddef.h>
#include "errdefns.h"
#include "fnovload.h"
#include "memmgr.h"
#include "ring.h"
#include "cgfront.h"
#include "template.h"
#include "decl.h"
#include "brinfo.h"
typedef enum base_info {
IS_REF = 0x01,
IS_CONST = 0x02,
IS_DLLIMPORT= 0x04,
IS_NULL = 0x00
} base_info;
typedef enum prev_sym_adjust {
PSA_USE_CURR_MODS = 0x01,
PSA_NULL = 0x00
} prev_sym_adjust;
typedef enum fn_stg_class_status {
FSCS_SAME_FN = 0x01,
FSCS_DIFF_FN = 0x02,
FSCS_NULL = 0x00
} fn_stg_class_status;
static TYPE baseTypeInfo( TYPE type, base_info *extra )
{
type_flag flags;
*extra = IS_NULL;
for(;;) {
type = TypeGetActualFlags( type, &flags );
if( flags & TF1_CONST ) {
*extra |= IS_CONST;
}
if( flags & TF1_DLLIMPORT ) {
*extra |= IS_DLLIMPORT;
}
switch( type->id ) {
case TYP_POINTER:
if( type->flag & TF1_REFERENCE ) {
*extra |= IS_REF;
}
break;
case TYP_ARRAY:
type = type->of;
continue;
}
break;
}
return( type );
}
boolean ConstNeedsExplicitInitializer( TYPE type )
/************************************************/
{
CLASSINFO *info;
SYMBOL dummy;
type = StructType( type );
if( type == NULL ) {
/* const non-class types need explicit initializers */
return( TRUE );
}
info = type->u.c.info;
if( info->needs_ctor ) {
/* if class doesn't have a default ctor, it needs an explicit init */
if( ClassDefaultCtorFind( type, &dummy, NULL ) != CNV_OK ) {
return( TRUE );
}
} else {
/* doesn't need a constructor */
if( info->has_data ) {
/* has some fields */
return( TRUE );
}
}
return( FALSE );
}
static boolean diagnoseAbstractDefn( SYMBOL sym, TYPE type )
{
type = ArrayBaseType( type );
CErr( ERR_CANNOT_DEFINE_ABSTRACT_VARIABLE, sym, type );
ScopeNotePureFunctions( type );
return( FALSE );
}
boolean DeclNoInit( DECL_INFO *dinfo )
/************************************/
{
SYMBOL sym;
SCOPE scope;
TYPE type;
base_info info;
sym = dinfo->sym;
if( sym == NULL ) {
return( FALSE );
}
if( SymIsTypedef( sym ) || SymIsFunction( sym ) || sym->id == SC_EXTERN ) {
return( FALSE );
}
type = sym->sym_type;
if( SymIsStaticMember( sym ) ) {
if( ScopeType( GetCurrScope(), SCOPE_CLASS ) ) {
if( TypeAbstract( type ) ) {
return( diagnoseAbstractDefn( sym, type ) );
}
return( FALSE );
}
/* "int C::a;" instead of "static int a;" in "class C" */
CompFlags.external_defn_found = TRUE;
if( SymIsInitialized( sym ) ) {
if( ! ( sym->flag & SF_IN_CLASS_INIT ) ) {
if( ! TemplateMemberCanBeIgnored() ) {
CErr2p( ERR_CANNOT_INIT_AGAIN, sym );
}
return( FALSE );
} else {
/* reset in-class initialization flag to get the
* symbol exported */
sym->flag &= ~SF_IN_CLASS_INIT;
}
}
if( ! TypeDefined( type ) ) {
CErr2p( ERR_CANNOT_DEFINE_VARIABLE, sym );
return( FALSE );
}
if( TypeAbstract( type ) ) {
return( diagnoseAbstractDefn( sym, type ) );
}
} else {
if( ! TypeDefined( type ) ) {
CErr2p( ERR_CANNOT_DEFINE_VARIABLE, sym );
return( FALSE );
}
if( TypeAbstract( type ) ) {
return( diagnoseAbstractDefn( sym, type ) );
}
scope = SymScope( sym );
if( ScopeType( scope, SCOPE_TEMPLATE_INST ) ) {
if( TemplateVerifyDecl( sym ) ) {
return( FALSE );
}
}
if( sym->id != SC_STATIC && ScopeType( scope, SCOPE_FILE ) ) {
CompFlags.external_defn_found = TRUE;
if( LinkageIsC( sym ) ) {
CompFlags.extern_C_defn_found = 1;
}
}
if( ! ScopeType( scope, SCOPE_FILE ) && ! ScopeType( scope, SCOPE_BLOCK ) ){
return( FALSE );
}
if( SymIsInitialized( sym ) ) {
return( FALSE );
}
}
type = baseTypeInfo( type, &info );
switch( info ) {
case IS_REF:
CErr1( ERR_REFERENCE_MUST_BE_INITIALIZED );
return( FALSE );
case IS_CONST:
if( ConstNeedsExplicitInitializer( type )
&& ! SymIsInitialized( sym ) ) {
CErr1( ERR_CONST_MUST_BE_INITIALIZED );
return( FALSE );
}
}
return( TRUE );
}
boolean DeclWithInit( DECL_INFO *dinfo )
/**************************************/
{
TYPE type;
SYMBOL sym;
SCOPE scope;
sym = dinfo->sym;
if( sym == NULL ) {
return( FALSE );
}
if( SymIsTypedef( sym ) ) {
CErr1( ERR_CANNOT_INIT_TYPEDEF );
return( FALSE );
}
if( SymIsFunction( sym ) ) {
CErr1( ERR_CANNOT_INIT_FUNCTION );
return( FALSE );
}
if( SymIsInitialized( sym ) ) {
if( SymIsStaticMember( sym ) && TemplateMemberCanBeIgnored() ) {
return( FALSE );
}
CErr2p( ERR_CANNOT_INIT_AGAIN, sym );
return( FALSE );
}
if( sym->id == SC_PUBLIC ) {
CErr2p( ERR_SYM_ALREADY_DEFINED, sym );
return( FALSE );
}
scope = SymScope( sym );
if( ScopeEquivalent( scope, SCOPE_FILE ) ) {
if( ScopeType( GetCurrScope(), SCOPE_TEMPLATE_INST ) ) {
if( TemplateVerifyDecl( sym ) ) {
return( FALSE );
}
}
if( sym->id != SC_STATIC ) {
CompFlags.external_defn_found = TRUE;
if( LinkageIsC( sym ) ) {
CompFlags.extern_C_defn_found = 1;
}
}
if( ! ScopeType( GetCurrScope(), SCOPE_FILE ) ) {
CErr2p( ERR_CANNOT_INIT_IN_NON_FILE_SCOPE, sym );
}
} else if( SymIsStaticMember( sym ) && ! ScopeType( GetCurrScope(), SCOPE_CLASS ) ) {
/* "int C::a;" instead of "static int a;" in "class C" */
CompFlags.external_defn_found = TRUE;
}
type = sym->sym_type;
if( TypeDefined( type ) ) {
if( TypeAbstract( type ) ) {
return( diagnoseAbstractDefn( sym, type ) );
}
return( TRUE );
}
/* must only be unknown array size with defined base type */
type = TypedefModifierRemove( type );
if( type->id == TYP_ARRAY ) {
if( type->u.a.array_size == 0 ) {
if( TypeDefined( type->of ) ) {
if( TypeAbstract( type->of ) ) {
return( diagnoseAbstractDefn( sym, type ) );
}
return( TRUE );
}
}
}
CErr2p( ERR_CANNOT_DEFINE_VARIABLE, sym );
return( FALSE );
}
static void handleInlineFunction( SYMBOL sym )
{
switch( sym->id ) {
case SC_STATIC:
case SC_TYPEDEF:
case SC_FUNCTION_TEMPLATE:
case SC_STATIC_FUNCTION_TEMPLATE:
case SC_EXTERN:
return;
}
sym->id = SC_STATIC;
}
void DeclDefaultStorageClass( SCOPE scope, SYMBOL sym )
/*****************************************************/
{
TYPE fn_type;
base_info info;
if( sym->id == SC_DEFAULT ) {
return;
}
if( scope->id == SCOPE_FILE ) {
fn_type = FunctionDeclarationType( sym->sym_type );
if( fn_type != NULL && ( fn_type->flag & TF1_INLINE ) != 0 ) {
handleInlineFunction( sym );
}
}
if( sym->id != SC_NULL ) {
return;
}
switch( scope->id ) {
case SCOPE_CLASS:
sym->id = SC_MEMBER;
break;
case SCOPE_FILE:
baseTypeInfo( sym->sym_type, &info );
if( info & IS_CONST ) {
/* default linkage is internal for a const object */
sym->id = SC_STATIC;
} else if( info & IS_DLLIMPORT ) {
/* default linkage is extern for a __declspec(dllimport) object */
sym->id = SC_EXTERN;
}
break;
case SCOPE_BLOCK:
case SCOPE_FUNCTION:
sym->id = SC_AUTO;
break;
#ifndef NDEBUG
case SCOPE_TEMPLATE_PARM:
case SCOPE_TEMPLATE_SPEC_PARM:
case SCOPE_TEMPLATE_DECL:
case SCOPE_TEMPLATE_INST:
break;
default:
CFatal( "unknown scope type" );
#endif
}
}
static boolean commonCheck( SYMBOL prev, SYMBOL curr, decl_check *control )
{
SCOPE scope;
if( SymIsStaticMember( prev ) ) {
switch( curr->id ) {
case SC_NULL:
case SC_STATIC:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?