analctor.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 676 行 · 第 1/2 页

C
676
字号
/****************************************************************************
*
*                            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 "fnovload.h"
#include "calldiag.h"
#include "memmgr.h"
#include "errdefns.h"
#include "rtfuncod.h"
#include "ring.h"
#include "defarg.h"
#include "class.h"
#include "objmodel.h"

static CNV_DIAG diagCtor =      // diagnosis for CTORing
    {   ERR_CTOR_IMPOSSIBLE
    ,   ERR_CTOR_AMBIGUOUS
    ,   ERR_CALL_WATCOM
    ,   ERR_CALL_WATCOM
    ,   ERR_CALL_WATCOM
    };


static boolean ctorDefineDefault(   // DEFINE A DEFAULT CTOR
    TYPE cl_type,               // - class type
    arg_list *alist )           // - arguments list
{
    boolean retn;               // - TRUE ==> a default CTOR was defined
    SYMBOL ctor;                // - CTOR symbol

    if( ! TypeDefined( cl_type ) ) {
        retn = FALSE;
    } else if( alist->num_args == 0 ) {
        if( CNV_OK == ClassDefaultCtorDefine( cl_type, &ctor ) ) {
            retn = TRUE;
        } else {
            retn = FALSE;
        }
    } else if( alist->num_args == 1 ) {
        if( NULL == ClassAddDefaultCopy( cl_type->u.c.scope ) ) {
            retn = FALSE;
        } else {
            retn = TRUE;
        }
    } else {
        retn = FALSE;
    }
    return retn;
}


static boolean ctorDefineDefaultCnv( // DEFINE A DEFAULT CTOR FOR CONVERSION
    TYPE cl_type,               // - class type
    arg_list *alist )           // - arguments list
{
    boolean retn;               // - TRUE ==> a default CTOR was defined

    if( ! TypeDefined( cl_type ) ) {
        retn = FALSE;
    } else if( alist->num_args == 0 ) {
        retn = ctorDefineDefault( cl_type, alist );
    } else if( alist->num_args == 1 ) {
        cl_type = ClassTypeForType( cl_type );
        if( NULL == ClassAddDefaultCopy( cl_type->u.c.scope ) ) {
            retn = FALSE;
        } else {
            retn = TRUE;
        }
    } else {
        retn = FALSE;
    }
    return retn;
}


static SEARCH_RESULT *ctorResult(   // GET SEARCH RESULT FOR A CTOR
    SCOPE access,               // - accessing derived class
    TOKEN_LOCN *locn,           // - location for any access errors
    TYPE cl_type )              // - a class type
{
    SCOPE class_scope;
    char *ctor_name;
    SEARCH_RESULT *result;

    ctor_name = CppConstructorName();
    class_scope = TypeScope( cl_type );
    if( access != NULL ) {
        result = ScopeFindBaseMember( class_scope, ctor_name );
    } else {
        result = ScopeContainsMember( class_scope, ctor_name );
    }
    if( locn != NULL && result != NULL ) {
        ScopeResultErrLocn( result, locn );
    }
    return result;
}


FNOV_LIST *CtorFindList( TYPE src, TYPE tgt )
/*******************************************/
// Find all ctors from src to tgt type
// - does not rank or resolve list
{
    arg_list            alist;          // argument list for ctor
    SEARCH_RESULT       *search_result; // search result
    SYMBOL              sym;            // current symbol in list
    FNOV_LIST           *list;          // FNOV_LIST of ctors found

    search_result = ctorResult( NULL, NULL, tgt );
    if( search_result == NULL ) {
        InitArgList( &alist );
        alist.num_args = 1;
        alist.type_list[0] = src;
        if( ctorDefineDefaultCnv( tgt, &alist ) ) {
            search_result = ctorResult( NULL, NULL, tgt );
        }
    }
    list = NULL;
    if( search_result != NULL ) {
        RingIterBeg( search_result->sym_name->name_syms, sym ) {
            BuildUdcList( &list, sym );
        } RingIterEnd( sym )
        ScopeFreeResult( search_result );
    }
    return list;
}


static FNOV_RESULT ctorExplicitDiag(// FIND CONSTRUCTOR FOR ARGUMENT LIST
    SCOPE access,               // - accessing derived class
    TYPE cl_type,               // - type for class
    arg_list *alist,            // - arguments list
    PTREE *ptlist,              // - parse tree nodes for arguments
    TOKEN_LOCN *locn,           // - location for access errors
    SYMBOL *ctor,               // - ctor symbol
    FNOV_DIAG *fnov_diag )      // - diagnosis information
{
    SEARCH_RESULT *result;      // - search result
    FNOV_RESULT ovret;          // - overload resolution result

    cl_type = ClassTypeForType( cl_type );
    result = ctorResult( access, locn, cl_type );
    if( result == NULL ) {
        ovret = FNOV_NO_MATCH;
    } else {
        ovret = FuncOverloadedLimitDiag( ctor
                                       , result
                                       , result->sym_name->name_syms
                                       , alist
                                       , ptlist
                                       , FNC_RANKING_CTORS
                                       , fnov_diag );
        if( ovret == FNOV_NONAMBIGUOUS ) {
            if( ScopeCheckSymbol( result, *ctor ) ) {
                ovret = FNOV_ERR;
            }
        }
        ScopeFreeResult( result );
    }
    return ovret;
}


