aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd/dstruct.c
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2019-06-18 20:42:10 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2021-11-30 16:53:28 +0100
commit5fee5ec362f7a243f459e6378fd49dfc89dc9fb5 (patch)
tree61d1bdbca854a903c0860406f457f06b2040be7a /gcc/d/dmd/dstruct.c
parentb3f60112edcb85b459e60f66c44a55138b1cef49 (diff)
downloadgcc-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/dstruct.c')
-rw-r--r--gcc/d/dmd/dstruct.c1303
1 files changed, 0 insertions, 1303 deletions
diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c
deleted file mode 100644
index 9862159..0000000
--- a/gcc/d/dmd/dstruct.c
+++ /dev/null
@@ -1,1303 +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/struct.c
- */
-
-#include "root/dsystem.h"
-#include "root/root.h"
-
-#include "errors.h"
-#include "aggregate.h"
-#include "scope.h"
-#include "mtype.h"
-#include "init.h"
-#include "declaration.h"
-#include "module.h"
-#include "id.h"
-#include "statement.h"
-#include "template.h"
-#include "tokens.h"
-#include "target.h"
-#include "utf.h"
-#include "root/ctfloat.h"
-
-Type *getTypeInfoType(Loc loc, Type *t, Scope *sc);
-void unSpeculative(Scope *sc, RootObject *o);
-bool MODimplicitConv(MOD modfrom, MOD modto);
-Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
-
-FuncDeclaration *StructDeclaration::xerreq; // object.xopEquals
-FuncDeclaration *StructDeclaration::xerrcmp; // object.xopCmp
-
-/***************************************
- * Search toString member function for TypeInfo_Struct.
- * string toString();
- */
-FuncDeclaration *search_toString(StructDeclaration *sd)
-{
- Dsymbol *s = search_function(sd, Id::tostring);
- FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL;
- if (fd)
- {
- static TypeFunction *tftostring;
- if (!tftostring)
- {
- tftostring = new TypeFunction(ParameterList(), Type::tstring, LINKd);
- tftostring = tftostring->merge()->toTypeFunction();
- }
-
- fd = fd->overloadExactMatch(tftostring);
- }
- return fd;
-}
-
-/***************************************
- * Request additonal semantic analysis for TypeInfo generation.
- */
-void semanticTypeInfo(Scope *sc, Type *t)
-{
- class FullTypeInfoVisitor : public Visitor
- {
- public:
- Scope *sc;
-
- void visit(Type *t)
- {
- Type *tb = t->toBasetype();
- if (tb != t)
- tb->accept(this);
- }
- void visit(TypeNext *t)
- {
- if (t->next)
- t->next->accept(this);
- }
- void visit(TypeBasic *) { }
- void visit(TypeVector *t)
- {
- t->basetype->accept(this);
- }
- void visit(TypeAArray *t)
- {
- t->index->accept(this);
- visit((TypeNext *)t);
- }
- void visit(TypeFunction *t)
- {
- visit((TypeNext *)t);
- // Currently TypeInfo_Function doesn't store parameter types.
- }
- void visit(TypeStruct *t)
- {
- //printf("semanticTypeInfo::visit(TypeStruct = %s)\n", t->toChars());
- StructDeclaration *sd = t->sym;
-
- /* Step 1: create TypeInfoDeclaration
- */
- if (!sc) // inline may request TypeInfo.
- {
- Scope scx;
- scx._module = sd->getModule();
- getTypeInfoType(sd->loc, t, &scx);
- sd->requestTypeInfo = true;
- }
- else if (!sc->minst)
- {
- // don't yet have to generate TypeInfo instance if
- // the typeid(T) expression exists in speculative scope.
- }
- else
- {
- getTypeInfoType(sd->loc, t, sc);
- sd->requestTypeInfo = true;
-
- // Bugzilla 15149, if the typeid operand type comes from a
- // result of auto function, it may be yet speculative.
- // unSpeculative(sc, sd);
- }
-
- /* Step 2: If the TypeInfo generation requires sd.semantic3, run it later.
- * This should be done even if typeid(T) exists in speculative scope.
- * Because it may appear later in non-speculative scope.
- */
- if (!sd->members)
- return; // opaque struct
- if (!sd->xeq && !sd->xcmp && !sd->postblit &&
- !sd->dtor && !sd->xhash && !search_toString(sd))
- return; // none of TypeInfo-specific members
-
- // If the struct is in a non-root module, run semantic3 to get
- // correct symbols for the member function.
- if (sd->semanticRun >= PASSsemantic3)
- {
- // semantic3 is already done
- }
- else if (TemplateInstance *ti = sd->isInstantiated())
- {
- if (ti->minst && !ti->minst->isRoot())
- Module::addDeferredSemantic3(sd);
- }
- else
- {
- if (sd->inNonRoot())
- {
- //printf("deferred sem3 for TypeInfo - sd = %s, inNonRoot = %d\n", sd->toChars(), sd->inNonRoot());
- Module::addDeferredSemantic3(sd);
- }
- }
- }
- void visit(TypeClass *) { }
- void visit(TypeTuple *t)
- {
- if (t->arguments)
- {
- for (size_t i = 0; i < t->arguments->length; i++)
- {
- Type *tprm = (*t->arguments)[i]->type;
- if (tprm)
- tprm->accept(this);
- }
- }
- }
- };
-
- if (sc)
- {
- if (!sc->func)
- return;
- if (sc->intypeof)
- return;
- if (sc->flags & (SCOPEctfe | SCOPEcompile))
- return;
- }
-
- FullTypeInfoVisitor v;
- v.sc = sc;
- t->accept(&v);
-}
-
-/********************************* AggregateDeclaration ****************************/
-
-AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
- : ScopeDsymbol(id)
-{
- this->loc = loc;
-
- storage_class = 0;
- protection = Prot(Prot::public_);
- type = NULL;
- structsize = 0; // size of struct
- alignsize = 0; // size of struct for alignment purposes
- sizeok = SIZEOKnone; // size not determined yet
- deferred = NULL;
- isdeprecated = false;
- classKind = ClassKind::d;
- inv = NULL;
- aggNew = NULL;
- aggDelete = NULL;
-
- stag = NULL;
- sinit = NULL;
- enclosing = NULL;
- vthis = NULL;
-
- ctor = NULL;
- defaultCtor = NULL;
- aliasthis = NULL;
- noDefaultCtor = false;
- dtor = NULL;
- getRTInfo = NULL;
-}
-
-Prot AggregateDeclaration::prot()
-{
- return protection;
-}
-
-/***************************************
- * Create a new scope from sc.
- * semantic, semantic2 and semantic3 will use this for aggregate members.
- */
-Scope *AggregateDeclaration::newScope(Scope *sc)
-{
- Scope *sc2 = sc->push(this);
- sc2->stc &= STCsafe | STCtrusted | STCsystem;
- sc2->parent = this;
- if (isUnionDeclaration())
- sc2->inunion = 1;
- sc2->protection = Prot(Prot::public_);
- sc2->explicitProtection = 0;
- sc2->aligndecl = NULL;
- sc2->userAttribDecl = NULL;
- return sc2;
-}
-
-void AggregateDeclaration::setScope(Scope *sc)
-{
- // Might need a scope to resolve forward references. The check for
- // semanticRun prevents unnecessary setting of _scope during deferred
- // setScope phases for aggregates which already finished semantic().
- // Also see https://issues.dlang.org/show_bug.cgi?id=16607
- if (semanticRun < PASSsemanticdone)
- ScopeDsymbol::setScope(sc);
-}
-
-/***************************************
- * Find all instance fields, then push them into `fields`.
- *
- * Runs semantic() for all instance field variables, but also
- * the field types can reamin yet not resolved forward references,
- * except direct recursive definitions.
- * After the process sizeok is set to SIZEOKfwd.
- *
- * Returns:
- * false if any errors occur.
- */
-bool AggregateDeclaration::determineFields()
-{
- if (_scope)
- dsymbolSemantic(this, NULL);
- if (sizeok != SIZEOKnone)
- return true;
-
- //printf("determineFields() %s, fields.length = %d\n", toChars(), fields.length);
- fields.setDim(0);
-
- struct SV
- {
- AggregateDeclaration *agg;
-
- static int func(Dsymbol *s, void *param)
- {
- VarDeclaration *v = s->isVarDeclaration();
- if (!v)
- return 0;
- if (v->storage_class & STCmanifest)
- return 0;
-
- AggregateDeclaration *ad = ((SV *)param)->agg;
-
- if (v->semanticRun < PASSsemanticdone)
- dsymbolSemantic(v, NULL);
- // Note: Aggregate fields or size could have determined during v->semantic.
- if (ad->sizeok != SIZEOKnone)
- return 1;
-
- if (v->aliassym)
- return 0; // If this variable was really a tuple, skip it.
-
- if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCctfe | STCtemplateparameter))
- return 0;
- if (!v->isField() || v->semanticRun < PASSsemanticdone)
- return 1; // unresolvable forward reference
-
- ad->fields.push(v);
-
- if (v->storage_class & STCref)
- return 0;
- Type *tv = v->type->baseElemOf();
- if (tv->ty != Tstruct)
- return 0;
- if (ad == ((TypeStruct *)tv)->sym)
- {
- const char *psz = (v->type->toBasetype()->ty == Tsarray) ? "static array of " : "";
- ad->error("cannot have field %s with %ssame struct type", v->toChars(), psz);
- ad->type = Type::terror;
- ad->errors = true;
- return 1;
- }
- return 0;
- }
- };
- SV sv;
- sv.agg = this;
-
- for (size_t i = 0; i < members->length; i++)
- {
- Dsymbol *s = (*members)[i];
- if (s->apply(&SV::func, &sv))
- {
- if (sizeok != SIZEOKnone)
- return true;
- return false;
- }
- }
-
- if (sizeok != SIZEOKdone)
- sizeok = SIZEOKfwd;
-
- return true;
-}
-
-/***************************************
- * Collect all instance fields, then determine instance size.
- * Returns:
- * false if failed to determine the size.
- */
-bool AggregateDeclaration::determineSize(Loc loc)
-{
- //printf("AggregateDeclaration::determineSize() %s, sizeok = %d\n", toChars(), sizeok);
-
- // The previous instance size finalizing had:
- if (type->ty == Terror)
- return false; // failed already
- if (sizeok == SIZEOKdone)
- return true; // succeeded
-
- if (!members)
- {
- error(loc, "unknown size");
- return false;
- }
-
- if (_scope)
- dsymbolSemantic(this, NULL);
-
- // Determine the instance size of base class first.
- if (ClassDeclaration *cd = isClassDeclaration())
- {
- cd = cd->baseClass;
- if (cd && !cd->determineSize(loc))
- goto Lfail;
- }
-
- // Determine instance fields when sizeok == SIZEOKnone
- if (!determineFields())
- goto Lfail;
- if (sizeok != SIZEOKdone)
- finalizeSize();
-
- // this aggregate type has:
- if (type->ty == Terror)
- return false; // marked as invalid during the finalizing.
- if (sizeok == SIZEOKdone)
- return true; // succeeded to calculate instance size.
-
-Lfail:
- // There's unresolvable forward reference.
- if (type != Type::terror)
- error(loc, "no size because of forward reference");
- // Don't cache errors from speculative semantic, might be resolvable later.
- // https://issues.dlang.org/show_bug.cgi?id=16574
- if (!global.gag)
- {
- type = Type::terror;
- errors = true;
- }
- return false;
-}
-
-void StructDeclaration::semanticTypeInfoMembers()
-{
- if (xeq &&
- xeq->_scope &&
- xeq->semanticRun < PASSsemantic3done)
- {
- unsigned errors = global.startGagging();
- semantic3(xeq, xeq->_scope);
- if (global.endGagging(errors))
- xeq = xerreq;
- }
-
- if (xcmp &&
- xcmp->_scope &&
- xcmp->semanticRun < PASSsemantic3done)
- {
- unsigned errors = global.startGagging();
- semantic3(xcmp, xcmp->_scope);
- if (global.endGagging(errors))
- xcmp = xerrcmp;
- }
-
- FuncDeclaration *ftostr = search_toString(this);
- if (ftostr &&
- ftostr->_scope &&
- ftostr->semanticRun < PASSsemantic3done)
- {
- semantic3(ftostr, ftostr->_scope);
- }
-
- if (xhash &&
- xhash->_scope &&
- xhash->semanticRun < PASSsemantic3done)
- {
- semantic3(xhash, xhash->_scope);
- }
-
- if (postblit &&
- postblit->_scope &&
- postblit->semanticRun < PASSsemantic3done)
- {
- semantic3(postblit, postblit->_scope);
- }
-
- if (dtor &&
- dtor->_scope &&
- dtor->semanticRun < PASSsemantic3done)
- {
- semantic3(dtor, dtor->_scope);
- }
-}
-
-d_uns64 AggregateDeclaration::size(Loc loc)
-{
- //printf("+AggregateDeclaration::size() %s, scope = %p, sizeok = %d\n", toChars(), _scope, sizeok);
- bool ok = determineSize(loc);
- //printf("-AggregateDeclaration::size() %s, scope = %p, sizeok = %d\n", toChars(), _scope, sizeok);
- return ok ? structsize : SIZE_INVALID;
-}
-
-Type *AggregateDeclaration::getType()
-{
- return type;
-}
-
-bool AggregateDeclaration::isDeprecated()
-{
- return isdeprecated;
-}
-
-bool AggregateDeclaration::isExport() const
-{
- return protection.kind == Prot::export_;
-}
-
-/***************************************
- * Calculate field[i].overlapped and overlapUnsafe, and check that all of explicit
- * field initializers have unique memory space on instance.
- * Returns:
- * true if any errors happen.
- */
-
-bool AggregateDeclaration::checkOverlappedFields()
-{
- //printf("AggregateDeclaration::checkOverlappedFields() %s\n", toChars());
- assert(sizeok == SIZEOKdone);
- size_t nfields = fields.length;
- if (isNested())
- {
- ClassDeclaration *cd = isClassDeclaration();
- if (!cd || !cd->baseClass || !cd->baseClass->isNested())
- nfields--;
- }
- bool errors = false;
-
- // Fill in missing any elements with default initializers
- for (size_t i = 0; i < nfields; i++)
- {
- VarDeclaration *vd = fields[i];
- if (vd->errors)
- {
- errors = true;
- continue;
- }
-
- VarDeclaration *vx = vd;
- if (vd->_init && vd->_init->isVoidInitializer())
- vx = NULL;
-
- // Find overlapped fields with the hole [vd->offset .. vd->offset->size()].
- for (size_t j = 0; j < nfields; j++)
- {
- if (i == j)
- continue;
- VarDeclaration *v2 = fields[j];
- if (v2->errors)
- {
- errors = true;
- continue;
- }
- if (!vd->isOverlappedWith(v2))
- continue;
-
- // vd and v2 are overlapping.
- vd->overlapped = true;
- v2->overlapped = true;
-
- if (!MODimplicitConv(vd->type->mod, v2->type->mod))
- v2->overlapUnsafe = true;
- if (!MODimplicitConv(v2->type->mod, vd->type->mod))
- vd->overlapUnsafe = true;
-
- if (!vx)
- continue;
- if (v2->_init && v2->_init->isVoidInitializer())
- continue;
-
- if (vx->_init && v2->_init)
- {
- ::error(loc, "overlapping default initialization for field %s and %s", v2->toChars(), vd->toChars());
- errors = true;
- }
- }
- }
- return errors;
-}
-
-/***************************************
- * Fill out remainder of elements[] with default initializers for fields[].
- * Input:
- * loc: location
- * elements: explicit arguments which given to construct object.
- * ctorinit: true if the elements will be used for default initialization.
- * Returns:
- * false if any errors occur.
- * Otherwise, returns true and the missing arguments will be pushed in elements[].
- */
-bool AggregateDeclaration::fill(Loc loc, Expressions *elements, bool ctorinit)
-{
- //printf("AggregateDeclaration::fill() %s\n", toChars());
- assert(sizeok == SIZEOKdone);
- assert(elements);
- size_t nfields = fields.length - isNested();
- bool errors = false;
-
- size_t dim = elements->length;
- elements->setDim(nfields);
- for (size_t i = dim; i < nfields; i++)
- (*elements)[i] = NULL;
-
- // Fill in missing any elements with default initializers
- for (size_t i = 0; i < nfields; i++)
- {
- if ((*elements)[i])
- continue;
-
- VarDeclaration *vd = fields[i];
- VarDeclaration *vx = vd;
- if (vd->_init && vd->_init->isVoidInitializer())
- vx = NULL;
-
- // Find overlapped fields with the hole [vd->offset .. vd->offset->size()].
- size_t fieldi = i;
- for (size_t j = 0; j < nfields; j++)
- {
- if (i == j)
- continue;
- VarDeclaration *v2 = fields[j];
- if (!vd->isOverlappedWith(v2))
- continue;
-
- if ((*elements)[j])
- {
- vx = NULL;
- break;
- }
- if (v2->_init && v2->_init->isVoidInitializer())
- continue;
-
- if (1)
- {
- /* Prefer first found non-void-initialized field
- * union U { int a; int b = 2; }
- * U u; // Error: overlapping initialization for field a and b
- */
- if (!vx)
- {
- vx = v2;
- fieldi = j;
- }
- else if (v2->_init)
- {
- ::error(loc, "overlapping initialization for field %s and %s",
- v2->toChars(), vd->toChars());
- errors = true;
- }
- }
- else
- {
- // Will fix Bugzilla 1432 by enabling this path always
-
- /* Prefer explicitly initialized field
- * union U { int a; int b = 2; }
- * U u; // OK (u.b == 2)
- */
- if (!vx || (!vx->_init && v2->_init))
- {
- vx = v2;
- fieldi = j;
- }
- else if (vx != vd && !vx->isOverlappedWith(v2))
- {
- // Both vx and v2 fills vd, but vx and v2 does not overlap
- }
- else if (vx->_init && v2->_init)
- {
- ::error(loc, "overlapping default initialization for field %s and %s",
- v2->toChars(), vd->toChars());
- errors = true;
- }
- else
- assert(vx->_init || (!vx->_init && !v2->_init));
- }
- }
- if (vx)
- {
- Expression *e;
- if (vx->type->size() == 0)
- {
- e = NULL;
- }
- else if (vx->_init)
- {
- assert(!vx->_init->isVoidInitializer());
- if (vx->inuse) // https://issues.dlang.org/show_bug.cgi?id=18057
- {
- vx->error(loc, "recursive initialization of field");
- errors = true;
- e = NULL;
- }
- else
- e = vx->getConstInitializer(false);
- }
- else
- {
- if ((vx->storage_class & STCnodefaultctor) && !ctorinit)
- {
- ::error(loc, "field %s.%s must be initialized because it has no default constructor",
- type->toChars(), vx->toChars());
- errors = true;
- }
-
- /* Bugzilla 12509: Get the element of static array type.
- */
- Type *telem = vx->type;
- if (telem->ty == Tsarray)
- {
- /* We cannot use Type::baseElemOf() here.
- * If the bottom of the Tsarray is an enum type, baseElemOf()
- * will return the base of the enum, and its default initializer
- * would be different from the enum's.
- */
- while (telem->toBasetype()->ty == Tsarray)
- telem = ((TypeSArray *)telem->toBasetype())->next;
-
- if (telem->ty == Tvoid)
- telem = Type::tuns8->addMod(telem->mod);
- }
- if (telem->needsNested() && ctorinit)
- e = telem->defaultInit(loc);
- else
- e = telem->defaultInitLiteral(loc);
- }
- (*elements)[fieldi] = e;
- }
- }
-
- for (size_t i = 0; i < elements->length; i++)
- {
- Expression *e = (*elements)[i];
- if (e && e->op == TOKerror)
- return false;
- }
-
- return !errors;
-}
-
-/****************************
- * Do byte or word alignment as necessary.
- * Align sizes of 0, as we may not know array sizes yet.
- *
- * alignment: struct alignment that is in effect
- * size: alignment requirement of field
- */
-
-void AggregateDeclaration::alignmember(
- structalign_t alignment,
- unsigned size,
- unsigned *poffset)
-{
- //printf("alignment = %d, size = %d, offset = %d\n",alignment,size,offset);
- switch (alignment)
- {
- case (structalign_t) 1:
- // No alignment
- break;
-
- case (structalign_t) STRUCTALIGN_DEFAULT:
- // Alignment in target.fieldalignsize must match what the
- // corresponding C compiler's default alignment behavior is.
- assert(size > 0 && !(size & (size - 1)));
- *poffset = (*poffset + size - 1) & ~(size - 1);
- break;
-
- default:
- // Align on alignment boundary, which must be a positive power of 2
- assert(alignment > 0 && !(alignment & (alignment - 1)));
- *poffset = (*poffset + alignment - 1) & ~(alignment - 1);
- break;
- }
-}
-
-/****************************************
- * Place a member (mem) into an aggregate (agg), which can be a struct, union or class
- * Returns:
- * offset to place field at
- *
- * nextoffset: next location in aggregate
- * memsize: size of member
- * memalignsize: natural alignment of member
- * alignment: alignment in effect for this member
- * paggsize: size of aggregate (updated)
- * paggalignsize: alignment of aggregate (updated)
- * isunion: the aggregate is a union
- */
-unsigned AggregateDeclaration::placeField(
- unsigned *nextoffset,
- unsigned memsize,
- unsigned memalignsize,
- structalign_t alignment,
- unsigned *paggsize,
- unsigned *paggalignsize,
- bool isunion
- )
-{
- unsigned ofs = *nextoffset;
-
- const unsigned actualAlignment =
- alignment == STRUCTALIGN_DEFAULT ? memalignsize : alignment;
-
- alignmember(alignment, memalignsize, &ofs);
- unsigned memoffset = ofs;
- ofs += memsize;
- if (ofs > *paggsize)
- *paggsize = ofs;
- if (!isunion)
- *nextoffset = ofs;
-
- if (*paggalignsize < actualAlignment)
- *paggalignsize = actualAlignment;
-
- return memoffset;
-}
-
-
-/****************************************
- * Returns true if there's an extra member which is the 'this'
- * pointer to the enclosing context (enclosing aggregate or function)
- */
-
-bool AggregateDeclaration::isNested()
-{
- return enclosing != NULL;
-}
-
-/* Append vthis field (this->tupleof[$-1]) to make this aggregate type nested.
- */
-void AggregateDeclaration::makeNested()
-{
- if (enclosing) // if already nested
- return;
- if (sizeok == SIZEOKdone)
- return;
- if (isUnionDeclaration() || isInterfaceDeclaration())
- return;
- if (storage_class & STCstatic)
- return;
-
- // If nested struct, add in hidden 'this' pointer to outer scope
- Dsymbol *s = toParent2();
- if (!s)
- return;
- Type *t = NULL;
- if (FuncDeclaration *fd = s->isFuncDeclaration())
- {
- enclosing = fd;
-
- /* Bugzilla 14422: If a nested class parent is a function, its
- * context pointer (== `outer`) should be void* always.
- */
- t = Type::tvoidptr;
- }
- else if (AggregateDeclaration *ad = s->isAggregateDeclaration())
- {
- if (isClassDeclaration() && ad->isClassDeclaration())
- {
- enclosing = ad;
- }
- else if (isStructDeclaration())
- {
- if (TemplateInstance *ti = ad->parent->isTemplateInstance())
- {
- enclosing = ti->enclosing;
- }
- }
-
- t = ad->handleType();
- }
- if (enclosing)
- {
- //printf("makeNested %s, enclosing = %s\n", toChars(), enclosing->toChars());
- assert(t);
- if (t->ty == Tstruct)
- t = Type::tvoidptr; // t should not be a ref type
- assert(!vthis);
- vthis = new ThisDeclaration(loc, t);
- //vthis->storage_class |= STCref;
-
- // Emulate vthis->addMember()
- members->push(vthis);
-
- // Emulate vthis->semantic()
- vthis->storage_class |= STCfield;
- vthis->parent = this;
- vthis->protection = Prot(Prot::public_);
- vthis->alignment = t->alignment();
- vthis->semanticRun = PASSsemanticdone;
-
- if (sizeok == SIZEOKfwd)
- fields.push(vthis);
- }
-}
-
-/*******************************************
- * Look for constructor declaration.
- */
-Dsymbol *AggregateDeclaration::searchCtor()
-{
- Dsymbol *s = search(Loc(), Id::ctor);
- if (s)
- {
- if (!(s->isCtorDeclaration() ||
- s->isTemplateDeclaration() ||
- s->isOverloadSet()))
- {
- s->error("is not a constructor; identifiers starting with __ are reserved for the implementation");
- errors = true;
- s = NULL;
- }
- }
- if (s && s->toParent() != this)
- s = NULL; // search() looks through ancestor classes
- if (s)
- {
- // Finish all constructors semantics to determine this->noDefaultCtor.
- struct SearchCtor
- {
- static int fp(Dsymbol *s, void *)
- {
- CtorDeclaration *f = s->isCtorDeclaration();
- if (f && f->semanticRun == PASSinit)
- dsymbolSemantic(f, NULL);
- return 0;
- }
- };
-
- for (size_t i = 0; i < members->length; i++)
- {
- Dsymbol *sm = (*members)[i];
- sm->apply(&SearchCtor::fp, NULL);
- }
- }
- return s;
-}
-
-/********************************* StructDeclaration ****************************/
-
-StructDeclaration::StructDeclaration(Loc loc, Identifier *id, bool inObject)
- : AggregateDeclaration(loc, id)
-{
- zeroInit = 0; // assume false until we do semantic processing
- hasIdentityAssign = false;
- hasIdentityEquals = false;
- postblit = NULL;
-
- xeq = NULL;
- xcmp = NULL;
- xhash = NULL;
- alignment = 0;
- ispod = ISPODfwd;
- arg1type = NULL;
- arg2type = NULL;
- requestTypeInfo = false;
-
- // For forward references
- type = new TypeStruct(this);
-
- if (inObject)
- {
- if (id == Id::ModuleInfo && !Module::moduleinfo)
- Module::moduleinfo = this;
- }
-}
-
-StructDeclaration *StructDeclaration::create(Loc loc, Identifier *id, bool inObject)
-{
- return new StructDeclaration(loc, id, inObject);
-}
-
-Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
-{
- StructDeclaration *sd =
- s ? (StructDeclaration *)s
- : new StructDeclaration(loc, ident, false);
- return ScopeDsymbol::syntaxCopy(sd);
-}
-
-Dsymbol *StructDeclaration::search(const Loc &loc, Identifier *ident, int flags)
-{
- //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", toChars(), ident->toChars(), flags);
-
- if (_scope && !symtab)
- dsymbolSemantic(this, _scope);
-
- if (!members || !symtab) // opaque or semantic() is not yet called
- {
- error("is forward referenced when looking for `%s`", ident->toChars());
- return NULL;
- }
-
- return ScopeDsymbol::search(loc, ident, flags);
-}
-
-/**********************************
- * Determine if exp is all binary zeros.
- * Params:
- * exp = expression to check
- * Returns:
- * true if it's all binary 0
- */
-static bool isZeroInit(Expression *exp)
-{
- switch (exp->op)
- {
- case TOKint64:
- return exp->toInteger() == 0;
-
- case TOKnull:
- case TOKfalse:
- return true;
-
- case TOKstructliteral:
- {
- StructLiteralExp *sle = (StructLiteralExp *) exp;
- for (size_t i = 0; i < sle->sd->fields.length; i++)
- {
- VarDeclaration *field = sle->sd->fields[i];
- if (field->type->size(field->loc))
- {
- Expression *e = (*sle->elements)[i];
- if (e ? !isZeroInit(e)
- : !field->type->isZeroInit(field->loc))
- return false;
- }
- }
- return true;
- }
-
- case TOKarrayliteral:
- {
- ArrayLiteralExp *ale = (ArrayLiteralExp *) exp;
-
- const size_t dim = ale->elements ? ale->elements->length : 0;
-
- if (ale->type->toBasetype()->ty == Tarray) // if initializing a dynamic array
- return dim == 0;
-
- for (size_t i = 0; i < dim; i++)
- {
- if (!isZeroInit(ale->getElement(i)))
- return false;
- }
- /* Note that true is returned for all T[0]
- */
- return true;
- }
-
- case TOKstring:
- {
- StringExp *se = exp->toStringExp();
-
- if (se->type->toBasetype()->ty == Tarray) // if initializing a dynamic array
- return se->len == 0;
-
- void *s = se->string;
- for (size_t i = 0; i < se->len; i++)
- {
- dinteger_t val;
- switch (se->sz)
- {
- case 1: val = (( utf8_t *)s)[i]; break;
- case 2: val = ((utf16_t *)s)[i]; break;
- case 4: val = ((utf32_t *)s)[i]; break;
- default: assert(0); break;
- }
- if (val)
- return false;
- }
- return true;
- }
-
- case TOKvector:
- {
- VectorExp *ve = (VectorExp *) exp;
- return isZeroInit(ve->e1);
- }
-
- case TOKfloat64:
- case TOKcomplex80:
- {
- return (exp->toReal() == CTFloat::zero) &&
- (exp->toImaginary() == CTFloat::zero);
- }
-
- default:
- return false;
- }
-}
-
-void StructDeclaration::finalizeSize()
-{
- //printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
- assert(sizeok != SIZEOKdone);
-
- //printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok);
-
- fields.setDim(0); // workaround
-
- // Set the offsets of the fields and determine the size of the struct
- unsigned offset = 0;
- bool isunion = isUnionDeclaration() != NULL;
- for (size_t i = 0; i < members->length; i++)
- {
- Dsymbol *s = (*members)[i];
- s->setFieldOffset(this, &offset, isunion);
- }
- if (type->ty == Terror)
- return;
-
- // 0 sized struct's are set to 1 byte
- if (structsize == 0)
- {
- structsize = 1;
- alignsize = 1;
- }
-
- // Round struct size up to next alignsize boundary.
- // This will ensure that arrays of structs will get their internals
- // aligned properly.
- if (alignment == STRUCTALIGN_DEFAULT)
- structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
- else
- structsize = (structsize + alignment - 1) & ~(alignment - 1);
-
- sizeok = SIZEOKdone;
-
- //printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), fields.length, structsize);
-
- if (errors)
- return;
-
- // Calculate fields[i]->overlapped
- if (checkOverlappedFields())
- {
- errors = true;
- return;
- }
-
- // Determine if struct is all zeros or not
- zeroInit = 1;
- for (size_t i = 0; i < fields.length; i++)
- {
- VarDeclaration *vd = fields[i];
- if (vd->_init)
- {
- if (vd->_init->isVoidInitializer())
- /* Treat as 0 for the purposes of putting the initializer
- * in the BSS segment, or doing a mass set to 0
- */
- continue;
-
- // Zero size fields are zero initialized
- if (vd->type->size(vd->loc) == 0)
- continue;
-
- // Examine init to see if it is all 0s.
- Expression *exp = vd->getConstInitializer();
- if (!exp || !isZeroInit(exp))
- {
- zeroInit = 0;
- break;
- }
- }
- else if (!vd->type->isZeroInit(loc))
- {
- zeroInit = 0;
- break;
- }
- }
-
- TypeTuple *tt = target.toArgTypes(type);
- size_t dim = tt ? tt->arguments->length : 0;
- if (dim >= 1)
- {
- assert(dim <= 2);
- arg1type = (*tt->arguments)[0]->type;
- if (dim == 2)
- arg2type = (*tt->arguments)[1]->type;
- }
-}
-
-/***************************************
- * Fit elements[] to the corresponding type of field[].
- * Input:
- * loc
- * sc
- * elements The explicit arguments that given to construct object.
- * stype The constructed object type.
- * Returns false if any errors occur.
- * Otherwise, returns true and elements[] are rewritten for the output.
- */
-bool StructDeclaration::fit(Loc loc, Scope *sc, Expressions *elements, Type *stype)
-{
- if (!elements)
- return true;
-
- size_t nfields = fields.length - isNested();
- size_t offset = 0;
- for (size_t i = 0; i < elements->length; i++)
- {
- Expression *e = (*elements)[i];
- if (!e)
- continue;
-
- e = resolveProperties(sc, e);
- if (i >= nfields)
- {
- if (i == fields.length - 1 && isNested() && e->op == TOKnull)
- {
- // CTFE sometimes creates null as hidden pointer; we'll allow this.
- continue;
- }
- ::error(loc, "more initializers than fields (%d) of %s", (int)nfields, toChars());
- return false;
- }
- VarDeclaration *v = fields[i];
- if (v->offset < offset)
- {
- ::error(loc, "overlapping initialization for %s", v->toChars());
- return false;
- }
- offset = (unsigned)(v->offset + v->type->size());
-
- Type *t = v->type;
- if (stype)
- t = t->addMod(stype->mod);
- Type *origType = t;
- Type *tb = t->toBasetype();
-
- /* Look for case of initializing a static array with a too-short
- * string literal, such as:
- * char[5] foo = "abc";
- * Allow this by doing an explicit cast, which will lengthen the string
- * literal.
- */
- if (e->op == TOKstring && tb->ty == Tsarray)
- {
- StringExp *se = (StringExp *)e;
- Type *typeb = se->type->toBasetype();
- TY tynto = tb->nextOf()->ty;
- if (!se->committed &&
- (typeb->ty == Tarray || typeb->ty == Tsarray) &&
- (tynto == Tchar || tynto == Twchar || tynto == Tdchar) &&
- se->numberOfCodeUnits(tynto) < ((TypeSArray *)tb)->dim->toInteger())
- {
- e = se->castTo(sc, t);
- goto L1;
- }
- }
-
- while (!e->implicitConvTo(t) && tb->ty == Tsarray)
- {
- /* Static array initialization, as in:
- * T[3][5] = e;
- */
- t = tb->nextOf();
- tb = t->toBasetype();
- }
- if (!e->implicitConvTo(t))
- t = origType; // restore type for better diagnostic
-
- e = e->implicitCastTo(sc, t);
- L1:
- if (e->op == TOKerror)
- return false;
-
- (*elements)[i] = doCopyOrMove(sc, e);
- }
- return true;
-}
-
-/***************************************
- * Return true if struct is POD (Plain Old Data).
- * This is defined as:
- * not nested
- * no postblits, destructors, or assignment operators
- * no 'ref' fields or fields that are themselves non-POD
- * The idea being these are compatible with C structs.
- */
-bool StructDeclaration::isPOD()
-{
- // If we've already determined whether this struct is POD.
- if (ispod != ISPODfwd)
- return (ispod == ISPODyes);
-
- ispod = ISPODyes;
-
- if (enclosing || postblit || dtor)
- ispod = ISPODno;
-
- // Recursively check all fields are POD.
- for (size_t i = 0; i < fields.length; i++)
- {
- VarDeclaration *v = fields[i];
- if (v->storage_class & STCref)
- {
- ispod = ISPODno;
- break;
- }
-
- Type *tv = v->type->baseElemOf();
- if (tv->ty == Tstruct)
- {
- TypeStruct *ts = (TypeStruct *)tv;
- StructDeclaration *sd = ts->sym;
- if (!sd->isPOD())
- {
- ispod = ISPODno;
- break;
- }
- }
- }
-
- return (ispod == ISPODyes);
-}
-
-const char *StructDeclaration::kind() const
-{
- return "struct";
-}
-
-/********************************* UnionDeclaration ****************************/
-
-UnionDeclaration::UnionDeclaration(Loc loc, Identifier *id)
- : StructDeclaration(loc, id, false)
-{
-}
-
-Dsymbol *UnionDeclaration::syntaxCopy(Dsymbol *s)
-{
- assert(!s);
- UnionDeclaration *ud = new UnionDeclaration(loc, ident);
- return StructDeclaration::syntaxCopy(ud);
-}
-
-const char *UnionDeclaration::kind() const
-{
- return "union";
-}