diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2019-06-18 20:42:10 +0200 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2021-11-30 16:53:28 +0100 |
commit | 5fee5ec362f7a243f459e6378fd49dfc89dc9fb5 (patch) | |
tree | 61d1bdbca854a903c0860406f457f06b2040be7a /gcc/d/dmd/dclass.c | |
parent | b3f60112edcb85b459e60f66c44a55138b1cef49 (diff) | |
download | gcc-5fee5ec362f7a243f459e6378fd49dfc89dc9fb5.zip gcc-5fee5ec362f7a243f459e6378fd49dfc89dc9fb5.tar.gz gcc-5fee5ec362f7a243f459e6378fd49dfc89dc9fb5.tar.bz2 |
d: Import dmd b8384668f, druntime e6caaab9, phobos 5ab9ad256 (v2.098.0-beta.1)
The D front-end is now itself written in D, in order to build GDC, you
will need a working GDC compiler (GCC version 9.1 or later).
GCC changes:
- Add support for bootstrapping the D front-end.
These add the required components in order to have a D front-end written
in D itself. Because the compiler front-end only depends on the core
runtime modules, only libdruntime is built for the bootstrap stages.
D front-end changes:
- Import dmd v2.098.0-beta.1.
Druntime changes:
- Import druntime v2.098.0-beta.1.
Phobos changes:
- Import phobos v2.098.0-beta.1.
The jump from v2.076.1 to v2.098.0 covers nearly 4 years worth of
development on the D programming language and run-time libraries.
ChangeLog:
* Makefile.def: Add bootstrap to libbacktrace, libphobos, zlib, and
libatomic.
* Makefile.in: Regenerate.
* Makefile.tpl (POSTSTAGE1_HOST_EXPORTS): Fix command for GDC.
(STAGE1_CONFIGURE_FLAGS): Add --with-libphobos-druntime-only if
target-libphobos-bootstrap.
(STAGE2_CONFIGURE_FLAGS): Likewise.
* configure: Regenerate.
* configure.ac: Add support for bootstrapping D front-end.
config/ChangeLog:
* acx.m4 (ACX_PROG_GDC): New m4 function.
gcc/ChangeLog:
* Makefile.in (GDC): New variable.
(GDCFLAGS): New variable.
* configure: Regenerate.
* configure.ac: Add call to ACX_PROG_GDC. Substitute GDCFLAGS.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd b8384668f.
* Make-lang.in (d-warn): Use strict warnings.
(DMD_WARN_CXXFLAGS): Remove.
(DMD_COMPILE): Remove.
(CHECKING_DFLAGS): Define.
(WARN_DFLAGS): Define.
(ALL_DFLAGS): Define.
(DCOMPILE.base): Define.
(DCOMPILE): Define.
(DPOSTCOMPILE): Define.
(DLINKER): Define.
(DLLINKER): Define.
(D_FRONTEND_OBJS): Add new dmd front-end objects.
(D_GENERATED_SRCS): Remove.
(D_GENERATED_OBJS): Remove.
(D_ALL_OBJS): Remove D_GENERATED_OBJS.
(d21$(exeext)): Build using DLLINKER and -static-libphobos.
(d.tags): Remove dmd/*.c and dmd/root/*.c.
(d.mostlyclean): Remove D_GENERATED_SRCS, d/idgen$(build_exeext),
d/impcnvgen$(build_exeext).
(D_INCLUDES): Include $(srcdir)/d/dmd/res.
(CFLAGS-d/id.o): Remove.
(CFLAGS-d/impcnvtab.o): Remove.
(d/%.o): Build using DCOMPILE and DPOSTCOMPILE. Update dependencies
from d/dmd/%.c to d/dmd/%.d.
(d/idgen$(build_exeext)): Remove.
(d/impcnvgen$(build_exeext)): Remove.
(d/id.c): Remove.
(d/id.h): Remove.
(d/impcnvtab.c): Remove.
(d/%.dmdgen.o): Remove.
(D_SYSTEM_H): Remove.
(d/idgen.dmdgen.o): Remove.
(d/impcnvgen.dmdgen.o): Remove.
* config-lang.in (boot_language): New variable.
* d-attribs.cc: Include dmd/expression.h.
* d-builtins.cc: Include d-frontend.h.
(build_frontend_type): Update for new front-end interface.
(d_eval_constant_expression): Likewise.
(d_build_builtins_module): Likewise.
(maybe_set_builtin_1): Likewise.
(d_build_d_type_nodes): Likewise.
* d-codegen.cc (d_decl_context): Likewise.
(declaration_reference_p): Likewise.
(declaration_type): Likewise.
(parameter_reference_p): Likewise.
(parameter_type): Likewise.
(get_array_length): Likewise.
(build_delegate_cst): Likewise.
(build_typeof_null_value): Likewise.
(identity_compare_p): Likewise.
(lower_struct_comparison): Likewise.
(build_filename_from_loc): Likewise.
(build_assert_call): Remove LIBCALL_SWITCH_ERROR.
(build_bounds_index_condition): Call LIBCALL_ARRAYBOUNDS_INDEXP on
bounds error.
(build_bounds_slice_condition): Call LIBCALL_ARRAYBOUNDS_SLICEP on
bounds error.
(array_bounds_check): Update for new front-end interface.
(checkaction_trap_p): Handle CHECKACTION_context.
(get_function_type): Update for new front-end interface.
(d_build_call): Likewise.
* d-compiler.cc: Remove include of dmd/scope.h.
(Compiler::genCmain): Remove.
(Compiler::paintAsType): Update for new front-end interface.
(Compiler::onParseModule): Likewise.
* d-convert.cc (convert_expr): Remove call to LIBCALL_ARRAYCAST.
(convert_for_rvalue): Update for new front-end interface.
(convert_for_assignment): Likewise.
(convert_for_condition): Likewise.
(d_array_convert): Likewise.
* d-diagnostic.cc (error): Remove.
(errorSupplemental): Remove.
(warning): Remove.
(warningSupplemental): Remove.
(deprecation): Remove.
(deprecationSupplemental): Remove.
(message): Remove.
(vtip): New.
* d-frontend.cc (global): Remove.
(Global::_init): Remove.
(Global::startGagging): Remove.
(Global::endGagging): Remove.
(Global::increaseErrorCount): Remove.
(Loc::Loc): Remove.
(Loc::toChars): Remove.
(Loc::equals): Remove.
(isBuiltin): Update for new front-end interface.
(eval_builtin): Likewise.
(getTypeInfoType): Likewise.
(inlineCopy): Remove.
* d-incpath.cc: Include d-frontend.h.
(add_globalpaths): Call d_gc_malloc to allocate Strings.
(add_filepaths): Likewise.
* d-lang.cc: Include dmd/id.h, dmd/root/file.h, d-frontend.h. Remove
include of dmd/mars.h, id.h.
(entrypoint_module): Remove.
(entrypoint_root_module): Remove.
(deps_write_string): Update for new front-end interface.
(deps_write): Likewise.
(d_init_options): Call rt_init. Remove setting global params that are
default initialized by the front-end.
(d_handle_option): Handle OPT_fcheckaction_, OPT_fdump_c___spec_,
OPT_fdump_c___spec_verbose, OPT_fextern_std_, OPT_fpreview,
OPT_revert, OPT_fsave_mixins_, and OPT_ftransition.
(d_post_options): Propagate dip1021 and dip1000 preview flags to
dip25, and flag_diagnostics_show_caret to printErrorContext.
(d_add_entrypoint_module): Remove.
(d_parse_file): Update for new front-end interface.
(d_type_promotes_to): Likewise.
(d_types_compatible_p): Likewise.
* d-longdouble.cc (CTFloat::zero): Remove.
(CTFloat::one): Remove.
(CTFloat::minusone): Remove.
(CTFloat::half): Remove.
* d-system.h (POSIX): Remove.
(realpath): Remove.
(isalpha): Remove.
(isalnum): Remove.
(isdigit): Remove.
(islower): Remove.
(isprint): Remove.
(isspace): Remove.
(isupper): Remove.
(isxdigit): Remove.
(tolower): Remove.
(_mkdir): Remove.
(INT32_MAX): Remove.
(INT32_MIN): Remove.
(INT64_MIN): Remove.
(UINT32_MAX): Remove.
(UINT64_MAX): Remove.
* d-target.cc: Include calls.h.
(target): Remove.
(define_float_constants): Remove initialization of snan.
(Target::_init): Update for new front-end interface.
(Target::isVectorTypeSupported): Likewise.
(Target::isVectorOpSupported): Remove cases for unordered operators.
(TargetCPP::typeMangle): Update for new front-end interface.
(TargetCPP::parameterType): Likewise.
(Target::systemLinkage): Likewise.
(Target::isReturnOnStack): Likewise.
(Target::isCalleeDestroyingArgs): Define.
(Target::preferPassByRef): Define.
* d-tree.h (d_add_entrypoint_module): Remove.
* decl.cc (gcc_attribute_p): Update for new front-end interface.
(apply_pragma_crt): Define.
(DeclVisitor::visit(PragmaDeclaration *)): Handle pragmas
crt_constructor and crt_destructor.
(DeclVisitor::visit(TemplateDeclaration *)): Update for new front-end
interface.
(DeclVisitor::visit): Likewise.
(DeclVisitor::finish_vtable): Likewise.
(get_symbol_decl): Error if template has more than one nesting
context. Update for new front-end interface.
(make_thunk): Update for new front-end interface.
(get_vtable_decl): Likewise.
* expr.cc (ExprVisitor::visit): Likewise.
(build_return_dtor): Likewise.
* imports.cc (ImportVisitor::visit): Likewise.
* intrinsics.cc: Include dmd/expression.h. Remove include of
dmd/mangle.h.
(maybe_set_intrinsic): Update for new front-end interface.
* intrinsics.def (INTRINSIC_ROL): Update intrinsic signature.
(INTRINSIC_ROR): Likewise.
(INTRINSIC_ROR_TIARG): Likewise.
(INTRINSIC_TOPREC): Likewise.
(INTRINSIC_TOPRECL): Likewise.
(INTRINSIC_TAN): Update intrinsic module and signature.
(INTRINSIC_ISNAN): Likewise.
(INTRINSIC_ISFINITE): Likewise.
(INTRINSIC_COPYSIGN): Define intrinsic.
(INTRINSIC_COPYSIGNI): Define intrinsic.
(INTRINSIC_EXP): Update intrinsic module.
(INTRINSIC_EXPM1): Likewise.
(INTRINSIC_EXP2): Likewise.
(INTRINSIC_LOG): Likewise.
(INTRINSIC_LOG2): Likewise.
(INTRINSIC_LOG10): Likewise.
(INTRINSIC_POW): Likewise.
(INTRINSIC_ROUND): Likewise.
(INTRINSIC_FLOORF): Likewise.
(INTRINSIC_FLOOR): Likewise.
(INTRINSIC_FLOORL): Likewise.
(INTRINSIC_CEILF): Likewise.
(INTRINSIC_CEIL): Likewise.
(INTRINSIC_CEILL): Likewise.
(INTRINSIC_TRUNC): Likewise.
(INTRINSIC_FMIN): Likewise.
(INTRINSIC_FMAX): Likewise.
(INTRINSIC_FMA): Likewise.
(INTRINSIC_VA_ARG): Update intrinsic signature.
(INTRINSIC_VASTART): Likewise.
* lang.opt (fcheck=): Add alternate aliases for contract switches.
(fcheckaction=): New option.
(check_action): New Enum and EnumValue entries.
(fdump-c++-spec-verbose): New option.
(fdump-c++-spec=): New option.
(fextern-std=): New option.
(extern_stdcpp): New Enum and EnumValue entries
(fpreview=): New options.
(frevert=): New options.
(fsave-mixins): New option.
(ftransition=): Update options.
* modules.cc (get_internal_fn): Replace Prot with Visibility.
(build_internal_fn): Likewise.
(build_dso_cdtor_fn): Likewise.
(build_module_tree): Remove check for __entrypoint module.
* runtime.def (P5): Define.
(ARRAYBOUNDS_SLICEP): Define.
(ARRAYBOUNDS_INDEXP): Define.
(NEWTHROW): Define.
(ADCMP2): Remove.
(ARRAYCAST): Remove.
(SWITCH_STRING): Remove.
(SWITCH_USTRING): Remove.
(SWITCH_DSTRING): Remove.
(SWITCH_ERROR): Remove.
* toir.cc (IRVisitor::visit): Update for new front-end interface.
(IRVisitor::check_previous_goto): Remove checks for case and default
statements.
(IRVisitor::visit(SwitchStatement *)): Remove handling of string
switch conditions.
* typeinfo.cc: Include d-frontend.h.
(get_typeinfo_kind): Update for new front-end interface.
(make_frontend_typeinfo): Likewise.
(TypeInfoVisitor::visit): Likewise.
(builtin_typeinfo_p): Likewise.
(get_typeinfo_decl): Likewise.
(build_typeinfo): Likewise.
* types.cc (valist_array_p): Likewise.
(make_array_type): Likewise.
(merge_aggregate_types): Likewise.
(TypeVisitor::visit(TypeBasic *)): Likewise.
(TypeVisitor::visit(TypeFunction *)): Likewise.
(TypeVisitor::visit(TypeStruct *)): Update comment.
* verstr.h: Removed.
* d-frontend.h: New file.
gcc/po/ChangeLog:
* EXCLUDES: Remove d/dmd sources from list.
gcc/testsuite/ChangeLog:
* gdc.dg/Wcastresult2.d: Update test.
* gdc.dg/asm1.d: Likewise.
* gdc.dg/asm2.d: Likewise.
* gdc.dg/asm3.d: Likewise.
* gdc.dg/gdc282.d: Likewise.
* gdc.dg/imports/gdc170.d: Likewise.
* gdc.dg/intrinsics.d: Likewise.
* gdc.dg/pr101672.d: Likewise.
* gdc.dg/pr90650a.d: Likewise.
* gdc.dg/pr90650b.d: Likewise.
* gdc.dg/pr94777a.d: Likewise.
* gdc.dg/pr95250.d: Likewise.
* gdc.dg/pr96869.d: Likewise.
* gdc.dg/pr98277.d: Likewise.
* gdc.dg/pr98457.d: Likewise.
* gdc.dg/simd1.d: Likewise.
* gdc.dg/simd2a.d: Likewise.
* gdc.dg/simd2b.d: Likewise.
* gdc.dg/simd2c.d: Likewise.
* gdc.dg/simd2d.d: Likewise.
* gdc.dg/simd2e.d: Likewise.
* gdc.dg/simd2f.d: Likewise.
* gdc.dg/simd2g.d: Likewise.
* gdc.dg/simd2h.d: Likewise.
* gdc.dg/simd2i.d: Likewise.
* gdc.dg/simd2j.d: Likewise.
* gdc.dg/simd7951.d: Likewise.
* gdc.dg/torture/gdc309.d: Likewise.
* gdc.dg/torture/pr94424.d: Likewise.
* gdc.dg/torture/pr94777b.d: Likewise.
* lib/gdc-utils.exp (gdc-convert-args): Handle new compiler options.
(gdc-convert-test): Handle CXXFLAGS, EXTRA_OBJC_SOURCES, and ARG_SETS
test directives.
(gdc-do-test): Only import modules in the test run directory.
* gdc.dg/pr94777c.d: New test.
* gdc.dg/pr96156b.d: New test.
* gdc.dg/pr96157c.d: New test.
* gdc.dg/simd_ctfe.d: New test.
* gdc.dg/torture/simd17344.d: New test.
* gdc.dg/torture/simd20052.d: New test.
* gdc.dg/torture/simd6.d: New test.
* gdc.dg/torture/simd7.d: New test.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime e6caaab9.
* libdruntime/Makefile.am (D_EXTRA_FLAGS): Build libdruntime with
-fpreview=dip1000, -fpreview=fieldwise, and -fpreview=dtorfields.
(ALL_DRUNTIME_SOURCES): Add DRUNTIME_DSOURCES_STDCXX.
(DRUNTIME_DSOURCES): Update list of C binding modules.
(DRUNTIME_DSOURCES_STDCXX): Likewise.
(DRUNTIME_DSOURCES_LINUX): Likewise.
(DRUNTIME_DSOURCES_OPENBSD): Likewise.
(DRUNTIME_DISOURCES): Remove __entrypoint.di.
* libdruntime/Makefile.in: Regenerated.
* libdruntime/__entrypoint.di: Removed.
* libdruntime/gcc/deh.d (_d_isbaseof): Update signature.
(_d_createTrace): Likewise.
(__gdc_begin_catch): Remove reference to the exception.
(_d_throw): Increment reference count of thrown object before unwind.
(__gdc_personality): Chain exceptions with Throwable.chainTogether.
* libdruntime/gcc/emutls.d: Update imports.
* libdruntime/gcc/sections/elf.d: Update imports.
(DSO.moduleGroup): Update signature.
* libdruntime/gcc/sections/macho.d: Update imports.
(DSO.moduleGroup): Update signature.
* libdruntime/gcc/sections/pecoff.d: Update imports.
(DSO.moduleGroup): Update signature.
* src/MERGE: Merge upstream phobos 5ab9ad256.
* src/Makefile.am (D_EXTRA_DFLAGS): Add -fpreview=dip1000 and
-fpreview=dtorfields flags.
(PHOBOS_DSOURCES): Update list of std modules.
* src/Makefile.in: Regenerate.
* testsuite/lib/libphobos.exp (libphobos-dg-test): Handle assembly
compile types.
(dg-test): Override.
(additional_prunes): Define.
(libphobos-dg-prune): Filter any additional_prunes set by tests.
* testsuite/libphobos.aa/test_aa.d: Update test.
* testsuite/libphobos.druntime/druntime.exp (version_flags): Add
-fversion=CoreUnittest.
* testsuite/libphobos.druntime_shared/druntime_shared.exp
(version_flags): Add -fversion=CoreUnittest -fversion=Shared.
* testsuite/libphobos.exceptions/unknown_gc.d: Update test.
* testsuite/libphobos.hash/test_hash.d: Update test.
* testsuite/libphobos.phobos/phobos.exp (version_flags): Add
-fversion=StdUnittest
* testsuite/libphobos.phobos_shared/phobos_shared.exp (version_flags):
Likewise.
* testsuite/libphobos.shared/host.c: Update test.
* testsuite/libphobos.shared/load.d: Update test.
* testsuite/libphobos.shared/load_13414.d: Update test.
* testsuite/libphobos.thread/fiber_guard_page.d: Update test.
* testsuite/libphobos.thread/tlsgc_sections.d: Update test.
* testsuite/testsuite_flags.in: Add -fpreview=dip1000 to --gdcflags.
* testsuite/libphobos.shared/link_mod_collision.d: Removed.
* testsuite/libphobos.shared/load_mod_collision.d: Removed.
* testsuite/libphobos.betterc/betterc.exp: New test.
* testsuite/libphobos.config/config.exp: New test.
* testsuite/libphobos.gc/gc.exp: New test.
* testsuite/libphobos.imports/imports.exp: New test.
* testsuite/libphobos.lifetime/lifetime.exp: New test.
* testsuite/libphobos.unittest/unittest.exp: New test.
Diffstat (limited to 'gcc/d/dmd/dclass.c')
-rw-r--r-- | gcc/d/dmd/dclass.c | 1041 |
1 files changed, 0 insertions, 1041 deletions
diff --git a/gcc/d/dmd/dclass.c b/gcc/d/dmd/dclass.c deleted file mode 100644 index 3f33014..0000000 --- a/gcc/d/dmd/dclass.c +++ /dev/null @@ -1,1041 +0,0 @@ - -/* Compiler implementation of the D programming language - * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved - * written by Walter Bright - * http://www.digitalmars.com - * Distributed under the Boost Software License, Version 1.0. - * http://www.boost.org/LICENSE_1_0.txt - * https://github.com/D-Programming-Language/dmd/blob/master/src/class.c - */ - -#include "root/dsystem.h" // mem{cpy|set}() -#include "root/root.h" -#include "root/rmem.h" - -#include "errors.h" -#include "enum.h" -#include "init.h" -#include "attrib.h" -#include "declaration.h" -#include "aggregate.h" -#include "id.h" -#include "mtype.h" -#include "scope.h" -#include "module.h" -#include "expression.h" -#include "statement.h" -#include "template.h" -#include "target.h" -#include "objc.h" - -bool symbolIsVisible(Dsymbol *origin, Dsymbol *s); -Objc *objc(); - - -/********************************* ClassDeclaration ****************************/ - -ClassDeclaration *ClassDeclaration::object; -ClassDeclaration *ClassDeclaration::throwable; -ClassDeclaration *ClassDeclaration::exception; -ClassDeclaration *ClassDeclaration::errorException; -ClassDeclaration *ClassDeclaration::cpp_type_info_ptr; // Object.__cpp_type_info_ptr - -ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject) - : AggregateDeclaration(loc, id ? id : Identifier::generateId("__anonclass")) -{ - static const char msg[] = "only object.d can define this reserved class name"; - - if (baseclasses) - { - // Actually, this is a transfer - this->baseclasses = baseclasses; - } - else - this->baseclasses = new BaseClasses(); - - this->members = members; - - baseClass = NULL; - - interfaces.length = 0; - interfaces.ptr = NULL; - - vtblInterfaces = NULL; - - //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses->length); - - // For forward references - type = new TypeClass(this); - - staticCtor = NULL; - staticDtor = NULL; - - vtblsym = NULL; - vclassinfo = NULL; - - if (id) - { - // Look for special class names - - if (id == Id::__sizeof || id == Id::__xalignof || id == Id::_mangleof) - error("illegal class name"); - - // BUG: What if this is the wrong TypeInfo, i.e. it is nested? - if (id->toChars()[0] == 'T') - { - if (id == Id::TypeInfo) - { - if (!inObject) - error("%s", msg); - Type::dtypeinfo = this; - } - - if (id == Id::TypeInfo_Class) - { - if (!inObject) - error("%s", msg); - Type::typeinfoclass = this; - } - - if (id == Id::TypeInfo_Interface) - { - if (!inObject) - error("%s", msg); - Type::typeinfointerface = this; - } - - if (id == Id::TypeInfo_Struct) - { - if (!inObject) - error("%s", msg); - Type::typeinfostruct = this; - } - - if (id == Id::TypeInfo_Pointer) - { - if (!inObject) - error("%s", msg); - Type::typeinfopointer = this; - } - - if (id == Id::TypeInfo_Array) - { - if (!inObject) - error("%s", msg); - Type::typeinfoarray = this; - } - - if (id == Id::TypeInfo_StaticArray) - { - //if (!inObject) - // Type::typeinfostaticarray->error("%s", msg); - Type::typeinfostaticarray = this; - } - - if (id == Id::TypeInfo_AssociativeArray) - { - if (!inObject) - error("%s", msg); - Type::typeinfoassociativearray = this; - } - - if (id == Id::TypeInfo_Enum) - { - if (!inObject) - error("%s", msg); - Type::typeinfoenum = this; - } - - if (id == Id::TypeInfo_Function) - { - if (!inObject) - error("%s", msg); - Type::typeinfofunction = this; - } - - if (id == Id::TypeInfo_Delegate) - { - if (!inObject) - error("%s", msg); - Type::typeinfodelegate = this; - } - - if (id == Id::TypeInfo_Tuple) - { - if (!inObject) - error("%s", msg); - Type::typeinfotypelist = this; - } - - if (id == Id::TypeInfo_Const) - { - if (!inObject) - error("%s", msg); - Type::typeinfoconst = this; - } - - if (id == Id::TypeInfo_Invariant) - { - if (!inObject) - error("%s", msg); - Type::typeinfoinvariant = this; - } - - if (id == Id::TypeInfo_Shared) - { - if (!inObject) - error("%s", msg); - Type::typeinfoshared = this; - } - - if (id == Id::TypeInfo_Wild) - { - if (!inObject) - error("%s", msg); - Type::typeinfowild = this; - } - - if (id == Id::TypeInfo_Vector) - { - if (!inObject) - error("%s", msg); - Type::typeinfovector = this; - } - } - - if (id == Id::Object) - { - if (!inObject) - error("%s", msg); - object = this; - } - - if (id == Id::Throwable) - { - if (!inObject) - error("%s", msg); - throwable = this; - } - - if (id == Id::Exception) - { - if (!inObject) - error("%s", msg); - exception = this; - } - - if (id == Id::Error) - { - if (!inObject) - error("%s", msg); - errorException = this; - } - - if (id == Id::cpp_type_info_ptr) - { - if (!inObject) - error("%s", msg); - cpp_type_info_ptr = this; - } - } - - com = false; - isscope = false; - isabstract = ABSfwdref; - inuse = 0; - baseok = BASEOKnone; - cpp_type_info_ptr_sym = NULL; -} - -ClassDeclaration *ClassDeclaration::create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject) -{ - return new ClassDeclaration(loc, id, baseclasses, members, inObject); -} - -Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) -{ - //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars()); - ClassDeclaration *cd = - s ? (ClassDeclaration *)s - : new ClassDeclaration(loc, ident, NULL, NULL, false); - - cd->storage_class |= storage_class; - - cd->baseclasses->setDim(this->baseclasses->length); - for (size_t i = 0; i < cd->baseclasses->length; i++) - { - BaseClass *b = (*this->baseclasses)[i]; - BaseClass *b2 = new BaseClass(b->type->syntaxCopy()); - (*cd->baseclasses)[i] = b2; - } - - return ScopeDsymbol::syntaxCopy(cd); -} - -Scope *ClassDeclaration::newScope(Scope *sc) -{ - Scope *sc2 = AggregateDeclaration::newScope(sc); - if (isCOMclass()) - { - /* This enables us to use COM objects under Linux and - * work with things like XPCOM - */ - sc2->linkage = target.systemLinkage(); - } - return sc2; -} - -/********************************************* - * Determine if 'this' is a base class of cd. - * This is used to detect circular inheritance only. - */ - -bool ClassDeclaration::isBaseOf2(ClassDeclaration *cd) -{ - if (!cd) - return false; - //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); - for (size_t i = 0; i < cd->baseclasses->length; i++) - { - BaseClass *b = (*cd->baseclasses)[i]; - if (b->sym == this || isBaseOf2(b->sym)) - return true; - } - return false; -} - -/******************************************* - * Determine if 'this' is a base class of cd. - */ - -bool ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) -{ - //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); - if (poffset) - *poffset = 0; - while (cd) - { - /* cd->baseClass might not be set if cd is forward referenced. - */ - if (!cd->baseClass && cd->semanticRun < PASSsemanticdone && !cd->isInterfaceDeclaration()) - { - dsymbolSemantic(cd, NULL); - if (!cd->baseClass && cd->semanticRun < PASSsemanticdone) - cd->error("base class is forward referenced by %s", toChars()); - } - - if (this == cd->baseClass) - return true; - - cd = cd->baseClass; - } - return false; -} - -/********************************************* - * Determine if 'this' has complete base class information. - * This is used to detect forward references in covariant overloads. - */ - -bool ClassDeclaration::isBaseInfoComplete() -{ - return baseok >= BASEOKdone; -} - -Dsymbol *ClassDeclaration::search(const Loc &loc, Identifier *ident, int flags) -{ - //printf("%s.ClassDeclaration::search('%s', flags=x%x)\n", toChars(), ident->toChars(), flags); - - //if (_scope) printf("%s baseok = %d\n", toChars(), baseok); - if (_scope && baseok < BASEOKdone) - { - if (!inuse) - { - // must semantic on base class/interfaces - ++inuse; - dsymbolSemantic(this, NULL); - --inuse; - } - } - - if (!members || !symtab) // opaque or addMember is not yet done - { - error("is forward referenced when looking for `%s`", ident->toChars()); - //*(char*)0=0; - return NULL; - } - - Dsymbol *s = ScopeDsymbol::search(loc, ident, flags); - - // don't search imports of base classes - if (flags & SearchImportsOnly) - return s; - - if (!s) - { - // Search bases classes in depth-first, left to right order - - for (size_t i = 0; i < baseclasses->length; i++) - { - BaseClass *b = (*baseclasses)[i]; - - if (b->sym) - { - if (!b->sym->symtab) - error("base %s is forward referenced", b->sym->ident->toChars()); - else - { - s = b->sym->search(loc, ident, flags); - if (!s) - continue; - else if (s == this) // happens if s is nested in this and derives from this - s = NULL; - else if (!(flags & IgnoreSymbolVisibility) && !(s->prot().kind == Prot::protected_) && !symbolIsVisible(this, s)) - s = NULL; - else - break; - } - } - } - } - return s; -} - -/************************************ - * Search base classes in depth-first, left-to-right order for - * a class or interface named 'ident'. - * Stops at first found. Does not look for additional matches. - * Params: - * ident = identifier to search for - * Returns: - * ClassDeclaration if found, null if not - */ -ClassDeclaration *ClassDeclaration::searchBase(Identifier *ident) -{ - for (size_t i = 0; i < baseclasses->length; i++) - { - BaseClass *b = (*baseclasses)[i]; - ClassDeclaration *cdb = b->type->isClassHandle(); - if (!cdb) // Bugzilla 10616 - return NULL; - if (cdb->ident->equals(ident)) - return cdb; - cdb = cdb->searchBase(ident); - if (cdb) - return cdb; - } - return NULL; -} - -/**** - * Runs through the inheritance graph to set the BaseClass.offset fields. - * Recursive in order to account for the size of the interface classes, if they are - * more than just interfaces. - * Params: - * cd = interface to look at - * baseOffset = offset of where cd will be placed - * Returns: - * subset of instantiated size used by cd for interfaces - */ -static unsigned membersPlace(BaseClasses *vtblInterfaces, size_t &bi, ClassDeclaration *cd, unsigned baseOffset) -{ - //printf(" membersPlace(%s, %d)\n", cd->toChars(), baseOffset); - unsigned offset = baseOffset; - - for (size_t i = 0; i < cd->interfaces.length; i++) - { - BaseClass *b = cd->interfaces.ptr[i]; - if (b->sym->sizeok != SIZEOKdone) - b->sym->finalizeSize(); - assert(b->sym->sizeok == SIZEOKdone); - - if (!b->sym->alignsize) - b->sym->alignsize = target.ptrsize; - cd->alignmember(b->sym->alignsize, b->sym->alignsize, &offset); - assert(bi < vtblInterfaces->length); - BaseClass *bv = (*vtblInterfaces)[bi]; - if (b->sym->interfaces.length == 0) - { - //printf("\tvtblInterfaces[%d] b=%p b->sym = %s, offset = %d\n", bi, bv, bv->sym->toChars(), offset); - bv->offset = offset; - ++bi; - // All the base interfaces down the left side share the same offset - for (BaseClass *b2 = bv; b2->baseInterfaces.length; ) - { - b2 = &b2->baseInterfaces.ptr[0]; - b2->offset = offset; - //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2->sym->toChars(), b2->offset); - } - } - membersPlace(vtblInterfaces, bi, b->sym, offset); - //printf(" %s size = %d\n", b->sym->toChars(), b->sym->structsize); - offset += b->sym->structsize; - if (cd->alignsize < b->sym->alignsize) - cd->alignsize = b->sym->alignsize; - } - return offset - baseOffset; -} - -void ClassDeclaration::finalizeSize() -{ - assert(sizeok != SIZEOKdone); - - // Set the offsets of the fields and determine the size of the class - if (baseClass) - { - assert(baseClass->sizeok == SIZEOKdone); - - alignsize = baseClass->alignsize; - if (classKind == ClassKind::cpp) - structsize = target.cpp.derivedClassOffset(baseClass); - else - structsize = baseClass->structsize; - } - else if (isInterfaceDeclaration()) - { - if (interfaces.length == 0) - { - alignsize = target.ptrsize; - structsize = target.ptrsize; // allow room for __vptr - } - } - else - { - alignsize = target.ptrsize; - structsize = target.ptrsize; // allow room for __vptr - if (hasMonitor()) - structsize += target.ptrsize; // allow room for __monitor - } - - //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); - size_t bi = 0; // index into vtblInterfaces[] - - // Add vptr's for any interfaces implemented by this class - structsize += membersPlace(vtblInterfaces, bi, this, structsize); - - if (isInterfaceDeclaration()) - { - sizeok = SIZEOKdone; - return; - } - - // FIXME: Currently setFieldOffset functions need to increase fields - // to calculate each variable offsets. It can be improved later. - fields.setDim(0); - - unsigned offset = structsize; - for (size_t i = 0; i < members->length; i++) - { - Dsymbol *s = (*members)[i]; - s->setFieldOffset(this, &offset, false); - } - - sizeok = SIZEOKdone; - - // Calculate fields[i]->overlapped - checkOverlappedFields(); -} - -/************** - * Returns: true if there's a __monitor field - */ -bool ClassDeclaration::hasMonitor() -{ - return classKind == ClassKind::d; -} - -/********************************************************** - * fd is in the vtbl[] for this class. - * Return 1 if function is hidden (not findable through search). - */ - -int isf(void *param, Dsymbol *s) -{ - FuncDeclaration *fd = s->isFuncDeclaration(); - if (!fd) - return 0; - //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars()); - return (RootObject *)param == fd; -} - -bool ClassDeclaration::isFuncHidden(FuncDeclaration *fd) -{ - //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toPrettyChars()); - Dsymbol *s = search(Loc(), fd->ident, IgnoreAmbiguous | IgnoreErrors); - if (!s) - { - //printf("not found\n"); - /* Because, due to a hack, if there are multiple definitions - * of fd->ident, NULL is returned. - */ - return false; - } - s = s->toAlias(); - OverloadSet *os = s->isOverloadSet(); - if (os) - { - for (size_t i = 0; i < os->a.length; i++) - { - Dsymbol *s2 = os->a[i]; - FuncDeclaration *f2 = s2->isFuncDeclaration(); - if (f2 && overloadApply(f2, (void *)fd, &isf)) - return false; - } - return true; - } - else - { - FuncDeclaration *fdstart = s->isFuncDeclaration(); - //printf("%s fdstart = %p\n", s->kind(), fdstart); - if (overloadApply(fdstart, (void *)fd, &isf)) - return false; - - return !fd->parent->isTemplateMixin(); - } -} - -/**************** - * Find virtual function matching identifier and type. - * Used to build virtual function tables for interface implementations. - */ - -FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) -{ - //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars()); - FuncDeclaration *fdmatch = NULL; - FuncDeclaration *fdambig = NULL; - - ClassDeclaration *cd = this; - Dsymbols *vtbl = &cd->vtbl; - while (1) - { - for (size_t i = 0; i < vtbl->length; i++) - { - FuncDeclaration *fd = (*vtbl)[i]->isFuncDeclaration(); - if (!fd) - continue; // the first entry might be a ClassInfo - - //printf("\t[%d] = %s\n", i, fd->toChars()); - if (ident == fd->ident && - fd->type->covariant(tf) == 1) - { - //printf("fd->parent->isClassDeclaration() = %p\n", fd->parent->isClassDeclaration()); - if (!fdmatch) - goto Lfd; - if (fd == fdmatch) - goto Lfdmatch; - - { - // Function type matcing: exact > covariant - MATCH m1 = tf->equals(fd ->type) ? MATCHexact : MATCHnomatch; - MATCH m2 = tf->equals(fdmatch->type) ? MATCHexact : MATCHnomatch; - if (m1 > m2) - goto Lfd; - else if (m1 < m2) - goto Lfdmatch; - } - - { - MATCH m1 = (tf->mod == fd ->type->mod) ? MATCHexact : MATCHnomatch; - MATCH m2 = (tf->mod == fdmatch->type->mod) ? MATCHexact : MATCHnomatch; - if (m1 > m2) - goto Lfd; - else if (m1 < m2) - goto Lfdmatch; - } - - { - // The way of definition: non-mixin > mixin - MATCH m1 = fd ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch; - MATCH m2 = fdmatch->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch; - if (m1 > m2) - goto Lfd; - else if (m1 < m2) - goto Lfdmatch; - } - - fdambig = fd; - //printf("Lambig fdambig = %s %s [%s]\n", fdambig->toChars(), fdambig->type->toChars(), fdambig->loc.toChars()); - continue; - - Lfd: - fdmatch = fd; - fdambig = NULL; - //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch->toChars(), fdmatch->type->toChars(), fdmatch->loc.toChars()); - continue; - - Lfdmatch: - continue; - } - //else printf("\t\t%d\n", fd->type->covariant(tf)); - } - if (!cd) - break; - vtbl = &cd->vtblFinal; - cd = cd->baseClass; - } - - if (fdambig) - error("ambiguous virtual function %s", fdambig->toChars()); - return fdmatch; -} - -/**************************************** - */ - -bool ClassDeclaration::isCOMclass() const -{ - return com; -} - -bool ClassDeclaration::isCOMinterface() const -{ - return false; -} - -bool ClassDeclaration::isCPPclass() const -{ - return classKind == ClassKind::cpp; -} - -bool ClassDeclaration::isCPPinterface() const -{ - return false; -} - - -/**************************************** - */ - -bool ClassDeclaration::isAbstract() -{ - if (isabstract != ABSfwdref) - return isabstract == ABSyes; - - /* Bugzilla 11169: Resolve forward references to all class member functions, - * and determine whether this class is abstract. - */ - struct SearchAbstract - { - static int fp(Dsymbol *s, void *) - { - FuncDeclaration *fd = s->isFuncDeclaration(); - if (!fd) - return 0; - if (fd->storage_class & STCstatic) - return 0; - - if (fd->_scope) - dsymbolSemantic(fd, NULL); - - if (fd->isAbstract()) - return 1; - return 0; - } - }; - - for (size_t i = 0; i < members->length; i++) - { - Dsymbol *s = (*members)[i]; - if (s->apply(&SearchAbstract::fp, this)) - { - isabstract = ABSyes; - return true; - } - } - - /* Iterate inherited member functions and check their abstract attribute. - */ - for (size_t i = 1; i < vtbl.length; i++) - { - FuncDeclaration *fd = vtbl[i]->isFuncDeclaration(); - //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd->loc.toChars(), fd->toChars()); - if (!fd || fd->isAbstract()) - { - isabstract = ABSyes; - return true; - } - } - - isabstract = ABSno; - return false; -} - - -/**************************************** - * Determine if slot 0 of the vtbl[] is reserved for something else. - * For class objects, yes, this is where the classinfo ptr goes. - * For COM interfaces, no. - * For non-COM interfaces, yes, this is where the Interface ptr goes. - * Returns: - * 0 vtbl[0] is first virtual function pointer - * 1 vtbl[0] is classinfo/interfaceinfo pointer - */ - -int ClassDeclaration::vtblOffset() const -{ - return classKind == ClassKind::cpp ? 0 : 1; -} - -/**************************************** - */ - -const char *ClassDeclaration::kind() const -{ - return "class"; -} - -/**************************************** - */ - -void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses) -{ - aclasses->push(this); -} - -/********************************* InterfaceDeclaration ****************************/ - -InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses) - : ClassDeclaration(loc, id, baseclasses, NULL, false) -{ - if (id == Id::IUnknown) // IUnknown is the root of all COM interfaces - { - com = true; - classKind = ClassKind::cpp; // IUnknown is also a C++ interface - } -} - -Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s) -{ - InterfaceDeclaration *id = - s ? (InterfaceDeclaration *)s - : new InterfaceDeclaration(loc, ident, NULL); - return ClassDeclaration::syntaxCopy(id); -} - -Scope *InterfaceDeclaration::newScope(Scope *sc) -{ - Scope *sc2 = ClassDeclaration::newScope(sc); - if (com) - sc2->linkage = LINKwindows; - else if (classKind == ClassKind::cpp) - sc2->linkage = LINKcpp; - else if (classKind == ClassKind::objc) - sc2->linkage = LINKobjc; - return sc2; -} - -/******************************************* - * Determine if 'this' is a base class of cd. - * (Actually, if it is an interface supported by cd) - * Output: - * *poffset offset to start of class - * OFFSET_RUNTIME must determine offset at runtime - * Returns: - * false not a base - * true is a base - */ - -bool InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) -{ - //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars()); - assert(!baseClass); - for (size_t j = 0; j < cd->interfaces.length; j++) - { - BaseClass *b = cd->interfaces.ptr[j]; - - //printf("\tX base %s\n", b->sym->toChars()); - if (this == b->sym) - { - //printf("\tfound at offset %d\n", b->offset); - if (poffset) - { - // don't return incorrect offsets https://issues.dlang.org/show_bug.cgi?id=16980 - *poffset = cd->sizeok == SIZEOKdone ? b->offset : OFFSET_FWDREF; - } - //printf("\tfound at offset %d\n", b->offset); - return true; - } - if (isBaseOf(b, poffset)) - return true; - } - - if (cd->baseClass && isBaseOf(cd->baseClass, poffset)) - return true; - - if (poffset) - *poffset = 0; - return false; -} - -bool InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset) -{ - //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->sym->toChars()); - for (size_t j = 0; j < bc->baseInterfaces.length; j++) - { - BaseClass *b = &bc->baseInterfaces.ptr[j]; - - //printf("\tY base %s\n", b->sym->toChars()); - if (this == b->sym) - { - //printf("\tfound at offset %d\n", b->offset); - if (poffset) - { - *poffset = b->offset; - } - return true; - } - if (isBaseOf(b, poffset)) - { - return true; - } - } - if (poffset) - *poffset = 0; - return false; -} - -/**************************************** - * Determine if slot 0 of the vtbl[] is reserved for something else. - * For class objects, yes, this is where the ClassInfo ptr goes. - * For COM interfaces, no. - * For non-COM interfaces, yes, this is where the Interface ptr goes. - */ - -int InterfaceDeclaration::vtblOffset() const -{ - if (isCOMinterface() || isCPPinterface()) - return 0; - return 1; -} - -bool InterfaceDeclaration::isCOMinterface() const -{ - return com; -} - -bool InterfaceDeclaration::isCPPinterface() const -{ - return classKind == ClassKind::cpp; -} - -/******************************************* - */ - -const char *InterfaceDeclaration::kind() const -{ - return "interface"; -} - - -/******************************** BaseClass *****************************/ - -BaseClass::BaseClass() -{ - this->type = NULL; - this->sym = NULL; - this->offset = 0; - - this->baseInterfaces.length = 0; - this->baseInterfaces.ptr = NULL; -} - -BaseClass::BaseClass(Type *type) -{ - //printf("BaseClass(this = %p, '%s')\n", this, type->toChars()); - this->type = type; - this->sym = NULL; - this->offset = 0; - - this->baseInterfaces.length = 0; - this->baseInterfaces.ptr = NULL; -} - -/**************************************** - * Fill in vtbl[] for base class based on member functions of class cd. - * Input: - * vtbl if !=NULL, fill it in - * newinstance !=0 means all entries must be filled in by members - * of cd, not members of any base classes of cd. - * Returns: - * true if any entries were filled in by members of cd (not exclusively - * by base classes) - */ - -bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance) -{ - bool result = false; - - //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", sym->toChars(), cd->toChars()); - if (vtbl) - vtbl->setDim(sym->vtbl.length); - - // first entry is ClassInfo reference - for (size_t j = sym->vtblOffset(); j < sym->vtbl.length; j++) - { - FuncDeclaration *ifd = sym->vtbl[j]->isFuncDeclaration(); - FuncDeclaration *fd; - TypeFunction *tf; - - //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null"); - - assert(ifd); - // Find corresponding function in this class - tf = ifd->type->toTypeFunction(); - fd = cd->findFunc(ifd->ident, tf); - if (fd && !fd->isAbstract()) - { - //printf(" found\n"); - // Check that calling conventions match - if (fd->linkage != ifd->linkage) - fd->error("linkage doesn't match interface function"); - - // Check that it is current - //printf("newinstance = %d fd->toParent() = %s ifd->toParent() = %s\n", - //newinstance, fd->toParent()->toChars(), ifd->toParent()->toChars()); - if (newinstance && fd->toParent() != cd && ifd->toParent() == sym) - cd->error("interface function `%s` is not implemented", ifd->toFullSignature()); - - if (fd->toParent() == cd) - result = true; - } - else - { - //printf(" not found %p\n", fd); - // BUG: should mark this class as abstract? - if (!cd->isAbstract()) - cd->error("interface function `%s` is not implemented", ifd->toFullSignature()); - - fd = NULL; - } - if (vtbl) - (*vtbl)[j] = fd; - } - - return result; -} - -void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces) -{ - //printf("+copyBaseInterfaces(), %s\n", sym->toChars()); -// if (baseInterfaces.length) -// return; - - baseInterfaces.length = sym->interfaces.length; - baseInterfaces.ptr = (BaseClass *)mem.xcalloc(baseInterfaces.length, sizeof(BaseClass)); - - //printf("%s.copyBaseInterfaces()\n", sym->toChars()); - for (size_t i = 0; i < baseInterfaces.length; i++) - { - void *pb = &baseInterfaces.ptr[i]; - BaseClass *b2 = sym->interfaces.ptr[i]; - - assert(b2->vtbl.length == 0); // should not be filled yet - BaseClass *b = (BaseClass *)memcpy(pb, b2, sizeof(BaseClass)); - - if (i) // single inheritance is i==0 - vtblInterfaces->push(b); // only need for M.I. - b->copyBaseInterfaces(vtblInterfaces); - } - //printf("-copyBaseInterfaces\n"); -} |