static CNV_RETN ctorFindDiag(   // FIND CONSTRUCTOR FOR ARGUMENT LIST
    SCOPE access,               // - accessing derived class
    TYPE cl_type,               // - type for class
    arg_list *alist,            // - arguments list
    PTREE *ptlist,              // - parse tree nodes for arguments
    TOKEN_LOCN *locn,           // - location for access errors
    SYMBOL *ctor,               // - addr( constructor symbol )
    FNOV_DIAG *fnov_diag )      // - diagnosis information
{
    CNV_RETN retn;              // - return: TRUE ==> no error
    FNOV_RESULT ovret;          // - overload resolution result

    *ctor = NULL;
    ovret = ctorExplicitDiag( access, cl_type, alist, ptlist, locn, ctor, fnov_diag );
    if( ovret == FNOV_NO_MATCH ) {
        if( ctorDefineDefault( cl_type, alist ) ) {
            FnovInitDiag( fnov_diag );
            ovret = ctorExplicitDiag( access, cl_type, alist, ptlist, locn, ctor, fnov_diag );
        }
    }
    switch( ovret ) {
      case FNOV_ERR :
        retn = CNV_ERR;
        break;
      case FNOV_NONAMBIGUOUS :
        retn = CNV_OK;
        break;
      case FNOV_NO_MATCH :
        retn = CNV_IMPOSSIBLE;
        break;
      case FNOV_AMBIGUOUS :
        retn = CNV_AMBIGUOUS;
        break;
      DbgDefault( "unexpected return from ctorExplicitDiag" );
    }
    return retn;
}


CNV_RETN CtorFind(              // FIND CONSTRUCTOR FOR ARGUMENT LIST
    SCOPE access,               // - accessing derived class
    TYPE cl_type,               // - type for class
    arg_list *alist,            // - arguments list
    PTREE *ptlist,              // - parse tree nodes for arguments
    TOKEN_LOCN *locn,           // - location for access errors
    SYMBOL *ctor )              // - addr( constructor symbol )
{
    return ctorFindDiag( access, cl_type, alist, ptlist, locn, ctor, NULL );
}


static CNV_RETN single_arg(     // VERIFY ZERO OR SINGLE CTOR ARGUMENT
    PTREE *a_expr )             // - addr( expression )
{
    CNV_RETN retn;              // - return: CNV_...
    PTREE expr;                 // - expression

    expr = *a_expr;
    if( expr == NULL ) {
        retn = CNV_OK;
    } else if( expr->u.subtree[0] != NULL ) {
        PTreeErrorExpr( expr, ERR_ONE_CTOR_ARG_REQD );
        retn = CNV_ERR;
    } else {
        *a_expr = expr->u.subtree[1];
        PTreeFree( expr );
        retn = CNV_OK;
    }
    return retn;
}


static CNV_RETN analyseCtorClassDiag( // ANALYSE A CLASS CTOR
    TYPE type,                  // - class type for CTOR
    SCOPE access,               // - scope ctor is accessed from
    SYMBOL *ctor,               // - ctor to be filled in
    PTREE initial,              // - initialization arguments (modified)
    PTREE *expr,                // - expression, when CTOR'd
    FNOV_DIAG *fnov_diag )      // - diagnosis information
{
    PTREE node;                 // - converted arguments
    arg_list *alist;            // - arguments structure
    PTREE *ptlist;              // - parse tree for arguments
    unsigned count;             // - # arg.s
    CNV_RETN retn;              // - return: CNV_...
    TOKEN_LOCN err_locn;        // - location for access errors
    TEMP_PT_LIST default_list;  // - default PTREE list
    TEMP_ARG_LIST default_args; // - default arg_list

    node = NodeReverseArgs( &count, initial );
    alist = ArgListTempAlloc( &default_args, count );
    ptlist = PtListAlloc( default_list, count );
    NodeBuildArgList( alist, ptlist, node, count );
    PTreeExtractLocn( initial, &err_locn );
    retn = ctorFindDiag( access
                       , type
                       , alist
                       , ptlist
                       , &err_locn
                       , ctor
                       , fnov_diag );
    switch( retn ) {
      case CNV_OK :
        node = NodeConvertCallArgList( node
                                     , count
                                     , (*ctor)->sym_type
                                     , &node );
        if( ( node != NULL ) && ( node->op == PT_ERROR ) ) {
            retn = CNV_ERR;
        }
        break;
      case CNV_AMBIGUOUS :
        if( fnov_diag != NULL ) {
            CallDiagAmbiguous( node, ERR_CTOR_AMBIGUOUS, fnov_diag );
            retn = CNV_ERR;
        }
        break;
      case CNV_IMPOSSIBLE :
        if( count == 1
         && StructType( initial->type ) == type
         && OMR_CLASS_VAL == ObjModelArgument( type ) ) {
            retn = CNV_OK;
            break;
        }
        // drops thru
      default :
        if( initial != NULL ) {
            ConversionTypesSet( NodeType( initial ), type );
        }
        break;
    }
    *expr = node;
    ArgListTempFree( alist, count );
    PtListFree( ptlist, count );
    return retn;
}

// Determine if the "type" is properly CTORable:
//
// - for a scalar type, this is so if there is no initializer list
// - for a scalar type, this is so if there is one argument which can be
//   converted to the argument type
// - for a class, this is so if there is no initializer list
//      - the ctor SYMBOL might be found
// - for a class, this is so if there exists a CTOR to match the initializer

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?