@@ -46,30 +46,61 @@ gdc-cross$(exeext): gdc$(exeext)
-rm -f gdc-cross$(exeext)
cp gdc$(exeext) gdc-cross$(exeext)
-# Filter out pedantic and virtual overload warnings.
-d-warn = $(filter-out -pedantic -Woverloaded-virtual, $(STRICT_WARN))
-
-# Also filter out warnings for missing format attributes in the D Frontend.
-DMD_WARN_CXXFLAGS = $(filter-out -Wmissing-format-attribute, $(WARN_CXXFLAGS))
-DMD_COMPILE = $(subst $(WARN_CXXFLAGS), $(DMD_WARN_CXXFLAGS), $(COMPILE))
+# Use strict warnings.
+d-warn = $(STRICT_WARN)
+
+# D compiler and flags for building the front-end.
+ifeq ($(TREECHECKING),)
+CHECKING_DFLAGS = -frelease
+else
+CHECKING_DFLAGS =
+endif
+WARN_DFLAGS = -Wall -Wdeprecated $(NOCOMMON_FLAG)
+
+ALL_DFLAGS = $(DFLAGS-$@) $(GDCFLAGS) -fversion=IN_GCC $(CHECKING_DFLAGS) \
+ $(PICFLAG) $(ALIASING_FLAGS) $(COVERAGE_FLAGS) $(WARN_DFLAGS)
+
+DCOMPILE.base = $(GDC) $(NO_PIE_CFLAGS) -c $(ALL_DFLAGS) -o $@
+DCOMPILE = $(DCOMPILE.base) -MT $@ -MMD -MP -MF $(@D)/$(DEPDIR)/$(*F).TPo
+DPOSTCOMPILE = @mv $(@D)/$(DEPDIR)/$(*F).TPo $(@D)/$(DEPDIR)/$(*F).Po
+DLINKER = $(GDC) $(NO_PIE_FLAG) -lstdc++
+
+# Like LINKER, but use a mutex for serializing front end links.
+ifeq (@DO_LINK_MUTEX@,true)
+DLLINKER = $(SHELL) $(srcdir)/lock-and-run.sh linkfe.lck $(DLINKER)
+else
+DLLINKER = $(DLINKER)
+endif
# D Frontend object files.
D_FRONTEND_OBJS = \
d/aav.o \
d/access.o \
+ d/aggregate.o \
d/aliasthis.o \
d/apply.o \
+ d/array.o \
d/arrayop.o \
+ d/arraytypes.o \
d/attrib.o \
+ d/ast_node.o \
+ d/astcodegen.o \
+ d/astenums.o \
+ d/bitarray.o \
d/blockexit.o \
+ d/builtin.o \
d/canthrow.o \
- d/checkedint.o \
d/chkformat.o \
d/clone.o \
+ d/compiler.o \
+ d/complex.o \
d/cond.o \
d/constfold.o \
+ d/cparse.o \
d/cppmangle.o \
d/ctfeexpr.o \
+ d/ctfloat.o \
+ d/ctorflow.o \
d/dcast.o \
d/dclass.o \
d/declaration.o \
@@ -86,32 +117,49 @@ D_FRONTEND_OBJS = \
d/dsymbol.o \
d/dsymbolsem.o \
d/dtemplate.o \
+ d/dtoh.o \
d/dversion.o \
d/entity.o \
+ d/errors.o \
d/escape.o \
d/expression.o \
d/expressionsem.o \
d/file.o \
d/filename.o \
+ d/foreachvar.o \
d/func.o \
+ d/globals.o \
+ d/gluelayer.o \
+ d/hash.o \
d/hdrgen.o \
d/iasm.o \
d/iasmgcc.o \
+ d/id.o \
d/identifier.o \
+ d/impcnvtab.o \
d/imphint.o \
d/init.o \
d/initsem.o \
+ d/inline.o \
d/intrange.o \
d/json.o \
+ d/lambdacomp.o \
d/lexer.o \
+ d/longdouble.o \
d/mtype.o \
d/nogc.o \
d/nspace.o \
+ d/ob.o \
d/objc.o \
d/opover.o \
d/optimize.o \
d/outbuffer.o \
d/parse.o \
+ d/parsetimevisitor.o \
+ d/permissivevisitor.o \
+ d/port.o \
+ d/printast.o \
+ d/region.o \
d/rmem.o \
d/rootobject.o \
d/safe.o \
@@ -121,20 +169,23 @@ D_FRONTEND_OBJS = \
d/sideeffect.o \
d/speller.o \
d/statement.o \
+ d/statement_rewrite_walker.o \
d/statementsem.o \
d/staticassert.o \
d/staticcond.o \
+ d/stmtstate.o \
+ d/string.o \
d/stringtable.o \
+ d/target.o \
d/templateparamsem.o \
d/tokens.o \
d/traits.o \
+ d/transitivevisitor.o \
d/typesem.o \
+ d/typinf.o \
d/utf.o \
- d/utils.o
-
-# D Frontend generated files.
-D_GENERATED_SRCS = d/id.c d/id.h d/impcnvtab.c
-D_GENERATED_OBJS = d/id.o d/impcnvtab.o
+ d/utils.o \
+ d/visitor.o
# Language-specific object files for D.
D_OBJS = \
@@ -163,13 +214,13 @@ D_OBJS = \
d/types.o
# All language-specific object files for D.
-D_ALL_OBJS = $(D_FRONTEND_OBJS) $(D_GENERATED_OBJS) $(D_OBJS) $(D_TARGET_OBJS)
+D_ALL_OBJS = $(D_FRONTEND_OBJS) $(D_OBJS) $(D_TARGET_OBJS)
d_OBJS = $(D_ALL_OBJS) d/d-spec.o
d21$(exeext): $(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS) $(d.prev)
@$(call LINK_PROGRESS,$(INDEX.d),start)
- +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+ +$(DLLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -static-libphobos -o $@ \
$(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
@$(call LINK_PROGRESS,$(INDEX.d),end)
@@ -221,7 +272,7 @@ d.srcextra:
d.tags: force
cd $(srcdir)/d; \
- $(ETAGS) -o TAGS.sub *.c *.cc *.h dmd/*.c dmd/*.h dmd/root/*.h dmd/root/*.c; \
+ $(ETAGS) -o TAGS.sub *.c *.cc *.h dmd/*.h dmd/root/*.h; \
$(ETAGS) --include TAGS.sub --include ../TAGS.sub
d.man: doc/gdc.1
@@ -313,8 +364,6 @@ d.uninstall:
d.mostlyclean:
-rm -f d/*$(objext)
-rm -f d/*$(coverageexts)
- -rm -f $(D_GENERATED_SRCS)
- -rm -f d/idgen$(build_exeext) d/impcnvgen$(build_exeext)
-rm -f gdc$(exeext) gdc-cross$(exeext) d21$(exeext)
d.clean:
d.distclean:
@@ -337,48 +386,13 @@ d.stagefeedback: stagefeedback-start
-mv d/*$(objext) stagefeedback/d
# Include the dfrontend and build directories for headers.
-D_INCLUDES = -I$(srcdir)/d -I$(srcdir)/d/dmd -Id
-
-CFLAGS-d/id.o += $(D_INCLUDES)
-CFLAGS-d/impcnvtab.o += $(D_INCLUDES)
+D_INCLUDES = -I$(srcdir)/d -J$(srcdir)/d/dmd -J$(srcdir)/d/dmd/res
# Override build rules for D frontend.
-d/%.o: d/dmd/%.c $(D_GENERATED_SRCS)
- $(DMD_COMPILE) $(D_INCLUDES) $<
- $(POSTCOMPILE)
-
-d/%.o: d/dmd/root/%.c $(D_GENERATED_SRCS)
- $(DMD_COMPILE) $(D_INCLUDES) $<
- $(POSTCOMPILE)
-
-# Generated programs.
-d/idgen$(build_exeext): d/idgen.dmdgen.o $(BUILD_LIBDEPS)
- +$(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ \
- $(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
-
-d/impcnvgen$(build_exeext): d/impcnvgen.dmdgen.o $(BUILD_LIBDEPS)
- +$(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ \
- $(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
-
-# Generated sources.
-d/id.c: d/idgen$(build_exeext)
- cd d && ./idgen$(build_exeext)
-
-# idgen also generates id.h; just verify it exists.
-d/id.h: d/id.c
-
-d/impcnvtab.c: d/impcnvgen$(build_exeext)
- cd d && ./impcnvgen$(build_exeext)
-
-# Compile the generator programs.
-d/%.dmdgen.o: $(srcdir)/d/dmd/%.c
- $(COMPILER_FOR_BUILD) -c $(BUILD_COMPILERFLAGS) $(D_INCLUDES) \
- $(BUILD_CPPFLAGS) -o $@ $<
-
-# Header dependencies for the generator programs.
-D_SYSTEM_H = d/dmd/root/dsystem.h d/d-system.h
-
-d/idgen.dmdgen.o: d/dmd/idgen.c $(D_SYSTEM_H) $(BCONFIG_H) $(SYSTEM_H)
+d/%.o: d/dmd/%.d
+ $(DCOMPILE) $(D_INCLUDES) $<
+ $(DPOSTCOMPILE)
-d/impcnvgen.dmdgen.o: d/dmd/impcnvgen.c d/dmd/mtype.h $(D_SYSTEM_H) \
- $(BCONFIG_H) $(SYSTEM_H)
+d/%.o: d/dmd/root/%.d
+ $(DCOMPILE) $(D_INCLUDES) $<
+ $(DPOSTCOMPILE)
@@ -19,10 +19,12 @@
# We define several parameters used by configure:
#
# language - name of language as it would appear in $(LANGUAGES)
+# boot_language - "yes" if we need to build this language in stage1
# compilers - value to add to $(COMPILERS)
language="d"
+boot_language=yes
compilers="d21\$(exeext)"
phobos_target_deps="target-zlib target-libbacktrace"
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "dmd/attrib.h"
#include "dmd/declaration.h"
+#include "dmd/expression.h"
#include "dmd/module.h"
#include "dmd/mtype.h"
#include "dmd/template.h"
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "d-tree.h"
+#include "d-frontend.h"
#include "d-target.h"
@@ -98,7 +99,7 @@ build_frontend_type (tree type)
if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == char_type_node)
return Type::tchar->addMod (dtype->mod)->pointerTo ()->addMod (mod);
- if (dtype->ty == Tfunction)
+ if (dtype->ty == TY::Tfunction)
return (TypePointer::create (dtype))->addMod (mod);
return dtype->pointerTo ()->addMod (mod);
@@ -130,7 +131,7 @@ build_frontend_type (tree type)
/* For now, skip support for cent/ucent until the frontend
has better support for handling it. */
- for (size_t i = Tint8; i <= Tuns64; i++)
+ for (size_t i = (size_t) TY::Tint8; i <= (size_t) TY::Tuns64; i++)
{
dtype = Type::basic[i];
@@ -148,7 +149,7 @@ build_frontend_type (tree type)
{
unsigned size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
- for (size_t i = Tfloat32; i <= Tfloat80; i++)
+ for (size_t i = (size_t) TY::Tfloat32; i <= (size_t) TY::Tfloat80; i++)
{
dtype = Type::basic[i];
@@ -164,7 +165,8 @@ build_frontend_type (tree type)
case COMPLEX_TYPE:
{
unsigned size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
- for (size_t i = Tcomplex32; i <= Tcomplex80; i++)
+ for (size_t i = (size_t) TY::Tcomplex32; i <= (size_t) TY::Tcomplex80;
+ i++)
{
dtype = Type::basic[i];
@@ -235,7 +237,7 @@ build_frontend_type (tree type)
sdecl->structsize = int_size_in_bytes (type);
sdecl->alignsize = TYPE_ALIGN_UNIT (type);
sdecl->alignment = STRUCTALIGN_DEFAULT;
- sdecl->sizeok = SIZEOKdone;
+ sdecl->sizeok = Sizeok::done;
sdecl->type = (TypeStruct::create (sdecl))->addMod (mod);
sdecl->type->ctype = type;
sdecl->type->merge2 ();
@@ -243,7 +245,7 @@ build_frontend_type (tree type)
/* Add both named and anonymous fields as members of the struct.
Anonymous fields still need a name in D, so call them "__pad%u". */
unsigned anonfield_id = 0;
- sdecl->members = new Dsymbols;
+ sdecl->members = d_gc_malloc<Dsymbols> ();
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
@@ -253,7 +255,6 @@ build_frontend_type (tree type)
/* Drop any field types that got cached before the conversion
of this record type failed. */
builtin_converted_decls.truncate (saved_builtin_decls_length);
- delete sdecl->members;
return NULL;
}
@@ -292,7 +293,7 @@ build_frontend_type (tree type)
tree parms = TYPE_ARG_TYPES (type);
VarArg varargs_p = VARARGvariadic;
- Parameters *args = new Parameters;
+ Parameters *args = d_gc_malloc<Parameters> ();
args->reserve (list_length (parms));
/* Attempt to convert all parameter types. */
@@ -318,7 +319,6 @@ build_frontend_type (tree type)
/* Drop any parameter types that got cached before the
conversion of this function type failed. */
builtin_converted_decls.truncate (saved_builtin_decls_length);
- delete args;
return NULL;
}
@@ -329,7 +329,7 @@ build_frontend_type (tree type)
have no named parameters, and so can't be represented in D. */
if (args->length != 0 || varargs_p == VARARGnone)
{
- dtype = TypeFunction::create (args, dtype, varargs_p, LINKc);
+ dtype = TypeFunction::create (args, dtype, varargs_p, LINK::c);
return dtype->addMod (mod);
}
}
@@ -386,7 +386,7 @@ d_eval_constant_expression (const Loc &loc, tree cst)
else if (code == VECTOR_CST)
{
dinteger_t nunits = VECTOR_CST_NELTS (cst).to_constant ();
- Expressions *elements = new Expressions;
+ Expressions *elements = d_gc_malloc<Expressions> ();
elements->setDim (nunits);
for (size_t i = 0; i < nunits; i++)
@@ -520,7 +520,7 @@ build_alias_declaration (const char *alias, Type *type)
void
d_build_builtins_module (Module *m)
{
- Dsymbols *members = new Dsymbols;
+ Dsymbols *members = d_gc_malloc<Dsymbols> ();
tree decl;
for (size_t i = 0; vec_safe_iterate (gcc_builtins_functions, i, &decl); ++i)
@@ -543,16 +543,16 @@ d_build_builtins_module (Module *m)
flag_unsafe_math_optimizations.
- Built-ins never use the GC or raise a D exception, and so are always
marked as `nothrow' and `@nogc'. */
- tf->purity = DECL_PURE_P (decl) ? PUREstrong
- : TREE_READONLY (decl) ? PUREconst
- : DECL_IS_NOVOPS (decl) ? PUREweak
- : !DECL_ASSEMBLER_NAME_SET_P (decl) ? PUREweak
- : PUREimpure;
- tf->trust = !DECL_ASSEMBLER_NAME_SET_P (decl) ? TRUSTsafe
- : TREE_NOTHROW (decl) ? TRUSTtrusted
- : TRUSTsystem;
- tf->isnothrow = true;
- tf->isnogc = true;
+ tf->purity = DECL_PURE_P (decl) ? PURE::strong
+ : TREE_READONLY (decl) ? PURE::const_
+ : DECL_IS_NOVOPS (decl) ? PURE::weak
+ : !DECL_ASSEMBLER_NAME_SET_P (decl) ? PURE::weak
+ : PURE::impure;
+ tf->trust = !DECL_ASSEMBLER_NAME_SET_P (decl) ? TRUST::safe
+ : TREE_NOTHROW (decl) ? TRUST::trusted
+ : TRUST::system;
+ tf->isnothrow (true);
+ tf->isnogc (true);
FuncDeclaration *func
= FuncDeclaration::create (Loc (), Loc (),
@@ -560,7 +560,7 @@ d_build_builtins_module (Module *m)
STCextern, tf);
DECL_LANG_SPECIFIC (decl) = build_lang_decl (func);
func->csym = decl;
- func->builtin = BUILTINgcc;
+ func->builtin = BUILTIN::gcc;
members->push (func);
}
@@ -660,7 +660,7 @@ d_build_builtins_module (Module *m)
members->push (build_alias_declaration ("__builtin_unwind_uint", t));
}
- m->members->push (LinkDeclaration::create (LINKc, members));
+ m->members->push (LinkDeclaration::create (Loc (), LINK::c, members));
}
/* Search for any `extern(C)' functions that match any known GCC library builtin
@@ -700,7 +700,7 @@ maybe_set_builtin_1 (Dsymbol *d)
/* Found a match, tell the frontend this is a builtin. */
DECL_LANG_SPECIFIC (t) = build_lang_decl (fd);
fd->csym = t;
- fd->builtin = BUILTINgcc;
+ fd->builtin = BUILTIN::gcc;
return;
}
}
@@ -858,7 +858,7 @@ d_build_d_type_nodes (void)
/* Calling build_ctype() links the front-end Type to the GCC node,
and sets the TYPE_NAME to the D language type. */
- for (unsigned ty = 0; ty < TMAX; ty++)
+ for (unsigned ty = 0; ty < (unsigned) TY::TMAX; ty++)
{
if (Type::basic[ty] != NULL)
build_ctype (Type::basic[ty]);
@@ -76,7 +76,7 @@ d_decl_context (Dsymbol *dsym)
but only for extern(D) symbols. */
if (parent->isModule ())
{
- if ((decl != NULL && decl->linkage != LINKd)
+ if ((decl != NULL && decl->linkage != LINK::d)
|| (ad != NULL && ad->classKind != ClassKind::d))
return NULL_TREE;
@@ -131,7 +131,7 @@ declaration_reference_p (Declaration *decl)
Type *tb = decl->type->toBasetype ();
/* Declaration is a reference type. */
- if (tb->ty == Treference || decl->storage_class & (STCout | STCref))
+ if (tb->ty == TY::Treference || decl->storage_class & (STCout | STCref))
return true;
return false;
@@ -146,7 +146,7 @@ declaration_type (Declaration *decl)
if (decl->storage_class & STClazy)
{
TypeFunction *tf = TypeFunction::create (NULL, decl->type,
- VARARGnone, LINKd);
+ VARARGnone, LINK::d);
TypeDelegate *t = TypeDelegate::create (tf);
return build_ctype (t->merge2 ());
}
@@ -181,7 +181,7 @@ parameter_reference_p (Parameter *arg)
Type *tb = arg->type->toBasetype ();
/* Parameter is a reference type. */
- if (tb->ty == Treference || arg->storageClass & (STCout | STCref))
+ if (tb->ty == TY::Treference || arg->storageClass & (STCout | STCref))
return true;
return false;
@@ -196,7 +196,7 @@ parameter_type (Parameter *arg)
if (arg->storageClass & STClazy)
{
TypeFunction *tf = TypeFunction::create (NULL, arg->type,
- VARARGnone, LINKd);
+ VARARGnone, LINK::d);
TypeDelegate *t = TypeDelegate::create (tf);
return build_ctype (t->merge2 ());
}
@@ -319,10 +319,10 @@ get_array_length (tree exp, Type *type)
switch (tb->ty)
{
- case Tsarray:
+ case TY::Tsarray:
return size_int (tb->isTypeSArray ()->dim->toUInteger ());
- case Tarray:
+ case TY::Tarray:
return d_array_length (exp);
default:
@@ -411,7 +411,7 @@ build_delegate_cst (tree method, tree object, Type *type)
tree ctype;
Type *tb = type->toBasetype ();
- if (tb->ty == Tdelegate)
+ if (tb->ty == TY::Tdelegate)
ctype = build_ctype (type);
else
{
@@ -464,11 +464,11 @@ build_typeof_null_value (Type *type)
tree value;
/* For dynamic arrays, set length and pointer fields to zero. */
- if (tb->ty == Tarray)
+ if (tb->ty == TY::Tarray)
value = d_array_value (build_ctype (type), size_int (0), null_pointer_node);
/* For associative arrays, set the pointer field to null. */
- else if (tb->ty == Taarray)
+ else if (tb->ty == TY::Taarray)
{
tree ctype = build_ctype (type);
gcc_assert (TYPE_ASSOCIATIVE_ARRAY (ctype));
@@ -478,7 +478,7 @@ build_typeof_null_value (Type *type)
}
/* For delegates, set the frame and function pointer fields to null. */
- else if (tb->ty == Tdelegate)
+ else if (tb->ty == TY::Tdelegate)
value = build_delegate_cst (null_pointer_node, null_pointer_node, type);
/* Simple zero constant for all other types. */
@@ -882,7 +882,9 @@ identity_compare_p (StructDeclaration *sd)
}
/* Check for types that may have padding. */
- if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80)
+ if ((tb->ty == TY::Tcomplex80
+ || tb->ty == TY::Tfloat80
+ || tb->ty == TY::Timaginary80)
&& target.realpad != 0)
return false;
@@ -960,12 +962,12 @@ lower_struct_comparison (tree_code code, StructDeclaration *sd,
/* Compare inner data structures. */
tcmp = lower_struct_comparison (code, ts->sym, t1ref, t2ref);
}
- else if (type->ty != Tvector && type->isintegral ())
+ else if (type->ty != TY::Tvector && type->isintegral ())
{
/* Integer comparison, no special handling required. */
tcmp = build_boolop (code, t1ref, t2ref);
}
- else if (type->ty != Tvector && type->isfloating ())
+ else if (type->ty != TY::Tvector && type->isfloating ())
{
/* Floating-point comparison, don't compare padding in type. */
if (!type->iscomplex ())
@@ -1839,7 +1841,7 @@ static tree
build_filename_from_loc (const Loc &loc)
{
const char *filename = loc.filename
- ? loc.filename : d_function_chain->module->srcfile->toChars ();
+ ? loc.filename : d_function_chain->module->srcfile.toChars ();
unsigned length = strlen (filename);
tree str = build_string (length, filename);
@@ -1862,7 +1864,6 @@ build_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
{
case LIBCALL_ASSERT_MSG:
case LIBCALL_UNITTEST_MSG:
- case LIBCALL_SWITCH_ERROR:
/* File location is passed as a D string. */
if (loc.filename)
{
@@ -1912,7 +1913,7 @@ build_array_bounds_call (const Loc &loc)
/* Builds a bounds condition checking that INDEX is between 0 and LENGTH
in the index expression IE. The condition returns the INDEX if true, or
- throws a `RangeError`. */
+ throws a `ArrayIndexError`. */
tree
build_bounds_index_condition (IndexExp *ie, tree index, tree length)
@@ -1927,7 +1928,16 @@ build_bounds_index_condition (IndexExp *ie, tree index, tree length)
No need to check whether INDEX >= 0 as the front-end should
have already taken care of implicit casts to unsigned. */
tree condition = fold_build2 (GE_EXPR, d_bool_type, index, length);
- tree boundserr = build_array_bounds_call (ie->e2->loc);
+ tree boundserr;
+
+ if (checkaction_trap_p ())
+ boundserr = build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ else
+ {
+ boundserr = build_libcall (LIBCALL_ARRAYBOUNDS_INDEXP, Type::tvoid, 4,
+ build_filename_from_loc (ie->e2->loc),
+ size_int (ie->e2->loc.linnum), index, length);
+ }
return build_condition (TREE_TYPE (index), condition, boundserr, index);
}
@@ -1963,7 +1973,22 @@ build_bounds_slice_condition (SliceExp *se, tree lower, tree upper, tree length)
if (condition != NULL_TREE)
{
- tree boundserr = build_array_bounds_call (se->loc);
+ tree boundserr;
+
+ if (checkaction_trap_p ())
+ {
+ boundserr =
+ build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
+ }
+ else
+ {
+ boundserr = build_libcall (LIBCALL_ARRAYBOUNDS_SLICEP,
+ Type::tvoid, 5,
+ build_filename_from_loc (se->loc),
+ size_int (se->loc.linnum),
+ lower, upper, length);
+ }
+
upper = build_condition (TREE_TYPE (upper), condition,
boundserr, upper);
}
@@ -1993,9 +2018,9 @@ array_bounds_check (void)
case CHECKENABLEsafeonly:
/* For D2 safe functions only. */
fd = d_function_chain->function;
- if (fd && fd->type->ty == Tfunction)
+ if (fd && fd->type->ty == TY::Tfunction)
{
- if (fd->type->isTypeFunction ()->trust == TRUSTsafe)
+ if (fd->type->isTypeFunction ()->trust == TRUST::safe)
return true;
}
return false;
@@ -2014,6 +2039,7 @@ checkaction_trap_p (void)
switch (global.params.checkAction)
{
case CHECKACTION_D:
+ case CHECKACTION_context:
return false;
case CHECKACTION_C:
@@ -2032,11 +2058,11 @@ TypeFunction *
get_function_type (Type *t)
{
TypeFunction *tf = NULL;
- if (t->ty == Tpointer)
+ if (t->ty == TY::Tpointer)
t = t->nextOf ()->toBasetype ();
- if (t->ty == Tfunction)
+ if (t->ty == TY::Tfunction)
tf = t->isTypeFunction ();
- else if (t->ty == Tdelegate)
+ else if (t->ty == TY::Tdelegate)
tf = t->isTypeDelegate ()->next->isTypeFunction ();
return tf;
}
@@ -2096,7 +2122,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
gcc_assert (FUNC_OR_METHOD_TYPE_P (ctype));
gcc_assert (tf != NULL);
- gcc_assert (tf->ty == Tfunction);
+ gcc_assert (tf->ty == TY::Tfunction);
if (TREE_CODE (ctype) != FUNCTION_TYPE && object == NULL_TREE)
{
@@ -2195,7 +2221,7 @@ d_build_call (TypeFunction *tf, tree callable, tree object,
SET_EXPR_LOCATION (result, input_location);
/* Enforce left to right evaluation. */
- if (tf->linkage == LINKd)
+ if (tf->linkage == LINK::d)
CALL_EXPR_ARGS_ORDERED (result) = 1;
result = maybe_expand_intrinsic (result);
@@ -20,7 +20,6 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "dmd/compiler.h"
-#include "dmd/scope.h"
#include "dmd/expression.h"
#include "dmd/identifier.h"
#include "dmd/module.h"
@@ -34,40 +33,6 @@ along with GCC; see the file COPYING3. If not see
/* Implements the Compiler interface used by the frontend. */
-/* Generate C main() in response to seeing D main(). This used to be in
- libdruntime, but contained a reference to _Dmain which didn't work when
- druntime was made into a shared library and was linked to a program, such
- as a C++ program, that didn't have a _Dmain. */
-
-void
-Compiler::genCmain (Scope *sc)
-{
- static bool initialized = false;
-
- if (initialized)
- return;
-
- /* The D code to be generated is provided by __entrypoint.di, try to load it,
- but don't fail if unfound. */
- unsigned errors = global.startGagging ();
- Module *m = Module::load (Loc (), NULL, Identifier::idPool ("__entrypoint"));
-
- if (global.endGagging (errors))
- m = NULL;
-
- if (m != NULL)
- {
- m->importedFrom = m;
- m->importAll (NULL);
- dsymbolSemantic (m, NULL);
- semantic2 (m, NULL);
- semantic3 (m, NULL);
- d_add_entrypoint_module (m, sc->_module);
- }
-
- initialized = true;
-}
-
/* Perform a reinterpret cast of EXPR to type TYPE for use in CTFE.
The front end should have already ensured that EXPR is a constant,
so we just lower the value to GCC and return the converted CST. */
@@ -123,7 +88,7 @@ Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
/* Encode CST to buffer. */
int len = native_encode_expr (cst, buffer, sizeof (buffer));
- if (tb->ty == Tsarray)
+ if (tb->ty == TY::Tsarray)
{
/* Interpret value as a vector of the same size,
then return the array literal. */
@@ -161,22 +126,22 @@ Compiler::onParseModule (Module *m)
{
ModuleDeclaration *md = m->md;
- if (!md || !md->id || !md->packages)
+ if (!md || !md->id|| md->packages.length == 0)
{
Identifier *id = (md && md->id) ? md->id : m->ident;
if (!strcmp (id->toChars (), "object"))
create_tinfo_types (m);
}
- else if (md->packages->length == 1)
+ else if (md->packages.length == 1)
{
- if (!strcmp ((*md->packages)[0]->toChars (), "gcc")
+ if (!strcmp (md->packages.ptr[0]->toChars (), "gcc")
&& !strcmp (md->id->toChars (), "builtins"))
d_build_builtins_module (m);
}
- else if (md->packages->length == 2)
+ else if (md->packages.length == 2)
{
- if (!strcmp ((*md->packages)[0]->toChars (), "core")
- && !strcmp ((*md->packages)[1]->toChars (), "stdc"))
+ if (!strcmp (md->packages.ptr[0]->toChars (), "core")
+ && !strcmp (md->packages.ptr[1]->toChars (), "stdc"))
d_add_builtin_module (m);
}
}
@@ -361,14 +361,14 @@ convert_expr (tree exp, Type *etype, Type *totype)
switch (ebtype->ty)
{
- case Tdelegate:
- if (tbtype->ty == Tdelegate)
+ case TY::Tdelegate:
+ if (tbtype->ty == TY::Tdelegate)
{
exp = d_save_expr (exp);
return build_delegate_cst (delegate_method (exp),
delegate_object (exp), totype);
}
- else if (tbtype->ty == Tpointer)
+ else if (tbtype->ty == TY::Tpointer)
{
/* The front-end converts <delegate>.ptr to cast (void *)<delegate>.
Maybe should only allow void* ? */
@@ -382,8 +382,8 @@ convert_expr (tree exp, Type *etype, Type *totype)
}
break;
- case Tstruct:
- if (tbtype->ty == Tstruct)
+ case TY::Tstruct:
+ if (tbtype->ty == TY::Tstruct)
{
if (totype->size () == etype->size ())
{
@@ -400,8 +400,8 @@ convert_expr (tree exp, Type *etype, Type *totype)
/* else, default conversion, which should produce an error. */
break;
- case Tclass:
- if (tbtype->ty == Tclass)
+ case TY::Tclass:
+ if (tbtype->ty == TY::Tclass)
{
ClassDeclaration *cdfrom = ebtype->isClassHandle ();
ClassDeclaration *cdto = tbtype->isClassHandle ();
@@ -460,12 +460,12 @@ convert_expr (tree exp, Type *etype, Type *totype)
/* else default conversion. */
break;
- case Tsarray:
- if (tbtype->ty == Tpointer)
+ case TY::Tsarray:
+ if (tbtype->ty == TY::Tpointer)
{
result = build_nop (build_ctype (totype), build_address (exp));
}
- else if (tbtype->ty == Tarray)
+ else if (tbtype->ty == TY::Tarray)
{
dinteger_t dim = ebtype->isTypeSArray ()->dim->toInteger ();
dinteger_t esize = ebtype->nextOf ()->size ();
@@ -490,12 +490,12 @@ convert_expr (tree exp, Type *etype, Type *totype)
return d_array_value (build_ctype (totype), size_int (dim),
build_nop (ptrtype, build_address (exp)));
}
- else if (tbtype->ty == Tsarray)
+ else if (tbtype->ty == TY::Tsarray)
{
/* D allows casting a static array to any static array type. */
return build_nop (build_ctype (totype), exp);
}
- else if (tbtype->ty == Tstruct)
+ else if (tbtype->ty == TY::Tstruct)
{
/* And allows casting a static array to any struct type too.
Type sizes should have already been checked by the frontend. */
@@ -510,12 +510,12 @@ convert_expr (tree exp, Type *etype, Type *totype)
}
break;
- case Tarray:
- if (tbtype->ty == Tpointer)
+ case TY::Tarray:
+ if (tbtype->ty == TY::Tpointer)
{
return d_convert (build_ctype (totype), d_array_ptr (exp));
}
- else if (tbtype->ty == Tarray)
+ else if (tbtype->ty == TY::Tarray)
{
/* Assume tvoid->size() == 1. */
d_uns64 fsize = ebtype->nextOf ()->toBasetype ()->size ();
@@ -523,9 +523,18 @@ convert_expr (tree exp, Type *etype, Type *totype)
if (fsize != tsize)
{
- /* Conversion requires a reinterpret cast of array. */
- return build_libcall (LIBCALL_ARRAYCAST, totype, 3,
- size_int (tsize), size_int (fsize), exp);
+ /* Conversion requires a reinterpret cast of array.
+ This case should have been lowered in the semantic pass. */
+ if (tsize != 0 && fsize % tsize == 0)
+ {
+ /* Set array dimension to (length * (fsize / tsize)). */
+ tree newlength = size_mult_expr (d_array_length (exp),
+ size_int (fsize / tsize));
+ return d_array_value (build_ctype (totype), newlength,
+ d_array_ptr (exp));
+ }
+ else
+ gcc_unreachable ();
}
else
{
@@ -534,7 +543,7 @@ convert_expr (tree exp, Type *etype, Type *totype)
return build_vconvert (build_ctype (totype), exp);
}
}
- else if (tbtype->ty == Tsarray)
+ else if (tbtype->ty == TY::Tsarray)
{
/* Strings are treated as dynamic arrays in D2. */
if (ebtype->isString () && tbtype->isString ())
@@ -548,23 +557,23 @@ convert_expr (tree exp, Type *etype, Type *totype)
}
break;
- case Taarray:
- if (tbtype->ty == Taarray)
+ case TY::Taarray:
+ if (tbtype->ty == TY::Taarray)
return build_vconvert (build_ctype (totype), exp);
/* Can convert associative arrays to void pointers. */
- else if (tbtype->ty == Tpointer && tbtype->nextOf ()->ty == Tvoid)
+ else if (tbtype->ty == TY::Tpointer && tbtype->nextOf ()->ty == TY::Tvoid)
return build_vconvert (build_ctype (totype), exp);
/* Else, default conversion, which should product an error. */
break;
- case Tpointer:
+ case TY::Tpointer:
/* Can convert void pointers to associative arrays too. */
- if (tbtype->ty == Taarray && ebtype->nextOf ()->ty == Tvoid)
+ if (tbtype->ty == TY::Taarray && ebtype->nextOf ()->ty == TY::Tvoid)
return build_vconvert (build_ctype (totype), exp);
break;
- case Tnull:
- case Tnoreturn:
+ case TY::Tnull:
+ case TY::Tnoreturn:
/* Casting from `typeof(null)' for `null' expressions, or `typeof(*null)'
for `noreturn' expressions is represented as all zeros. */
result = build_typeof_null_value (totype);
@@ -574,8 +583,8 @@ convert_expr (tree exp, Type *etype, Type *totype)
result = compound_expr (exp, result);
break;
- case Tvector:
- if (tbtype->ty == Tsarray)
+ case TY::Tvector:
+ if (tbtype->ty == TY::Tsarray)
{
if (tbtype->size () == ebtype->size ())
return build_vconvert (build_ctype (totype), exp);
@@ -613,7 +622,7 @@ convert_for_rvalue (tree expr, Type *etype, Type *totype)
Type *ebtype = etype->toBasetype ();
Type *tbtype = totype->toBasetype ();
- if (ebtype->ty == Tbool)
+ if (ebtype->ty == TY::Tbool)
{
/* If casting from bool, the result is either 0 or 1, any other value
violates @safe code, so enforce that it is never invalid. */
@@ -651,7 +660,7 @@ convert_for_assignment (tree expr, Type *etype, Type *totype)
/* Assuming this only has to handle converting a non Tsarray type to
arbitrarily dimensioned Tsarrays. */
- if (tbtype->ty == Tsarray)
+ if (tbtype->ty == TY::Tsarray)
{
Type *telem = tbtype->nextOf ()->baseElemOf ();
@@ -685,7 +694,7 @@ convert_for_assignment (tree expr, Type *etype, Type *totype)
}
/* D Front end uses IntegerExp(0) to mean zero-init an array or structure. */
- if ((tbtype->ty == Tsarray || tbtype->ty == Tstruct)
+ if ((tbtype->ty == TY::Tsarray || tbtype->ty == TY::Tstruct)
&& ebtype->isintegral ())
{
if (!integer_zerop (expr))
@@ -736,12 +745,12 @@ convert_for_condition (tree expr, Type *type)
switch (type->toBasetype ()->ty)
{
- case Taarray:
+ case TY::Taarray:
/* Checks that aa.ptr !is null. */
result = component_ref (expr, TYPE_FIELDS (TREE_TYPE (expr)));
break;
- case Tarray:
+ case TY::Tarray:
{
/* Checks (arr.length || arr.ptr) (i.e arr !is null). */
expr = d_save_expr (expr);
@@ -762,7 +771,7 @@ convert_for_condition (tree expr, Type *type)
break;
}
- case Tdelegate:
+ case TY::Tdelegate:
{
/* Checks (function || object), but what good is it if there is
a null function pointer? */
@@ -783,7 +792,7 @@ convert_for_condition (tree expr, Type *type)
break;
}
- case Tnoreturn:
+ case TY::Tnoreturn:
/* Front-end allows conditionals that never return, represent the
conditional result value as all zeros. */
result = build_zero_cst (d_bool_type);
@@ -810,10 +819,10 @@ d_array_convert (Expression *exp)
{
Type *tb = exp->type->toBasetype ();
- if (tb->ty == Tarray)
+ if (tb->ty == TY::Tarray)
return build_expr (exp);
- if (tb->ty == Tsarray)
+ if (tb->ty == TY::Tsarray)
{
Type *totype = tb->nextOf ()->arrayOf ();
return convert_expr (build_expr (exp), exp->type, totype);
@@ -832,7 +841,8 @@ d_array_convert (Type *etype, Expression *exp)
{
Type *tb = exp->type->toBasetype ();
- if ((tb->ty != Tarray && tb->ty != Tsarray) || same_type_p (tb, etype))
+ if ((tb->ty != TY::Tarray && tb->ty != TY::Tsarray)
+ || same_type_p (tb, etype))
{
/* Convert single element to an array. */
tree expr = build_expr (exp);
@@ -222,15 +222,6 @@ d_diagnostic_report_diagnostic (const Loc &loc, int opt, const char *format,
message prefix PREFIX1 and PREFIX2, increasing the global or gagged
error count. */
-void ATTRIBUTE_GCC_DIAG(2,3)
-error (const Loc &loc, const char *format, ...)
-{
- va_list ap;
- va_start (ap, format);
- verror (loc, format, ap);
- va_end (ap);
-}
-
void ATTRIBUTE_GCC_DIAG(2,0)
verror (const Loc &loc, const char *format, va_list ap,
const char *prefix1, const char *prefix2, const char *)
@@ -263,15 +254,6 @@ verror (const Loc &loc, const char *format, va_list ap,
/* Print supplementary message about the last error with explicit location LOC.
This doesn't increase the global error count. */
-void ATTRIBUTE_GCC_DIAG(2,3)
-errorSupplemental (const Loc &loc, const char *format, ...)
-{
- va_list ap;
- va_start (ap, format);
- verrorSupplemental (loc, format, ap);
- va_end (ap);
-}
-
void ATTRIBUTE_GCC_DIAG(2,0)
verrorSupplemental (const Loc &loc, const char *format, va_list ap)
{
@@ -284,15 +266,6 @@ verrorSupplemental (const Loc &loc, const char *format, va_list ap)
/* Print a warning message with explicit location LOC, increasing the
global warning count. */
-void ATTRIBUTE_GCC_DIAG(2,3)
-warning (const Loc &loc, const char *format, ...)
-{
- va_list ap;
- va_start (ap, format);
- vwarning (loc, format, ap);
- va_end (ap);
-}
-
void ATTRIBUTE_GCC_DIAG(2,0)
vwarning (const Loc &loc, const char *format, va_list ap)
{
@@ -311,15 +284,6 @@ vwarning (const Loc &loc, const char *format, va_list ap)
/* Print supplementary message about the last warning with explicit location
LOC. This doesn't increase the global warning count. */
-void ATTRIBUTE_GCC_DIAG(2,3)
-warningSupplemental (const Loc &loc, const char *format, ...)
-{
- va_list ap;
- va_start (ap, format);
- vwarningSupplemental (loc, format, ap);
- va_end (ap);
-}
-
void ATTRIBUTE_GCC_DIAG(2,0)
vwarningSupplemental (const Loc &loc, const char *format, va_list ap)
{
@@ -333,15 +297,6 @@ vwarningSupplemental (const Loc &loc, const char *format, va_list ap)
message prefix PREFIX1 and PREFIX2, increasing the global warning or
error count depending on how deprecations are treated. */
-void ATTRIBUTE_GCC_DIAG(2,3)
-deprecation (const Loc &loc, const char *format, ...)
-{
- va_list ap;
- va_start (ap, format);
- vdeprecation (loc, format, ap);
- va_end (ap);
-}
-
void ATTRIBUTE_GCC_DIAG(2,0)
vdeprecation (const Loc &loc, const char *format, va_list ap,
const char *prefix1, const char *prefix2)
@@ -372,15 +327,6 @@ vdeprecation (const Loc &loc, const char *format, va_list ap,
/* Print supplementary message about the last deprecation with explicit
location LOC. This does not increase the global error count. */
-void ATTRIBUTE_GCC_DIAG(2,3)
-deprecationSupplemental (const Loc &loc, const char *format, ...)
-{
- va_list ap;
- va_start (ap, format);
- vdeprecationSupplemental (loc, format, ap);
- va_end (ap);
-}
-
void ATTRIBUTE_GCC_DIAG(2,0)
vdeprecationSupplemental (const Loc &loc, const char *format, va_list ap)
{
@@ -392,30 +338,19 @@ vdeprecationSupplemental (const Loc &loc, const char *format, va_list ap)
/* Print a verbose message with explicit location LOC. */
-void ATTRIBUTE_GCC_DIAG(2, 3)
-message (const Loc &loc, const char *format, ...)
-{
- va_list ap;
- va_start (ap, format);
- vmessage (loc, format, ap);
- va_end (ap);
-}
-
void ATTRIBUTE_GCC_DIAG(2,0)
vmessage (const Loc &loc, const char *format, va_list ap)
{
d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, true);
}
-/* Same as above, but doesn't take a location argument. */
+/* Print a tip message with prefix and highlighing. */
-void ATTRIBUTE_GCC_DIAG(1, 2)
-message (const char *format, ...)
+void ATTRIBUTE_GCC_DIAG(1,0)
+vtip (const char *format, va_list ap)
{
- va_list ap;
- va_start (ap, format);
- vmessage (Loc (), format, ap);
- va_end (ap);
+ if (!global.gag)
+ d_diagnostic_report_diagnostic (Loc (), 0, format, ap, DK_DEBUG, true);
}
/* Call this after printing out fatal error messages to clean up and
@@ -27,116 +27,11 @@ along with GCC; see the file COPYING3. If not see
#include "dmd/scope.h"
#include "tree.h"
-#include "options.h"
#include "fold-const.h"
#include "diagnostic.h"
#include "d-tree.h"
-
-/* Implements the Global interface defined by the frontend.
- Used for managing the state of the current compilation. */
-
-Global global;
-
-void
-Global::_init (void)
-{
- this->mars_ext = "d";
- this->hdr_ext = "di";
- this->doc_ext = "html";
- this->ddoc_ext = "ddoc";
- this->json_ext = "json";
- this->obj_ext = "o";
-
- this->run_noext = true;
- this->version = "v"
-#include "verstr.h"
- ;
-
- this->stdmsg = stderr;
-}
-
-/* Start gagging. Return the current number of gagged errors. */
-
-unsigned
-Global::startGagging (void)
-{
- this->gag++;
- return this->gaggedErrors;
-}
-
-/* End gagging, restoring the old gagged state. Return true if errors
- occured while gagged. */
-
-bool
-Global::endGagging (unsigned oldGagged)
-{
- bool anyErrs = (this->gaggedErrors != oldGagged);
- this->gag--;
-
- /* Restore the original state of gagged errors; set total errors
- to be original errors + new ungagged errors. */
- this->errors -= (this->gaggedErrors - oldGagged);
- this->gaggedErrors = oldGagged;
-
- return anyErrs;
-}
-
-/* Increment the error count to record that an error has occured in the
- current context. An error message may or may not have been printed. */
-
-void
-Global::increaseErrorCount (void)
-{
- if (gag)
- this->gaggedErrors++;
-
- this->errors++;
-}
-
-
-/* Implements the Loc interface defined by the frontend.
- Used for keeping track of current file/line position in code. */
-
-Loc::Loc (const char *filename, unsigned linnum, unsigned charnum)
-{
- this->linnum = linnum;
- this->charnum = charnum;
- this->filename = filename;
-}
-
-const char *
-Loc::toChars (void) const
-{
- OutBuffer buf;
-
- if (this->filename)
- buf.printf ("%s", this->filename);
-
- if (this->linnum)
- {
- buf.printf (":%u", this->linnum);
- if (this->charnum)
- buf.printf (":%u", this->charnum);
- }
-
- return buf.extractChars ();
-}
-
-bool
-Loc::equals (const Loc &loc)
-{
- if (this->linnum != loc.linnum || this->charnum != loc.charnum)
- return false;
-
- if (!FileName::equals (this->filename, loc.filename))
- return false;
-
- return true;
-}
-
-
/* Implements back-end specific interfaces used by the frontend. */
/* Determine if function FD is a builtin one that we can evaluate in CTFE. */
@@ -144,7 +39,7 @@ Loc::equals (const Loc &loc)
BUILTIN
isBuiltin (FuncDeclaration *fd)
{
- if (fd->builtin != BUILTINunknown)
+ if (fd->builtin != BUILTIN::unknown)
return fd->builtin;
maybe_set_intrinsic (fd);
@@ -158,7 +53,7 @@ isBuiltin (FuncDeclaration *fd)
Expression *
eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
{
- if (fd->builtin == BUILTINunimp)
+ if (fd->builtin == BUILTIN::unimp)
return NULL;
tree decl = get_symbol_decl (fd);
@@ -185,16 +80,8 @@ eval_builtin (Loc loc, FuncDeclaration *fd, Expressions *arguments)
Type *
getTypeInfoType (Loc loc, Type *type, Scope *sc)
{
- gcc_assert (type->ty != Terror);
+ gcc_assert (type->ty != TY::Terror);
check_typeinfo_type (loc, sc);
create_typeinfo (type, sc ? sc->_module->importedFrom : NULL);
return type->vtinfo->type;
}
-
-/* Return an inlined copy of a default argument for a function parameter. */
-
-Expression *
-inlineCopy (Expression *e, Scope *)
-{
- return e->copy ();
-}
new file mode 100644
@@ -0,0 +1,37 @@
+/* d-frontend.h -- D frontend interface to the gcc back-end.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_D_FRONTEND_H
+#define GCC_D_FRONTEND_H
+
+/* These functions are defined in D runtime. */
+extern "C" int rt_init (void);
+extern "C" int rt_term (void);
+//extern "C" void gc_disable (void);
+extern "C" void *gc_malloc (size_t sz, unsigned ba = 0, const void *ti = NULL);
+extern "C" void gc_free (void *);
+extern "C" void gc_collect (void);
+
+template<typename T>
+inline T *
+d_gc_malloc (void)
+{
+ void *ptr = gc_malloc (sizeof (T));
+ return new(ptr) T ();
+}
+
+#endif
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "dmd/globals.h"
+#include "d-frontend.h"
#include "cppdefault.h"
@@ -71,7 +72,7 @@ add_globalpaths (Strings *paths)
if (paths)
{
if (!global.path)
- global.path = new Strings ();
+ global.path = d_gc_malloc<Strings> ();
for (size_t i = 0; i < paths->length; i++)
{
@@ -98,7 +99,7 @@ add_filepaths (Strings *paths)
if (paths)
{
if (!global.filePath)
- global.filePath = new Strings ();
+ global.filePath = d_gc_malloc<Strings> ();
for (size_t i = 0; i < paths->length; i++)
{
@@ -26,12 +26,13 @@ along with GCC; see the file COPYING3. If not see
#include "dmd/errors.h"
#include "dmd/expression.h"
#include "dmd/hdrgen.h"
+#include "dmd/id.h"
#include "dmd/identifier.h"
#include "dmd/json.h"
#include "dmd/mangle.h"
-#include "dmd/mars.h"
#include "dmd/module.h"
#include "dmd/mtype.h"
+#include "dmd/root/file.h"
#include "dmd/target.h"
#include "opts.h"
@@ -53,7 +54,7 @@ along with GCC; see the file COPYING3. If not see
#include "input.h"
#include "d-tree.h"
-#include "id.h"
+#include "d-frontend.h"
/* Array of D frontend type/decl nodes. */
@@ -83,10 +84,6 @@ d_option;
/* List of modules being compiled. */
static Modules builtin_modules;
-/* Module where `C main' is defined, compiled in if needed. */
-static Module *entrypoint_module = NULL;
-static Module *entrypoint_root_module = NULL;
-
/* The current and global binding level in effect. */
struct binding_level *current_binding_level;
struct binding_level *global_binding_level;
@@ -202,7 +199,7 @@ deps_write (Module *module, obstack *buffer)
deps_write_string (d_option.deps_target[i], buffer, column);
}
else
- deps_write_string (module->objfile->name->str, buffer, column);
+ deps_write_string (module->objfile.toChars (), buffer, column);
obstack_1grow (buffer, ':');
column++;
@@ -212,7 +209,7 @@ deps_write (Module *module, obstack *buffer)
{
Module *depmod = modlist.pop ();
- const char *modstr = depmod->srcfile->name->str;
+ const char *modstr = depmod->srcfile.toChars ();
/* Skip modules that have already been looked at. */
if (seen_modules.add (modstr))
@@ -238,9 +235,7 @@ deps_write (Module *module, obstack *buffer)
Module *m = depmod->aimports[i];
/* Ignore compiler-generated modules. */
- if ((m->ident == Identifier::idPool ("__entrypoint")
- || m->ident == Identifier::idPool ("__main"))
- && m->parent == NULL)
+ if (m->ident == Identifier::idPool ("__main") && m->parent == NULL)
continue;
/* Don't search system installed modules, this includes
@@ -251,9 +246,9 @@ deps_write (Module *module, obstack *buffer)
&& m->parent == NULL)
continue;
- if (m->md && m->md->packages)
+ if (m->md && m->md->packages.length)
{
- Identifier *package = (*m->md->packages)[0];
+ Identifier *package = m->md->packages.ptr[0];
if (package == Identifier::idPool ("core")
|| package == Identifier::idPool ("std")
@@ -291,27 +286,15 @@ deps_write (Module *module, obstack *buffer)
static void
d_init_options (unsigned int, cl_decoded_option *decoded_options)
{
+ /* Initialize the D runtime. */
+ rt_init ();
+// gc_disable ();
+
/* Set default values. */
global._init ();
global.vendor = lang_hooks.name;
global.params.argv0 = xstrdup (decoded_options[0].arg);
- global.params.link = true;
- global.params.useAssert = CHECKENABLEdefault;
- global.params.useInvariants = CHECKENABLEdefault;
- global.params.useIn = CHECKENABLEdefault;
- global.params.useOut = CHECKENABLEdefault;
- global.params.useArrayBounds = CHECKENABLEdefault;
- global.params.useSwitchError = CHECKENABLEdefault;
- global.params.checkAction = CHECKACTION_D;
- global.params.useModuleInfo = true;
- global.params.useTypeInfo = true;
- global.params.useExceptions = true;
- global.params.useInline = false;
- global.params.obj = true;
- global.params.hdrStripPlainFunctions = true;
- global.params.betterC = false;
- global.params.allInst = false;
global.params.errorLimit = flag_max_errors;
/* Default extern(C++) mangling to C++14. */
@@ -320,9 +303,10 @@ d_init_options (unsigned int, cl_decoded_option *decoded_options)
/* Warnings and deprecations are disabled by default. */
global.params.useDeprecated = DIAGNOSTICinform;
global.params.warnings = DIAGNOSTICoff;
+ global.params.messageStyle = MESSAGESTYLEgnu;
- global.params.imppath = new Strings ();
- global.params.fileImppath = new Strings ();
+ global.params.imppath = d_gc_malloc<Strings> ();
+ global.params.fileImppath = d_gc_malloc<Strings> ();
/* Extra GDC-specific options. */
d_option.fonly = NULL;
@@ -462,6 +446,11 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
: (value == 1) ? CHECKENABLEsafeonly : CHECKENABLEoff;
break;
+ case OPT_fcheckaction_:
+ global.params.checkAction = (value == 0) ? CHECKACTION_D
+ : (value == 1) ? CHECKACTION_halt : CHECKACTION_context;
+ break;
+
case OPT_fdebug:
global.params.debuglevel = value ? 1 : 0;
break;
@@ -480,7 +469,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
{
if (!global.params.debugids)
- global.params.debugids = new Strings ();
+ global.params.debugids = d_gc_malloc<Strings> ();
global.params.debugids->push (arg);
break;
}
@@ -510,6 +499,16 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.betterC = !value;
break;
+ case OPT_fdump_c___spec_:
+ if (global.params.doCxxHdrGeneration == CxxHeaderMode::none)
+ global.params.doCxxHdrGeneration = CxxHeaderMode::silent;
+ global.params.cxxhdrname = arg;
+ break;
+
+ case OPT_fdump_c___spec_verbose:
+ global.params.doCxxHdrGeneration = CxxHeaderMode::verbose;
+ break;
+
case OPT_fdump_d_original:
global.params.vcg_ast = value;
break;
@@ -518,6 +517,22 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.useExceptions = value;
break;
+ case OPT_fextern_std_:
+ switch (value)
+ {
+ case CppStdRevisionCpp98:
+ case CppStdRevisionCpp11:
+ case CppStdRevisionCpp14:
+ case CppStdRevisionCpp17:
+ case CppStdRevisionCpp20:
+ global.params.cplusplus = (CppStdRevision) value;
+ break;
+
+ default:
+ error ("bad argument for %<-fextern-std%>: %qs", arg);
+ }
+ break;
+
case OPT_fignore_unknown_pragmas:
global.params.ignoreUnsupportedPragmas = value;
break;
@@ -552,35 +567,115 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.useIn = value ? CHECKENABLEon : CHECKENABLEoff;
break;
+ case OPT_fpreview_all:
+ global.params.ehnogc = value;
+ global.params.useDIP25 = FeatureState::enabled;
+ global.params.useDIP1000 = FeatureState::enabled;
+ global.params.useDIP1021 = value;
+ global.params.dtorFields = FeatureState::enabled;
+ global.params.fieldwise = value;
+ global.params.fixAliasThis = value;
+ global.params.previewIn = value;
+ global.params.fix16997 = value;
+ global.params.markdown = value;
+ global.params.noSharedAccess = value;
+ global.params.rvalueRefParam = value;
+ global.params.inclusiveInContracts = value;
+ global.params.shortenedMethods = value;
+ break;
+
+ case OPT_fpreview_dip1000:
+ global.params.useDIP1000 = FeatureState::enabled;
+ break;
+
+ case OPT_fpreview_dip1008:
+ global.params.ehnogc = value;
+ break;
+
+ case OPT_fpreview_dip1021:
+ global.params.useDIP1021 = value;
+ break;
+
+ case OPT_fpreview_dip25:
+ global.params.useDIP25 = FeatureState::enabled;
+ break;
+
+ case OPT_fpreview_dtorfields:
+ global.params.dtorFields = FeatureState::enabled;
+ break;
+
+ case OPT_fpreview_fieldwise:
+ global.params.fieldwise = value;
+ break;
+
+ case OPT_fpreview_fixaliasthis:
+ global.params.fixAliasThis = value;
+ break;
+
+ case OPT_fpreview_in:
+ global.params.previewIn = value;
+ break;
+
+ case OPT_fpreview_inclusiveincontracts:
+ global.params.inclusiveInContracts = value;
+ break;
+
+ case OPT_fpreview_intpromote:
+ global.params.fix16997 = value;
+ break;
+
+ case OPT_fpreview_nosharedaccess:
+ global.params.noSharedAccess = value;
+ break;
+
+ case OPT_fpreview_rvaluerefparam:
+ global.params.rvalueRefParam = value;
+ break;
+
+ case OPT_fpreview_shortenedmethods:
+ global.params.shortenedMethods = value;
+ break;
+
case OPT_frelease:
global.params.release = value;
break;
- case OPT_frtti:
- global.params.useTypeInfo = value;
+ case OPT_frevert_all:
+ global.params.useDIP25 = FeatureState::disabled;
+ global.params.markdown = !value;
+ global.params.dtorFields = FeatureState::disabled;
break;
- case OPT_fswitch_errors:
- global.params.useSwitchError = value ? CHECKENABLEon : CHECKENABLEoff;
+ case OPT_frevert_dip25:
+ global.params.useDIP25 = FeatureState::disabled;
break;
- case OPT_ftransition_all:
- global.params.vtls = value;
- global.params.vfield = value;
- global.params.vcomplex = value;
+ case OPT_frevert_dtorfields:
+ global.params.dtorFields = FeatureState::disabled;
+ break;
+
+ case OPT_frevert_markdown:
+ global.params.markdown = !value;
break;
- case OPT_ftransition_complex:
- global.params.vcomplex = value;
+ case OPT_frtti:
+ global.params.useTypeInfo = value;
break;
- case OPT_ftransition_dip1000:
- global.params.vsafe = value;
- global.params.useDIP25 = value;
+ case OPT_fsave_mixins_:
+ global.params.mixinFile = arg;
+ global.params.mixinOut = d_gc_malloc<OutBuffer> ();
break;
- case OPT_ftransition_dip25:
- global.params.useDIP25 = value;
+ case OPT_fswitch_errors:
+ global.params.useSwitchError = value ? CHECKENABLEon : CHECKENABLEoff;
+ break;
+
+ case OPT_ftransition_all:
+ global.params.vfield = value;
+ global.params.vgc = value;
+ global.params.vmarkdown= value;
+ global.params.vtls = value;
break;
case OPT_ftransition_field:
@@ -591,6 +686,14 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
global.params.vgc = value;
break;
+ case OPT_ftransition_vmarkdown:
+ global.params.vmarkdown = value;
+ break;
+
+ case OPT_ftransition_templates:
+ global.params.vtemplates = value;
+ break;
+
case OPT_ftransition_tls:
global.params.vtls = value;
break;
@@ -613,7 +716,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
if (Identifier::isValidIdentifier (CONST_CAST (char *, arg)))
{
if (!global.params.versionids)
- global.params.versionids = new Strings ();
+ global.params.versionids = d_gc_malloc<Strings> ();
global.params.versionids->push (arg);
break;
}
@@ -804,6 +907,14 @@ d_post_options (const char ** fn)
global.params.checkAction = CHECKACTION_C;
}
+ /* Enabling DIP1021 implies DIP1000. */
+ if (global.params.useDIP1021)
+ global.params.useDIP1000 = FeatureState::enabled;
+
+ /* Enabling DIP1000 implies DIP25. */
+ if (global.params.useDIP1000 == FeatureState::enabled)
+ global.params.useDIP25 = FeatureState::enabled;
+
/* Keep in sync with existing -fbounds-check flag. */
flag_bounds_check = (global.params.useArrayBounds == CHECKENABLEon);
@@ -828,6 +939,7 @@ d_post_options (const char ** fn)
global.params.symdebug = write_symbols != NO_DEBUG;
global.params.useInline = flag_inline_functions;
global.params.showColumns = flag_show_column;
+ global.params.printErrorContext = flag_diagnostics_show_caret;
if (global.params.useInline)
global.params.hdrStripPlainFunctions = false;
@@ -872,17 +984,6 @@ d_add_builtin_module (Module *m)
builtin_modules.push (m);
}
-/* Record the entrypoint module ENTRY which will be compiled in the current
- compilation. ROOT is the module scope where this was requested from. */
-
-void
-d_add_entrypoint_module (Module *entry, Module *root)
-{
- /* We are emitting this straight to object file. */
- entrypoint_module = entry;
- entrypoint_root_module = root;
-}
-
/* Implements the lang_hooks.parse_file routine for language D. */
static void
@@ -891,7 +992,7 @@ d_parse_file (void)
if (global.params.verbose)
{
message ("binary %s", global.params.argv0.ptr);
- message ("version %s", global.version.ptr);
+ message ("version %s", global.versionChars ());
if (global.versionids)
{
@@ -955,16 +1056,16 @@ d_parse_file (void)
/* Handling stdin, generate a unique name for the module. */
Module *m = Module::create (in_fnames[i],
- Identifier::generateId ("__stdin"),
+ Identifier::idPool ("__stdin"),
global.params.doDocComments,
global.params.doHdrGeneration);
modules.push (m);
/* Overwrite the source file for the module, the one created by
Module::create would have a forced a `.d' suffix. */
- m->srcfile = File::create ("<stdin>");
- m->srcfile->len = len;
- m->srcfile->buffer = buffer;
+ m->srcBuffer = FileBuffer::create ();
+ m->srcBuffer->data.length = len;
+ m->srcBuffer->data.ptr = buffer;
}
else
{
@@ -1011,15 +1112,16 @@ d_parse_file (void)
}
/* Load the module containing D main. */
+ Module *main_module = NULL;
if (global.params.addMain)
{
unsigned errors = global.startGagging ();
- Module *m = Module::load (Loc (), NULL, Identifier::idPool ("__main"));
+ main_module = Module::load (Loc (), NULL, Identifier::idPool ("__main"));
if (!global.endGagging (errors))
{
- m->importedFrom = m;
- modules.push (m);
+ main_module->importedFrom = main_module;
+ modules.push (main_module);
}
}
@@ -1038,7 +1140,7 @@ d_parse_file (void)
for (size_t i = 0; i < modules.length; i++)
{
Module *m = modules[i];
- if (d_option.fonly && m != Module::rootModule)
+ if (m->isHdrFile || (d_option.fonly && m != Module::rootModule))
continue;
if (global.params.verbose)
@@ -1203,7 +1305,7 @@ d_parse_file (void)
if (name && (name[0] != '-' || name[1] != '\0'))
{
const char *nameext
- = FileName::defaultExt (name, global.json_ext.ptr);
+ = FileName::defaultExt (name, json_ext.ptr);
json_stream = fopen (nameext, "w");
if (!json_stream)
{
@@ -1245,22 +1347,25 @@ d_parse_file (void)
}
}
+ /* Generate C++ header files. */
+ if (global.params.doCxxHdrGeneration != CxxHeaderMode::none)
+ genCppHdrFiles (modules);
+
+ if (global.errors)
+ goto had_errors;
+
for (size_t i = 0; i < modules.length; i++)
{
Module *m = modules[i];
- if (d_option.fonly && m != Module::rootModule)
+ if ((m->isHdrFile && m != main_module)
+ || (d_option.fonly && m != Module::rootModule))
continue;
if (global.params.verbose)
message ("code %s", m->toChars ());
if (!flag_syntax_only)
- {
- if ((entrypoint_module != NULL) && (m == entrypoint_root_module))
- build_decl_tree (entrypoint_module);
-
- build_decl_tree (m);
- }
+ build_decl_tree (m);
}
/* And end the main input file, if the debug writer wants it. */
@@ -1272,16 +1377,37 @@ d_parse_file (void)
exit with an error status. */
errorcount += (global.errors + global.warnings);
+ /* We want to write the mixin expansion file also on error. */
+ if (global.params.mixinOut)
+ {
+ FILE *mixin_stream = fopen (global.params.mixinFile, "w");
+
+ if (mixin_stream)
+ {
+ OutBuffer *buf = global.params.mixinOut;
+ fprintf (mixin_stream, "%s", buf->peekChars ());
+
+ if (ferror (mixin_stream) || fclose (mixin_stream))
+ fatal_error (input_location, "closing mixin file %s: %m",
+ global.params.mixinFile);
+ }
+ else
+ {
+ fatal_error (input_location, "opening mixin file %s: %m",
+ global.params.mixinFile);
+ }
+ }
+
/* Remove generated .di files on error. */
if (errorcount && dump_headers)
{
for (size_t i = 0; i < modules.length; i++)
{
Module *m = modules[i];
- if (d_option.fonly && m != Module::rootModule)
+ if (m->isHdrFile || (d_option.fonly && m != Module::rootModule))
continue;
- remove (m->hdrfile->toChars ());
+ remove (m->hdrfile.toChars ());
}
}
@@ -1406,7 +1532,7 @@ d_type_promotes_to (tree type)
/* Promotions are only applied on unnamed function arguments for declarations
with `extern(C)' or `extern(C++)' linkage. */
if (cfun && DECL_LANG_FRONTEND (cfun->decl)
- && DECL_LANG_FRONTEND (cfun->decl)->linkage != LINKd)
+ && DECL_LANG_FRONTEND (cfun->decl)->linkage != LINK::d)
{
/* In [type/integer-promotions], integer promotions are conversions of the
following types:
@@ -1559,7 +1685,8 @@ d_types_compatible_p (tree x, tree y)
return true;
/* Type system allows implicit conversion between. */
- if (tx->implicitConvTo (ty) || ty->implicitConvTo (tx))
+ if (tx->implicitConvTo (ty) != MATCH::nomatch
+ || ty->implicitConvTo (tx) != MATCH::nomatch)
return true;
}
@@ -30,12 +30,6 @@ along with GCC; see the file COPYING3. If not see
#include "longdouble.h"
-/* Constant real values 0, 1, -1 and 0.5. */
-real_t CTFloat::zero;
-real_t CTFloat::one;
-real_t CTFloat::minusone;
-real_t CTFloat::half;
-
/* Truncate longdouble to the highest precision supported by target. */
longdouble
@@ -26,60 +26,8 @@
#endif
#include "system.h"
-/* Used by the dmd front-end to determine if we have POSIX-style IO. */
-#define POSIX (__linux__ || __GLIBC__ || __gnu_hurd__ || __APPLE__ \
- || __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ \
- || __sun || __unix__)
-
/* Forward assert invariants to gcc_assert. */
#undef assert
#define assert(EXPR) gcc_assert(EXPR)
-/* Use libiberty's lrealpath to avoid portability problems. */
-#undef realpath
-#define realpath(a, b) lrealpath((a))
-
-/* Forward ctype.h macros used by the dmd front-end to safe-ctype.h. */
-#undef isalpha
-#define isalpha(c) ISALPHA(c)
-#undef isalnum
-#define isalnum(c) ISALNUM(c)
-#undef isdigit
-#define isdigit(c) ISDIGIT(c)
-#undef islower
-#define islower(c) ISLOWER(c)
-#undef isprint
-#define isprint(c) ISPRINT(c)
-#undef isspace
-#define isspace(c) ISSPACE(c)
-#undef isupper
-#define isupper(c) ISUPPER(c)
-#undef isxdigit
-#define isxdigit(c) ISXDIGIT(c)
-#undef tolower
-#define tolower(c) TOLOWER(c)
-
-/* Forward _mkdir on MinGW to mkdir in system.h. */
-#ifdef _WIN32
-#undef _mkdir
-#define _mkdir(p) mkdir(p, 0)
-#endif
-
-/* Define any missing _MAX and _MIN macros. */
-#ifndef INT32_MAX
-# define INT32_MAX INTTYPE_MAXIMUM (int32_t)
-#endif
-#ifndef INT32_MIN
-# define INT32_MIN INTTYPE_MINIMUM (int32_t)
-#endif
-#ifndef INT64_MIN
-# define INT64_MIN INTTYPE_MINIMUM (int64_t)
-#endif
-#ifndef UINT32_MAX
-# define UINT32_MAX INTTYPE_MAXIMUM (uint32_t)
-#endif
-#ifndef UINT64_MAX
-# define UINT64_MAX INTTYPE_MAXIMUM (uint64_t)
-#endif
-
#endif /* GCC_D_SYSTEM_H */
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "tm_p.h"
#include "target.h"
+#include "calls.h"
#include "d-tree.h"
#include "d-target.h"
@@ -42,8 +43,6 @@ along with GCC; see the file COPYING3. If not see
/* Implements the Target interface defined by the front end.
Used for retrieving target-specific information. */
-Target target;
-
/* Internal key handlers for `__traits(getTargetInfo)'. */
static tree d_handle_target_cpp_std (void);
static tree d_handle_target_cpp_runtime_library (void);
@@ -89,9 +88,6 @@ define_float_constants (T &f, tree type)
/* Floating-point NaN. */
real_nan (&f.nan.rv (), "", 1, mode);
- /* Signalling floating-point NaN. */
- real_nan (&f.snan.rv (), "", 0, mode);
-
/* Floating-point +Infinity if the target supports infinities. */
real_inf (&f.infinity.rv ());
@@ -142,19 +138,19 @@ Target::_init (const Param &)
/* Define what type to use for size_t, ptrdiff_t. */
if (this->ptrsize == 8)
{
- global.params.isLP64 = true;
- Type::tsize_t = Type::basic[Tuns64];
- Type::tptrdiff_t = Type::basic[Tint64];
+ this->isLP64 = true;
+ Type::tsize_t = Type::basic[(int)TY::Tuns64];
+ Type::tptrdiff_t = Type::basic[(int)TY::Tint64];
}
else if (this->ptrsize == 4)
{
- Type::tsize_t = Type::basic[Tuns32];
- Type::tptrdiff_t = Type::basic[Tint32];
+ Type::tsize_t = Type::basic[(int)TY::Tuns32];
+ Type::tptrdiff_t = Type::basic[(int)TY::Tint32];
}
else if (this->ptrsize == 2)
{
- Type::tsize_t = Type::basic[Tuns16];
- Type::tptrdiff_t = Type::basic[Tint16];
+ Type::tsize_t = Type::basic[(int)TY::Tuns16];
+ Type::tptrdiff_t = Type::basic[(int)TY::Tint16];
}
else
sorry ("D does not support pointers on this target.");
@@ -164,15 +160,7 @@ Target::_init (const Param &)
/* Set-up target C ABI. */
this->c.longsize = int_size_in_bytes (long_integer_type_node);
this->c.long_doublesize = int_size_in_bytes (long_double_type_node);
-
- /* Define what type to use for wchar_t. We don't want to support wide
- characters less than "short" in D. */
- if (WCHAR_TYPE_SIZE == 32)
- this->c.twchar_t = Type::basic[Tdchar];
- else if (WCHAR_TYPE_SIZE == 16)
- this->c.twchar_t = Type::basic[Twchar];
- else
- sorry ("D does not support wide characters on this target.");
+ this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT);
/* Set-up target C++ ABI. */
this->cpp.reverseOverloads = false;
@@ -182,6 +170,12 @@ Target::_init (const Param &)
/* Set-up target Objective-C ABI. */
this->objc.supported = false;
+ /* Set-up environmental settings. */
+ this->obj_ext = "o";
+ this->lib_ext = "a";
+ this->dll_ext = "so";
+ this->run_noext = true;
+
/* Initialize all compile-time properties for floating-point types.
Should ensure that our real_t type is able to represent real_value. */
gcc_assert (sizeof (real_t) >= sizeof (real_value));
@@ -273,7 +267,7 @@ Target::isVectorTypeSupported (int sz, Type *type)
type = Type::tuns8;
/* No support for non-trivial types, complex types, or booleans. */
- if (!type->isTypeBasic () || type->iscomplex () || type->ty == Tbool)
+ if (!type->isTypeBasic () || type->iscomplex () || type->ty == TY::Tbool)
return 2;
/* In [simd/vector extensions], which vector types are supported depends on
@@ -293,9 +287,9 @@ Target::isVectorTypeSupported (int sz, Type *type)
Returns true if the operation is supported or type is not a vector. */
bool
-Target::isVectorOpSupported (Type *type, TOK op, Type *)
+Target::isVectorOpSupported (Type *type, unsigned op, Type *)
{
- if (type->ty != Tvector)
+ if (type->ty != TY::Tvector)
return true;
/* Don't support if type is non-scalar, such as __vector(void[]). */
@@ -322,18 +316,10 @@ Target::isVectorOpSupported (Type *type, TOK op, Type *)
/* Logical operators must have a result type of bool. */
return false;
- case TOKue:
- case TOKlg:
- case TOKule:
- case TOKul:
- case TOKuge:
- case TOKug:
case TOKle:
case TOKlt:
case TOKge:
case TOKgt:
- case TOKleg:
- case TOKunord:
case TOKequal:
case TOKnotequal:
case TOKidentity:
@@ -379,7 +365,8 @@ TargetCPP::thunkMangle (FuncDeclaration *fd, int offset)
const char *
TargetCPP::typeMangle (Type *type)
{
- if (type->isTypeBasic () || type->ty == Tvector || type->ty == Tstruct)
+ if (type->isTypeBasic () || type->ty == TY::Tvector
+ || type->ty == TY::Tstruct)
{
tree ctype = build_ctype (type);
return targetm.mangle_type (ctype);
@@ -400,14 +387,14 @@ TargetCPP::parameterType (Parameter *arg)
else if (arg->storageClass & STClazy)
{
/* Mangle as delegate. */
- Type *td = TypeFunction::create (NULL, t, VARARGnone, LINKd);
- td = TypeDelegate::create (td);
- t = t->merge2 ();
+ TypeFunction *tf = TypeFunction::create (NULL, t, VARARGnone, LINK::d);
+ TypeDelegate *td = TypeDelegate::create (tf);
+ t = td->merge2 ();
}
/* Could be a va_list, which we mangle as a pointer. */
Type *tvalist = target.va_listType (Loc (), NULL);
- if (t->ty == Tsarray && tvalist->ty == Tsarray)
+ if (t->ty == TY::Tsarray && tvalist->ty == TY::Tsarray)
{
Type *tb = t->toBasetype ()->mutableOf ();
if (tb == tvalist)
@@ -450,10 +437,10 @@ Target::systemLinkage (void)
/* In [attribute/linkage], `System' is the same as `Windows' on Windows
platforms, and `C' on other platforms. */
if (link_system)
- return LINKwindows;
+ return LINK::windows;
}
- return LINKc;
+ return LINK::c;
}
/* Generate a TypeTuple of the equivalent types used to determine if a
@@ -477,12 +464,12 @@ Target::isReturnOnStack (TypeFunction *tf, bool)
/* Need the back-end type to determine this, but this is called from the
frontend before semantic processing is finished. An accurate value
is not currently needed anyway. */
- if (tf->isref)
+ if (tf->isref ())
return false;
Type *tn = tf->next->toBasetype ();
- return (tn->ty == Tstruct || tn->ty == Tsarray);
+ return (tn->ty == TY::Tstruct || tn->ty == TY::Tsarray);
}
/* Add all target info in HANDLERS to D_TARGET_INFO_TABLE for use by
@@ -575,12 +562,49 @@ Target::getTargetInfo (const char *key, const Loc &loc)
return NULL;
}
-/**
- * Returns true if the implementation for object monitors is always defined
- * in the D runtime library (rt/monitor_.d). */
+/* Returns true if the callee invokes destructors for arguments. */
+
+bool
+Target::isCalleeDestroyingArgs (TypeFunction *tf)
+{
+ return tf->linkage == LINK::d;
+}
+
+/* Returns true if the implementation for object monitors is always defined
+ in the D runtime library (rt/monitor_.d). */
bool
Target::libraryObjectMonitors (FuncDeclaration *, Statement *)
{
return true;
}
+
+/* Decides whether an `in' parameter of the specified POD type PARAM_TYPE is to
+ be passed by reference or by valie. This is used only when compiling with
+ `-fpreview=in' enabled. */
+
+bool
+Target::preferPassByRef (Type *param_type)
+{
+ if (param_type->size () == SIZE_INVALID)
+ return false;
+
+ tree type = build_ctype (param_type);
+
+ /* Prefer a `ref' if the type is an aggregate, and its size is greater than
+ its alignment. */
+ if (AGGREGATE_TYPE_P (type)
+ && (!valid_constant_size_p (TYPE_SIZE_UNIT (type))
+ || compare_tree_int (TYPE_SIZE_UNIT (type), TYPE_ALIGN (type)) > 0))
+ return true;
+
+ /* If the back-end is always going to pass this by invisible reference. */
+ if (pass_by_reference (NULL, function_arg_info (type, true)))
+ return true;
+
+ /* If returning the parameter means the caller will do RVO. */
+ if (targetm.calls.return_in_memory (type, NULL_TREE))
+ return true;
+
+ return false;
+}
@@ -617,7 +617,6 @@ extern void add_import_paths (const char *, const char *, bool);
/* In d-lang.cc. */
extern void d_add_builtin_module (Module *);
-extern void d_add_entrypoint_module (Module *, Module *);
extern d_tree_node_structure_enum d_tree_node_structure (lang_tree_node *);
extern struct lang_type *build_lang_type (Type *);
extern struct lang_decl *build_lang_decl (Declaration *);
@@ -106,9 +106,9 @@ gcc_attribute_p (Dsymbol *decl)
{
ModuleDeclaration *md = decl->getModule ()->md;
- if (md && md->packages && md->packages->length == 1)
+ if (md && md->packages.length == 1)
{
- if (!strcmp ((*md->packages)[0]->toChars (), "gcc")
+ if (!strcmp (md->packages.ptr[0]->toChars (), "gcc")
&& !strcmp (md->id->toChars (), "attributes"))
return true;
}
@@ -116,6 +116,59 @@ gcc_attribute_p (Dsymbol *decl)
return false;
}
+/* Subroutine of pragma declaration visitor for marking the function in the
+ defined in SYM as a global constructor or destructor. If ISCTOR is true,
+ then we're applying pragma(crt_constructor). */
+
+static int
+apply_pragma_crt (Dsymbol *sym, bool isctor)
+{
+ AttribDeclaration *ad = sym->isAttribDeclaration ();
+ if (ad != NULL)
+ {
+ int nested = 0;
+
+ /* Walk all declarations of the attribute scope. */
+ Dsymbols *ds = ad->include (NULL);
+ if (ds)
+ {
+ for (size_t i = 0; i < ds->length; i++)
+ nested += apply_pragma_crt ((*ds)[i], isctor);
+ }
+
+ return nested;
+ }
+
+ FuncDeclaration *fd = sym->isFuncDeclaration ();
+ if (fd != NULL)
+ {
+ tree decl = get_decl_tree (fd);
+
+ /* Apply flags to the function. */
+ if (isctor)
+ {
+ DECL_STATIC_CONSTRUCTOR (decl) = 1;
+ decl_init_priority_insert (decl, DEFAULT_INIT_PRIORITY);
+ }
+ else
+ {
+ DECL_STATIC_DESTRUCTOR (decl) = 1;
+ decl_fini_priority_insert (decl, DEFAULT_INIT_PRIORITY);
+ }
+
+ if (fd->linkage != LINK::c)
+ {
+ error_at (make_location_t (fd->loc),
+ "must be %<extern(C)%> for %<pragma(%s)%>",
+ isctor ? "crt_constructor" : "crt_destructor");
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
/* Implements the visitor interface to lower all Declaration AST classes
emitted from the D Front-end to GCC trees.
All visit methods accept one parameter D, which holds the frontend AST
@@ -246,19 +299,31 @@ public:
}
/* Pragmas are a way to pass special information to the compiler and to add
- vendor specific extensions to D. We don't do anything here, yet. */
+ vendor specific extensions to D. */
void visit (PragmaDeclaration *d)
{
- if (!global.params.ignoreUnsupportedPragmas)
+ if (d->ident == Identifier::idPool ("lib")
+ || d->ident == Identifier::idPool ("startaddress"))
{
- if (d->ident == Identifier::idPool ("lib")
- || d->ident == Identifier::idPool ("startaddress"))
+ if (!global.params.ignoreUnsupportedPragmas)
{
warning_at (make_location_t (d->loc), OPT_Wunknown_pragmas,
"pragma(%s) not implemented", d->ident->toChars ());
}
}
+ else if (d->ident == Identifier::idPool ("crt_constructor")
+ || d->ident == Identifier::idPool ("crt_destructor"))
+ {
+ /* Handle pragma(crt_constructor) and pragma(crt_destructor). Apply
+ flag to indicate that the functions enclosed should run automatically
+ at the beginning or end of execution. */
+ bool isctor = (d->ident == Identifier::idPool ("crt_constructor"));
+
+ if (apply_pragma_crt (d, isctor) > 1)
+ error_at (make_location_t (d->loc),
+ "can only apply to a single declaration");
+ }
visit ((AttribDeclaration *) d);
}
@@ -311,14 +376,14 @@ public:
nested members. Only applies to classes or structs. */
Type *tb = fd->type->nextOf ()->baseElemOf ();
- while (tb->ty == Tarray || tb->ty == Tpointer)
+ while (tb->ty == TY::Tarray || tb->ty == TY::Tpointer)
tb = tb->nextOf ()->baseElemOf ();
TemplateInstance *ti = NULL;
- if (tb->ty == Tstruct)
+ if (tb->ty == TY::Tstruct)
ti = tb->isTypeStruct ()->sym->isInstantiated ();
- else if (tb->ty == Tclass)
+ else if (tb->ty == TY::Tclass)
ti = tb->isTypeClass ()->sym->isInstantiated ();
/* Return type is instantiated from this template declaration, walk over
@@ -360,7 +425,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->type->ty == Terror)
+ if (d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -447,7 +512,8 @@ public:
if (fd2->isFuture ())
continue;
- if (fd->leastAsSpecialized (fd2) || fd2->leastAsSpecialized (fd))
+ if (fd->leastAsSpecialized (fd2) != MATCH::nomatch
+ || fd2->leastAsSpecialized (fd) != MATCH::nomatch)
{
error_at (make_location_t (fd->loc), "use of %qs",
fd->toPrettyChars ());
@@ -474,7 +540,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->type->ty == Terror)
+ if (d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -495,7 +561,8 @@ public:
/* Generate C symbols. */
d->csym = get_classinfo_decl (d);
- d->vtblsym = get_vtable_decl (d);
+ Dsymbol *vtblsym = d->vtblSymbol ();
+ vtblsym->csym = get_vtable_decl (d);
tree sinit = aggregate_initializer_decl (d);
/* Generate static initializer. */
@@ -527,9 +594,9 @@ public:
}
}
- DECL_INITIAL (d->vtblsym)
- = build_constructor (TREE_TYPE (d->vtblsym), elms);
- d_finish_decl (d->vtblsym);
+ DECL_INITIAL (vtblsym->csym)
+ = build_constructor (TREE_TYPE (vtblsym->csym), elms);
+ d_finish_decl (vtblsym->csym);
/* Add this decl to the current binding level. */
tree ctype = TREE_TYPE (build_ctype (d->type));
@@ -547,7 +614,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->type->ty == Terror)
+ if (d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -590,7 +657,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->errors || d->type->ty == Terror)
+ if (d->errors || d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -629,7 +696,7 @@ public:
if (d->semanticRun >= PASSobj)
return;
- if (d->type->ty == Terror)
+ if (d->type->ty == TY::Terror)
{
error_at (make_location_t (d->loc),
"had semantic errors when compiling");
@@ -695,7 +762,7 @@ public:
/* Frontend should have already caught this. */
gcc_assert (!integer_zerop (size)
- || d->type->toBasetype ()->ty == Tsarray);
+ || d->type->toBasetype ()->ty == TY::Tsarray);
d_finish_decl (decl);
@@ -770,7 +837,7 @@ public:
/* Check if any errors occurred when running semantic. */
if (TypeFunction *tf = d->type->isTypeFunction ())
{
- if (tf->next == NULL || tf->next->ty == Terror)
+ if (tf->next == NULL || tf->next->ty == TY::Terror)
return;
}
@@ -1183,6 +1250,17 @@ get_symbol_decl (Declaration *decl)
}
else if (TREE_CODE (decl->csym) == FUNCTION_DECL)
{
+ /* Dual-context functions require the code generation to build an array
+ for the context pointer of the function, making the delicate task of
+ tracking which context to follow when encountering a non-local symbol,
+ and so are a not planned to be supported. */
+ if (fd->needThis () && !fd->isMember2 ())
+ {
+ fatal_error (make_location_t (fd->loc),
+ "function requires a dual-context, which is not yet "
+ "supported by GDC");
+ }
+
/* The real function type may differ from its declaration. */
tree fntype = TREE_TYPE (decl->csym);
tree newfntype = NULL_TREE;
@@ -1238,9 +1316,9 @@ get_symbol_decl (Declaration *decl)
/* In [pragma/inline], functions decorated with `pragma(inline)' affects
whether they are inlined or not. */
- if (fd->inlining == PINLINEalways)
+ if (fd->inlining == PINLINE::always)
DECL_DECLARED_INLINE_P (decl->csym) = 1;
- else if (fd->inlining == PINLINEnever)
+ else if (fd->inlining == PINLINE::never)
DECL_UNINLINABLE (decl->csym) = 1;
/* Function was declared `naked'. */
@@ -1254,13 +1332,6 @@ get_symbol_decl (Declaration *decl)
if (fd->generated)
DECL_ARTIFICIAL (decl->csym) = 1;
- /* Vector array operations are always compiler generated. */
- if (fd->isArrayOp)
- {
- DECL_ARTIFICIAL (decl->csym) = 1;
- DECL_DECLARED_INLINE_P (decl->csym) = 1;
- }
-
/* Ensure and require contracts are lexically nested in the function they
part of, but are always publicly callable. */
if (fd->ident == Identifier::idPool ("ensure")
@@ -1271,7 +1342,7 @@ get_symbol_decl (Declaration *decl)
DECL_FINAL_P (decl->csym) = 1;
/* Function is of type `noreturn' or `typeof(*null)'. */
- if (fd->type->nextOf ()->ty == Tnoreturn)
+ if (fd->type->nextOf ()->ty == TY::Tnoreturn)
TREE_THIS_VOLATILE (decl->csym) = 1;
/* Check whether this function is expanded by the frontend. */
@@ -1298,10 +1369,10 @@ get_symbol_decl (Declaration *decl)
if (decl->storage_class & STCvolatile)
TREE_THIS_VOLATILE (decl->csym) = 1;
- /* Protection attributes are used by the debugger. */
- if (decl->protection.kind == Prot::private_)
+ /* Visibility attributes are used by the debugger. */
+ if (decl->visibility.kind == Visibility::private_)
TREE_PRIVATE (decl->csym) = 1;
- else if (decl->protection.kind == Prot::protected_)
+ else if (decl->visibility.kind == Visibility::protected_)
TREE_PROTECTED (decl->csym) = 1;
/* Likewise, so could the deprecated attribute. */
@@ -1794,7 +1865,7 @@ make_thunk (FuncDeclaration *decl, int offset)
forcing a D local thunk to be emitted. */
const char *ident;
- if (decl->linkage == LINKcpp)
+ if (decl->linkage == LINK::cpp)
ident = target.cpp.thunkMangle (decl, offset);
else
{
@@ -1810,7 +1881,9 @@ make_thunk (FuncDeclaration *decl, int offset)
SET_DECL_ASSEMBLER_NAME (thunk, DECL_NAME (thunk));
d_keep (thunk);
- free (CONST_CAST (char *, ident));
+
+ if (decl->linkage != LINK::cpp)
+ free (CONST_CAST (char *, ident));
if (!DECL_EXTERNAL (function))
finish_thunk (thunk, function);
@@ -1989,26 +2062,27 @@ d_mark_needed (tree decl)
tree
get_vtable_decl (ClassDeclaration *decl)
{
- if (decl->vtblsym)
- return decl->vtblsym;
+ if (decl->vtblsym && decl->vtblsym->csym)
+ return decl->vtblsym->csym;
tree ident = mangle_internal_decl (decl, "__vtbl", "Z");
/* Note: Using a static array type for the VAR_DECL, the DECL_INITIAL value
will have a different type. However the back-end seems to accept this. */
tree type = build_ctype (Type::tvoidptr->sarrayOf (decl->vtbl.length));
- decl->vtblsym = declare_extern_var (ident, type);
- DECL_LANG_SPECIFIC (decl->vtblsym) = build_lang_decl (NULL);
+ Dsymbol *vtblsym = decl->vtblSymbol ();
+ vtblsym->csym = declare_extern_var (ident, type);
+ DECL_LANG_SPECIFIC (vtblsym->csym) = build_lang_decl (NULL);
/* Class is a reference, want the record type. */
- DECL_CONTEXT (decl->vtblsym) = TREE_TYPE (build_ctype (decl->type));
- TREE_READONLY (decl->vtblsym) = 1;
- DECL_VIRTUAL_P (decl->vtblsym) = 1;
+ DECL_CONTEXT (vtblsym->csym) = TREE_TYPE (build_ctype (decl->type));
+ TREE_READONLY (vtblsym->csym) = 1;
+ DECL_VIRTUAL_P (vtblsym->csym) = 1;
- SET_DECL_ALIGN (decl->vtblsym, TARGET_VTABLE_ENTRY_ALIGN);
- DECL_USER_ALIGN (decl->vtblsym) = true;
+ SET_DECL_ALIGN (vtblsym->csym, TARGET_VTABLE_ENTRY_ALIGN);
+ DECL_USER_ALIGN (vtblsym->csym) = true;
- return decl->vtblsym;
+ return vtblsym->csym;
}
/* Helper function of build_class_instance. Find the field inside aggregate
@@ -249,7 +249,7 @@ public:
tree t1 = build_expr (e->e1);
tree t2 = build_expr (e->e2);
- if (e->type->ty != Tvoid)
+ if (e->type->ty != TY::Tvoid)
{
t1 = convert_expr (t1, e->e1->type, e->type);
t2 = convert_expr (t2, e->e2->type, e->type);
@@ -268,8 +268,8 @@ public:
Type *tb1 = e->e1->type->toBasetype ();
Type *tb2 = e->e2->type->toBasetype ();
- if ((tb1->ty == Tsarray || tb1->ty == Tarray)
- && (tb2->ty == Tsarray || tb2->ty == Tarray))
+ if ((tb1->ty == TY::Tsarray || tb1->ty == TY::Tarray)
+ && (tb2->ty == TY::Tsarray || tb2->ty == TY::Tarray))
{
/* For static and dynamic arrays, identity is defined as referring to
the same array elements and the same number of elements. */
@@ -278,7 +278,7 @@ public:
this->result_ = d_convert (build_ctype (e->type),
build_boolop (code, t1, t2));
}
- else if (tb1->isfloating () && tb1->ty != Tvector)
+ else if (tb1->isfloating () && tb1->ty != TY::Tvector)
{
/* For floating-point values, identity is defined as the bits in the
operands being identical. */
@@ -333,8 +333,8 @@ public:
Type *tb2 = e->e2->type->toBasetype ();
tree_code code = (e->op == TOKequal) ? EQ_EXPR : NE_EXPR;
- if ((tb1->ty == Tsarray || tb1->ty == Tarray)
- && (tb2->ty == Tsarray || tb2->ty == Tarray))
+ if ((tb1->ty == TY::Tsarray || tb1->ty == TY::Tarray)
+ && (tb2->ty == TY::Tsarray || tb2->ty == TY::Tarray))
{
/* For static and dynamic arrays, equality is defined as the lengths of
the arrays matching, and all the elements are equal. */
@@ -346,8 +346,9 @@ public:
e1.length == e2.length && memcmp(e1.ptr, e2.ptr, size) == 0;
Or when generating a NE expression:
e1.length != e2.length || memcmp(e1.ptr, e2.ptr, size) != 0; */
- if ((t1elem->isintegral () || t1elem->ty == Tvoid
- || (t1elem->ty == Tstruct && !t1elem->isTypeStruct ()->sym->xeq))
+ if ((t1elem->isintegral () || t1elem->ty == TY::Tvoid
+ || (t1elem->ty == TY::Tstruct
+ && !t1elem->isTypeStruct ()->sym->xeq))
&& t1elem->ty == t2elem->ty)
{
tree t1 = d_array_convert (e->e1);
@@ -368,7 +369,7 @@ public:
/* Compare arrays using memcmp if possible, otherwise for structs,
each field is compared inline. */
- if (t1elem->ty != Tstruct
+ if (t1elem->ty != TY::Tstruct
|| identity_compare_p (t1elem->isTypeStruct ()->sym))
{
tree size = size_mult_expr (t1len, size_int (t1elem->size ()));
@@ -398,7 +399,7 @@ public:
/* Finally, check if lengths of both arrays match if dynamic.
The frontend should have already guaranteed that static arrays
have same size. */
- if (tb1->ty == Tsarray && tb2->ty == Tsarray)
+ if (tb1->ty == TY::Tsarray && tb2->ty == TY::Tsarray)
gcc_assert (tb1->size () == tb2->size ());
else
{
@@ -444,7 +445,7 @@ public:
this->result_ = build_struct_comparison (code, ts->sym, t1, t2);
}
- else if (tb1->ty == Taarray && tb2->ty == Taarray)
+ else if (tb1->ty == TY::Taarray && tb2->ty == TY::Taarray)
{
/* Use _aaEqual() for associative arrays. */
tree result = build_libcall (LIBCALL_AAEQUAL, e->type, 3,
@@ -518,23 +519,14 @@ public:
gcc_unreachable ();
}
- if ((tb1->ty == Tsarray || tb1->ty == Tarray)
- && (tb2->ty == Tsarray || tb2->ty == Tarray))
+ /* For static and dynamic arrays, the relational op is turned into a
+ library call. It is not lowered during codegen. */
+ if ((tb1->ty == TY::Tsarray || tb1->ty == TY::Tarray)
+ && (tb2->ty == TY::Tsarray || tb2->ty == TY::Tarray))
{
- /* For static and dynamic arrays, the result of the relational op is
- the result of the operator applied to the first non-equal element
- of the array. If two arrays compare equal, but are of different
- lengths, the shorter array compares as less than the longer. */
- Type *telem = tb1->nextOf ()->toBasetype ();
-
- tree call = build_libcall (LIBCALL_ADCMP2, Type::tint32, 3,
- d_array_convert (e->e1),
- d_array_convert (e->e2),
- build_typeinfo (e->loc, telem->arrayOf ()));
- result = build_boolop (code, call, integer_zero_node);
-
- this->result_ = d_convert (build_ctype (e->type), result);
- return;
+ error ("cannot handle comparison of type %<%s == %s%>",
+ tb1->toChars (), tb2->toChars ());
+ gcc_unreachable ();
}
/* Simple comparison. */
@@ -550,7 +542,7 @@ public:
{
tree_code code = (e->op == TOKandand) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
- if (e->e2->type->toBasetype ()->ty != Tvoid)
+ if (e->e2->type->toBasetype ()->ty != TY::Tvoid)
{
tree t1 = build_expr (e->e1);
tree t2 = build_expr (e->e2);
@@ -618,7 +610,8 @@ public:
The front-end rewrites `(p1 - p2)' into `(p1 - p2) / stride'. */
if (MinExp *me = e->e1->isMinExp ())
{
- if (me->e1->type->ty == Tpointer && me->e2->type->ty == Tpointer
+ if (me->e1->type->ty == TY::Tpointer
+ && me->e2->type->ty == TY::Tpointer
&& e->e2->op == TOKint64)
{
code = EXACT_DIV_EXPR;
@@ -678,7 +671,7 @@ public:
Type *tb2 = e->e2->type->toBasetype ();
Type *etype;
- if (tb1->ty == Tarray || tb1->ty == Tsarray)
+ if (tb1->ty == TY::Tarray || tb1->ty == TY::Tsarray)
etype = tb1->nextOf ();
else
etype = tb2->nextOf ();
@@ -839,13 +832,13 @@ public:
tree ptr = d_save_expr (build_address (lhs));
tree result = NULL_TREE;
- if (tb1->ty == Tarray && tb2->ty == Tdchar
- && (etype->ty == Tchar || etype->ty == Twchar))
+ if (tb1->ty == TY::Tarray && tb2->ty == TY::Tdchar
+ && (etype->ty == TY::Tchar || etype->ty == TY::Twchar))
{
/* Append a dchar to a char[] or wchar[]:
The assignment is handled by the D run-time library, so only
need to call `_d_arrayappend[cw]d(&e1, e2)' */
- libcall_fn libcall = (etype->ty == Tchar)
+ libcall_fn libcall = (etype->ty == TY::Tchar)
? LIBCALL_ARRAYAPPENDCD : LIBCALL_ARRAYAPPENDWD;
result = build_libcall (libcall, e->type, 2,
@@ -853,9 +846,9 @@ public:
}
else
{
- gcc_assert (tb1->ty == Tarray || tb2->ty == Tsarray);
+ gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray);
- if ((tb2->ty == Tarray || tb2->ty == Tsarray)
+ if ((tb2->ty == TY::Tarray || tb2->ty == TY::Tsarray)
&& same_type_p (etype, tb2->nextOf ()->toBasetype ()))
{
/* Append an array to another array:
@@ -917,23 +910,9 @@ public:
/* Look for array.length = n; */
if (e->e1->op == TOKarraylength)
{
- /* Assignment to an array's length property; resize the array. */
- ArrayLengthExp *ale = e->e1->isArrayLengthExp ();
- tree newlength = convert_expr (build_expr (e->e2), e->e2->type,
- Type::tsize_t);
- tree ptr = build_address (build_expr (ale->e1));
-
- /* Don't want the basetype for the element type. */
- Type *etype = ale->e1->type->toBasetype ()->nextOf ();
- libcall_fn libcall = etype->isZeroInit ()
- ? LIBCALL_ARRAYSETLENGTHT : LIBCALL_ARRAYSETLENGTHIT;
-
- tree result = build_libcall (libcall, ale->e1->type, 3,
- build_typeinfo (ale->loc, ale->e1->type),
- newlength, ptr);
-
- this->result_ = d_array_length (result);
- return;
+ /* This case should have been rewritten to `_d_arraysetlengthT` in the
+ semantic phase. */
+ gcc_unreachable ();
}
/* Look for array[] = n; */
@@ -947,13 +926,17 @@ public:
bool postblit = needs_postblit (etype) && lvalue_p (e->e2);
bool destructor = needs_dtor (etype);
- if (e->memset & blockAssign)
+ if (e->memset == MemorySet::blockAssign)
{
/* Set a range of elements to one value. */
- tree t1 = d_save_expr (build_expr (e->e1));
+ tree t1 = build_expr (e->e1);
tree t2 = build_expr (e->e2);
tree result;
+ /* Extract any array bounds checks from the slice expression. */
+ tree init = stabilize_expr (&t1);
+ t1 = d_save_expr (t1);
+
if ((postblit || destructor) && e->op != TOKblit)
{
libcall_fn libcall = (e->op == TOKconstruct)
@@ -962,15 +945,12 @@ public:
Type *tm = etype->unSharedOf ()->mutableOf ();
tree ti = build_typeinfo (e->loc, tm);
- tree result = build_libcall (libcall, Type::tvoid, 4,
- d_array_ptr (t1),
- build_address (t2),
- d_array_length (t1), ti);
- this->result_ = compound_expr (result, t1);
- return;
+ result = build_libcall (libcall, Type::tvoid, 4,
+ d_array_ptr (t1),
+ build_address (t2),
+ d_array_length (t1), ti);
}
-
- if (integer_zerop (t2))
+ else if (integer_zerop (t2))
{
tree size = size_mult_expr (d_array_length (t1),
size_int (etype->size ()));
@@ -980,12 +960,13 @@ public:
result = build_array_set (d_array_ptr (t1),
d_array_length (t1), t2);
+ result = compound_expr (init, result);
this->result_ = compound_expr (result, t1);
}
else
{
/* Perform a memcpy operation. */
- gcc_assert (e->e2->type->ty != Tpointer);
+ gcc_assert (e->e2->type->ty != TY::Tpointer);
if (!postblit && !destructor)
{
@@ -1056,7 +1037,7 @@ public:
}
/* Look for reference initializations. */
- if (e->memset & referenceInit)
+ if (e->memset == MemorySet::referenceInit)
{
gcc_assert (e->op == TOKconstruct || e->op == TOKblit);
gcc_assert (e->e1->op == TOKvar);
@@ -1082,7 +1063,7 @@ public:
tree_code modifycode = (e->op == TOKconstruct) ? INIT_EXPR : MODIFY_EXPR;
/* Look for struct assignment. */
- if (tb1->ty == Tstruct)
+ if (tb1->ty == TY::Tstruct)
{
tree t1 = build_expr (e->e1);
tree t2 = convert_for_assignment (build_expr (e->e2, false, true),
@@ -1136,7 +1117,7 @@ public:
}
/* Look for static array assignment. */
- if (tb1->ty == Tsarray)
+ if (tb1->ty == TY::Tsarray)
{
/* Look for array = 0. */
if (e->e2->op == TOKint64)
@@ -1148,7 +1129,7 @@ public:
}
Type *etype = tb1->nextOf ();
- gcc_assert (e->e2->type->toBasetype ()->ty == Tsarray);
+ gcc_assert (e->e2->type->toBasetype ()->ty == TY::Tsarray);
/* Determine if we need to run postblit. */
bool postblit = needs_postblit (etype);
@@ -1171,7 +1152,8 @@ public:
return;
}
- Type *arrtype = (e->type->ty == Tsarray) ? etype->arrayOf () : e->type;
+ Type *arrtype = (e->type->ty == TY::Tsarray)
+ ? etype->arrayOf () : e->type;
tree result;
if (e->op == TOKconstruct)
@@ -1198,7 +1180,7 @@ public:
}
/* Cast the libcall result back to a static array. */
- if (e->type->ty == Tsarray)
+ if (e->type->ty == TY::Tsarray)
result = indirect_ref (build_ctype (e->type),
d_array_ptr (result));
@@ -1243,7 +1225,7 @@ public:
{
Type *tb1 = e->e1->type->toBasetype ();
- if (tb1->ty == Taarray)
+ if (tb1->ty == TY::Taarray)
{
/* Get the key for the associative array. */
Type *tkey = tb1->isTypeAArray ()->index->toBasetype ();
@@ -1289,7 +1271,7 @@ public:
tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
tree length = NULL_TREE;
- if (tb1->ty != Tpointer)
+ if (tb1->ty != TY::Tpointer)
length = get_array_length (array, tb1);
else
gcc_assert (e->lengthVar == NULL);
@@ -1304,7 +1286,7 @@ public:
/* If it's a static array and the index is constant, the front end has
already checked the bounds. */
- if (tb1->ty != Tpointer)
+ if (tb1->ty != TY::Tpointer)
index = build_bounds_index_condition (e, index, length);
/* Index the .ptr. */
@@ -1330,7 +1312,7 @@ public:
void visit (ArrayLengthExp *e)
{
- if (e->e1->type->toBasetype ()->ty == Tarray)
+ if (e->e1->type->toBasetype ()->ty == TY::Tarray)
this->result_ = d_array_length (build_expr (e->e1));
else
{
@@ -1364,13 +1346,13 @@ public:
{
Type *tb = e->type->toBasetype ();
Type *tb1 = e->e1->type->toBasetype ();
- gcc_assert (tb->ty == Tarray || tb->ty == Tsarray);
+ gcc_assert (tb->ty == TY::Tarray || tb->ty == TY::Tsarray);
/* Use convert-to-dynamic-array code if possible. */
if (!e->lwr)
{
tree result = build_expr (e->e1);
- if (e->e1->type->toBasetype ()->ty == Tsarray)
+ if (e->e1->type->toBasetype ()->ty == TY::Tsarray)
result = convert_expr (result, e->e1->type, e->type);
this->result_ = result;
@@ -1386,7 +1368,7 @@ public:
/* Our array is already a SAVE_EXPR if necessary, so we don't make length
a SAVE_EXPR which is, at most, a COMPONENT_REF on top of array. */
- if (tb1->ty != Tpointer)
+ if (tb1->ty != TY::Tpointer)
length = get_array_length (array, tb1);
else
gcc_assert (e->lengthVar == NULL);
@@ -1415,13 +1397,13 @@ public:
/* Nothing more to do for static arrays, their bounds checking has been
done at compile-time. */
- if (tb->ty == Tsarray)
+ if (tb->ty == TY::Tsarray)
{
this->result_ = indirect_ref (build_ctype (e->type), ptr);
return;
}
else
- gcc_assert (tb->ty == Tarray);
+ gcc_assert (tb->ty == TY::Tarray);
/* Generate bounds checking code. */
tree newlength = build_bounds_slice_condition (e, lwr_tree, upr_tree,
@@ -1440,7 +1422,7 @@ public:
tree result = build_expr (e->e1, this->constp_, this->literalp_);
/* Just evaluate e1 if it has any side effects. */
- if (tbtype->ty == Tvoid)
+ if (tbtype->ty == TY::Tvoid)
this->result_ = build_nop (build_ctype (tbtype), result);
else
this->result_ = convert_for_rvalue (result, ebtype, tbtype);
@@ -1453,7 +1435,7 @@ public:
tree t1 = build_expr (e->e1);
Type *tb1 = e->e1->type->toBasetype ();
- if (tb1->ty == Tclass)
+ if (tb1->ty == TY::Tclass)
{
/* For class object references, if there is a destructor for that class,
the destructor is called for the object instance. */
@@ -1480,7 +1462,7 @@ public:
t1 = build_address (t1);
this->result_ = build_libcall (libcall, Type::tvoid, 1, t1);
}
- else if (tb1->ty == Tarray)
+ else if (tb1->ty == TY::Tarray)
{
/* For dynamic arrays, the garbage collector is called to immediately
release the memory. */
@@ -1498,7 +1480,7 @@ public:
this->result_ = build_libcall (LIBCALL_DELARRAYT, Type::tvoid, 2,
build_address (t1), ti);
}
- else if (tb1->ty == Tpointer)
+ else if (tb1->ty == TY::Tpointer)
{
/* For pointers to a struct instance, if the struct has overloaded
operator delete, then that operator is called. */
@@ -1533,7 +1515,7 @@ public:
void visit (RemoveExp *e)
{
/* Check that the array is actually an associative array. */
- if (e->e1->type->toBasetype ()->ty == Taarray)
+ if (e->e1->type->toBasetype ()->ty == TY::Taarray)
{
Type *tb = e->e1->type->toBasetype ();
Type *tkey = tb->isTypeAArray ()->index->toBasetype ();
@@ -1569,7 +1551,7 @@ public:
void visit (ComExp *e)
{
TY ty1 = e->e1->type->toBasetype ()->ty;
- gcc_assert (ty1 != Tarray && ty1 != Tsarray);
+ gcc_assert (ty1 != TY::Tarray && ty1 != TY::Tsarray);
this->result_ = fold_build1 (BIT_NOT_EXPR, build_ctype (e->type),
build_expr (e->e1));
@@ -1580,7 +1562,7 @@ public:
void visit (NegExp *e)
{
TY ty1 = e->e1->type->toBasetype ()->ty;
- gcc_assert (ty1 != Tarray && ty1 != Tsarray);
+ gcc_assert (ty1 != TY::Tarray && ty1 != TY::Tsarray);
tree type = build_ctype (e->type);
tree expr = build_expr (e->e1);
@@ -1630,7 +1612,7 @@ public:
/* Produce better code by converting *(#record + n) to
COMPONENT_REFERENCE. Otherwise, the variable will always be
allocated in memory because its address is taken. */
- if (tnext && tnext->ty == Tstruct)
+ if (tnext && tnext->ty == TY::Tstruct)
{
StructDeclaration *sd = tnext->isTypeStruct ()->sym;
@@ -1716,7 +1698,7 @@ public:
gcc_assert (var->isFuncDeclaration () && !var->needThis ());
}
- if (e1b->op == TOKdotvar && tb->ty != Tdelegate)
+ if (e1b->op == TOKdotvar && tb->ty != TY::Tdelegate)
{
DotVarExp *dve = e1b->isDotVarExp ();
@@ -1775,7 +1757,7 @@ public:
/* C++ constructors return void, even though front-end semantic
treats them as implicitly returning `this'. Set returnvalue
to override the result of this expression. */
- if (fd->isCtorDeclaration () && fd->linkage == LINKcpp)
+ if (fd->isCtorDeclaration () && fd->linkage == LINK::cpp)
{
thisexp = d_save_expr (thisexp);
returnvalue = thisexp;
@@ -1805,7 +1787,7 @@ public:
extract_from_method_call (callee, callee, object);
}
- else if (tb->ty == Tdelegate)
+ else if (tb->ty == TY::Tdelegate)
{
/* Delegate call, extract .object and .funcptr from var. */
callee = d_save_expr (callee);
@@ -1850,7 +1832,7 @@ public:
if (returnvalue != NULL_TREE)
exp = compound_expr (exp, returnvalue);
- if (tf->isref)
+ if (tf->isref ())
exp = build_deref (exp);
/* Some library calls are defined to return a generic type.
@@ -1888,7 +1870,7 @@ public:
tree fndecl;
tree object;
- if (e->func->isNested ())
+ if (e->func->isNested () && !e->func->isThis ())
{
if (e->e1->op == TOKnull)
object = build_expr (e->e1);
@@ -1909,12 +1891,12 @@ public:
object = build_expr (e->e1);
/* Want reference to `this' object. */
- if (e->e1->type->ty != Tclass && e->e1->type->ty != Tpointer)
+ if (e->e1->type->ty != TY::Tclass && e->e1->type->ty != TY::Tpointer)
object = build_address (object);
/* Object reference could be the outer `this' field of a class or
closure of type `void*'. Cast it to the right type. */
- if (e->e1->type->ty == Tclass)
+ if (e->e1->type->ty == TY::Tclass)
object = d_convert (build_ctype (e->e1->type), object);
fndecl = get_symbol_decl (e->func);
@@ -1958,7 +1940,7 @@ public:
{
tree object = build_expr (e->e1);
- if (e->e1->type->toBasetype ()->ty != Tstruct)
+ if (e->e1->type->toBasetype ()->ty != TY::Tstruct)
object = build_deref (object);
this->result_ = component_ref (object, get_symbol_decl (vd));
@@ -2005,7 +1987,7 @@ public:
{
/* If the condition is a D class or struct object with an invariant,
call it if the condition result is true. */
- if (tb1->ty == Tclass)
+ if (tb1->ty == TY::Tclass)
{
ClassDeclaration *cd = tb1->isClassHandle ();
if (!cd->isInterfaceDeclaration () && !cd->isCPPclass ())
@@ -2015,7 +1997,8 @@ public:
Type::tvoid, 1, arg);
}
}
- else if (tb1->ty == Tpointer && tb1->nextOf ()->ty == Tstruct)
+ else if (tb1->ty == TY::Tpointer
+ && tb1->nextOf ()->ty == TY::Tstruct)
{
StructDeclaration *sd = tb1->nextOf ()->isTypeStruct ()->sym;
if (sd->inv != NULL)
@@ -2093,7 +2076,7 @@ public:
else if (Expression *tid = isExpression (e->obj))
{
Type *type = tid->type->toBasetype ();
- assert (type->ty == Tclass);
+ assert (type->ty == TY::Tclass);
/* Generate **classptr to get the classinfo. */
tree ci = build_expr (tid);
@@ -2117,7 +2100,7 @@ public:
Type *ftype = e->type->toBasetype ();
/* This check is for lambda's, remove `vthis' as function isn't nested. */
- if (e->fd->tok == TOKreserved && ftype->ty == Tpointer)
+ if (e->fd->tok == TOKreserved && ftype->ty == TY::Tpointer)
{
e->fd->tok = TOKfunction;
e->fd->vthis = NULL;
@@ -2226,7 +2209,7 @@ public:
tree init = NULL_TREE;
if (var && (var->isConst () || var->isImmutable ())
- && e->type->toBasetype ()->ty != Tsarray && var->_init)
+ && e->type->toBasetype ()->ty != TY::Tsarray && var->_init)
{
if (var->inuse)
error_at (make_location_t (e->loc), "recursive reference %qs",
@@ -2279,7 +2262,7 @@ public:
result = get_decl_tree (fd->vthis);
}
- if (e->type->ty == Tstruct)
+ if (e->type->ty == TY::Tstruct)
result = build_deref (result);
this->result_ = result;
@@ -2293,10 +2276,7 @@ public:
Type *tb = e->type->toBasetype ();
tree result;
- if (e->allocator)
- gcc_assert (e->newargs);
-
- if (tb->ty == Tclass)
+ if (tb->ty == TY::Tclass)
{
/* Allocating a new class. */
tb = e->newtype->toBasetype ();
@@ -2315,20 +2295,13 @@ public:
new_call = build_nop (type, build_address (var));
setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
}
- else if (e->allocator)
- {
- /* Call class allocator, and copy the initializer into memory. */
- new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs);
- new_call = d_save_expr (new_call);
- new_call = build_nop (type, new_call);
- setup_exp = modify_expr (build_deref (new_call),
- aggregate_initializer_decl (cd));
- }
else
{
/* Generate: _d_newclass() */
tree arg = build_address (get_classinfo_decl (cd));
- new_call = build_libcall (LIBCALL_NEWCLASS, tb, 1, arg);
+ libcall_fn libcall = (global.params.ehnogc && e->thrownew)
+ ? LIBCALL_NEWTHROW : LIBCALL_NEWCLASS;
+ new_call = build_libcall (libcall, tb, 1, arg);
}
/* Set the context pointer for nested classes. */
@@ -2340,13 +2313,15 @@ public:
if (e->thisexp)
{
ClassDeclaration *tcd = e->thisexp->type->isClassHandle ();
- Dsymbol *outer = cd->toParent2 ();
- int offset = 0;
+ /* The class or function we're nested in. */
+ Dsymbol *outer = cd->toParentLocal ();
value = build_expr (e->thisexp);
+
if (outer != tcd)
{
ClassDeclaration *ocd = outer->isClassDeclaration ();
+ int offset = 0;
gcc_assert (ocd->isBaseOf (tcd, &offset));
/* Could just add offset... */
value = convert_expr (value, e->thisexp->type, ocd->type);
@@ -2375,7 +2350,8 @@ public:
if (e->argprefix)
result = compound_expr (build_expr (e->argprefix), result);
}
- else if (tb->ty == Tpointer && tb->nextOf ()->toBasetype ()->ty == Tstruct)
+ else if (tb->ty == TY::Tpointer
+ && tb->nextOf ()->toBasetype ()->ty == TY::Tstruct)
{
/* Allocating memory for a new struct. */
Type *htype = e->newtype->toBasetype ();
@@ -2393,20 +2369,11 @@ public:
return;
}
- if (e->allocator)
- {
- /* Call struct allocator. */
- new_call = d_build_call_expr (e->allocator, NULL_TREE, e->newargs);
- new_call = build_nop (build_ctype (tb), new_call);
- }
- else
- {
- /* Generate: _d_newitemT() */
- libcall_fn libcall = htype->isZeroInit ()
- ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
- tree arg = build_typeinfo (e->loc, e->newtype);
- new_call = build_libcall (libcall, tb, 1, arg);
- }
+ /* Generate: _d_newitemT() */
+ libcall_fn libcall = htype->isZeroInit ()
+ ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
+ tree arg = build_typeinfo (e->loc, e->newtype);
+ new_call = build_libcall (libcall, tb, 1, arg);
if (e->member || !e->arguments)
{
@@ -2449,13 +2416,12 @@ public:
if (e->argprefix)
result = compound_expr (build_expr (e->argprefix), result);
}
- else if (tb->ty == Tarray)
+ else if (tb->ty == TY::Tarray)
{
/* Allocating memory for a new D array. */
tb = e->newtype->toBasetype ();
TypeDArray *tarray = tb->isTypeDArray ();
- gcc_assert (!e->allocator);
gcc_assert (e->arguments && e->arguments->length >= 1);
if (e->arguments->length == 1)
@@ -2492,7 +2458,7 @@ public:
Expression *arg = (*e->arguments)[i];
CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_expr (arg));
- gcc_assert (telem->ty == Tarray);
+ gcc_assert (telem->ty == TY::Tarray);
telem = telem->toBasetype ()->nextOf ();
gcc_assert (telem);
}
@@ -2517,7 +2483,7 @@ public:
if (e->argprefix)
result = compound_expr (build_expr (e->argprefix), result);
}
- else if (tb->ty == Tpointer)
+ else if (tb->ty == TY::Tpointer)
{
/* Allocating memory for a new pointer. */
TypePointer *tpointer = tb->isTypePointer ();
@@ -2576,15 +2542,15 @@ public:
switch (e->type->toBasetype ()->ty)
{
- case Tcomplex32:
+ case TY::Tcomplex32:
tnext = (TypeBasic *) Type::tfloat32;
break;
- case Tcomplex64:
+ case TY::Tcomplex64:
tnext = (TypeBasic *) Type::tfloat64;
break;
- case Tcomplex80:
+ case TY::Tcomplex80:
tnext = (TypeBasic *) Type::tfloat80;
break;
@@ -2605,7 +2571,7 @@ public:
Type *tb = e->type->toBasetype ();
tree type = build_ctype (e->type);
- if (tb->ty == Tsarray)
+ if (tb->ty == TY::Tsarray)
{
/* Turn the string into a constructor for the static array. */
vec <constructor_elt, va_gc> *elms = NULL;
@@ -2635,7 +2601,7 @@ public:
TREE_TYPE (value) = make_array_type (tb->nextOf (), length + 1);
value = build_address (value);
- if (tb->ty == Tarray)
+ if (tb->ty == TY::Tarray)
value = d_array_value (type, size_int (e->len), value);
TREE_CONSTANT (value) = 1;
@@ -2674,15 +2640,16 @@ public:
Type *tb = e->type->toBasetype ();
/* Implicitly convert void[n] to ubyte[n]. */
- if (tb->ty == Tsarray && tb->nextOf ()->toBasetype ()->ty == Tvoid)
+ if (tb->ty == TY::Tsarray && tb->nextOf ()->toBasetype ()->ty == TY::Tvoid)
tb = Type::tuns8->sarrayOf (tb->isTypeSArray ()->dim->toUInteger ());
- gcc_assert (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tpointer);
+ gcc_assert (tb->ty == TY::Tarray || tb->ty == TY::Tsarray
+ || tb->ty == TY::Tpointer);
/* Handle empty array literals. */
if (e->elements->length == 0)
{
- if (tb->ty == Tarray)
+ if (tb->ty == TY::Tarray)
this->result_ = d_array_value (build_ctype (e->type),
size_int (0), null_pointer_node);
else
@@ -2732,15 +2699,15 @@ public:
tree type = build_ctype (e->type);
/* Nothing else to do for static arrays. */
- if (tb->ty == Tsarray || this->constp_)
+ if (tb->ty == TY::Tsarray || this->constp_)
{
/* Can't take the address of the constructor, so create an anonymous
static symbol, and then refer to it. */
- if (tb->ty != Tsarray)
+ if (tb->ty != TY::Tsarray)
{
tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor, "A");
ctor = build_address (decl);
- if (tb->ty == Tarray)
+ if (tb->ty == TY::Tarray)
ctor = d_array_value (type, size_int (e->elements->length), ctor);
d_pushdecl (decl);
@@ -2789,7 +2756,7 @@ public:
/* Return the array pointed to by MEM. */
result = compound_expr (result, mem);
- if (tb->ty == Tarray)
+ if (tb->ty == TY::Tarray)
result = d_array_value (type, size_int (e->elements->length), result);
this->result_ = compound_expr (saved_elems, result);
@@ -2882,7 +2849,7 @@ public:
gcc_assert (e->elements->length <= e->sd->fields.length);
Type *tb = e->type->toBasetype ();
- gcc_assert (tb->ty == Tstruct);
+ gcc_assert (tb->ty == TY::Tstruct);
for (size_t i = 0; i < e->elements->length; i++)
{
@@ -2895,7 +2862,7 @@ public:
Type *ftype = field->type->toBasetype ();
tree value = NULL_TREE;
- if (ftype->ty == Tsarray && !same_type_p (type, ftype))
+ if (ftype->ty == TY::Tsarray && !same_type_p (type, ftype))
{
/* Initialize a static array with a single element. */
tree elem = build_expr (exp, this->constp_, true);
@@ -3126,7 +3093,7 @@ build_return_dtor (Expression *e, Type *type, TypeFunction *tf)
tree result = build_expr (e);
/* Convert for initializing the DECL_RESULT. */
- if (tf->isref)
+ if (tf->isref ())
{
/* If we are returning a reference, take the address. */
result = convert_expr (result, e->type, type);
@@ -68,7 +68,7 @@ public:
void visit (Module *m)
{
Loc loc = (m->md != NULL) ? m->md->loc
- : Loc (m->srcfile->toChars (), 1, 0);
+ : Loc (m->srcfile.toChars (), 1, 0);
m->isym = build_decl (make_location_t (loc), NAMESPACE_DECL,
get_identifier (m->toPrettyChars ()),
@@ -130,11 +130,11 @@ public:
/* Type imports should really be part of their own visit method. */
if (type != NULL)
{
- if (type->ty == Tenum)
+ if (type->ty == TY::Tenum)
dsym = type->isTypeEnum ()->sym;
- else if (type->ty == Tstruct)
+ else if (type->ty == TY::Tstruct)
dsym = type->isTypeStruct ()->sym;
- else if (type->ty == Tclass)
+ else if (type->ty == TY::Tclass)
dsym = type->isTypeClass ()->sym;
}
}
@@ -20,9 +20,9 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "dmd/declaration.h"
+#include "dmd/expression.h"
#include "dmd/identifier.h"
#include "dmd/mangle.h"
-#include "dmd/mangle.h"
#include "dmd/module.h"
#include "dmd/template.h"
@@ -76,12 +76,12 @@ static const intrinsic_decl intrinsic_decls[] =
void
maybe_set_intrinsic (FuncDeclaration *decl)
{
- if (!decl->ident || decl->builtin != BUILTINunknown)
+ if (!decl->ident || decl->builtin != BUILTIN::unknown)
return;
/* The builtin flag is updated only if we can evaluate the intrinsic
at compile-time. Such as the math or bitop intrinsics. */
- decl->builtin = BUILTINunimp;
+ decl->builtin = BUILTIN::unimp;
/* Check if it's a compiler intrinsic. We only require that any
internally recognised intrinsics are declared in a module with
@@ -177,12 +177,12 @@ maybe_set_intrinsic (FuncDeclaration *decl)
built-in function. It could be `int pow(int, int)'. */
tree rettype = TREE_TYPE (TREE_TYPE (decl->csym));
if (mathfn_built_in (rettype, BUILT_IN_POW) != NULL_TREE)
- decl->builtin = BUILTINgcc;
+ decl->builtin = BUILTIN::gcc;
break;
}
default:
- decl->builtin = BUILTINgcc;
+ decl->builtin = BUILTIN::gcc;
break;
}
@@ -77,12 +77,12 @@ DEF_D_BUILTIN (INTRINSIC_POPCNT32, BUILT_IN_NONE, "popcnt", "core.bitop",
DEF_D_BUILTIN (INTRINSIC_POPCNT64, BUILT_IN_NONE, "popcnt", "core.bitop",
"FNaNbNiNfmZi")
-DEF_D_BUILTIN (INTRINSIC_ROL, BUILT_IN_NONE, "rol", "core.bitop", "FNaI1TkZI1T")
+DEF_D_BUILTIN (INTRINSIC_ROL, BUILT_IN_NONE, "rol", "core.bitop", "FNa@1TkZ@1T")
DEF_D_BUILTIN (INTRINSIC_ROL_TIARG, BUILT_IN_NONE, "rol", "core.bitop",
- "FNaI1TZI1T")
-DEF_D_BUILTIN (INTRINSIC_ROR, BUILT_IN_NONE, "ror", "core.bitop", "FNaI1TkZI1T")
+ "FNa@1TZ@1T")
+DEF_D_BUILTIN (INTRINSIC_ROR, BUILT_IN_NONE, "ror", "core.bitop", "FNa@1TkZ@1T")
DEF_D_BUILTIN (INTRINSIC_ROR_TIARG, BUILT_IN_NONE, "ror", "core.bitop",
- "FNaI1TZI1T")
+ "FNa@1TZ@1T")
/* core.volatile intrinsics. */
@@ -183,75 +183,74 @@ DEF_D_BUILTIN (INTRINSIC_SQRT, BUILT_IN_SQRT, "sqrt", "core.math",
DEF_D_BUILTIN (INTRINSIC_SQRTL, BUILT_IN_SQRTL, "sqrt", "core.math",
"FNaNbNiNfeZe")
DEF_D_BUILTIN (INTRINSIC_TOPRECF, BUILT_IN_NONE, "toPrec", "core.math",
- "FfZI1T")
-DEF_D_BUILTIN (INTRINSIC_TOPREC, BUILT_IN_NONE, "toPrec", "core.math", "FdZI1T")
+ "FfZ@1T")
+DEF_D_BUILTIN (INTRINSIC_TOPREC, BUILT_IN_NONE, "toPrec", "core.math", "FdZ@1T")
DEF_D_BUILTIN (INTRINSIC_TOPRECL, BUILT_IN_NONE, "toPrec", "core.math",
- "FeZI1T")
+ "FeZ@1T")
/* std.math intrinsics. */
-DEF_CTFE_BUILTIN (INTRINSIC_TAN, BUILT_IN_TANL, "tan", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_TAN, BUILT_IN_TANL, "tan", "std.math.trigonometry",
"FNaNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_ISNAN, BUILT_IN_ISNAN, "isNaN", "std.math",
- "FNaNbNiNeI1XZb")
+
+DEF_CTFE_BUILTIN (INTRINSIC_ISNAN, BUILT_IN_ISNAN, "isNaN", "std.math.traits",
+ "FNaNbNiNe@1XZb")
DEF_CTFE_BUILTIN (INTRINSIC_ISINFINITY, BUILT_IN_ISINF, "isInfinity",
- "std.math", "FNaNbNiNeI1XZb")
-DEF_CTFE_BUILTIN (INTRINSIC_ISFINITE, BUILT_IN_ISFINITE, "isFinite", "std.math",
- "FNaNbNiNeI1XZb")
+ "std.math.traits", "FNaNbNiNe@1XZb")
+DEF_CTFE_BUILTIN (INTRINSIC_ISFINITE, BUILT_IN_ISFINITE, "isFinite",
+ "std.math.traits", "FNaNbNiNe@1XZb")
+DEF_CTFE_BUILTIN (INTRINSIC_COPYSIGN, BUILT_IN_NONE, "copysign",
+ "std.math.traits", "FNaNbNiNe@1R@1XZ@1R")
+DEF_CTFE_BUILTIN (INTRINSIC_COPYSIGNI, BUILT_IN_NONE, "copysign",
+ "std.math.traits", "FNaNbNiNe@1X@1RZ@1R")
-DEF_CTFE_BUILTIN (INTRINSIC_EXP, BUILT_IN_EXPL, "exp", "std.math",
- "FNaNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_EXPM1, BUILT_IN_EXPM1L, "expm1", "std.math",
- "FNaNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_EXP2, BUILT_IN_EXP2L, "exp2", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_EXP, BUILT_IN_EXPL, "exp", "std.math.exponential",
"FNaNbNiNeeZe")
-
-DEF_CTFE_BUILTIN (INTRINSIC_LOG, BUILT_IN_LOGL, "log", "std.math",
- "FNaNbNiNfeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_LOG2, BUILT_IN_LOG2L, "log2", "std.math",
- "FNaNbNiNfeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_LOG10, BUILT_IN_LOG10L, "log10", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_EXPM1, BUILT_IN_EXPM1L, "expm1",
+ "std.math.exponential", "FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_EXP2, BUILT_IN_EXP2L, "exp2",
+ "std.math.exponential", "FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_LOG, BUILT_IN_LOGL, "log", "std.math.exponential",
"FNaNbNiNfeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_LOG2, BUILT_IN_LOG2L, "log2",
+ "std.math.exponential", "FNaNbNiNfeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_LOG10, BUILT_IN_LOG10L, "log10",
+ "std.math.exponential", "FNaNbNiNfeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_POW, BUILT_IN_NONE, "pow", "std.math.exponential",
+ "FNaNbNiNe@1F@1GZ@")
-DEF_CTFE_BUILTIN (INTRINSIC_ROUND, BUILT_IN_ROUNDL, "round", "std.math",
- "FNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_FLOORF, BUILT_IN_FLOORF, "floor", "std.math",
- "FNaNbNiNefZf")
-DEF_CTFE_BUILTIN (INTRINSIC_FLOOR, BUILT_IN_FLOOR, "floor", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_ROUND, BUILT_IN_ROUNDL, "round",
+ "std.math.rounding", "FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_FLOORF, BUILT_IN_FLOORF, "floor",
+ "std.math.rounding", "FNaNbNiNefZf")
+DEF_CTFE_BUILTIN (INTRINSIC_FLOOR, BUILT_IN_FLOOR, "floor", "std.math.rounding",
"FNaNbNiNedZd")
-DEF_CTFE_BUILTIN (INTRINSIC_FLOORL, BUILT_IN_FLOORL, "floor", "std.math",
- "FNaNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_CEILF, BUILT_IN_CEILF, "ceil", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_FLOORL, BUILT_IN_FLOORL, "floor",
+ "std.math.rounding", "FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_CEILF, BUILT_IN_CEILF, "ceil", "std.math.rounding",
"FNaNbNiNefZf")
-DEF_CTFE_BUILTIN (INTRINSIC_CEIL, BUILT_IN_CEIL, "ceil", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_CEIL, BUILT_IN_CEIL, "ceil", "std.math.rounding",
"FNaNbNiNedZd")
-DEF_CTFE_BUILTIN (INTRINSIC_CEILL, BUILT_IN_CEILL, "ceil", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_CEILL, BUILT_IN_CEILL, "ceil", "std.math.rounding",
"FNaNbNiNeeZe")
+DEF_CTFE_BUILTIN (INTRINSIC_TRUNC, BUILT_IN_TRUNCL, "trunc",
+ "std.math.rounding", "FNaNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_TRUNC, BUILT_IN_TRUNCL, "trunc", "std.math",
- "FNbNiNeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_FMIN, BUILT_IN_FMINL, "fmin", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_FMIN, BUILT_IN_FMINL, "fmin", "std.math.operations",
"FNaNbNiNfeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_FMAX, BUILT_IN_FMAXL, "fmax", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_FMAX, BUILT_IN_FMAXL, "fmax", "std.math.operations",
"FNaNbNiNfeeZe")
-DEF_CTFE_BUILTIN (INTRINSIC_COPYSIGN, BUILT_IN_NONE, "copysign", "std.math",
- "FNaNbNiNeI1RI1XZI1R")
-DEF_CTFE_BUILTIN (INTRINSIC_COPYSIGNI, BUILT_IN_NONE, "copysign", "std.math",
- "FNaNbNiNeI1XI1RZI1R")
-
-DEF_CTFE_BUILTIN (INTRINSIC_POW, BUILT_IN_NONE, "pow", "std.math",
- "FNaNbNiNeI1FI1GZ@")
-DEF_CTFE_BUILTIN (INTRINSIC_FMA, BUILT_IN_FMAL, "fma", "std.math",
+DEF_CTFE_BUILTIN (INTRINSIC_FMA, BUILT_IN_FMAL, "fma", "std.math.operations",
"FNaNbNiNfeeeZe")
/* core.stdc.stdarg intrinsics. */
DEF_D_BUILTIN (INTRINSIC_VA_ARG, BUILT_IN_NONE, "va_arg", "core.stdc.stdarg",
- "FKI7va_listKI1TZv")
+ "FK@7va_listK@1TZv")
DEF_D_BUILTIN (INTRINSIC_C_VA_ARG, BUILT_IN_NONE, "va_arg", "core.stdc.stdarg",
- "FKI7va_listZI1T")
+ "FK@7va_listZ@1T")
DEF_D_BUILTIN (INTRINSIC_VASTART, BUILT_IN_NONE, "va_start", "core.stdc.stdarg",
- "FJI7va_listKI1TZv")
+ "FJ@7va_listK@1TZv")
#undef DEF_D_BUILTIN
#undef DEF_CTFE_BUILTIN
@@ -209,6 +209,40 @@ fbuiltin
D Var(flag_no_builtin, 0)
; Documented in C
+fcheck=assert
+D Alias(fassert)
+
+fcheck=bounds
+D Alias(fbounds-check)
+
+fcheck=in
+D Alias(fpreconditions)
+
+fcheck=invariant
+D Alias(finvariants)
+
+fcheck=out
+D Alias(fpostconditions)
+
+fcheck=switch
+D Alias(fswitch-errors)
+
+fcheckaction=
+D Joined RejectNegative Enum(check_action) Var(flag_check_action)
+-fcheckaction=[throw,halt,context] Behavior on contract failure.
+
+Enum
+Name(check_action) Type(int) UnknownError(unknown checkaction setting %qs)
+
+EnumValue
+Enum(check_action) String(throw) Value(0)
+
+EnumValue
+Enum(check_action) String(halt) Value(1)
+
+EnumValue
+Enum(check_action) String(context) Value(2)
+
fdebug
D
Compile in debug code.
@@ -237,10 +271,43 @@ fdruntime
D
Assume that standard D runtime libraries and \"D main\" exist.
+fdump-c++-spec-verbose
+D RejectNegative
+Add comments for ignored declarations in the generated C++ header.
+
+fdump-c++-spec=
+D RejectNegative Joined
+-fdump-cxx-spec=<filename> Write all declarations as C++ code to <file>.
+
fdump-d-original
D
Display the frontend AST after parsing and semantic passes.
+fextern-std=
+D Joined RejectNegative Enum(extern_stdcpp) Var(flag_extern_stdcpp)
+-fextern-std=<standard> Set C++ name mangling compatibility with <standard>.
+
+Enum
+Name(extern_stdcpp) Type(int) UnknownError(unknown C++ standard %qs)
+
+EnumValue
+Enum(extern_stdcpp) String(c++98) Value(199711)
+
+EnumValue
+Enum(extern_stdcpp) String(c++03) Value(199711)
+
+EnumValue
+Enum(extern_stdcpp) String(c++11) Value(201103)
+
+EnumValue
+Enum(extern_stdcpp) String(c++14) Value(201402)
+
+EnumValue
+Enum(extern_stdcpp) String(c++17) Value(201703)
+
+EnumValue
+Enum(extern_stdcpp) String(c++20) Value(202002)
+
fignore-unknown-pragmas
D
Ignore unsupported pragmas.
@@ -273,33 +340,97 @@ fpreconditions
D Var(flag_preconditions)
Generate code for precondition contracts.
+fpreview=all
+D RejectNegative
+Turn on all upcoming D language features.
+
+fpreview=dip1000
+D RejectNegative
+Implement DIP1000: Scoped pointers.
+
+fpreview=dip1008
+D RejectNegative
+Implement DIP1008: Allow exceptions in @nogc code.
+
+fpreview=dip1021
+D RejectNegative
+Implement DIP1021: Mutable function arguments.
+
+fpreview=dip25
+D RejectNegative
+Implement DIP25: Sealed references.
+
+fpreview=dtorfields
+D RejectNegative
+Destruct fields of partially constructed objects.
+
+fpreview=fieldwise
+D RejectNegative
+Use field-wise comparisons for struct equality.
+
+fpreview=fixaliasthis
+D RejectNegative
+When a symbol is resolved, check alias this scope before going to upper scopes.
+
+fpreview=in
+D RejectNegative
+Implement 'in' parameters to mean scope const.
+
+fpreview=inclusiveincontracts
+D RejectNegative
+Implement 'in' contracts of overridden methods to be a superset of parent contract.
+
+fpreview=intpromote
+D RejectNegative
+Use C-style integral promotion for unary '+', '-' and '~'.
+
+fpreview=nosharedaccess
+D RejectNegative
+Disable access to shared memory objects.
+
+fpreview=rvaluerefparam
+D RejectNegative
+Enable rvalue arguments to ref parameters.
+
+fpreview=shortenedmethods
+D RejectNegative
+Allow use of '=>' for methods and top-level functions in addition to lambdas.
+
frelease
D
Compile release version.
+frevert=all
+D RejectNegative
+Turn off all revertable D language features.
+
+frevert=dip25
+D RejectNegative
+Revert DIP25: Sealed references.
+
+frevert=dtorfields
+D RejectNegative
+Don't destruct fields of partially constructed objects.
+
+frevert=markdown
+D RejectNegative
+Disable Markdown replacements in Ddoc.
+
frtti
D
; Documented in C
+fsave-mixins=
+D Joined RejectNegative
+-fsave-mixins=<filename> Expand and save mixins to file specified by <filename>.
+
fswitch-errors
D Var(flag_switch_errors)
Generate code for switches without a default case.
ftransition=all
D RejectNegative
-List information on all language changes.
-
-ftransition=complex
-D RejectNegative
-List all usages of complex or imaginary types.
-
-ftransition=dip1000
-D RejectNegative
-Implement DIP1000: Scoped pointers (experimental).
-
-ftransition=dip25
-D RejectNegative
-Implement DIP25: Sealed references (experimental).
+List information on all D language transitions.
ftransition=field
D RejectNegative
@@ -309,10 +440,18 @@ ftransition=nogc
D RejectNegative
List all hidden GC allocations.
+ftransition=templates
+D RejectNegative
+List statistics on template instantiations.
+
ftransition=tls
D RejectNegative
List all variables going into thread local storage.
+ftransition=vmarkdown
+D RejectNegative
+List instances of Markdown replacements in Ddoc.
+
funittest
D
Compile in unittest code.
@@ -125,7 +125,7 @@ static Module *current_module_decl;
by both module initialization and dso handlers. */
static FuncDeclaration *
-get_internal_fn (tree ident, const Prot &prot)
+get_internal_fn (tree ident, const Visibility &visibility)
{
Module *mod = current_module_decl;
const char *name = IDENTIFIER_POINTER (ident);
@@ -142,9 +142,9 @@ get_internal_fn (tree ident, const Prot &prot)
FuncDeclaration *fd = FuncDeclaration::genCfunc (NULL, Type::tvoid,
Identifier::idPool (name));
fd->generated = true;
- fd->loc = Loc (mod->srcfile->toChars (), 1, 0);
+ fd->loc = Loc (mod->srcfile.toChars (), 1, 0);
fd->parent = mod;
- fd->protection = prot;
+ fd->visibility = visibility;
fd->semanticRun = PASSsemantic3done;
return fd;
@@ -156,7 +156,9 @@ get_internal_fn (tree ident, const Prot &prot)
static tree
build_internal_fn (tree ident, tree expr)
{
- FuncDeclaration *fd = get_internal_fn (ident, Prot (Prot::private_));
+ Visibility visibility;
+ visibility.kind = Visibility::private_;
+ FuncDeclaration *fd = get_internal_fn (ident, visibility);
tree decl = get_symbol_decl (fd);
tree old_context = start_function (fd);
@@ -338,8 +340,9 @@ build_dso_cdtor_fn (bool ctor_p)
}
}
*/
- FuncDeclaration *fd = get_internal_fn (get_identifier (name),
- Prot (Prot::public_));
+ Visibility visibility;
+ visibility.kind = Visibility::public_;
+ FuncDeclaration *fd = get_internal_fn (get_identifier (name), visibility);
tree decl = get_symbol_decl (fd);
TREE_PUBLIC (decl) = 1;
@@ -740,7 +743,8 @@ build_module_tree (Module *decl)
/* Associate the module info symbol with a mock module. */
const char *name = concat (GDC_PREFIX ("modtest__"),
decl->ident->toChars (), NULL);
- Module *tm = Module::create (decl->arg, Identifier::idPool (name), 0, 0);
+ Module *tm = Module::create (decl->arg.ptr, Identifier::idPool (name),
+ 0, 0);
Dsymbols members;
/* Setting parent puts module in the same package as the current, to
@@ -780,9 +784,7 @@ build_module_tree (Module *decl)
/* Default behavior is to always generate module info because of templates.
Can be switched off for not compiling against runtime library. */
- if (global.params.useModuleInfo
- && Module::moduleinfo != NULL
- && decl->ident != Identifier::idPool ("__entrypoint"))
+ if (global.params.useModuleInfo && Module::moduleinfo != NULL)
{
if (mi.ctors || mi.ctorgates)
decl->sctor = build_funcs_gates_fn (get_identifier ("*__modctor"),
@@ -34,6 +34,8 @@ along with GCC; see the file COPYING3. If not see
3, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3
#define P4(T1, T2, T3, T4) \
4, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3, LCT_ ## T4
+#define P5(T1, T2, T3, T4, T5) \
+ 5, LCT_ ## T1, LCT_ ## T2, LCT_ ## T3, LCT_ ## T4, LCT_ ## T5
#define RT(T1) LCT_ ## T1
/* Used when an assert() contract fails. */
@@ -51,9 +53,15 @@ DEF_D_RUNTIME (UNITTEST_MSG, "_d_unittest_msg", RT(VOID),
/* Used when an array index outside the bounds of its range. */
DEF_D_RUNTIME (ARRAYBOUNDSP, "_d_arrayboundsp", RT(VOID),
P2(IMMUTABLE_CHARPTR, UINT), ECF_NORETURN)
+DEF_D_RUNTIME (ARRAYBOUNDS_SLICEP, "_d_arraybounds_slicep", RT(VOID),
+ P5(IMMUTABLE_CHARPTR, UINT, SIZE_T, SIZE_T, SIZE_T),
+ ECF_NORETURN)
+DEF_D_RUNTIME (ARRAYBOUNDS_INDEXP, "_d_arraybounds_indexp", RT(VOID),
+ P4(IMMUTABLE_CHARPTR, UINT, SIZE_T, SIZE_T), ECF_NORETURN)
/* Used when calling new on a class. */
DEF_D_RUNTIME (NEWCLASS, "_d_newclass", RT(OBJECT), P1(CONST_CLASSINFO), 0)
+DEF_D_RUNTIME (NEWTHROW, "_d_newThrowable", RT(OBJECT), P1(CONST_CLASSINFO), 0)
/* Used when calling delete on a class or interface. */
DEF_D_RUNTIME (DELCLASS, "_d_delclass", RT(VOID), P1(VOIDPTR), 0)
@@ -104,13 +112,6 @@ DEF_D_RUNTIME (DELARRAYT, "_d_delarray_t", RT(VOID),
arrays. Such as an array of structs or classes. */
DEF_D_RUNTIME (ADEQ2, "_adEq2", RT(INT),
P3(ARRAY_VOID, ARRAY_VOID, CONST_TYPEINFO), 0)
-DEF_D_RUNTIME (ADCMP2, "_adCmp2", RT(INT),
- P3(ARRAY_VOID, ARRAY_VOID, CONST_TYPEINFO), 0)
-
-/* Used when casting from one array type to another where the index type
- sizes differ. Such as from int[] to short[]. */
-DEF_D_RUNTIME (ARRAYCAST, "_d_arraycast", RT(ARRAY_VOID),
- P3(SIZE_T, SIZE_T, ARRAY_VOID), 0)
/* Used for (array.length = n) expressions. The `i' variant is for when the
initializer is nonzero. */
@@ -206,23 +207,10 @@ DEF_D_RUNTIME (CXA_END_CATCH, "__cxa_end_catch", RT(VOID), P0(), 0)
DEF_D_RUNTIME (INVARIANT, "_D9invariant12_d_invariantFC6ObjectZv", RT(VOID),
P1(OBJECT), 0)
-/* Used when performing a switch/cases on a string. The `u' and `d' variants
- are for UTF-16 and UTF-32 strings respectively. */
-DEF_D_RUNTIME (SWITCH_STRING, "_d_switch_string", RT(INT),
- P2(ARRAY_STRING, STRING), 0)
-DEF_D_RUNTIME (SWITCH_USTRING, "_d_switch_ustring", RT(INT),
- P2(ARRAY_WSTRING, WSTRING), 0)
-DEF_D_RUNTIME (SWITCH_DSTRING, "_d_switch_dstring", RT(INT),
- P2(ARRAY_DSTRING, DSTRING), 0)
-
-/* Used when throwing an error that a switch statement has no default case,
- and yet none of the existing cases matched. */
-DEF_D_RUNTIME (SWITCH_ERROR, "_d_switch_error", RT(VOID), P2(STRING, UINT),
- ECF_NORETURN)
-
#undef P0
#undef P1
#undef P2
#undef P3
#undef P4
+#undef P5
#undef RT
@@ -413,18 +413,6 @@ public:
else
error_at (location, "cannot %<goto%> into %<catch%> block");
}
- else if (s->isCaseStatement ())
- {
- location = make_location_t (s->loc);
- error_at (location, "case cannot be in different "
- "%<try%> block level from %<switch%>");
- }
- else if (s->isDefaultStatement ())
- {
- location = make_location_t (s->loc);
- error_at (location, "default cannot be in different "
- "%<try%> block level from %<switch%>");
- }
else
gcc_unreachable ();
}
@@ -709,7 +697,8 @@ public:
{
/* The break label may actually be some levels up.
eg: on a try/finally wrapping a loop. */
- LabelStatement *label = this->func_->searchLabel (s->ident)->statement;
+ LabelDsymbol *sym = this->func_->searchLabel (s->ident, s->loc);
+ LabelStatement *label = sym->statement;
gcc_assert (label != NULL);
Statement *stmt = label->statement->getRelatedLabeled ();
this->do_jump (this->lookup_bc_label (stmt, bc_break));
@@ -725,7 +714,8 @@ public:
{
if (s->ident)
{
- LabelStatement *label = this->func_->searchLabel (s->ident)->statement;
+ LabelDsymbol *sym = this->func_->searchLabel (s->ident, s->loc);
+ LabelStatement *label = sym->statement;
gcc_assert (label != NULL);
this->do_jump (this->lookup_bc_label (label->statement,
bc_continue));
@@ -759,7 +749,7 @@ public:
if (this->is_return_label (s->ident))
sym = this->func_->returnLabel;
else
- sym = this->func_->searchLabel (s->ident);
+ sym = this->func_->searchLabel (s->ident, s->loc);
/* If no label found, there was an error. */
tree label = this->define_label (sym->statement, sym->ident);
@@ -784,69 +774,9 @@ public:
tree condition = build_expr_dtor (s->condition);
Type *condtype = s->condition->type->toBasetype ();
- /* A switch statement on a string gets turned into a library call,
- which does a binary lookup on list of string cases. */
- if (s->condition->type->isString ())
- {
- Type *etype = condtype->nextOf ()->toBasetype ();
- libcall_fn libcall;
-
- switch (etype->ty)
- {
- case Tchar:
- libcall = LIBCALL_SWITCH_STRING;
- break;
-
- case Twchar:
- libcall = LIBCALL_SWITCH_USTRING;
- break;
-
- case Tdchar:
- libcall = LIBCALL_SWITCH_DSTRING;
- break;
-
- default:
- ::error ("switch statement value must be an array of "
- "some character type, not %s", etype->toChars ());
- gcc_unreachable ();
- }
-
- /* Apparently the backend is supposed to sort and set the indexes
- on the case array, have to change them to be usable. */
- Type *satype = condtype->sarrayOf (s->cases->length);
- vec <constructor_elt, va_gc> *elms = NULL;
-
- s->cases->sort ();
-
- for (size_t i = 0; i < s->cases->length; i++)
- {
- CaseStatement *cs = (*s->cases)[i];
- cs->index = i;
-
- if (cs->exp->op != TOKstring)
- s->error ("case '%s' is not a string", cs->exp->toChars ());
- else
- {
- tree exp = build_expr (cs->exp, true);
- CONSTRUCTOR_APPEND_ELT (elms, size_int (i), exp);
- }
- }
-
- /* Build static declaration to reference constructor. */
- tree ctor = build_constructor (build_ctype (satype), elms);
- tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor);
- TREE_READONLY (decl) = 1;
- d_pushdecl (decl);
- rest_of_decl_compilation (decl, 1, 0);
-
- /* Pass it as a dynamic array. */
- decl = d_array_value (build_ctype (condtype->arrayOf ()),
- size_int (s->cases->length),
- build_address (decl));
-
- condition = build_libcall (libcall, Type::tint32, 2, decl, condition);
- }
- else if (!condtype->isscalar ())
+ /* A switch statement on a string gets turned into a library call.
+ It is not lowered during codegen. */
+ if (!condtype->isscalar ())
{
error ("cannot handle switch condition of type %s",
condtype->toChars ());
@@ -992,7 +922,10 @@ public:
void visit (SwitchErrorStatement *s)
{
- add_stmt (build_assert_call (s->loc, LIBCALL_SWITCH_ERROR));
+ /* A throw SwitchError statement gets turned into a library call.
+ The call is wrapped in the enclosed expression. */
+ gcc_assert (s->exp != NULL);
+ add_stmt (build_expr (s->exp));
}
/* A return statement exits the current function and supplies its return
@@ -1000,7 +933,7 @@ public:
void visit (ReturnStatement *s)
{
- if (s->exp == NULL || s->exp->type->toBasetype ()->ty == Tvoid)
+ if (s->exp == NULL || s->exp->type->toBasetype ()->ty == TY::Tvoid)
{
/* Return has no value. */
add_stmt (return_expr (NULL_TREE));
@@ -1012,7 +945,7 @@ public:
? this->func_->tintro->nextOf () : tf->nextOf ();
if ((this->func_->isMain () || this->func_->isCMain ())
- && type->toBasetype ()->ty == Tvoid)
+ && type->toBasetype ()->ty == TY::Tvoid)
type = Type::tint32;
if (this->func_->shidden)
@@ -1020,7 +953,7 @@ public:
/* Returning by hidden reference, store the result into the retval decl.
The result returned then becomes the retval reference itself. */
tree decl = DECL_RESULT (get_symbol_decl (this->func_));
- gcc_assert (!tf->isref);
+ gcc_assert (!tf->isref ());
/* If returning via NRVO, just refer to the DECL_RESULT; this differs
from using NULL_TREE in that it indicates that we care about the
@@ -1096,7 +1029,7 @@ public:
add_stmt (return_expr (decl));
}
- else if (tf->next->ty == Tnoreturn)
+ else if (tf->next->ty == TY::Tnoreturn)
{
/* Returning an expression that has no value, but has a side effect
that should never return. */
@@ -1514,7 +1447,7 @@ public:
/* If the function has been annotated with `pragma(inline)', then mark
the asm expression as being inline as well. */
- if (this->func_->inlining == PINLINEalways)
+ if (this->func_->inlining == PINLINE::always)
ASM_INLINE_P (exp) = 1;
add_stmt (exp);
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "d-tree.h"
+#include "d-frontend.h"
#include "d-target.h"
@@ -110,37 +111,37 @@ get_typeinfo_kind (Type *type)
switch (type->ty)
{
- case Tpointer:
+ case TY::Tpointer:
return TK_POINTER_TYPE;
- case Tarray:
+ case TY::Tarray:
return TK_ARRAY_TYPE;
- case Tsarray:
+ case TY::Tsarray:
return TK_STATICARRAY_TYPE;
- case Taarray:
+ case TY::Taarray:
return TK_ASSOCIATIVEARRAY_TYPE;
- case Tstruct:
+ case TY::Tstruct:
return TK_STRUCT_TYPE;
- case Tvector:
+ case TY::Tvector:
return TK_VECTOR_TYPE;
- case Tenum:
+ case TY::Tenum:
return TK_ENUMERAL_TYPE;
- case Tfunction:
+ case TY::Tfunction:
return TK_FUNCTION_TYPE;
- case Tdelegate:
+ case TY::Tdelegate:
return TK_DELEGATE_TYPE;
- case Ttuple:
+ case TY::Ttuple:
return TK_TYPELIST_TYPE;
- case Tclass:
+ case TY::Tclass:
if (type->isTypeClass ()->sym->isInterfaceDeclaration ())
return TK_INTERFACE_TYPE;
else
@@ -216,7 +217,7 @@ make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
= ClassDeclaration::create (loc, Identifier::idPool ("Object"),
NULL, NULL, true);
object->parent = object_module;
- object->members = new Dsymbols;
+ object->members = d_gc_malloc<Dsymbols> ();
object->storage_class |= STCtemp;
}
@@ -228,7 +229,7 @@ make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
ClassDeclaration *tinfo = ClassDeclaration::create (loc, ident, NULL, NULL,
true);
tinfo->parent = object_module;
- tinfo->members = new Dsymbols;
+ tinfo->members = d_gc_malloc<Dsymbols> ();
dsymbolSemantic (tinfo, object_module->_scope);
tinfo->baseClass = base;
/* This is a compiler generated class, and shouldn't be mistaken for being
@@ -836,7 +837,7 @@ public:
/* Name of the class declaration. */
const char *name = cd->ident->toChars ();
if (!(strlen (name) > 9 && memcmp (name, "TypeInfo_", 9) == 0))
- name = cd->toPrettyChars ();
+ name = cd->toPrettyChars (true);
this->layout_string (name);
/* The vtable of the class declaration. */
@@ -857,7 +858,7 @@ public:
this->layout_field (base);
/* void *destructor; */
- tree dtor = (cd->dtor) ? build_address (get_symbol_decl (cd->dtor))
+ tree dtor = (cd->tidtor) ? build_address (get_symbol_decl (cd->tidtor))
: null_pointer_node;
this->layout_field (dtor);
@@ -911,10 +912,7 @@ public:
this->layout_field (build_integer_cst (flags, d_uint_type));
/* void *deallocator; */
- tree ddtor = (cd->aggDelete)
- ? build_address (get_symbol_decl (cd->aggDelete))
- : null_pointer_node;
- this->layout_field (ddtor);
+ this->layout_field (null_pointer_node);
/* OffsetTypeInfo[] m_offTi; (not implemented) */
this->layout_field (null_array_node);
@@ -942,7 +940,7 @@ public:
this->layout_field (null_array_node);
/* Name of the interface declaration. */
- this->layout_string (cd->toPrettyChars ());
+ this->layout_string (cd->toPrettyChars (true));
/* No vtable for interface declaration. */
this->layout_field (null_array_node);
@@ -1024,7 +1022,7 @@ public:
/* Layout of TypeInfo_Struct is:
void **__vptr;
void *__monitor;
- string name;
+ string mangledName;
void[] m_init;
hash_t function(in void*) xtoHash;
bool function(in void*, in void*) xopEquals;
@@ -1047,8 +1045,8 @@ public:
if (!sd->members)
return;
- /* Name of the struct declaration. */
- this->layout_string (sd->toPrettyChars ());
+ /* Mangled name of the struct declaration. */
+ this->layout_string (ti->deco);
/* Default initializer for struct. */
tree ptr = (sd->zeroInit) ? null_pointer_node
@@ -1064,7 +1062,7 @@ public:
if (sd->xhash)
{
TypeFunction *tf = sd->xhash->type->toTypeFunction ();
- if (!tf->isnothrow || tf->trust == TRUSTsystem)
+ if (!tf->isnothrow () || tf->trust == TRUST::system)
{
warning (sd->xhash->loc, "toHash() must be declared as "
"extern (D) size_t toHash() const nothrow @safe, "
@@ -1096,7 +1094,7 @@ public:
this->layout_field (build_integer_cst (m_flags, d_uint_type));
/* void function(void*) xdtor; */
- tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor))
+ tree dtor = (sd->tidtor) ? build_address (get_symbol_decl (sd->tidtor))
: null_pointer_node;
this->layout_field (dtor);
@@ -1298,17 +1296,17 @@ layout_classinfo_interfaces (ClassDeclaration *decl)
static bool
builtin_typeinfo_p (Type *type)
{
- if (type->isTypeBasic () || type->ty == Tclass || type->ty == Tnull)
+ if (type->isTypeBasic () || type->ty == TY::Tclass || type->ty == TY::Tnull)
return !type->mod;
- if (type->ty == Tarray)
+ if (type->ty == TY::Tarray)
{
/* Strings are so common, make them builtin. */
Type *next = type->nextOf ();
return !type->mod
&& ((next->isTypeBasic () != NULL && !next->mod)
- || (next->ty == Tchar && next->mod == MODimmutable)
- || (next->ty == Tchar && next->mod == MODconst));
+ || (next->ty == TY::Tchar && next->mod == MODimmutable)
+ || (next->ty == TY::Tchar && next->mod == MODconst));
}
return false;
@@ -1361,7 +1359,7 @@ get_typeinfo_decl (TypeInfoDeclaration *decl)
if (decl->csym)
return decl->csym;
- gcc_assert (decl->tinfo->ty != Terror);
+ gcc_assert (decl->tinfo->ty != TY::Terror);
TypeInfoDeclVisitor v = TypeInfoDeclVisitor ();
decl->accept (&v);
@@ -1436,7 +1434,7 @@ check_typeinfo_type (const Loc &loc, Scope *sc)
tree
build_typeinfo (const Loc &loc, Type *type)
{
- gcc_assert (type->ty != Terror);
+ gcc_assert (type->ty != TY::Terror);
check_typeinfo_type (loc, NULL);
create_typeinfo (type, NULL);
return build_address (get_typeinfo_decl (type->vtinfo));
@@ -94,7 +94,7 @@ bool
valist_array_p (Type *type)
{
Type *tvalist = target.va_listType (Loc (), NULL);
- if (tvalist->ty == Tsarray)
+ if (tvalist->ty == TY::Tsarray)
{
Type *tb = type->toBasetype ();
if (same_type_p (tb, tvalist))
@@ -170,7 +170,7 @@ make_array_type (Type *type, unsigned HOST_WIDE_INT size)
{
/* In [arrays/void-arrays], void arrays can also be static, the length is
specified in bytes. */
- if (type->toBasetype ()->ty == Tvoid)
+ if (type->toBasetype ()->ty == TY::Tvoid)
type = Type::tuns8;
/* In [arrays/static-arrays], a static array with a dimension of 0 is allowed,
@@ -546,9 +546,9 @@ merge_aggregate_types (Type *type, tree deco)
{
AggregateDeclaration *sym;
- if (type->ty == Tstruct)
+ if (type->ty == TY::Tstruct)
sym = type->isTypeStruct ()->sym;
- else if (type->ty == Tclass)
+ else if (type->ty == TY::Tclass)
sym = type->isTypeClass ()->sym;
else
gcc_unreachable ();
@@ -646,31 +646,31 @@ public:
switch (t->ty)
{
- case Tvoid: t->ctype = void_type_node; break;
- case Tbool: t->ctype = d_bool_type; break;
- case Tint8: t->ctype = d_byte_type; break;
- case Tuns8: t->ctype = d_ubyte_type; break;
- case Tint16: t->ctype = d_short_type; break;
- case Tuns16: t->ctype = d_ushort_type; break;
- case Tint32: t->ctype = d_int_type; break;
- case Tuns32: t->ctype = d_uint_type; break;
- case Tint64: t->ctype = d_long_type; break;
- case Tuns64: t->ctype = d_ulong_type; break;
- case Tint128: t->ctype = d_cent_type; break;
- case Tuns128: t->ctype = d_ucent_type; break;
- case Tfloat32: t->ctype = float_type_node; break;
- case Tfloat64: t->ctype = double_type_node; break;
- case Tfloat80: t->ctype = long_double_type_node; break;
- case Timaginary32: t->ctype = ifloat_type_node; break;
- case Timaginary64: t->ctype = idouble_type_node; break;
- case Timaginary80: t->ctype = ireal_type_node; break;
- case Tcomplex32: t->ctype = complex_float_type_node; break;
- case Tcomplex64: t->ctype = complex_double_type_node; break;
- case Tcomplex80: t->ctype = complex_long_double_type_node; break;
- case Tchar: t->ctype = char8_type_node; break;
- case Twchar: t->ctype = char16_type_node; break;
- case Tdchar: t->ctype = char32_type_node; break;
- default: gcc_unreachable ();
+ case TY::Tvoid: t->ctype = void_type_node; break;
+ case TY::Tbool: t->ctype = d_bool_type; break;
+ case TY::Tint8: t->ctype = d_byte_type; break;
+ case TY::Tuns8: t->ctype = d_ubyte_type; break;
+ case TY::Tint16: t->ctype = d_short_type; break;
+ case TY::Tuns16: t->ctype = d_ushort_type; break;
+ case TY::Tint32: t->ctype = d_int_type; break;
+ case TY::Tuns32: t->ctype = d_uint_type; break;
+ case TY::Tint64: t->ctype = d_long_type; break;
+ case TY::Tuns64: t->ctype = d_ulong_type; break;
+ case TY::Tint128: t->ctype = d_cent_type; break;
+ case TY::Tuns128: t->ctype = d_ucent_type; break;
+ case TY::Tfloat32: t->ctype = float_type_node; break;
+ case TY::Tfloat64: t->ctype = double_type_node; break;
+ case TY::Tfloat80: t->ctype = long_double_type_node; break;
+ case TY::Timaginary32: t->ctype = ifloat_type_node; break;
+ case TY::Timaginary64: t->ctype = idouble_type_node; break;
+ case TY::Timaginary80: t->ctype = ireal_type_node; break;
+ case TY::Tcomplex32: t->ctype = complex_float_type_node; break;
+ case TY::Tcomplex64: t->ctype = complex_double_type_node; break;
+ case TY::Tcomplex80: t->ctype = complex_long_double_type_node; break;
+ case TY::Tchar: t->ctype = char8_type_node; break;
+ case TY::Twchar: t->ctype = char16_type_node; break;
+ case TY::Tdchar: t->ctype = char32_type_node; break;
+ default: gcc_unreachable ();
}
TYPE_NAME (t->ctype) = get_identifier (t->toChars ());
@@ -786,7 +786,7 @@ public:
if (t->next != NULL)
{
fntype = build_ctype (t->next);
- if (t->isref)
+ if (t->isref ())
fntype = build_reference_type (fntype);
}
else
@@ -800,7 +800,7 @@ public:
/* Handle any special support for calling conventions. */
switch (t->linkage)
{
- case LINKwindows:
+ case LINK::windows:
{
/* [attribute/linkage]
@@ -815,10 +815,10 @@ public:
break;
}
- case LINKc:
- case LINKcpp:
- case LINKd:
- case LINKobjc:
+ case LINK::c:
+ case LINK::cpp:
+ case LINK::d:
+ case LINK::objc:
/* [abi/function-calling-conventions]
The extern (C) and extern (D) calling convention matches
@@ -1013,8 +1013,8 @@ public:
TYPE_CONTEXT (t->ctype) = d_decl_context (t->sym);
build_type_decl (t->ctype, t->sym);
- /* For structs with a user defined postblit or a destructor,
- also set TREE_ADDRESSABLE on the type and all variants.
+ /* For structs with a user defined postblit, copy constructor, or a
+ destructor, also set TREE_ADDRESSABLE on the type and all variants.
This will make the struct be passed around by reference. */
if (!t->sym->isPOD ())
{
deleted file mode 100644
@@ -1 +0,0 @@
-"2.076.1"