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 + -
显示快捷键?