d: Merge upstream dmd 52844d4b1, druntime dbd0c874, phobos 896b1d0e1.
D front-end changes: - Parsing and compiling C code is now possible using `import'. - `throw' statements can now be used as an expression. - Improvements to the D template emission strategy when compiling with `-funittest'. D Runtime changes: - New core.int128 module for implementing intrinsics to support 128-bit integer types. - C bindings for the kernel and C runtime have been better separated to allow compiling for hybrid targets, such as kFreeBSD. Phobos changes: - The std.experimental.checkedint module has been renamed to std.checkedint. gcc/d/ChangeLog: * d-builtins.cc (d_build_builtins_module): Set purity of DECL_PURE_P functions to PURE::const_. * d-gimplify.cc (bit_field_ref): New function. (d_gimplify_modify_expr): Handle implicit casting for assignments to bit-fields. (d_gimplify_unary_expr): New function. (d_gimplify_binary_expr): New function. (d_gimplify_expr): Handle UNARY_CLASS_P and BINARY_CLASS_P. * d-target.cc (Target::_init): Initialize bitFieldStyle. (TargetCPP::parameterType): Update signature. (Target::supportsLinkerDirective): New function. * dmd/MERGE: Merge upstream dmd 52844d4b1. * expr.cc (ExprVisitor::visit (ThrowExp *)): New function. * types.cc (d_build_bitfield_integer_type): New function. (insert_aggregate_bitfield): New function. (layout_aggregate_members): Handle inserting bit-fields into an aggregate type. libphobos/ChangeLog: * Makefile.in: Regenerate. * libdruntime/MERGE: Merge upstream druntime dbd0c874. * libdruntime/Makefile.am (DRUNTIME_CSOURCES): Add core/int128.d. (DRUNTIME_DISOURCES): Add __builtins.di. * libdruntime/Makefile.in: Regenerate. * src/MERGE: Merge upstream phobos 896b1d0e1. * src/Makefile.am (PHOBOS_DSOURCES): Add std/checkedint.d. * src/Makefile.in: Regenerate. * testsuite/testsuite_flags.in: Add -fall-instantiations to --gdcflags.
This commit is contained in:
parent
0233276439
commit
d75691877c
289 changed files with 10868 additions and 10528 deletions
|
@ -543,7 +543,7 @@ 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) ? PURE::strong
|
||||
tf->purity = DECL_PURE_P (decl) ? PURE::const_
|
||||
: TREE_READONLY (decl) ? PURE::const_
|
||||
: DECL_IS_NOVOPS (decl) ? PURE::weak
|
||||
: !DECL_ASSEMBLER_NAME_SET_P (decl) ? PURE::weak
|
||||
|
|
|
@ -62,6 +62,18 @@ empty_modify_p (tree type, tree op)
|
|||
return empty_aggregate_p (type);
|
||||
}
|
||||
|
||||
/* Return TRUE if EXPR is a COMPONENT_REF to a bit-field declaration. */
|
||||
|
||||
static bool
|
||||
bit_field_ref (const_tree expr)
|
||||
{
|
||||
if (TREE_CODE (expr) == COMPONENT_REF
|
||||
&& DECL_BIT_FIELD (TREE_OPERAND (expr, 1)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Gimplify assignment from an INIT_EXPR or MODIFY_EXPR. */
|
||||
|
||||
static gimplify_status
|
||||
|
@ -96,6 +108,13 @@ d_gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
|
|||
return GS_OK;
|
||||
}
|
||||
|
||||
/* Same as above, but for bit-field assignments. */
|
||||
if (bit_field_ref (op0) && TREE_TYPE (op0) != TREE_TYPE (op1))
|
||||
{
|
||||
TREE_OPERAND (*expr_p, 1) = convert (TREE_TYPE (op0), op1);
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
return GS_UNHANDLED;
|
||||
}
|
||||
|
||||
|
@ -178,6 +197,54 @@ d_gimplify_unsigned_rshift_expr (tree *expr_p)
|
|||
return GS_OK;
|
||||
}
|
||||
|
||||
/* Gimplify an unary expression node. */
|
||||
|
||||
static gimplify_status
|
||||
d_gimplify_unary_expr (tree *expr_p)
|
||||
{
|
||||
tree op0 = TREE_OPERAND (*expr_p, 0);
|
||||
|
||||
if (error_operand_p (op0))
|
||||
return GS_UNHANDLED;
|
||||
|
||||
/* Front end doesn't know that bit-field types are really different
|
||||
from basic types, add an explicit conversion in unary expressions. */
|
||||
if (bit_field_ref (op0) && TREE_TYPE (op0) != TREE_TYPE (*expr_p))
|
||||
{
|
||||
TREE_OPERAND (*expr_p, 0) = convert (TREE_TYPE (*expr_p), op0);
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
return GS_UNHANDLED;
|
||||
}
|
||||
|
||||
/* Gimplify a binary expression node. */
|
||||
|
||||
static gimplify_status
|
||||
d_gimplify_binary_expr (tree *expr_p)
|
||||
{
|
||||
tree op0 = TREE_OPERAND (*expr_p, 0);
|
||||
tree op1 = TREE_OPERAND (*expr_p, 1);
|
||||
|
||||
if (error_operand_p (op0) || error_operand_p (op1))
|
||||
return GS_UNHANDLED;
|
||||
|
||||
/* Front end doesn't know that bit-field types are really different
|
||||
from basic types, add an explicit conversion in binary expressions. */
|
||||
if (bit_field_ref (op0) || bit_field_ref (op1))
|
||||
{
|
||||
if (TREE_TYPE (op0) != TREE_TYPE (*expr_p))
|
||||
TREE_OPERAND (*expr_p, 0) = convert (TREE_TYPE (*expr_p), op0);
|
||||
|
||||
if (TREE_TYPE (op1) != TREE_TYPE (*expr_p))
|
||||
TREE_OPERAND (*expr_p, 1) = convert (TREE_TYPE (*expr_p), op1);
|
||||
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
return GS_UNHANDLED;
|
||||
}
|
||||
|
||||
/* Implements the lang_hooks.gimplify_expr routine for language D.
|
||||
Do gimplification of D specific expression trees in EXPR_P. */
|
||||
|
||||
|
@ -203,6 +270,10 @@ d_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
|
|||
gcc_unreachable ();
|
||||
|
||||
default:
|
||||
if (UNARY_CLASS_P (*expr_p) && !CONVERT_EXPR_P (*expr_p))
|
||||
return d_gimplify_unary_expr (expr_p);
|
||||
if (BINARY_CLASS_P (*expr_p))
|
||||
return d_gimplify_binary_expr (expr_p);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,8 @@ Target::_init (const Param &)
|
|||
this->c.longsize = int_size_in_bytes (long_integer_type_node);
|
||||
this->c.long_doublesize = int_size_in_bytes (long_double_type_node);
|
||||
this->c.wchar_tsize = (WCHAR_TYPE_SIZE / BITS_PER_UNIT);
|
||||
this->c.bitFieldStyle = targetm.ms_bitfield_layout_p (unknown_type_node)
|
||||
? TargetC::BitFieldStyle::MS : TargetC::BitFieldStyle::Gcc_Clang;
|
||||
|
||||
/* Set-up target C++ ABI. */
|
||||
this->cpp.reverseOverloads = false;
|
||||
|
@ -379,32 +381,21 @@ TargetCPP::typeMangle (Type *type)
|
|||
ARG to an extern(C++) function. */
|
||||
|
||||
Type *
|
||||
TargetCPP::parameterType (Parameter *arg)
|
||||
TargetCPP::parameterType (Type *type)
|
||||
{
|
||||
Type *t = arg->type->merge2 ();
|
||||
if (arg->storageClass & (STCout | STCref))
|
||||
t = t->referenceTo ();
|
||||
else if (arg->storageClass & STClazy)
|
||||
{
|
||||
/* Mangle as delegate. */
|
||||
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 == TY::Tsarray && tvalist->ty == TY::Tsarray)
|
||||
if (type->ty == TY::Tsarray && tvalist->ty == TY::Tsarray)
|
||||
{
|
||||
Type *tb = t->toBasetype ()->mutableOf ();
|
||||
Type *tb = type->toBasetype ()->mutableOf ();
|
||||
if (tb == tvalist)
|
||||
{
|
||||
tb = t->nextOf ()->pointerTo ();
|
||||
t = tb->castMod (t->mod);
|
||||
tb = type->nextOf ()->pointerTo ();
|
||||
type = tb->castMod (type->mod);
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Checks whether TYPE is a vendor-specific fundamental type. Stores the result
|
||||
|
@ -579,6 +570,14 @@ Target::libraryObjectMonitors (FuncDeclaration *, Statement *)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Returns true if the target supports `pragma(linkerDirective)'. */
|
||||
|
||||
bool
|
||||
Target::supportsLinkerDirective (void) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
001bfd97b0e75423970260dac54f453be9b57f4c
|
||||
52844d4b1e9d6714bfd2e535f25a72074a046209
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
|
|
@ -33,6 +33,7 @@ Note that these groups have no strict meaning, the category assignments are a bi
|
|||
|-----------------------------------------------------------------------------|-----------------------------------------------------------------------|
|
||||
| [mars.d](https://github.com/dlang/dmd/blob/master/src/dmd/mars.d) | The entry point. Contains `main`. |
|
||||
| [cli.d](https://github.com/dlang/dmd/blob/master/src/dmd/cli.d) | Define the command line interface |
|
||||
| [dmdparams.d](https://github.com/dlang/dmd/blob/master/src/dmd/dmdparams.d) | DMD-specific parameters |
|
||||
| [globals.d](https://github.com/dlang/dmd/blob/master/src/dmd/globals.d) | Define a structure storing command line options |
|
||||
| [dinifile.d](https://github.com/dlang/dmd/blob/master/src/dmd/dinifile.d) | Parse settings from .ini file (`sc.ini` / `dmd.conf`) |
|
||||
| [vsoptions.d](https://github.com/dlang/dmd/blob/master/src/dmd/vsoptions.d) | Detect the Microsoft Visual Studio toolchain for linking |
|
||||
|
|
|
@ -51,15 +51,7 @@ bool checkAccess(AggregateDeclaration ad, Loc loc, Scope* sc, Dsymbol smember)
|
|||
|
||||
if (!symbolIsVisible(sc, smember))
|
||||
{
|
||||
// when in @safe code or with -preview=dip1000
|
||||
if (sc.flags & SCOPE.onlysafeaccess)
|
||||
{
|
||||
// if there is a func. ask for it's opinion of safety, and if it considers the access @safe accept it.
|
||||
if (sc.func && !sc.func.setUnsafe())
|
||||
return false;
|
||||
}
|
||||
|
||||
ad.error(loc, "%s `%s` is not accessible%s", smember.kind(), smember.toChars(), (sc.flags & SCOPE.onlysafeaccess) ? " from `@safe` code".ptr : "".ptr);
|
||||
ad.error(loc, "%s `%s` is not accessible", smember.kind(), smember.toChars());
|
||||
//printf("smember = %s %s, vis = %d, semanticRun = %d\n",
|
||||
// smember.kind(), smember.toPrettyChars(), smember.visible() smember.semanticRun);
|
||||
return true;
|
||||
|
|
|
@ -134,6 +134,8 @@ enum STC : ulong // transfer changes to declaration.h
|
|||
|
||||
}
|
||||
|
||||
alias StorageClass = ulong;
|
||||
|
||||
/********
|
||||
* Determine if it's the ambigous case of where `return` attaches to.
|
||||
* Params:
|
||||
|
@ -302,8 +304,7 @@ enum PURE : ubyte
|
|||
impure = 0, // not pure at all
|
||||
fwdref = 1, // it's pure, but not known which level yet
|
||||
weak = 2, // no mutable globals are read or written
|
||||
const_ = 3, // parameters are values or const
|
||||
strong = 4, // parameters are values or immutable
|
||||
const_ = 3, // parameters are values or const = strongly pure
|
||||
}
|
||||
|
||||
// Whether alias this dependency is recursive or not
|
||||
|
@ -389,3 +390,43 @@ enum InitKind : ubyte
|
|||
C_,
|
||||
}
|
||||
|
||||
/// A linkage attribute as defined by `extern(XXX)`
|
||||
///
|
||||
/// https://dlang.org/spec/attribute.html#linkage
|
||||
enum LINK : ubyte
|
||||
{
|
||||
default_,
|
||||
d,
|
||||
c,
|
||||
cpp,
|
||||
windows,
|
||||
objc,
|
||||
system,
|
||||
}
|
||||
|
||||
/// Whether to mangle an external aggregate as a struct or class, as set by `extern(C++, struct)`
|
||||
enum CPPMANGLE : ubyte
|
||||
{
|
||||
def, /// default
|
||||
asStruct, /// `extern(C++, struct)`
|
||||
asClass, /// `extern(C++, class)`
|
||||
}
|
||||
|
||||
/// Function match levels
|
||||
///
|
||||
/// https://dlang.org/spec/function.html#function-overloading
|
||||
enum MATCH : int
|
||||
{
|
||||
nomatch, /// no match
|
||||
convert, /// match with conversions
|
||||
constant, /// match with conversion to const
|
||||
exact, /// exact match
|
||||
}
|
||||
|
||||
/// Inline setting as defined by `pragma(inline, XXX)`
|
||||
enum PINLINE : ubyte
|
||||
{
|
||||
default_, /// as specified on the command line
|
||||
never, /// never inline
|
||||
always, /// always inline
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import dmd.identifier;
|
|||
import dmd.mtype;
|
||||
import dmd.objc; // for objc.addSymbols
|
||||
import dmd.common.outbuffer;
|
||||
import dmd.root.array; // for each
|
||||
import dmd.target; // for target.systemLinkage
|
||||
import dmd.tokens;
|
||||
import dmd.visitor;
|
||||
|
@ -1519,3 +1520,60 @@ extern (C++) final class UserAttributeDeclaration : AttribDeclaration
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the given symbol is a symbol declared in
|
||||
* `core.attribute` and has the given identifier.
|
||||
*
|
||||
* This is used to determine if a symbol is a UDA declared in
|
||||
* `core.attribute`.
|
||||
*
|
||||
* Params:
|
||||
* sym = the symbol to check
|
||||
* ident = the name of the expected UDA
|
||||
*/
|
||||
bool isCoreUda(Dsymbol sym, Identifier ident)
|
||||
{
|
||||
if (sym.ident != ident || !sym.parent)
|
||||
return false;
|
||||
|
||||
auto _module = sym.parent.isModule();
|
||||
return _module && _module.isCoreModule(Id.attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates the UDAs attached to the given symbol.
|
||||
*
|
||||
* If `dg` returns `!= 0`, it will stop the iteration and return that
|
||||
* value, otherwise it will return 0.
|
||||
*
|
||||
* Params:
|
||||
* sym = the symbol to get the UDAs from
|
||||
* sc = scope to use for semantic analysis of UDAs
|
||||
* dg = called once for each UDA. If `dg` returns `!= 0`, it will stop the
|
||||
* iteration and return that value, otherwise it will return `0`.
|
||||
*/
|
||||
int foreachUda(Dsymbol sym, Scope* sc, int delegate(Expression) dg)
|
||||
{
|
||||
if (!sym.userAttribDecl)
|
||||
return 0;
|
||||
|
||||
auto udas = sym.userAttribDecl.getAttributes();
|
||||
arrayExpressionSemantic(udas, sc, true);
|
||||
|
||||
return udas.each!((uda) {
|
||||
if (!uda.isTupleExp())
|
||||
return 0;
|
||||
|
||||
auto exps = uda.isTupleExp().exps;
|
||||
|
||||
return exps.each!((e) {
|
||||
assert(e);
|
||||
|
||||
if (auto result = dg(e))
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -110,8 +110,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
}
|
||||
if (s.exp.type && s.exp.type.toBasetype().isTypeNoreturn())
|
||||
result = BE.halt;
|
||||
if (canThrow(s.exp, func, mustNotThrow))
|
||||
result |= BE.throw_;
|
||||
|
||||
result |= canThrow(s.exp, func, mustNotThrow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
else if (!func.getModule().isCFile)
|
||||
{
|
||||
const(char)* gototype = s.isCaseStatement() ? "case" : "default";
|
||||
s.deprecation("switch case fallthrough - use 'goto %s;' if intended", gototype);
|
||||
s.error("switch case fallthrough - use 'goto %s;' if intended", gototype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -214,8 +214,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
result = BE.fallthru;
|
||||
if (result & BE.fallthru)
|
||||
{
|
||||
if (canThrow(s.condition, func, mustNotThrow))
|
||||
result |= BE.throw_;
|
||||
result |= canThrow(s.condition, func, mustNotThrow);
|
||||
|
||||
if (!(result & BE.break_) && s.condition.toBool().hasValue(true))
|
||||
result &= ~BE.fallthru;
|
||||
}
|
||||
|
@ -233,8 +233,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
}
|
||||
if (s.condition)
|
||||
{
|
||||
if (canThrow(s.condition, func, mustNotThrow))
|
||||
result |= BE.throw_;
|
||||
result |= canThrow(s.condition, func, mustNotThrow);
|
||||
|
||||
const opt = s.condition.toBool();
|
||||
if (opt.hasValue(true))
|
||||
result &= ~BE.fallthru;
|
||||
|
@ -250,15 +250,15 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
result |= BE.fallthru;
|
||||
result |= r & ~(BE.fallthru | BE.break_ | BE.continue_);
|
||||
}
|
||||
if (s.increment && canThrow(s.increment, func, mustNotThrow))
|
||||
result |= BE.throw_;
|
||||
if (s.increment)
|
||||
result |= canThrow(s.increment, func, mustNotThrow);
|
||||
}
|
||||
|
||||
override void visit(ForeachStatement s)
|
||||
{
|
||||
result = BE.fallthru;
|
||||
if (canThrow(s.aggr, func, mustNotThrow))
|
||||
result |= BE.throw_;
|
||||
result |= canThrow(s.aggr, func, mustNotThrow);
|
||||
|
||||
if (s._body)
|
||||
result |= blockExit(s._body, func, mustNotThrow) & ~(BE.break_ | BE.continue_);
|
||||
}
|
||||
|
@ -273,8 +273,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
{
|
||||
//printf("IfStatement::blockExit(%p)\n", s);
|
||||
result = BE.none;
|
||||
if (canThrow(s.condition, func, mustNotThrow))
|
||||
result |= BE.throw_;
|
||||
result |= canThrow(s.condition, func, mustNotThrow);
|
||||
|
||||
const opt = s.condition.toBool();
|
||||
if (opt.hasValue(true))
|
||||
|
@ -313,8 +312,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
override void visit(SwitchStatement s)
|
||||
{
|
||||
result = BE.none;
|
||||
if (canThrow(s.condition, func, mustNotThrow))
|
||||
result |= BE.throw_;
|
||||
result |= canThrow(s.condition, func, mustNotThrow);
|
||||
|
||||
if (s._body)
|
||||
{
|
||||
result |= blockExit(s._body, func, mustNotThrow);
|
||||
|
@ -357,8 +356,8 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
override void visit(ReturnStatement s)
|
||||
{
|
||||
result = BE.return_;
|
||||
if (s.exp && canThrow(s.exp, func, mustNotThrow))
|
||||
result |= BE.throw_;
|
||||
if (s.exp)
|
||||
result |= canThrow(s.exp, func, mustNotThrow);
|
||||
}
|
||||
|
||||
override void visit(BreakStatement s)
|
||||
|
@ -380,8 +379,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
override void visit(WithStatement s)
|
||||
{
|
||||
result = BE.none;
|
||||
if (canThrow(s.exp, func, mustNotThrow))
|
||||
result = BE.throw_;
|
||||
result |= canThrow(s.exp, func, mustNotThrow);
|
||||
result |= blockExit(s._body, func, mustNotThrow);
|
||||
}
|
||||
|
||||
|
@ -483,19 +481,7 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
return;
|
||||
}
|
||||
|
||||
Type t = s.exp.type.toBasetype();
|
||||
ClassDeclaration cd = t.isClassHandle();
|
||||
assert(cd);
|
||||
|
||||
if (cd == ClassDeclaration.errorException || ClassDeclaration.errorException.isBaseOf(cd, null))
|
||||
{
|
||||
result = BE.errthrow;
|
||||
return;
|
||||
}
|
||||
if (mustNotThrow)
|
||||
s.error("`%s` is thrown but not caught", s.exp.type.toChars());
|
||||
|
||||
result = BE.throw_;
|
||||
result = checkThrow(s.loc, s.exp, mustNotThrow);
|
||||
}
|
||||
|
||||
override void visit(GotoStatement s)
|
||||
|
@ -537,3 +523,32 @@ int blockExit(Statement s, FuncDeclaration func, bool mustNotThrow)
|
|||
s.accept(be);
|
||||
return be.result;
|
||||
}
|
||||
|
||||
/++
|
||||
+ Checks whether `throw <exp>` throws an `Exception` or an `Error`
|
||||
+ and raises an error if this violates `nothrow`.
|
||||
+
|
||||
+ Params:
|
||||
+ loc = location of the `throw`
|
||||
+ exp = expression yielding the throwable
|
||||
+ mustNotThrow = inside of a `nothrow` scope?
|
||||
+
|
||||
+ Returns: `BE.[err]throw` depending on the type of `exp`
|
||||
+/
|
||||
BE checkThrow(ref const Loc loc, Expression exp, const bool mustNotThrow)
|
||||
{
|
||||
import dmd.errors : error;
|
||||
|
||||
Type t = exp.type.toBasetype();
|
||||
ClassDeclaration cd = t.isClassHandle();
|
||||
assert(cd);
|
||||
|
||||
if (cd == ClassDeclaration.errorException || ClassDeclaration.errorException.isBaseOf(cd, null))
|
||||
{
|
||||
return BE.errthrow;
|
||||
}
|
||||
if (mustNotThrow)
|
||||
loc.error("`%s` is thrown but not caught", exp.type.toChars());
|
||||
|
||||
return BE.throw_;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import dmd.apply;
|
|||
import dmd.arraytypes;
|
||||
import dmd.attrib;
|
||||
import dmd.astenums;
|
||||
import dmd.blockexit : BE, checkThrow;
|
||||
import dmd.declaration;
|
||||
import dmd.dsymbol;
|
||||
import dmd.expression;
|
||||
|
@ -29,11 +30,28 @@ import dmd.root.rootobject;
|
|||
import dmd.tokens;
|
||||
import dmd.visitor;
|
||||
|
||||
/**
|
||||
* Status indicating what kind of throwable might be caused by an expression.
|
||||
*
|
||||
* This is a subset of `BE` restricted to the values actually used by `canThrow`.
|
||||
*/
|
||||
enum CT : BE
|
||||
{
|
||||
/// Never throws an `Exception` or `Throwable`
|
||||
none = BE.none,
|
||||
|
||||
/// Might throw an `Exception`
|
||||
exception = BE.throw_,
|
||||
|
||||
// Might throw an `Error`
|
||||
error = BE.errthrow,
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Returns true if the expression may throw exceptions.
|
||||
* If 'mustNotThrow' is true, generate an error if it throws
|
||||
*/
|
||||
extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow)
|
||||
extern (C++) /* CT */ BE canThrow(Expression e, FuncDeclaration func, bool mustNotThrow)
|
||||
{
|
||||
//printf("Expression::canThrow(%d) %s\n", mustNotThrow, toChars());
|
||||
// stop walking if we determine this expression can throw
|
||||
|
@ -42,6 +60,7 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
|
|||
alias visit = typeof(super).visit;
|
||||
FuncDeclaration func;
|
||||
bool mustNotThrow;
|
||||
CT result;
|
||||
|
||||
public:
|
||||
extern (D) this(FuncDeclaration func, bool mustNotThrow)
|
||||
|
@ -62,7 +81,7 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
|
|||
|
||||
e.checkOverridenDtor(null, f, dd => dd.type.toTypeFunction().isnothrow, "not nothrow");
|
||||
}
|
||||
stop = true; // if any function throws, then the whole expression throws
|
||||
result |= CT.exception;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +91,7 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
|
|||
|
||||
override void visit(DeclarationExp de)
|
||||
{
|
||||
stop = Dsymbol_canThrow(de.declaration, func, mustNotThrow);
|
||||
result |= Dsymbol_canThrow(de.declaration, func, mustNotThrow);
|
||||
}
|
||||
|
||||
override void visit(CallExp ce)
|
||||
|
@ -83,18 +102,27 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
|
|||
if (global.errors && !ce.e1.type)
|
||||
return; // error recovery
|
||||
|
||||
import dmd.id : Id;
|
||||
|
||||
if (ce.f && ce.f.ident == Id._d_delstruct)
|
||||
if (ce.f && ce.arguments.dim > 0)
|
||||
{
|
||||
// Only check if the dtor throws.
|
||||
Type tb = (*ce.arguments)[0].type.toBasetype();
|
||||
auto ts = tb.nextOf().baseElemOf().isTypeStruct();
|
||||
if (ts)
|
||||
auto tbNext = tb.nextOf();
|
||||
if (tbNext)
|
||||
{
|
||||
auto sd = ts.sym;
|
||||
if (sd.dtor)
|
||||
checkFuncThrows(ce, sd.dtor);
|
||||
auto ts = tbNext.baseElemOf().isTypeStruct();
|
||||
if (ts)
|
||||
{
|
||||
import dmd.id : Id;
|
||||
|
||||
auto sd = ts.sym;
|
||||
if (sd.dtor && ce.f.ident == Id._d_delstruct)
|
||||
checkFuncThrows(ce, sd.dtor);
|
||||
else if (sd.postblit &&
|
||||
(ce.f.ident == Id._d_arrayctor || ce.f.ident == Id._d_arraysetctor))
|
||||
{
|
||||
checkFuncThrows(ce, sd.postblit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +152,7 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
|
|||
e1 = pe.e1;
|
||||
ce.error("`%s` is not `nothrow`", e1.toChars());
|
||||
}
|
||||
stop = true;
|
||||
result |= CT.exception;
|
||||
}
|
||||
|
||||
override void visit(NewExp ne)
|
||||
|
@ -187,6 +215,13 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
|
|||
checkFuncThrows(ae, postblit);
|
||||
}
|
||||
|
||||
override void visit(ThrowExp te)
|
||||
{
|
||||
const res = checkThrow(te.loc, te.e1, mustNotThrow);
|
||||
assert((res & ~(CT.exception | CT.error)) == 0);
|
||||
result |= res;
|
||||
}
|
||||
|
||||
override void visit(NewAnonClassExp)
|
||||
{
|
||||
assert(0); // should have been lowered by semantic()
|
||||
|
@ -194,18 +229,22 @@ extern (C++) bool canThrow(Expression e, FuncDeclaration func, bool mustNotThrow
|
|||
}
|
||||
|
||||
scope CanThrow ct = new CanThrow(func, mustNotThrow);
|
||||
return walkPostorder(e, ct);
|
||||
walkPostorder(e, ct);
|
||||
return ct.result;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Does symbol, when initialized, throw?
|
||||
* Mirrors logic in Dsymbol_toElem().
|
||||
*/
|
||||
private bool Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
|
||||
private CT Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow)
|
||||
{
|
||||
CT result;
|
||||
|
||||
int symbolDg(Dsymbol s)
|
||||
{
|
||||
return Dsymbol_canThrow(s, func, mustNotThrow);
|
||||
result |= Dsymbol_canThrow(s, func, mustNotThrow);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//printf("Dsymbol_toElem() %s\n", s.toChars());
|
||||
|
@ -225,20 +264,19 @@ private bool Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow
|
|||
if (vd._init)
|
||||
{
|
||||
if (auto ie = vd._init.isExpInitializer())
|
||||
if (canThrow(ie.exp, func, mustNotThrow))
|
||||
return true;
|
||||
result |= canThrow(ie.exp, func, mustNotThrow);
|
||||
}
|
||||
if (vd.needsScopeDtor())
|
||||
return canThrow(vd.edtor, func, mustNotThrow);
|
||||
result |= canThrow(vd.edtor, func, mustNotThrow);
|
||||
}
|
||||
}
|
||||
else if (auto ad = s.isAttribDeclaration())
|
||||
{
|
||||
return ad.include(null).foreachDsymbol(&symbolDg) != 0;
|
||||
ad.include(null).foreachDsymbol(&symbolDg);
|
||||
}
|
||||
else if (auto tm = s.isTemplateMixin())
|
||||
{
|
||||
return tm.members.foreachDsymbol(&symbolDg) != 0;
|
||||
tm.members.foreachDsymbol(&symbolDg);
|
||||
}
|
||||
else if (auto td = s.isTupleDeclaration())
|
||||
{
|
||||
|
@ -250,11 +288,10 @@ private bool Dsymbol_canThrow(Dsymbol s, FuncDeclaration func, bool mustNotThrow
|
|||
Expression eo = cast(Expression)o;
|
||||
if (auto se = eo.isDsymbolExp())
|
||||
{
|
||||
if (Dsymbol_canThrow(se.s, func, mustNotThrow))
|
||||
return true;
|
||||
result |= Dsymbol_canThrow(se.s, func, mustNotThrow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -120,18 +120,13 @@ UnionExp Not(Type type, Expression e1)
|
|||
{
|
||||
UnionExp ue = void;
|
||||
Loc loc = e1.loc;
|
||||
// BUG: Should be replaced with e1.toBool().get(), but this is apparently
|
||||
// executed for some expressions that cannot be const-folded
|
||||
// To be fixed in another PR
|
||||
emplaceExp!(IntegerExp)(&ue, loc, e1.toBool().hasValue(false) ? 1 : 0, type);
|
||||
return ue;
|
||||
}
|
||||
|
||||
private UnionExp Bool(Type type, Expression e1)
|
||||
{
|
||||
UnionExp ue = void;
|
||||
Loc loc = e1.loc;
|
||||
emplaceExp!(IntegerExp)(&ue, loc, e1.toBool().hasValue(true) ? 1 : 0, type);
|
||||
return ue;
|
||||
}
|
||||
|
||||
UnionExp Add(const ref Loc loc, Type type, Expression e1, Expression e2)
|
||||
{
|
||||
UnionExp ue = void;
|
||||
|
@ -1093,19 +1088,14 @@ UnionExp Cast(const ref Loc loc, Type type, Type to, Expression e1)
|
|||
}
|
||||
else if (tb.ty == Tbool)
|
||||
{
|
||||
bool val = void;
|
||||
const opt = e1.toBool();
|
||||
if (opt.hasValue(true))
|
||||
val = true;
|
||||
else if (opt.hasValue(false))
|
||||
val = false;
|
||||
else
|
||||
if (opt.isEmpty())
|
||||
{
|
||||
cantExp(ue);
|
||||
return ue;
|
||||
}
|
||||
|
||||
emplaceExp!(IntegerExp)(&ue, loc, val, type);
|
||||
emplaceExp!(IntegerExp)(&ue, loc, opt.get(), type);
|
||||
}
|
||||
else if (type.isintegral())
|
||||
{
|
||||
|
|
|
@ -35,7 +35,8 @@ final class CParser(AST) : Parser!AST
|
|||
{
|
||||
AST.Dsymbols* symbols; // symbols declared in current scope
|
||||
|
||||
bool addFuncName; /// add declaration of __func__ to function symbol table
|
||||
bool addFuncName; /// add declaration of __func__ to function symbol table
|
||||
bool importBuiltins; /// seen use of C compiler builtins, so import __builtins;
|
||||
|
||||
extern (D) this(TARGET)(AST.Module _module, const(char)[] input, bool doDocComment,
|
||||
const ref TARGET target)
|
||||
|
@ -72,7 +73,6 @@ final class CParser(AST) : Parser!AST
|
|||
{
|
||||
//printf("cparseTranslationUnit()\n");
|
||||
symbols = new AST.Dsymbols();
|
||||
addBuiltinDeclarations();
|
||||
while (1)
|
||||
{
|
||||
if (token.value == TOK.endOfFile)
|
||||
|
@ -82,6 +82,15 @@ final class CParser(AST) : Parser!AST
|
|||
auto ld = new AST.LinkDeclaration(token.loc, LINK.c, symbols);
|
||||
wrap.push(ld);
|
||||
|
||||
if (importBuiltins)
|
||||
{
|
||||
/* Seen references to C builtin functions.
|
||||
* Import their definitions
|
||||
*/
|
||||
auto s = new AST.Import(Loc.initial, null, Id.builtins, null, false);
|
||||
wrap.push(s);
|
||||
}
|
||||
|
||||
return wrap;
|
||||
}
|
||||
|
||||
|
@ -596,6 +605,7 @@ final class CParser(AST) : Parser!AST
|
|||
* string-literal
|
||||
* ( expression )
|
||||
* generic-selection
|
||||
* __builtin_va_arg(assign_expression, type)
|
||||
*/
|
||||
AST.Expression cparsePrimaryExp()
|
||||
{
|
||||
|
@ -606,9 +616,20 @@ final class CParser(AST) : Parser!AST
|
|||
switch (token.value)
|
||||
{
|
||||
case TOK.identifier:
|
||||
if (token.ident is Id.__func__)
|
||||
const id = token.ident.toString();
|
||||
if (id.length > 2 && id[0] == '_' && id[1] == '_') // leading double underscore
|
||||
{
|
||||
addFuncName = true; // implicitly declare __func__
|
||||
if (token.ident is Id.__func__)
|
||||
{
|
||||
addFuncName = true; // implicitly declare __func__
|
||||
}
|
||||
else if (token.ident is Id.builtin_va_arg)
|
||||
{
|
||||
e = cparseBuiltin_va_arg();
|
||||
break;
|
||||
}
|
||||
else
|
||||
importBuiltins = true; // probably one of those compiler extensions
|
||||
}
|
||||
e = new AST.IdentifierExp(loc, token.ident);
|
||||
nextToken();
|
||||
|
@ -1449,6 +1470,40 @@ final class CParser(AST) : Parser!AST
|
|||
return cparseAssignExp();
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* gcc extension:
|
||||
* type __builtin_va_arg(assign-expression, type)
|
||||
* Rewrite as `va_arg` template from `core.stdc.stdarg`:
|
||||
* va_arg!(type)(assign-expression);
|
||||
* Lexer is on `__builtin_va_arg`
|
||||
*/
|
||||
private AST.Expression cparseBuiltin_va_arg()
|
||||
{
|
||||
importBuiltins = true; // need core.stdc.stdarg
|
||||
|
||||
nextToken();
|
||||
check(TOK.leftParenthesis);
|
||||
|
||||
auto arguments = new AST.Expressions();
|
||||
auto arg = cparseAssignExp();
|
||||
arguments.push(arg);
|
||||
|
||||
check(TOK.comma);
|
||||
|
||||
auto t = cparseTypeName();
|
||||
auto tiargs = new AST.Objects();
|
||||
tiargs.push(t);
|
||||
|
||||
const loc = loc;
|
||||
auto ti = new AST.TemplateInstance(loc, Id.va_arg, tiargs);
|
||||
auto tie = new AST.ScopeExp(loc, ti);
|
||||
|
||||
AST.Expression e = new AST.CallExp(loc, tie, arguments);
|
||||
|
||||
check(TOK.rightParenthesis);
|
||||
return e;
|
||||
}
|
||||
|
||||
//}
|
||||
/********************************************************************************/
|
||||
/********************************* Declaration Parser ***************************/
|
||||
|
@ -1481,6 +1536,14 @@ final class CParser(AST) : Parser!AST
|
|||
return;
|
||||
}
|
||||
|
||||
if (token.value == TOK._import) // import declaration extension
|
||||
{
|
||||
auto a = parseImport();
|
||||
if (a && a.length)
|
||||
symbols.append(a);
|
||||
return;
|
||||
}
|
||||
|
||||
auto symbolsSave = symbols;
|
||||
Specifier specifier;
|
||||
specifier.packalign = this.packalign;
|
||||
|
@ -1504,7 +1567,7 @@ final class CParser(AST) : Parser!AST
|
|||
*/
|
||||
auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) :
|
||||
(tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) :
|
||||
new AST.EnumDeclaration(tt.loc, tt.id, AST.Type.tint32);
|
||||
new AST.EnumDeclaration(tt.loc, tt.id, tt.base);
|
||||
stag.members = tt.members;
|
||||
if (!symbols)
|
||||
symbols = new AST.Dsymbols();
|
||||
|
@ -1550,26 +1613,18 @@ final class CParser(AST) : Parser!AST
|
|||
case TOK.semicolon:
|
||||
case TOK.asm_:
|
||||
case TOK.__attribute__:
|
||||
/* This is a data definition, there cannot now be a
|
||||
* function definition.
|
||||
*/
|
||||
first = false;
|
||||
if (token.value == TOK.asm_)
|
||||
asmname = cparseSimpleAsmExpr();
|
||||
if (token.value == TOK.__attribute__)
|
||||
{
|
||||
cparseGnuAttributes(specifier);
|
||||
if (token.value == TOK.leftCurly)
|
||||
{
|
||||
error("attributes should be specified before the function definition");
|
||||
auto t = &token;
|
||||
if (skipBraces(t))
|
||||
{
|
||||
token = *t;
|
||||
return;
|
||||
}
|
||||
}
|
||||
break; // function definition
|
||||
}
|
||||
/* This is a data definition, there cannot now be a
|
||||
* function definition.
|
||||
*/
|
||||
first = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1636,6 +1691,30 @@ final class CParser(AST) : Parser!AST
|
|||
isalias = false;
|
||||
}
|
||||
}
|
||||
else if (auto tt = dt.isTypeTag())
|
||||
{
|
||||
if (tt.id || tt.tok == TOK.enum_)
|
||||
{
|
||||
/* `struct tag;` and `struct tag { ... };`
|
||||
* always result in a declaration in the current scope
|
||||
*/
|
||||
auto stag = (tt.tok == TOK.struct_) ? new AST.StructDeclaration(tt.loc, tt.id, false) :
|
||||
(tt.tok == TOK.union_) ? new AST.UnionDeclaration(tt.loc, tt.id) :
|
||||
new AST.EnumDeclaration(tt.loc, tt.id, tt.base);
|
||||
stag.members = tt.members;
|
||||
tt.members = null;
|
||||
if (!symbols)
|
||||
symbols = new AST.Dsymbols();
|
||||
symbols.push(stag);
|
||||
if (tt.tok == TOK.enum_)
|
||||
{
|
||||
if (!tt.members)
|
||||
error(tt.loc, "`enum %s` has no members", stag.toChars());
|
||||
isalias = false;
|
||||
s = new AST.AliasDeclaration(token.loc, id, stag);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isalias)
|
||||
s = new AST.AliasDeclaration(token.loc, id, dt);
|
||||
}
|
||||
|
@ -1768,6 +1847,7 @@ final class CParser(AST) : Parser!AST
|
|||
if (pl.varargs != AST.VarArg.none && pl.length)
|
||||
error("function identifier-list cannot end with `...`");
|
||||
ft.parameterList.varargs = AST.VarArg.variadic; // but C11 allows extra arguments
|
||||
importBuiltins = true; // will need __va_list_tag
|
||||
auto plLength = pl.length;
|
||||
if (symbols.length != plLength)
|
||||
error("%d identifiers does not match %d declarations", cast(int)plLength, cast(int)symbols.length);
|
||||
|
@ -2230,8 +2310,14 @@ final class CParser(AST) : Parser!AST
|
|||
case TKW.xcomplex | TKW.xdouble: t = AST.Type.tcomplex64; break;
|
||||
case TKW.xcomplex | TKW.xlong | TKW.xdouble: t = realType(RTFlags.complex); break;
|
||||
|
||||
case TKW.xident: t = new AST.TypeIdentifier(loc, previd);
|
||||
case TKW.xident:
|
||||
{
|
||||
const idx = previd.toString();
|
||||
if (idx.length > 2 && idx[0] == '_' && idx[1] == '_') // leading double underscore
|
||||
importBuiltins = true; // probably one of those compiler extensions
|
||||
t = new AST.TypeIdentifier(loc, previd);
|
||||
break;
|
||||
}
|
||||
|
||||
case TKW.xtag:
|
||||
break; // t is already set
|
||||
|
@ -2599,6 +2685,7 @@ final class CParser(AST) : Parser!AST
|
|||
if (token.value == TOK.rightParenthesis) // func()
|
||||
{
|
||||
nextToken();
|
||||
importBuiltins = true; // will need __va_list_tag
|
||||
return AST.ParameterList(parameters, AST.VarArg.variadic, varargsStc);
|
||||
}
|
||||
|
||||
|
@ -2613,6 +2700,7 @@ final class CParser(AST) : Parser!AST
|
|||
{
|
||||
if (parameters.length == 0) // func(...)
|
||||
error("named parameter required before `...`");
|
||||
importBuiltins = true; // will need __va_list_tag
|
||||
varargs = AST.VarArg.variadic; // C-style variadics
|
||||
nextToken();
|
||||
check(TOK.rightParenthesis);
|
||||
|
@ -3011,6 +3099,17 @@ final class CParser(AST) : Parser!AST
|
|||
nextToken();
|
||||
}
|
||||
|
||||
/* clang extension: add optional base type after the identifier
|
||||
* https://en.cppreference.com/w/cpp/language/enum
|
||||
* enum Identifier : Type
|
||||
*/
|
||||
AST.Type base = AST.Type.tint32; // C11 6.7.2.2-4 implementation defined default base type
|
||||
if (token.value == TOK.colon)
|
||||
{
|
||||
nextToken();
|
||||
base = cparseTypeName();
|
||||
}
|
||||
|
||||
AST.Dsymbols* members;
|
||||
if (token.value == TOK.leftCurly)
|
||||
{
|
||||
|
@ -3084,7 +3183,7 @@ final class CParser(AST) : Parser!AST
|
|||
* redeclaration, or reference to existing declaration.
|
||||
* Defer to the semantic() pass with a TypeTag.
|
||||
*/
|
||||
return new AST.TypeTag(loc, TOK.enum_, tag, members);
|
||||
return new AST.TypeTag(loc, TOK.enum_, tag, base, members);
|
||||
}
|
||||
|
||||
/*************************************
|
||||
|
@ -3124,17 +3223,14 @@ final class CParser(AST) : Parser!AST
|
|||
if (token.value == TOK.leftCurly)
|
||||
{
|
||||
nextToken();
|
||||
auto symbolsSave = symbols;
|
||||
symbols = new AST.Dsymbols();
|
||||
members = new AST.Dsymbols(); // so `members` will be non-null even with 0 members
|
||||
while (token.value != TOK.rightCurly)
|
||||
{
|
||||
cparseStructDeclaration();
|
||||
cparseStructDeclaration(members);
|
||||
|
||||
if (token.value == TOK.endOfFile)
|
||||
break;
|
||||
}
|
||||
members = symbols; // `members` will be non-null even with 0 members
|
||||
symbols = symbolsSave;
|
||||
check(TOK.rightCurly);
|
||||
|
||||
if ((*members).length == 0) // C11 6.7.2.1-8
|
||||
|
@ -3152,7 +3248,7 @@ final class CParser(AST) : Parser!AST
|
|||
* redeclaration, or reference to existing declaration.
|
||||
* Defer to the semantic() pass with a TypeTag.
|
||||
*/
|
||||
return new AST.TypeTag(loc, structOrUnion, tag, members);
|
||||
return new AST.TypeTag(loc, structOrUnion, tag, null, members);
|
||||
}
|
||||
|
||||
/*************************************
|
||||
|
@ -3169,18 +3265,19 @@ final class CParser(AST) : Parser!AST
|
|||
* struct-declarator:
|
||||
* declarator
|
||||
* declarator (opt) : constant-expression
|
||||
* Params:
|
||||
* members = where to put the fields (members)
|
||||
*/
|
||||
void cparseStructDeclaration()
|
||||
void cparseStructDeclaration(AST.Dsymbols* members)
|
||||
{
|
||||
//printf("cparseStructDeclaration()\n");
|
||||
if (token.value == TOK._Static_assert)
|
||||
{
|
||||
auto s = cparseStaticAssert();
|
||||
symbols.push(s);
|
||||
members.push(s);
|
||||
return;
|
||||
}
|
||||
|
||||
auto symbolsSave = symbols;
|
||||
Specifier specifier;
|
||||
specifier.packalign = this.packalign;
|
||||
auto tspec = cparseSpecifierQualifierList(LVL.member, specifier);
|
||||
|
@ -3209,10 +3306,8 @@ final class CParser(AST) : Parser!AST
|
|||
* the containing struct
|
||||
*/
|
||||
auto ad = new AST.AnonDeclaration(tt.loc, tt.tok == TOK.union_, tt.members);
|
||||
if (!symbols)
|
||||
symbols = new AST.Dsymbols();
|
||||
auto s = applySpecifier(ad, specifier);
|
||||
symbols.push(s);
|
||||
members.push(s);
|
||||
return;
|
||||
}
|
||||
if (!tt.id && !tt.members)
|
||||
|
@ -3270,18 +3365,14 @@ final class CParser(AST) : Parser!AST
|
|||
if (token.value == TOK.__attribute__)
|
||||
cparseGnuAttributes(specifier);
|
||||
|
||||
AST.Dsymbol s = null;
|
||||
symbols = symbolsSave;
|
||||
if (!symbols)
|
||||
symbols = new AST.Dsymbols; // lazilly create it
|
||||
|
||||
if (!tspec && !specifier.scw && !specifier.mod)
|
||||
error("specifier-qualifier-list required");
|
||||
else if (width)
|
||||
{
|
||||
if (specifier.alignExps)
|
||||
error("no alignment-specifier for bit field declaration"); // C11 6.7.5-2
|
||||
s = new AST.BitFieldDeclaration(width.loc, dt, id, width);
|
||||
auto s = new AST.BitFieldDeclaration(width.loc, dt, id, width);
|
||||
members.push(s);
|
||||
}
|
||||
else if (id)
|
||||
{
|
||||
|
@ -3291,11 +3382,10 @@ final class CParser(AST) : Parser!AST
|
|||
// declare the symbol
|
||||
// Give member variables an implicit void initializer
|
||||
auto initializer = new AST.VoidInitializer(token.loc);
|
||||
s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(LVL.member, specifier));
|
||||
AST.Dsymbol s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(LVL.member, specifier));
|
||||
s = applySpecifier(s, specifier);
|
||||
members.push(s);
|
||||
}
|
||||
if (s !is null)
|
||||
symbols.push(s);
|
||||
|
||||
switch (token.value)
|
||||
{
|
||||
|
@ -4391,39 +4481,5 @@ final class CParser(AST) : Parser!AST
|
|||
return s;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Add global target-dependent builtin declarations.
|
||||
*/
|
||||
private void addBuiltinDeclarations()
|
||||
{
|
||||
void genBuiltinFunc(Identifier id, AST.VarArg va)
|
||||
{
|
||||
auto tva_list = new AST.TypeIdentifier(Loc.initial, Id.builtin_va_list);
|
||||
auto parameters = new AST.Parameters();
|
||||
parameters.push(new AST.Parameter(STC.parameter | STC.ref_, tva_list, null, null, null));
|
||||
auto pl = AST.ParameterList(parameters, va, 0);
|
||||
auto tf = new AST.TypeFunction(pl, AST.Type.tvoid, LINK.c, 0);
|
||||
auto s = new AST.FuncDeclaration(Loc.initial, Loc.initial, id, AST.STC.static_, tf, false);
|
||||
symbols.push(s);
|
||||
}
|
||||
|
||||
/* void __builtin_va_start(__builtin_va_list, ...);
|
||||
* The second argument is supposed to be of any type, so fake it with the ...
|
||||
*/
|
||||
genBuiltinFunc(Id.builtin_va_start, AST.VarArg.variadic);
|
||||
|
||||
/* void __builtin_va_end(__builtin_va_list);
|
||||
*/
|
||||
genBuiltinFunc(Id.builtin_va_end, AST.VarArg.none);
|
||||
|
||||
/* struct __va_list_tag
|
||||
* {
|
||||
* uint, uint, void*, void*
|
||||
* }
|
||||
*/
|
||||
auto s = new AST.StructDeclaration(Loc.initial, Id.va_list_tag, false);
|
||||
symbols.push(s);
|
||||
}
|
||||
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -1315,7 +1315,18 @@ private final class CppMangleVisitor : Visitor
|
|||
|
||||
foreach (n, fparam; parameterList)
|
||||
{
|
||||
Type t = target.cpp.parameterType(fparam);
|
||||
Type t = fparam.type.merge2();
|
||||
if (fparam.isReference())
|
||||
t = t.referenceTo();
|
||||
else if (fparam.storageClass & STC.lazy_)
|
||||
{
|
||||
// Mangle as delegate
|
||||
auto tf = new TypeFunction(ParameterList(), t, LINK.d);
|
||||
auto td = new TypeDelegate(tf);
|
||||
t = td.merge();
|
||||
}
|
||||
else if (Type cpptype = target.cpp.parameterType(t))
|
||||
t = cpptype;
|
||||
if (t.ty == Tsarray)
|
||||
{
|
||||
// Static arrays in D are passed by value; no counterpart in C++
|
||||
|
|
|
@ -858,11 +858,8 @@ MATCH implicitConvTo(Expression e, Type t)
|
|||
* convert to immutable
|
||||
*/
|
||||
if (e.f &&
|
||||
(global.params.useDIP1000 != FeatureState.enabled || // lots of legacy code breaks with the following purity check
|
||||
e.f.isPure() >= PURE.strong ||
|
||||
// Special case exemption for Object.dup() which we assume is implemented correctly
|
||||
e.f.ident == Id.dup &&
|
||||
e.f.toParent2() == ClassDeclaration.object.toParent()) &&
|
||||
// lots of legacy code breaks with the following purity check
|
||||
(global.params.useDIP1000 != FeatureState.enabled || e.f.isPure() >= PURE.const_) &&
|
||||
e.f.isReturnIsolated() // check isReturnIsolated last, because it is potentially expensive.
|
||||
)
|
||||
{
|
||||
|
@ -2245,9 +2242,12 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
|
|||
ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
|
||||
(*te.exps)[i] = ex;
|
||||
}
|
||||
if (totuple)
|
||||
te.type = totuple;
|
||||
result = te;
|
||||
|
||||
/* Questionable behavior: In here, result.type is not set to t.
|
||||
/* Questionable behavior: In here, result.type is not set to t
|
||||
* if target type is not a tuple of same length.
|
||||
* Therefoe:
|
||||
* TypeTuple!(int, int) values;
|
||||
* auto values2 = cast(long)values;
|
||||
|
|
|
@ -446,6 +446,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
|
|||
*poffset = 0;
|
||||
while (cd)
|
||||
{
|
||||
assert(cd.baseClass || cd.semanticRun >= PASS.semanticdone || cd.isInterfaceDeclaration());
|
||||
if (this == cd.baseClass)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -1048,7 +1048,6 @@ extern (C++) class VarDeclaration : Declaration
|
|||
uint endlinnum; // line number of end of scope that this var lives in
|
||||
uint offset;
|
||||
uint sequenceNumber; // order the variables are declared
|
||||
__gshared uint nextSequenceNumber; // the counter for sequenceNumber
|
||||
structalign_t alignment;
|
||||
|
||||
// When interpreting, these point to the value (NULL if value not determinable)
|
||||
|
@ -1099,7 +1098,6 @@ extern (C++) class VarDeclaration : Declaration
|
|||
this._init = _init;
|
||||
ctfeAdrOnStack = AdrOnStackNone;
|
||||
this.storage_class = storage_class;
|
||||
sequenceNumber = ++nextSequenceNumber;
|
||||
}
|
||||
|
||||
static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
|
||||
|
@ -1657,12 +1655,10 @@ extern (C++) class VarDeclaration : Declaration
|
|||
// Sequence numbers work when there are no special VarDeclaration's involved
|
||||
if (!((this.storage_class | v.storage_class) & special))
|
||||
{
|
||||
// FIXME: VarDeclaration's for parameters are created in semantic3, so
|
||||
// they will have a greater sequence number than local variables.
|
||||
// Hence reverse the result for mixed comparisons.
|
||||
const exp = this.isParameter() == v.isParameter();
|
||||
assert(this.sequenceNumber != this.sequenceNumber.init);
|
||||
assert(v.sequenceNumber != v.sequenceNumber.init);
|
||||
|
||||
return (this.sequenceNumber < v.sequenceNumber) == exp;
|
||||
return (this.sequenceNumber < v.sequenceNumber);
|
||||
}
|
||||
|
||||
// Assume that semantic produces temporaries according to their lifetime
|
||||
|
|
|
@ -16,6 +16,7 @@ module dmd.denum;
|
|||
|
||||
import core.stdc.stdio;
|
||||
|
||||
import dmd.astenums;
|
||||
import dmd.attrib;
|
||||
import dmd.gluelayer;
|
||||
import dmd.declaration;
|
||||
|
@ -60,7 +61,7 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
|
|||
extern (D) this(const ref Loc loc, Identifier ident, Type memtype)
|
||||
{
|
||||
super(loc, ident);
|
||||
//printf("EnumDeclaration() %s\n", toChars());
|
||||
//printf("EnumDeclaration() %p %s : %s\n", this, toChars(), memtype.toChars());
|
||||
type = new TypeEnum(this);
|
||||
this.memtype = memtype;
|
||||
visibility = Visibility(Visibility.Kind.undefined);
|
||||
|
|
|
@ -99,7 +99,15 @@ public Expression ctfeInterpret(Expression e)
|
|||
|
||||
Expression result = interpret(e, null);
|
||||
|
||||
result = copyRegionExp(result);
|
||||
// Report an error if the expression contained a `ThrowException` and
|
||||
// hence generated an uncaught exception
|
||||
if (auto tee = result.isThrownExceptionExp())
|
||||
{
|
||||
tee.generateUncaughtError();
|
||||
result = CTFEExp.cantexp;
|
||||
}
|
||||
else
|
||||
result = copyRegionExp(result);
|
||||
|
||||
if (!CTFEExp.isCantExp(result))
|
||||
result = scrubReturnValue(e.loc, result);
|
||||
|
@ -1601,14 +1609,20 @@ public:
|
|||
istate.start = null;
|
||||
}
|
||||
|
||||
incUsageCtfe(istate, s.loc);
|
||||
interpretThrow(s.exp, s.loc);
|
||||
}
|
||||
|
||||
Expression e = interpretRegion(s.exp, istate);
|
||||
/// Interpret `throw <exp>` found at the specified location `loc`
|
||||
private void interpretThrow(Expression exp, const ref Loc loc)
|
||||
{
|
||||
incUsageCtfe(istate, loc);
|
||||
|
||||
Expression e = interpretRegion(exp, istate);
|
||||
if (exceptionOrCant(e))
|
||||
return;
|
||||
|
||||
assert(e.op == EXP.classReference);
|
||||
result = ctfeEmplaceExp!ThrownExceptionExp(s.loc, e.isClassReferenceExp());
|
||||
result = ctfeEmplaceExp!ThrownExceptionExp(loc, e.isClassReferenceExp());
|
||||
}
|
||||
|
||||
override void visit(ScopeGuardStatement s)
|
||||
|
@ -6149,6 +6163,15 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
override void visit(ThrowExp te)
|
||||
{
|
||||
debug (LOG)
|
||||
{
|
||||
printf("%s ThrowExpression::interpret()\n", e.loc.toChars());
|
||||
}
|
||||
interpretThrow(te.e1, te.loc);
|
||||
}
|
||||
|
||||
override void visit(PtrExp e)
|
||||
{
|
||||
debug (LOG)
|
||||
|
|
|
@ -59,7 +59,6 @@ enum SCOPE
|
|||
compile = 0x0100, /// inside __traits(compile)
|
||||
ignoresymbolvisibility = 0x0200, /// ignore symbol visibility
|
||||
/// https://issues.dlang.org/show_bug.cgi?id=15907
|
||||
onlysafeaccess = 0x0400, /// unsafe access is not allowed for @safe code
|
||||
Cfile = 0x0800, /// C semantics apply
|
||||
free = 0x8000, /// is on free list
|
||||
|
||||
|
@ -74,7 +73,7 @@ enum SCOPE
|
|||
/// Flags that are carried along with a scope push()
|
||||
private enum PersistentFlags =
|
||||
SCOPE.contract | SCOPE.debug_ | SCOPE.ctfe | SCOPE.compile | SCOPE.constraint |
|
||||
SCOPE.noaccesscheck | SCOPE.onlysafeaccess | SCOPE.ignoresymbolvisibility |
|
||||
SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility |
|
||||
SCOPE.printf | SCOPE.scanf | SCOPE.Cfile;
|
||||
|
||||
struct Scope
|
||||
|
|
|
@ -2345,7 +2345,7 @@ extern (C++) final class DsymbolTable : RootObject
|
|||
Dsymbol handleTagSymbols(ref Scope sc, Dsymbol s, Dsymbol s2, ScopeDsymbol sds)
|
||||
{
|
||||
enum log = false;
|
||||
if (log) printf("handleTagSymbols('%s')\n", s.toChars());
|
||||
if (log) printf("handleTagSymbols('%s') add %p existing %p\n", s.toChars(), s, s2);
|
||||
auto sd = s.isScopeDsymbol(); // new declaration
|
||||
auto sd2 = s2.isScopeDsymbol(); // existing declaration
|
||||
|
||||
|
|
|
@ -356,6 +356,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
if (sc && sc.inunion && sc.inunion.isAnonDeclaration())
|
||||
dsym.overlapped = true;
|
||||
|
||||
dsym.sequenceNumber = global.varSequenceNumber++;
|
||||
|
||||
Scope* scx = null;
|
||||
if (dsym._scope)
|
||||
{
|
||||
|
@ -1636,7 +1638,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
// Should be merged with PragmaStatement
|
||||
//printf("\tPragmaDeclaration::semantic '%s'\n", pd.toChars());
|
||||
if (target.mscoff)
|
||||
if (target.supportsLinkerDirective())
|
||||
{
|
||||
if (pd.ident == Id.linkerDirective)
|
||||
{
|
||||
|
@ -2177,7 +2179,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
{
|
||||
/* C11 6.7.2.2
|
||||
*/
|
||||
ed.memtype = Type.tint32; // C11 6.7.2.2-4 implementation defined
|
||||
assert(ed.memtype);
|
||||
int nextValue = 0; // C11 6.7.2.2-3 first member value defaults to 0
|
||||
|
||||
void emSemantic(EnumMember em, ref int nextValue)
|
||||
|
@ -3457,9 +3459,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
}
|
||||
}
|
||||
|
||||
/* These quirky conditions mimic what VC++ appears to do
|
||||
/* These quirky conditions mimic what happens when virtual
|
||||
inheritance is implemented by producing a virtual base table
|
||||
with offsets to each of the virtual bases.
|
||||
*/
|
||||
if (target.mscoff && cd.classKind == ClassKind.cpp &&
|
||||
if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp &&
|
||||
cd.baseClass && cd.baseClass.vtbl.dim)
|
||||
{
|
||||
/* if overriding an interface function, then this is not
|
||||
|
@ -3557,7 +3561,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
goto Lintro;
|
||||
}
|
||||
|
||||
if (fdv.isDeprecated)
|
||||
if (fdv.isDeprecated && !funcdecl.isDeprecated)
|
||||
deprecation(funcdecl.loc, "`%s` is overriding the deprecated method `%s`",
|
||||
funcdecl.toPrettyChars, fdv.toPrettyChars);
|
||||
|
||||
|
@ -3646,11 +3650,17 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
funcdecl.tintro = fdv.tintro;
|
||||
else if (!funcdecl.type.equals(fdv.type))
|
||||
{
|
||||
auto tnext = funcdecl.type.nextOf();
|
||||
if (auto handle = tnext.isClassHandle())
|
||||
{
|
||||
if (handle.semanticRun < PASS.semanticdone && !handle.isBaseInfoComplete())
|
||||
handle.dsymbolSemantic(null);
|
||||
}
|
||||
/* Only need to have a tintro if the vptr
|
||||
* offsets differ
|
||||
*/
|
||||
int offset;
|
||||
if (fdv.type.nextOf().isBaseOf(funcdecl.type.nextOf(), &offset))
|
||||
if (fdv.type.nextOf().isBaseOf(tnext, &offset))
|
||||
{
|
||||
funcdecl.tintro = fdv.type;
|
||||
}
|
||||
|
@ -3812,7 +3822,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
deprecation(funcdecl.loc,
|
||||
"`%s` cannot be annotated with `@disable` because it is overriding a function in the base class",
|
||||
funcdecl.toPrettyChars);
|
||||
if (funcdecl.isDeprecated)
|
||||
|
||||
if (funcdecl.isDeprecated && !(funcdecl.foverrides.length && funcdecl.foverrides[0].isDeprecated))
|
||||
deprecation(funcdecl.loc,
|
||||
"`%s` cannot be marked as `deprecated` because it is overriding a function in the base class",
|
||||
funcdecl.toPrettyChars);
|
||||
|
|
|
@ -6223,114 +6223,62 @@ extern (C++) class TemplateInstance : ScopeDsymbol
|
|||
*/
|
||||
final bool needsCodegen()
|
||||
{
|
||||
if (!minst)
|
||||
// minst is finalized after the 1st invocation.
|
||||
// tnext and tinst are only needed for the 1st invocation and
|
||||
// cleared for further invocations.
|
||||
TemplateInstance tnext = this.tnext;
|
||||
TemplateInstance tinst = this.tinst;
|
||||
this.tnext = null;
|
||||
this.tinst = null;
|
||||
|
||||
if (errors || (inst && inst.isDiscardable()))
|
||||
{
|
||||
// If this is a speculative instantiation,
|
||||
// 1. do codegen if ancestors really needs codegen.
|
||||
// 2. become non-speculative if siblings are not speculative
|
||||
|
||||
TemplateInstance tnext = this.tnext;
|
||||
TemplateInstance tinst = this.tinst;
|
||||
// At first, disconnect chain first to prevent infinite recursion.
|
||||
this.tnext = null;
|
||||
this.tinst = null;
|
||||
|
||||
// Determine necessity of tinst before tnext.
|
||||
if (tinst && tinst.needsCodegen())
|
||||
{
|
||||
minst = tinst.minst; // cache result
|
||||
if (global.params.allInst && minst)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
assert(minst);
|
||||
assert(minst.isRoot() || minst.rootImports());
|
||||
return true;
|
||||
}
|
||||
if (tnext && (tnext.needsCodegen() || tnext.minst))
|
||||
{
|
||||
minst = tnext.minst; // cache result
|
||||
if (global.params.allInst && minst)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
assert(minst);
|
||||
return minst.isRoot() || minst.rootImports();
|
||||
}
|
||||
|
||||
// Elide codegen because this is really speculative.
|
||||
minst = null; // mark as speculative
|
||||
return false;
|
||||
}
|
||||
|
||||
if (global.params.allInst)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Do codegen if there is an instantiation from a root module, to maximize link-ability.
|
||||
|
||||
if (isDiscardable())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Even when this is reached to the codegen pass,
|
||||
* a non-root nested template should not generate code,
|
||||
* due to avoid ODR violation.
|
||||
*/
|
||||
if (enclosing && enclosing.inNonRoot())
|
||||
{
|
||||
if (tinst)
|
||||
{
|
||||
auto r = tinst.needsCodegen();
|
||||
minst = tinst.minst; // cache result
|
||||
return r;
|
||||
}
|
||||
if (tnext)
|
||||
{
|
||||
auto r = tnext.needsCodegen();
|
||||
minst = tnext.minst; // cache result
|
||||
return r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (global.params.useUnitTests)
|
||||
{
|
||||
// Prefer instantiations from root modules, to maximize link-ability.
|
||||
if (minst.isRoot())
|
||||
// Do codegen if `this` is instantiated from a root module.
|
||||
if (minst && minst.isRoot())
|
||||
return true;
|
||||
|
||||
TemplateInstance tnext = this.tnext;
|
||||
TemplateInstance tinst = this.tinst;
|
||||
this.tnext = null;
|
||||
this.tinst = null;
|
||||
|
||||
// Do codegen if the ancestor needs it.
|
||||
if (tinst && tinst.needsCodegen())
|
||||
{
|
||||
minst = tinst.minst; // cache result
|
||||
assert(minst);
|
||||
assert(minst.isRoot() || minst.rootImports());
|
||||
assert(minst.isRoot());
|
||||
return true;
|
||||
}
|
||||
if (tnext && tnext.needsCodegen())
|
||||
|
||||
// Do codegen if a sibling needs it.
|
||||
if (tnext)
|
||||
{
|
||||
minst = tnext.minst; // cache result
|
||||
assert(minst);
|
||||
assert(minst.isRoot() || minst.rootImports());
|
||||
return true;
|
||||
if (tnext.needsCodegen())
|
||||
{
|
||||
minst = tnext.minst; // cache result
|
||||
assert(minst);
|
||||
assert(minst.isRoot());
|
||||
return true;
|
||||
}
|
||||
else if (!minst && tnext.minst)
|
||||
{
|
||||
minst = tnext.minst; // cache result from non-speculative sibling
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=2500 case
|
||||
if (minst.rootImports())
|
||||
return true;
|
||||
|
||||
// Elide codegen because this is not included in root instances.
|
||||
// Elide codegen because there's no instantiation from any root modules.
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prefer instantiations from non-root module, to minimize object code size.
|
||||
// Prefer instantiations from non-root modules, to minimize object code size.
|
||||
|
||||
/* If a TemplateInstance is ever instantiated by non-root modules,
|
||||
/* If a TemplateInstance is ever instantiated from a non-root module,
|
||||
* we do not have to generate code for it,
|
||||
* because it will be generated when the non-root module is compiled.
|
||||
*
|
||||
|
@ -6341,22 +6289,51 @@ extern (C++) class TemplateInstance : ScopeDsymbol
|
|||
* or the compilation of B do the actual instantiation?
|
||||
*
|
||||
* See https://issues.dlang.org/show_bug.cgi?id=2500.
|
||||
*
|
||||
* => Elide codegen if there is at least one instantiation from a non-root module
|
||||
* which doesn't import any root modules.
|
||||
*/
|
||||
if (!minst.isRoot() && !minst.rootImports())
|
||||
return false;
|
||||
|
||||
TemplateInstance tnext = this.tnext;
|
||||
this.tnext = null;
|
||||
|
||||
if (tnext && !tnext.needsCodegen() && tnext.minst)
|
||||
// If the ancestor isn't speculative,
|
||||
// 1. do codegen if the ancestor needs it
|
||||
// 2. elide codegen if the ancestor doesn't need it (non-root instantiation of ancestor incl. subtree)
|
||||
if (tinst)
|
||||
{
|
||||
minst = tnext.minst; // cache result
|
||||
assert(!minst.isRoot());
|
||||
return false;
|
||||
const needsCodegen = tinst.needsCodegen(); // sets tinst.minst
|
||||
if (tinst.minst) // not speculative
|
||||
{
|
||||
minst = tinst.minst; // cache result
|
||||
return needsCodegen;
|
||||
}
|
||||
}
|
||||
|
||||
// Do codegen because this is not included in non-root instances.
|
||||
return true;
|
||||
// Elide codegen if `this` doesn't need it.
|
||||
if (minst && !minst.isRoot() && !minst.rootImports())
|
||||
return false;
|
||||
|
||||
// Elide codegen if a (non-speculative) sibling doesn't need it.
|
||||
if (tnext)
|
||||
{
|
||||
const needsCodegen = tnext.needsCodegen(); // sets tnext.minst
|
||||
if (tnext.minst) // not speculative
|
||||
{
|
||||
if (!needsCodegen)
|
||||
{
|
||||
minst = tnext.minst; // cache result
|
||||
assert(!minst.isRoot() && !minst.rootImports());
|
||||
return false;
|
||||
}
|
||||
else if (!minst)
|
||||
{
|
||||
minst = tnext.minst; // cache result from non-speculative sibling
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unless `this` is still speculative (=> all further siblings speculative too),
|
||||
// do codegen because we found no guaranteed-codegen'd non-root instantiation.
|
||||
return minst !is null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7311,7 +7288,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
|
|||
if ((td && td.literal) || (ti && ti.enclosing) || (d && !d.isDataseg() && !(d.storage_class & STC.manifest) && (!d.isFuncDeclaration() || d.isFuncDeclaration().isNested()) && !isTemplateMixin()))
|
||||
{
|
||||
Dsymbol dparent = sa.toParent2();
|
||||
if (!dparent)
|
||||
if (!dparent || dparent.isModule)
|
||||
goto L1;
|
||||
else if (!enclosing)
|
||||
enclosing = dparent;
|
||||
|
@ -7370,13 +7347,6 @@ extern (C++) class TemplateInstance : ScopeDsymbol
|
|||
{
|
||||
Module mi = minst; // instantiated . inserted module
|
||||
|
||||
if (global.params.useUnitTests)
|
||||
{
|
||||
// Turn all non-root instances to speculative
|
||||
if (mi && !mi.isRoot())
|
||||
mi = null;
|
||||
}
|
||||
|
||||
//printf("%s.appendToModuleMember() enclosing = %s mi = %s\n",
|
||||
// toPrettyChars(),
|
||||
// enclosing ? enclosing.toPrettyChars() : null,
|
||||
|
|
|
@ -16,6 +16,7 @@ import core.stdc.string;
|
|||
import core.stdc.ctype;
|
||||
|
||||
import dmd.astcodegen;
|
||||
import dmd.astenums;
|
||||
import dmd.arraytypes;
|
||||
import dmd.attrib;
|
||||
import dmd.dsymbol;
|
||||
|
|
|
@ -691,11 +691,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
|
|||
}
|
||||
|
||||
// If va's lifetime encloses v's, then error
|
||||
if (va &&
|
||||
(va.enclosesLifetimeOf(v) && !(v.storage_class & (STC.parameter | STC.temp)) ||
|
||||
// va is class reference
|
||||
ae.e1.isDotVarExp() && va.type.toBasetype().isTypeClass() && (va.enclosesLifetimeOf(v) ||
|
||||
!va.isScope()) ||
|
||||
if (va && !va.isDataseg() &&
|
||||
(va.enclosesLifetimeOf(v) && !(v.storage_class & STC.temp) ||
|
||||
vaIsRef ||
|
||||
va.isReference() && !(v.storage_class & (STC.parameter | STC.temp))) &&
|
||||
fd.setUnsafe())
|
||||
|
@ -768,7 +765,6 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag)
|
|||
}
|
||||
}
|
||||
|
||||
ByRef:
|
||||
foreach (VarDeclaration v; er.byref)
|
||||
{
|
||||
if (log) printf("byref: %s\n", v.toChars());
|
||||
|
@ -797,8 +793,7 @@ ByRef:
|
|||
|
||||
// If va's lifetime encloses v's, then error
|
||||
if (va &&
|
||||
(va.enclosesLifetimeOf(v) && !(v.isParameter() && v.isRef()) ||
|
||||
va.isDataseg()) &&
|
||||
(va.enclosesLifetimeOf(v) || (va.isRef() && !(va.storage_class & STC.temp)) || va.isDataseg()) &&
|
||||
fd.setUnsafe())
|
||||
{
|
||||
if (!gag)
|
||||
|
@ -807,26 +802,6 @@ ByRef:
|
|||
continue;
|
||||
}
|
||||
|
||||
if (va && v.isReference())
|
||||
{
|
||||
Dsymbol pva = va.toParent2();
|
||||
for (Dsymbol pv = p; pv; )
|
||||
{
|
||||
pv = pv.toParent2();
|
||||
if (pva == pv) // if v is nested inside pva
|
||||
{
|
||||
if (fd.setUnsafe())
|
||||
{
|
||||
if (!gag)
|
||||
error(ae.loc, "reference `%s` assigned to `%s` with longer lifetime", v.toChars(), va.toChars());
|
||||
result = true;
|
||||
continue ByRef;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(va && va.isScope()))
|
||||
notMaybeScope(v);
|
||||
|
||||
|
@ -1323,7 +1298,9 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
|
|||
msg = "returning `%s` escapes a reference to parameter `%s`";
|
||||
supplemental = vsr == ScopeRef.Ref_ReturnScope
|
||||
? "perhaps remove `scope` parameter annotation so `return` applies to `ref`"
|
||||
: "perhaps annotate the parameter with `return`";
|
||||
: v.ident is Id.This
|
||||
? "perhaps annotate the function with `return`"
|
||||
: "perhaps annotate the parameter with `return`";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -25,7 +25,6 @@ import dmd.arraytypes;
|
|||
import dmd.astenums;
|
||||
import dmd.ast_node;
|
||||
import dmd.gluelayer;
|
||||
import dmd.canthrow;
|
||||
import dmd.constfold;
|
||||
import dmd.ctfeexpr;
|
||||
import dmd.ctorflow;
|
||||
|
@ -466,7 +465,17 @@ private Expression callCpCtor(Scope* sc, Expression e, Type destinationType)
|
|||
*/
|
||||
auto tmp = copyToTemp(STC.rvalue, "__copytmp", e);
|
||||
if (sd.hasCopyCtor && destinationType)
|
||||
tmp.type = destinationType;
|
||||
{
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22619
|
||||
// If the destination type is inout we can preserve it
|
||||
// only if inside an inout function; if we are not inside
|
||||
// an inout function, then we will preserve the type of
|
||||
// the source
|
||||
if (destinationType.hasWild && !(sc.func.storage_class & STC.wild))
|
||||
tmp.type = e.type;
|
||||
else
|
||||
tmp.type = destinationType;
|
||||
}
|
||||
tmp.storage_class |= STC.nodtor;
|
||||
tmp.dsymbolSemantic(sc);
|
||||
Expression de = new DeclarationExp(e.loc, tmp);
|
||||
|
@ -4680,6 +4689,31 @@ extern (C++) final class AssertExp : UnaExp
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* `throw <e1>` as proposed by DIP 1034.
|
||||
*
|
||||
* Replacement for the deprecated `ThrowStatement` that can be nested
|
||||
* in other expression.
|
||||
*/
|
||||
extern (C++) final class ThrowExp : UnaExp
|
||||
{
|
||||
extern (D) this(const ref Loc loc, Expression e)
|
||||
{
|
||||
super(loc, EXP.throw_, __traits(classInstanceSize, ThrowExp), e);
|
||||
this.type = Type.tnoreturn;
|
||||
}
|
||||
|
||||
override ThrowExp syntaxCopy()
|
||||
{
|
||||
return new ThrowExp(loc, e1.syntaxCopy());
|
||||
}
|
||||
|
||||
override void accept(Visitor v)
|
||||
{
|
||||
v.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
*/
|
||||
extern (C++) final class DotIdExp : UnaExp
|
||||
|
|
|
@ -48,7 +48,9 @@ struct Symbol; // back end symbol
|
|||
void expandTuples(Expressions *exps);
|
||||
bool isTrivialExp(Expression *e);
|
||||
bool hasSideEffect(Expression *e, bool assumeImpureCalls = false);
|
||||
bool canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow);
|
||||
|
||||
enum BE : int32_t;
|
||||
BE canThrow(Expression *e, FuncDeclaration *func, bool mustNotThrow);
|
||||
|
||||
typedef unsigned char OwnedBy;
|
||||
enum
|
||||
|
@ -742,6 +744,14 @@ public:
|
|||
void accept(Visitor *v) { v->visit(this); }
|
||||
};
|
||||
|
||||
class ThrowExp : public UnaExp
|
||||
{
|
||||
public:
|
||||
ThrowExp *syntaxCopy();
|
||||
|
||||
void accept(Visitor *v) { v->visit(this); }
|
||||
};
|
||||
|
||||
class DotIdExp : public UnaExp
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -3604,16 +3604,21 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
{
|
||||
if (!cdthis)
|
||||
{
|
||||
if (!sc.hasThis)
|
||||
{
|
||||
string msg = "cannot construct " ~
|
||||
(cd.isAnonymous ? "anonymous nested class" : "nested class `%s`") ~
|
||||
" because no implicit `this` reference to outer class" ~
|
||||
(cdn.isAnonymous ? "" : " `%s`") ~ " is available\0";
|
||||
|
||||
exp.error(msg.ptr, cd.toChars, cdn.toChars);
|
||||
return setError();
|
||||
}
|
||||
|
||||
// Supply an implicit 'this' and try again
|
||||
exp.thisexp = new ThisExp(exp.loc);
|
||||
for (Dsymbol sp = sc.parent; 1; sp = sp.toParentLocal())
|
||||
{
|
||||
if (!sp)
|
||||
{
|
||||
exp.error("outer class `%s` `this` needed to `new` nested class `%s`",
|
||||
cdn.toChars(), cd.toChars());
|
||||
return setError();
|
||||
}
|
||||
ClassDeclaration cdp = sp.isClassDeclaration();
|
||||
if (!cdp)
|
||||
continue;
|
||||
|
@ -5702,12 +5707,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|| global.params.useDeprecated != DiagnosticReporting.error;
|
||||
const bool preventAliasThis = e.targ.hasDeprecatedAliasThis && !deprecationAllowed;
|
||||
|
||||
// baseClass might not be set if either targ or tspec is forward referenced.
|
||||
if (auto tc = e.targ.isTypeClass())
|
||||
tc.sym.dsymbolSemantic(null);
|
||||
if (auto tc = e.tspec.isTypeClass())
|
||||
tc.sym.dsymbolSemantic(null);
|
||||
|
||||
if (preventAliasThis && e.targ.ty == Tstruct)
|
||||
{
|
||||
if ((cast(TypeStruct) e.targ).implicitConvToWithoutAliasThis(e.tspec))
|
||||
|
@ -6396,6 +6395,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
: Expression.combine(temporariesPrefix, exp).expressionSemantic(sc);
|
||||
}
|
||||
|
||||
override void visit(ThrowExp te)
|
||||
{
|
||||
import dmd.statementsem;
|
||||
|
||||
if (StatementSemanticVisitor.throwSemantic(te.loc, te.e1, sc))
|
||||
result = te;
|
||||
else
|
||||
setError();
|
||||
}
|
||||
|
||||
override void visit(DotIdExp exp)
|
||||
{
|
||||
static if (LOGSEMANTIC)
|
||||
|
@ -6913,6 +6922,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
exp.error("cannot take address of `%s`", exp.e1.toChars());
|
||||
return setError();
|
||||
}
|
||||
if (auto dve = exp.e1.isDotVarExp())
|
||||
{
|
||||
/* https://issues.dlang.org/show_bug.cgi?id=22749
|
||||
* Error about taking address of any bit-field, regardless of
|
||||
* whether SCOPE.Cfile is set.
|
||||
*/
|
||||
if (auto bf = dve.var.isBitFieldDeclaration())
|
||||
{
|
||||
exp.error("cannot take address of bit-field `%s`", bf.toChars());
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
|
||||
bool hasOverloads;
|
||||
if (auto f = isFuncAddress(exp, &hasOverloads))
|
||||
|
@ -7511,6 +7532,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
// https://issues.dlang.org/show_bug.cgi?id=19954
|
||||
if (exp.e1.type.ty == Ttuple)
|
||||
{
|
||||
if (exp.to)
|
||||
{
|
||||
if (TypeTuple tt = exp.to.isTypeTuple())
|
||||
{
|
||||
if (exp.e1.type.implicitConvTo(tt))
|
||||
{
|
||||
result = exp.e1.castTo(sc, tt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
TupleExp te = exp.e1.isTupleExp();
|
||||
if (te.exps.dim == 1)
|
||||
exp.e1 = (*te.exps)[0];
|
||||
|
@ -7531,7 +7563,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
if (exp.to.ty == Ttuple)
|
||||
{
|
||||
exp.error("cannot cast `%s` to tuple type `%s`", exp.e1.toChars(), exp.to.toChars());
|
||||
exp.error("cannot cast `%s` of type `%s` to tuple type `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars());
|
||||
return setError();
|
||||
}
|
||||
|
||||
|
@ -8016,7 +8048,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
Expression el = new ArrayLengthExp(exp.loc, exp.e1);
|
||||
el = el.expressionSemantic(sc);
|
||||
el = el.optimize(WANTvalue);
|
||||
if (el.op == EXP.int64)
|
||||
if (el.op == EXP.int64 && t1b.ty == Tsarray)
|
||||
{
|
||||
// Array length is known at compile-time. Upper is in bounds if it fits length.
|
||||
dinteger_t length = el.toInteger();
|
||||
|
@ -9894,7 +9926,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
Expression id = new IdentifierExp(exp.loc, Id.empty);
|
||||
id = new DotIdExp(exp.loc, id, Id.object);
|
||||
id = new DotIdExp(exp.loc, id, func);
|
||||
id = id.expressionSemantic(sc);
|
||||
|
||||
auto arguments = new Expressions();
|
||||
arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf).expressionSemantic(sc));
|
||||
|
@ -11355,7 +11386,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
return setError();
|
||||
}
|
||||
|
||||
EXP cmpop;
|
||||
|
||||
EXP cmpop = exp.op;
|
||||
if (auto e = exp.op_overload(sc, &cmpop))
|
||||
{
|
||||
if (!e.type.isscalar() && e.type.equals(exp.e1.type))
|
||||
|
@ -11365,6 +11397,38 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
}
|
||||
if (e.op == EXP.call)
|
||||
{
|
||||
|
||||
if (t1.ty == Tclass && t2.ty == Tclass)
|
||||
{
|
||||
// Lower to object.__cmp(e1, e2)
|
||||
Expression cl = new IdentifierExp(exp.loc, Id.empty);
|
||||
cl = new DotIdExp(exp.loc, cl, Id.object);
|
||||
cl = new DotIdExp(exp.loc, cl, Id.__cmp);
|
||||
cl = cl.expressionSemantic(sc);
|
||||
|
||||
auto arguments = new Expressions();
|
||||
// Check if op_overload found a better match by calling e2.opCmp(e1)
|
||||
// If the operands were swapped, then the result must be reversed
|
||||
// e1.opCmp(e2) == -e2.opCmp(e1)
|
||||
// cmpop takes care of this
|
||||
if (exp.op == cmpop)
|
||||
{
|
||||
arguments.push(exp.e1);
|
||||
arguments.push(exp.e2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use better match found by op_overload
|
||||
arguments.push(exp.e2);
|
||||
arguments.push(exp.e1);
|
||||
}
|
||||
|
||||
cl = new CallExp(exp.loc, cl, arguments);
|
||||
cl = new CmpExp(cmpop, exp.loc, cl, new IntegerExp(0));
|
||||
result = cl.expressionSemantic(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
e = new CmpExp(cmpop, exp.loc, e, IntegerExp.literal!0);
|
||||
e = e.expressionSemantic(sc);
|
||||
}
|
||||
|
@ -11372,6 +11436,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
if (Expression ex = typeCombine(exp, sc))
|
||||
{
|
||||
result = ex;
|
||||
|
@ -13213,7 +13278,16 @@ Expression getVarExp(EnumMember em, const ref Loc loc, Scope* sc)
|
|||
if (em.errors)
|
||||
return ErrorExp.get();
|
||||
Expression e = new VarExp(loc, em);
|
||||
return e.expressionSemantic(sc);
|
||||
e = e.expressionSemantic(sc);
|
||||
if (!(sc.flags & SCOPE.Cfile) && em.isCsymbol())
|
||||
{
|
||||
/* C11 types them as int. But if in D file,
|
||||
* type qualified names as the enum
|
||||
*/
|
||||
e.type = em.parent.isEnumDeclaration().type;
|
||||
assert(e.type);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
|
@ -13245,6 +13319,8 @@ Expression toBoolean(Expression exp, Scope* sc)
|
|||
case EXP.assign:
|
||||
case EXP.construct:
|
||||
case EXP.blit:
|
||||
if (sc.flags & SCOPE.Cfile)
|
||||
return exp;
|
||||
// Things like:
|
||||
// if (a = b) ...
|
||||
// are usually mistakes.
|
||||
|
|
|
@ -3052,7 +3052,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
|
|||
// all of overloads are templates
|
||||
if (td)
|
||||
{
|
||||
.error(loc, "%s `%s.%s` cannot deduce function from argument types `!(%s)%s`",
|
||||
.error(loc, "none of the overloads of %s `%s.%s` are callable using argument types `!(%s)%s`",
|
||||
td.kind(), td.parent.toPrettyChars(), td.ident.toChars(),
|
||||
tiargsBuf.peekChars(), fargsBuf.peekChars());
|
||||
|
||||
|
|
|
@ -327,6 +327,7 @@ extern (C++) struct Global
|
|||
Array!Identifier* debugids; /// command line debug versions and predefined versions
|
||||
|
||||
bool hasMainFunction; /// Whether a main function has already been compiled in (for -main switch)
|
||||
uint varSequenceNumber = 1; /// Relative lifetime of `VarDeclaration` within a function, used for `scope` checks
|
||||
|
||||
enum recursionLimit = 500; /// number of recursive template expansions before abort
|
||||
|
||||
|
@ -614,48 +615,5 @@ nothrow:
|
|||
}
|
||||
}
|
||||
|
||||
/// A linkage attribute as defined by `extern(XXX)`
|
||||
///
|
||||
/// https://dlang.org/spec/attribute.html#linkage
|
||||
enum LINK : ubyte
|
||||
{
|
||||
default_,
|
||||
d,
|
||||
c,
|
||||
cpp,
|
||||
windows,
|
||||
objc,
|
||||
system,
|
||||
}
|
||||
|
||||
/// Whether to mangle an external aggregate as a struct or class, as set by `extern(C++, struct)`
|
||||
enum CPPMANGLE : ubyte
|
||||
{
|
||||
def, /// default
|
||||
asStruct, /// `extern(C++, struct)`
|
||||
asClass, /// `extern(C++, class)`
|
||||
}
|
||||
|
||||
/// Function match levels
|
||||
///
|
||||
/// https://dlang.org/spec/function.html#function-overloading
|
||||
enum MATCH : int
|
||||
{
|
||||
nomatch, /// no match
|
||||
convert, /// match with conversions
|
||||
constant, /// match with conversion to const
|
||||
exact, /// exact match
|
||||
}
|
||||
|
||||
/// Inline setting as defined by `pragma(inline, XXX)`
|
||||
enum PINLINE : ubyte
|
||||
{
|
||||
default_, /// as specified on the command line
|
||||
never, /// never inline
|
||||
always, /// always inline
|
||||
}
|
||||
|
||||
alias StorageClass = ulong;
|
||||
|
||||
/// Collection of global state
|
||||
extern (C++) __gshared Global global;
|
||||
|
|
|
@ -290,6 +290,7 @@ struct Global
|
|||
Array<class Identifier*>* debugids; // command line debug versions and predefined versions
|
||||
|
||||
bool hasMainFunction;
|
||||
unsigned varSequenceNumber;
|
||||
|
||||
/* Start gagging. Return the current number of gagged errors
|
||||
*/
|
||||
|
|
|
@ -2364,6 +2364,12 @@ public:
|
|||
buf.writeByte(')');
|
||||
}
|
||||
|
||||
override void visit(ThrowExp e)
|
||||
{
|
||||
buf.writestring("throw ");
|
||||
expToBuffer(e.e1, PREC.unary, buf, hgs);
|
||||
}
|
||||
|
||||
override void visit(DotIdExp e)
|
||||
{
|
||||
expToBuffer(e.e1, PREC.primary, buf, hgs);
|
||||
|
@ -3896,6 +3902,11 @@ private void typeToBufferx(Type t, OutBuffer* buf, HdrGenState* hgs)
|
|||
buf.writeByte(' ');
|
||||
if (t.id)
|
||||
buf.writestring(t.id.toChars());
|
||||
if (t.base.ty != TY.Tint32)
|
||||
{
|
||||
buf.writestring(" : ");
|
||||
visitWithMask(t.base, t.mod, buf, hgs);
|
||||
}
|
||||
}
|
||||
|
||||
void visitTuple(TypeTuple t)
|
||||
|
|
|
@ -478,6 +478,7 @@ immutable Msgtable[] msgtable =
|
|||
{ "hasCopyConstructor" },
|
||||
{ "isCopyable" },
|
||||
{ "toType" },
|
||||
{ "parameters" },
|
||||
|
||||
// For C++ mangling
|
||||
{ "allocator" },
|
||||
|
@ -507,12 +508,11 @@ immutable Msgtable[] msgtable =
|
|||
{ "__func__" },
|
||||
{ "noreturn" },
|
||||
{ "__pragma", "pragma" },
|
||||
{ "builtins", "__builtins" },
|
||||
{ "builtin_va_list", "__builtin_va_list" },
|
||||
{ "builtin_va_start", "__builtin_va_start" },
|
||||
{ "builtin_va_arg", "__builtin_va_arg" },
|
||||
{ "builtin_va_copy", "__builtin_va_copy" },
|
||||
{ "builtin_va_end", "__builtin_va_end" },
|
||||
{ "va_list_tag", "__va_list_tag" },
|
||||
{ "va_arg" },
|
||||
{ "pack" },
|
||||
{ "show" },
|
||||
{ "push" },
|
||||
|
|
|
@ -302,8 +302,7 @@ public:
|
|||
//property(name, "impure");
|
||||
break;
|
||||
case PURE.weak: return property(name, "weak");
|
||||
case PURE.const_: return property(name, "const");
|
||||
case PURE.strong: return property(name, "strong");
|
||||
case PURE.const_: return property(name, "strong");
|
||||
case PURE.fwdref: return property(name, "fwdref");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,6 +230,57 @@ bool isSomeChar(TY ty) pure nothrow @nogc @safe
|
|||
return ty == Tchar || ty == Twchar || ty == Tdchar;
|
||||
}
|
||||
|
||||
/************************************
|
||||
* Determine mutability of indirections in (ref) t.
|
||||
*
|
||||
* Returns: When the type has any mutable indirections, returns 0.
|
||||
* When all indirections are immutable, returns 2.
|
||||
* Otherwise, when the type has const/inout indirections, returns 1.
|
||||
*
|
||||
* Params:
|
||||
* isref = if true, check `ref t`; otherwise, check just `t`
|
||||
* t = the type that is being checked
|
||||
*/
|
||||
int mutabilityOfType(bool isref, Type t)
|
||||
{
|
||||
if (isref)
|
||||
{
|
||||
if (t.mod & MODFlags.immutable_)
|
||||
return 2;
|
||||
if (t.mod & (MODFlags.const_ | MODFlags.wild))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
t = t.baseElemOf();
|
||||
|
||||
if (!t.hasPointers() || t.mod & MODFlags.immutable_)
|
||||
return 2;
|
||||
|
||||
/* Accept immutable(T)[] and immutable(T)* as being strongly pure
|
||||
*/
|
||||
if (t.ty == Tarray || t.ty == Tpointer)
|
||||
{
|
||||
Type tn = t.nextOf().toBasetype();
|
||||
if (tn.mod & MODFlags.immutable_)
|
||||
return 2;
|
||||
if (tn.mod & (MODFlags.const_ | MODFlags.wild))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* The rest of this is too strict; fix later.
|
||||
* For example, the only pointer members of a struct may be immutable,
|
||||
* which would maintain strong purity.
|
||||
* (Just like for dynamic arrays and pointers above.)
|
||||
*/
|
||||
if (t.mod & (MODFlags.const_ | MODFlags.wild))
|
||||
return 1;
|
||||
|
||||
/* Should catch delegates and function pointers, and fold in their purity
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* dotExp() bit flags
|
||||
*/
|
||||
|
@ -4217,54 +4268,11 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
if (tf.purity != PURE.fwdref)
|
||||
return;
|
||||
|
||||
/* Determine purity level based on mutability of t
|
||||
* and whether it is a 'ref' type or not.
|
||||
*/
|
||||
static PURE purityOfType(bool isref, Type t)
|
||||
{
|
||||
if (isref)
|
||||
{
|
||||
if (t.mod & MODFlags.immutable_)
|
||||
return PURE.strong;
|
||||
if (t.mod & (MODFlags.const_ | MODFlags.wild))
|
||||
return PURE.const_;
|
||||
return PURE.weak;
|
||||
}
|
||||
|
||||
t = t.baseElemOf();
|
||||
|
||||
if (!t.hasPointers() || t.mod & MODFlags.immutable_)
|
||||
return PURE.strong;
|
||||
|
||||
/* Accept immutable(T)[] and immutable(T)* as being strongly pure
|
||||
*/
|
||||
if (t.ty == Tarray || t.ty == Tpointer)
|
||||
{
|
||||
Type tn = t.nextOf().toBasetype();
|
||||
if (tn.mod & MODFlags.immutable_)
|
||||
return PURE.strong;
|
||||
if (tn.mod & (MODFlags.const_ | MODFlags.wild))
|
||||
return PURE.const_;
|
||||
}
|
||||
|
||||
/* The rest of this is too strict; fix later.
|
||||
* For example, the only pointer members of a struct may be immutable,
|
||||
* which would maintain strong purity.
|
||||
* (Just like for dynamic arrays and pointers above.)
|
||||
*/
|
||||
if (t.mod & (MODFlags.const_ | MODFlags.wild))
|
||||
return PURE.const_;
|
||||
|
||||
/* Should catch delegates and function pointers, and fold in their purity
|
||||
*/
|
||||
return PURE.weak;
|
||||
}
|
||||
|
||||
purity = PURE.strong; // assume strong until something weakens it
|
||||
purity = PURE.const_; // assume strong until something weakens it
|
||||
|
||||
/* Evaluate what kind of purity based on the modifiers for the parameters
|
||||
*/
|
||||
Lloop: foreach (i, fparam; tf.parameterList)
|
||||
foreach (i, fparam; tf.parameterList)
|
||||
{
|
||||
Type t = fparam.type;
|
||||
if (!t)
|
||||
|
@ -4275,33 +4283,11 @@ extern (C++) final class TypeFunction : TypeNext
|
|||
purity = PURE.weak;
|
||||
break;
|
||||
}
|
||||
switch (purityOfType((fparam.storageClass & STC.ref_) != 0, t))
|
||||
{
|
||||
case PURE.weak:
|
||||
purity = PURE.weak;
|
||||
break Lloop; // since PURE.weak, no need to check further
|
||||
|
||||
case PURE.const_:
|
||||
purity = PURE.const_;
|
||||
continue;
|
||||
|
||||
case PURE.strong:
|
||||
continue;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
const pref = (fparam.storageClass & STC.ref_) != 0;
|
||||
if (mutabilityOfType(pref, t) == 0)
|
||||
purity = PURE.weak;
|
||||
}
|
||||
|
||||
if (purity > PURE.weak && tf.nextOf())
|
||||
{
|
||||
/* Adjust purity based on mutability of return type.
|
||||
* https://issues.dlang.org/show_bug.cgi?id=15862
|
||||
*/
|
||||
const purity2 = purityOfType(tf.isref, tf.nextOf());
|
||||
if (purity2 < purity)
|
||||
purity = purity2;
|
||||
}
|
||||
tf.purity = purity;
|
||||
}
|
||||
|
||||
|
@ -6306,10 +6292,7 @@ extern (C++) final class TypeClass : Type
|
|||
|
||||
extern (D) MATCH implicitConvToWithoutAliasThis(Type to)
|
||||
{
|
||||
MATCH m = constConv(to);
|
||||
if (m > MATCH.nomatch)
|
||||
return m;
|
||||
|
||||
// Run semantic before checking whether class is convertible
|
||||
ClassDeclaration cdto = to.isClassHandle();
|
||||
if (cdto)
|
||||
{
|
||||
|
@ -6318,11 +6301,15 @@ extern (C++) final class TypeClass : Type
|
|||
cdto.dsymbolSemantic(null);
|
||||
if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
|
||||
sym.dsymbolSemantic(null);
|
||||
if (cdto.isBaseOf(sym, null) && MODimplicitConv(mod, to.mod))
|
||||
{
|
||||
//printf("'to' is base\n");
|
||||
return MATCH.convert;
|
||||
}
|
||||
}
|
||||
MATCH m = constConv(to);
|
||||
if (m > MATCH.nomatch)
|
||||
return m;
|
||||
|
||||
if (cdto && cdto.isBaseOf(sym, null) && MODimplicitConv(mod, to.mod))
|
||||
{
|
||||
//printf("'to' is base\n");
|
||||
return MATCH.convert;
|
||||
}
|
||||
return MATCH.nomatch;
|
||||
}
|
||||
|
@ -6373,6 +6360,9 @@ extern (C++) final class TypeClass : Type
|
|||
|
||||
override MOD deduceWild(Type t, bool isRef)
|
||||
{
|
||||
// If sym is forward referenced:
|
||||
if (sym.semanticRun < PASS.semanticdone && !sym.isBaseInfoComplete())
|
||||
sym.dsymbolSemantic(null);
|
||||
ClassDeclaration cd = t.isClassHandle();
|
||||
if (cd && (sym == cd || cd.isBaseOf(sym, null)))
|
||||
return Type.deduceWild(t, isRef);
|
||||
|
@ -6760,19 +6750,21 @@ extern (C++) final class TypeTag : Type
|
|||
Loc loc; /// location of declaration
|
||||
TOK tok; /// TOK.struct_, TOK.union_, TOK.enum_
|
||||
Identifier id; /// tag name identifier
|
||||
Type base; /// base type for enums otherwise null
|
||||
Dsymbols* members; /// members of struct, null if none
|
||||
|
||||
Type resolved; /// type after semantic() in case there are more others
|
||||
/// pointing to this instance, which can happen with
|
||||
/// struct S { int a; } s1, *s2;
|
||||
|
||||
extern (D) this(const ref Loc loc, TOK tok, Identifier id, Dsymbols* members)
|
||||
extern (D) this(const ref Loc loc, TOK tok, Identifier id, Type base, Dsymbols* members)
|
||||
{
|
||||
//printf("TypeTag %p\n", this);
|
||||
super(Ttag);
|
||||
this.loc = loc;
|
||||
this.tok = tok;
|
||||
this.id = id;
|
||||
this.base = base;
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
|
|
|
@ -553,7 +553,6 @@ enum class PURE : unsigned char
|
|||
fwdref = 1, // it's pure, but not known which level yet
|
||||
weak = 2, // no mutable globals are read or written
|
||||
const_ = 3, // parameters are values or const
|
||||
strong = 4 // parameters are values or immutable
|
||||
};
|
||||
|
||||
class Parameter : public ASTNode
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
if (!e.f)
|
||||
return;
|
||||
|
||||
// Treat lowered hook calls as their original expressions.
|
||||
auto fd = stripHookTraceImpl(e.f);
|
||||
if (fd.ident == Id._d_arraysetlengthT)
|
||||
{
|
||||
|
|
|
@ -48,6 +48,7 @@ module dmd.nspace;
|
|||
|
||||
import dmd.aggregate;
|
||||
import dmd.arraytypes;
|
||||
import dmd.astenums;
|
||||
import dmd.dscope;
|
||||
import dmd.dsymbol;
|
||||
import dmd.dsymbolsem;
|
||||
|
|
|
@ -818,64 +818,6 @@ extern(C++) private final class Supported : Objc
|
|||
expression.errorSupplemental("`tupleof` is not available for members " ~
|
||||
"of Objective-C classes. Please use the Objective-C runtime instead");
|
||||
}
|
||||
|
||||
extern(D) private:
|
||||
|
||||
/**
|
||||
* Returns `true` if the given symbol is a symbol declared in
|
||||
* `core.attribute` and has the given identifier.
|
||||
*
|
||||
* This is used to determine if a symbol is a UDA declared in
|
||||
* `core.attribute`.
|
||||
*
|
||||
* Params:
|
||||
* sd = the symbol to check
|
||||
* ident = the name of the expected UDA
|
||||
*/
|
||||
bool isCoreUda(ScopeDsymbol sd, Identifier ident) const
|
||||
{
|
||||
if (sd.ident != ident || !sd.parent)
|
||||
return false;
|
||||
|
||||
auto _module = sd.parent.isModule();
|
||||
return _module && _module.isCoreModule(Id.attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates the UDAs attached to the given function declaration.
|
||||
*
|
||||
* If `dg` returns `!= 0`, it will stop the iteration and return that
|
||||
* value, otherwise it will return 0.
|
||||
*
|
||||
* Params:
|
||||
* fd = the function declaration to get the UDAs from
|
||||
* dg = called once for each UDA. If `dg` returns `!= 0`, it will stop the
|
||||
* iteration and return that value, otherwise it will return `0`.
|
||||
*/
|
||||
int foreachUda(FuncDeclaration fd, Scope* sc, int delegate(Expression) dg) const
|
||||
{
|
||||
if (!fd.userAttribDecl)
|
||||
return 0;
|
||||
|
||||
auto udas = fd.userAttribDecl.getAttributes();
|
||||
arrayExpressionSemantic(udas, sc, true);
|
||||
|
||||
return udas.each!((uda) {
|
||||
if (!uda.isTupleExp())
|
||||
return 0;
|
||||
|
||||
auto exps = uda.isTupleExp().exps;
|
||||
|
||||
return exps.each!((e) {
|
||||
assert(e);
|
||||
|
||||
if (auto result = dg(e))
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -853,11 +853,11 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
|
|||
{
|
||||
// Rewrite (e1 op e2) as e2.opfunc(e1)
|
||||
result = build_overload(e.loc, sc, e.e2, e.e1, m.lastf ? m.lastf : s);
|
||||
// When reversing operands of comparison operators,
|
||||
// need to reverse the sense of the op
|
||||
if (pop)
|
||||
*pop = reverseRelation(e.op);
|
||||
}
|
||||
// When reversing operands of comparison operators,
|
||||
// need to reverse the sense of the op
|
||||
if (pop)
|
||||
*pop = reverseRelation(e.op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1052,7 +1052,7 @@ Expression op_overload(Expression e, Scope* sc, EXP* pop = null)
|
|||
e.e2 = new DotIdExp(e.loc, e.e2, Id._tupleof);
|
||||
|
||||
auto sc2 = sc.push();
|
||||
sc2.flags = (sc2.flags & ~SCOPE.onlysafeaccess) | SCOPE.noaccesscheck;
|
||||
sc2.flags |= SCOPE.noaccesscheck;
|
||||
result = e.expressionSemantic(sc2);
|
||||
sc2.pop();
|
||||
|
||||
|
|
|
@ -1130,8 +1130,8 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue)
|
|||
const e1Opt = e.e1.toBool();
|
||||
if (e.e2.isConst())
|
||||
{
|
||||
bool n1 = e1Opt.hasValue(true);
|
||||
bool n2 = e.e2.toBool().hasValue(true);
|
||||
bool n1 = e1Opt.get();
|
||||
bool n2 = e.e2.toBool().get();
|
||||
ret = new IntegerExp(e.loc, oror ? (n1 || n2) : (n1 && n2), e.type);
|
||||
}
|
||||
else if (e1Opt.hasValue(!oror))
|
||||
|
|
|
@ -128,6 +128,7 @@ immutable PREC[EXP.max + 1] precedence =
|
|||
EXP.new_ : PREC.unary,
|
||||
EXP.newAnonymousClass : PREC.unary,
|
||||
EXP.cast_ : PREC.unary,
|
||||
EXP.throw_ : PREC.unary,
|
||||
|
||||
EXP.vector : PREC.unary,
|
||||
EXP.pow : PREC.pow,
|
||||
|
@ -443,6 +444,13 @@ class Parser(AST) : Lexer
|
|||
}
|
||||
|
||||
decldefs = parseDeclDefs(0, &lastDecl);
|
||||
|
||||
if (token.value == TOK.rightCurly)
|
||||
{
|
||||
error(token.loc, "unmatched closing brace");
|
||||
goto Lerr;
|
||||
}
|
||||
|
||||
if (token.value != TOK.endOfFile)
|
||||
{
|
||||
error(token.loc, "unrecognized declaration");
|
||||
|
@ -643,7 +651,43 @@ class Parser(AST) : Lexer
|
|||
goto Lerror;
|
||||
|
||||
case TOK.unittest_:
|
||||
if (global.params.useUnitTests || global.params.doDocComments || global.params.doHdrGeneration)
|
||||
/**
|
||||
* Ignore unittests in non-root modules.
|
||||
*
|
||||
* This mainly means that unittests *inside templates* are only
|
||||
* ever instantiated if the module lexically declaring the
|
||||
* template is one of the root modules.
|
||||
*
|
||||
* E.g., compiling some project with `-unittest` does NOT
|
||||
* compile and later run any unittests in instantiations of
|
||||
* templates declared in other libraries.
|
||||
*
|
||||
* Declaring unittests *inside* templates is considered an anti-
|
||||
* pattern. In almost all cases, the unittests don't depend on
|
||||
* the template parameters, but instantiate the template with
|
||||
* fixed arguments (e.g., Nullable!T unittests instantiating
|
||||
* Nullable!int), so compiling and running identical tests for
|
||||
* each template instantiation is hardly desirable.
|
||||
* But adding a unittest right below some function being tested
|
||||
* is arguably good for locality, so unittests end up inside
|
||||
* templates.
|
||||
* To make sure a template's unittests are run, it should be
|
||||
* instantiated in the same module, e.g., some module-level
|
||||
* unittest.
|
||||
*
|
||||
* Another reason for ignoring unittests in templates from non-
|
||||
* root modules is for template codegen culling via
|
||||
* TemplateInstance.needsCodegen(). If the compiler decides not
|
||||
* to emit some Nullable!bool because there's an existing
|
||||
* instantiation in some non-root module, it has no idea whether
|
||||
* that module was compiled with -unittest too, and so whether
|
||||
* Nullable!int (instantiated in some unittest inside the
|
||||
* Nullable template) can be culled too. By ignoring unittests
|
||||
* in non-root modules, the compiler won't consider any
|
||||
* template instantiations in these unittests as candidates for
|
||||
* further codegen culling.
|
||||
*/
|
||||
if (mod.isRoot() && (global.params.useUnitTests || global.params.doDocComments || global.params.doHdrGeneration))
|
||||
{
|
||||
s = parseUnitTest(pAttrs);
|
||||
if (*pLastDecl)
|
||||
|
@ -1530,6 +1574,8 @@ class Parser(AST) : Lexer
|
|||
|
||||
case TOK.return_:
|
||||
stc = STC.return_;
|
||||
if (peekNext() == TOK.scope_)
|
||||
stc |= STC.returnScope; // recognize `return scope`
|
||||
break;
|
||||
|
||||
case TOK.scope_:
|
||||
|
@ -2880,7 +2926,7 @@ class Parser(AST) : Lexer
|
|||
StorageClass varargsStc;
|
||||
|
||||
// Attributes allowed for ...
|
||||
enum VarArgsStc = STC.const_ | STC.immutable_ | STC.shared_ | STC.scope_ | STC.return_;
|
||||
enum VarArgsStc = STC.const_ | STC.immutable_ | STC.shared_ | STC.scope_ | STC.return_ | STC.returnScope;
|
||||
|
||||
check(TOK.leftParenthesis);
|
||||
while (1)
|
||||
|
@ -2988,6 +3034,8 @@ class Parser(AST) : Lexer
|
|||
|
||||
case TOK.return_:
|
||||
stc = STC.return_;
|
||||
if (peekNext() == TOK.scope_)
|
||||
stc |= STC.returnScope;
|
||||
goto L2;
|
||||
L2:
|
||||
storageClass = appendStorageClass(storageClass, stc);
|
||||
|
@ -3491,7 +3539,7 @@ class Parser(AST) : Lexer
|
|||
return baseclasses;
|
||||
}
|
||||
|
||||
private AST.Dsymbols* parseImport()
|
||||
AST.Dsymbols* parseImport()
|
||||
{
|
||||
auto decldefs = new AST.Dsymbols();
|
||||
Identifier aliasid = null;
|
||||
|
@ -4453,7 +4501,6 @@ class Parser(AST) : Lexer
|
|||
private AST.Dsymbols* parseDeclarations(bool autodecl, PrefixAttributes!AST* pAttrs, const(char)* comment)
|
||||
{
|
||||
StorageClass storage_class = STC.undefined_;
|
||||
TOK tok = TOK.reserved;
|
||||
LINK link = linkage;
|
||||
Loc linkloc = this.linkLoc;
|
||||
bool setAlignment = false;
|
||||
|
@ -4464,245 +4511,22 @@ class Parser(AST) : Lexer
|
|||
if (!comment)
|
||||
comment = token.blockComment.ptr;
|
||||
|
||||
/* Look for AliasAssignment:
|
||||
* identifier = type;
|
||||
/* Look for AliasReassignment
|
||||
*/
|
||||
if (token.value == TOK.identifier && peekNext() == TOK.assign)
|
||||
{
|
||||
const loc = token.loc;
|
||||
auto ident = token.ident;
|
||||
nextToken();
|
||||
nextToken(); // advance past =
|
||||
auto t = parseType();
|
||||
AST.Dsymbol s = new AST.AliasAssign(loc, ident, t, null);
|
||||
check(TOK.semicolon);
|
||||
addComment(s, comment);
|
||||
auto a = new AST.Dsymbols();
|
||||
a.push(s);
|
||||
return a;
|
||||
}
|
||||
return parseAliasReassignment(comment);
|
||||
|
||||
/* Declarations that start with `alias`
|
||||
*/
|
||||
bool isAliasDeclaration = false;
|
||||
if (token.value == TOK.alias_)
|
||||
{
|
||||
const loc = token.loc;
|
||||
tok = token.value;
|
||||
nextToken();
|
||||
|
||||
/* Look for:
|
||||
* alias identifier this;
|
||||
*/
|
||||
if (token.value == TOK.identifier && peekNext() == TOK.this_)
|
||||
{
|
||||
auto s = new AST.AliasThis(loc, token.ident);
|
||||
nextToken();
|
||||
check(TOK.this_);
|
||||
check(TOK.semicolon);
|
||||
auto a = new AST.Dsymbols();
|
||||
a.push(s);
|
||||
addComment(s, comment);
|
||||
if (auto a = parseAliasDeclarations(comment))
|
||||
return a;
|
||||
}
|
||||
version (none)
|
||||
{
|
||||
/* Look for:
|
||||
* alias this = identifier;
|
||||
*/
|
||||
if (token.value == TOK.this_ && peekNext() == TOK.assign && peekNext2() == TOK.identifier)
|
||||
{
|
||||
check(TOK.this_);
|
||||
check(TOK.assign);
|
||||
auto s = new AliasThis(loc, token.ident);
|
||||
nextToken();
|
||||
check(TOK.semicolon);
|
||||
auto a = new Dsymbols();
|
||||
a.push(s);
|
||||
addComment(s, comment);
|
||||
return a;
|
||||
}
|
||||
}
|
||||
/* Look for:
|
||||
* alias identifier = type;
|
||||
* alias identifier(...) = type;
|
||||
/* Handle these later:
|
||||
* alias StorageClasses type ident;
|
||||
*/
|
||||
if (token.value == TOK.identifier && hasOptionalParensThen(peek(&token), TOK.assign))
|
||||
{
|
||||
auto a = new AST.Dsymbols();
|
||||
while (1)
|
||||
{
|
||||
auto ident = token.ident;
|
||||
nextToken();
|
||||
AST.TemplateParameters* tpl = null;
|
||||
if (token.value == TOK.leftParenthesis)
|
||||
tpl = parseTemplateParameterList();
|
||||
check(TOK.assign);
|
||||
|
||||
bool hasParsedAttributes;
|
||||
void parseAttributes()
|
||||
{
|
||||
if (hasParsedAttributes) // only parse once
|
||||
return;
|
||||
hasParsedAttributes = true;
|
||||
udas = null;
|
||||
storage_class = STC.undefined_;
|
||||
link = linkage;
|
||||
linkloc = this.linkLoc;
|
||||
setAlignment = false;
|
||||
ealign = null;
|
||||
parseStorageClasses(storage_class, link, setAlignment, ealign, udas, linkloc);
|
||||
}
|
||||
|
||||
if (token.value == TOK.at)
|
||||
parseAttributes;
|
||||
|
||||
AST.Declaration v;
|
||||
AST.Dsymbol s;
|
||||
|
||||
// try to parse function type:
|
||||
// TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes
|
||||
bool attributesAppended;
|
||||
const StorageClass funcStc = parseTypeCtor();
|
||||
Token* tlu = &token;
|
||||
Token* tk;
|
||||
if (token.value != TOK.function_ &&
|
||||
token.value != TOK.delegate_ &&
|
||||
isBasicType(&tlu) && tlu &&
|
||||
tlu.value == TOK.leftParenthesis)
|
||||
{
|
||||
AST.Type tret = parseBasicType();
|
||||
auto parameterList = parseParameterList(null);
|
||||
|
||||
parseAttributes();
|
||||
if (udas)
|
||||
error("user-defined attributes not allowed for `alias` declarations");
|
||||
|
||||
attributesAppended = true;
|
||||
storage_class = appendStorageClass(storage_class, funcStc);
|
||||
AST.Type tf = new AST.TypeFunction(parameterList, tret, link, storage_class);
|
||||
v = new AST.AliasDeclaration(loc, ident, tf);
|
||||
}
|
||||
else if (token.value == TOK.function_ ||
|
||||
token.value == TOK.delegate_ ||
|
||||
token.value == TOK.leftParenthesis &&
|
||||
skipAttributes(peekPastParen(&token), &tk) &&
|
||||
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly) ||
|
||||
token.value == TOK.leftCurly ||
|
||||
token.value == TOK.identifier && peekNext() == TOK.goesTo ||
|
||||
token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis &&
|
||||
skipAttributes(peekPastParen(peek(&token)), &tk) &&
|
||||
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly)
|
||||
)
|
||||
{
|
||||
// function (parameters) { statements... }
|
||||
// delegate (parameters) { statements... }
|
||||
// (parameters) { statements... }
|
||||
// (parameters) => expression
|
||||
// { statements... }
|
||||
// identifier => expression
|
||||
// ref (parameters) { statements... }
|
||||
// ref (parameters) => expression
|
||||
|
||||
s = parseFunctionLiteral();
|
||||
|
||||
if (udas !is null)
|
||||
{
|
||||
if (storage_class != 0)
|
||||
error("Cannot put a storage-class in an alias declaration.");
|
||||
// parseAttributes shouldn't have set these variables
|
||||
assert(link == linkage && !setAlignment && ealign is null);
|
||||
auto tpl_ = cast(AST.TemplateDeclaration) s;
|
||||
assert(tpl_ !is null && tpl_.members.dim == 1);
|
||||
auto fd = cast(AST.FuncLiteralDeclaration) (*tpl_.members)[0];
|
||||
auto tf = cast(AST.TypeFunction) fd.type;
|
||||
assert(tf.parameterList.parameters.dim > 0);
|
||||
auto as = new AST.Dsymbols();
|
||||
(*tf.parameterList.parameters)[0].userAttribDecl = new AST.UserAttributeDeclaration(udas, as);
|
||||
}
|
||||
|
||||
v = new AST.AliasDeclaration(loc, ident, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseAttributes();
|
||||
// type
|
||||
if (udas)
|
||||
error("user-defined attributes not allowed for `%s` declarations", Token.toChars(tok));
|
||||
|
||||
auto t = parseType();
|
||||
|
||||
// Disallow meaningless storage classes on type aliases
|
||||
if (storage_class)
|
||||
{
|
||||
// Don't raise errors for STC that are part of a function/delegate type, e.g.
|
||||
// `alias F = ref pure nothrow @nogc @safe int function();`
|
||||
auto tp = t.isTypePointer;
|
||||
const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate;
|
||||
const remStc = isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class;
|
||||
|
||||
if (remStc)
|
||||
{
|
||||
OutBuffer buf;
|
||||
AST.stcToBuffer(&buf, remStc);
|
||||
// @@@DEPRECATED_2.093@@@
|
||||
// Deprecated in 2020-07, can be made an error in 2.103
|
||||
deprecation("storage class `%s` has no effect in type aliases", buf.peekChars());
|
||||
}
|
||||
}
|
||||
|
||||
v = new AST.AliasDeclaration(loc, ident, t);
|
||||
}
|
||||
if (!attributesAppended)
|
||||
storage_class = appendStorageClass(storage_class, funcStc);
|
||||
v.storage_class = storage_class;
|
||||
|
||||
s = v;
|
||||
if (tpl)
|
||||
{
|
||||
auto a2 = new AST.Dsymbols();
|
||||
a2.push(s);
|
||||
auto tempdecl = new AST.TemplateDeclaration(loc, ident, tpl, null, a2);
|
||||
s = tempdecl;
|
||||
}
|
||||
if (link != linkage)
|
||||
{
|
||||
auto a2 = new AST.Dsymbols();
|
||||
a2.push(s);
|
||||
s = new AST.LinkDeclaration(linkloc, link, a2);
|
||||
}
|
||||
a.push(s);
|
||||
|
||||
switch (token.value)
|
||||
{
|
||||
case TOK.semicolon:
|
||||
nextToken();
|
||||
addComment(s, comment);
|
||||
break;
|
||||
|
||||
case TOK.comma:
|
||||
nextToken();
|
||||
addComment(s, comment);
|
||||
if (token.value != TOK.identifier)
|
||||
{
|
||||
error("identifier expected following comma, not `%s`", token.toChars());
|
||||
break;
|
||||
}
|
||||
if (peekNext() != TOK.assign && peekNext() != TOK.leftParenthesis)
|
||||
{
|
||||
error("`=` expected following identifier");
|
||||
nextToken();
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
||||
default:
|
||||
error("semicolon expected to close `%s` declaration", Token.toChars(tok));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// alias StorageClasses type ident;
|
||||
isAliasDeclaration = true;
|
||||
}
|
||||
|
||||
AST.Type ts;
|
||||
|
@ -4839,7 +4663,7 @@ class Parser(AST) : Lexer
|
|||
else if (!isThis && (t != AST.Type.terror))
|
||||
error("no identifier for declarator `%s`", t.toChars());
|
||||
|
||||
if (tok == TOK.alias_)
|
||||
if (isAliasDeclaration)
|
||||
{
|
||||
AST.Declaration v;
|
||||
AST.Initializer _init = null;
|
||||
|
@ -4852,7 +4676,7 @@ class Parser(AST) : Lexer
|
|||
*/
|
||||
|
||||
if (udas)
|
||||
error("user-defined attributes not allowed for `%s` declarations", Token.toChars(tok));
|
||||
error("user-defined attributes not allowed for `alias` declarations");
|
||||
|
||||
if (token.value == TOK.assign)
|
||||
{
|
||||
|
@ -4901,7 +4725,7 @@ class Parser(AST) : Lexer
|
|||
continue;
|
||||
|
||||
default:
|
||||
error("semicolon expected to close `%s` declaration", Token.toChars(tok));
|
||||
error("semicolon expected to close `alias` declaration");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5018,7 +4842,15 @@ class Parser(AST) : Lexer
|
|||
continue;
|
||||
|
||||
default:
|
||||
error("semicolon expected, not `%s`", token.toChars());
|
||||
if (loc.linnum != token.loc.linnum)
|
||||
{
|
||||
error("semicolon needed to end declaration of `%s`, instead of `%s`", v.toChars(), token.toChars());
|
||||
errorSupplemental(loc, "`%s` declared here", v.toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
error("semicolon needed to end declaration of `%s` instead of `%s`", v.toChars(), token.toChars());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5027,6 +4859,271 @@ class Parser(AST) : Lexer
|
|||
return a;
|
||||
}
|
||||
|
||||
/********************************
|
||||
* Parse AliasReassignment:
|
||||
* identifier = type;
|
||||
* Parser is sitting on the identifier.
|
||||
* https://dlang.org/spec/declaration.html#alias-reassignment
|
||||
* Params:
|
||||
* comment = if not null, comment to attach to symbol
|
||||
* Returns:
|
||||
* array of symbols
|
||||
*/
|
||||
private AST.Dsymbols* parseAliasReassignment(const(char)* comment)
|
||||
{
|
||||
const loc = token.loc;
|
||||
auto ident = token.ident;
|
||||
nextToken();
|
||||
nextToken(); // advance past =
|
||||
auto t = parseType();
|
||||
AST.Dsymbol s = new AST.AliasAssign(loc, ident, t, null);
|
||||
check(TOK.semicolon);
|
||||
addComment(s, comment);
|
||||
auto a = new AST.Dsymbols();
|
||||
a.push(s);
|
||||
return a;
|
||||
}
|
||||
|
||||
/********************************
|
||||
* Parse declarations that start with `alias`
|
||||
* Parser is sitting on the `alias`.
|
||||
* https://dlang.org/spec/declaration.html#alias
|
||||
* Params:
|
||||
* comment = if not null, comment to attach to symbol
|
||||
* Returns:
|
||||
* array of symbols
|
||||
*/
|
||||
private AST.Dsymbols* parseAliasDeclarations(const(char)* comment)
|
||||
{
|
||||
const loc = token.loc;
|
||||
nextToken();
|
||||
Loc linkloc = this.linkLoc;
|
||||
AST.Expressions* udas;
|
||||
LINK link = linkage;
|
||||
StorageClass storage_class = STC.undefined_;
|
||||
AST.Expression ealign;
|
||||
bool setAlignment = false;
|
||||
|
||||
/* Look for:
|
||||
* alias Identifier this;
|
||||
* https://dlang.org/spec/class.html#alias-this
|
||||
*/
|
||||
if (token.value == TOK.identifier && peekNext() == TOK.this_)
|
||||
{
|
||||
auto s = new AST.AliasThis(loc, token.ident);
|
||||
nextToken();
|
||||
check(TOK.this_);
|
||||
check(TOK.semicolon);
|
||||
auto a = new AST.Dsymbols();
|
||||
a.push(s);
|
||||
addComment(s, comment);
|
||||
return a;
|
||||
}
|
||||
version (none)
|
||||
{
|
||||
/* Look for:
|
||||
* alias this = identifier;
|
||||
*/
|
||||
if (token.value == TOK.this_ && peekNext() == TOK.assign && peekNext2() == TOK.identifier)
|
||||
{
|
||||
check(TOK.this_);
|
||||
check(TOK.assign);
|
||||
auto s = new AliasThis(loc, token.ident);
|
||||
nextToken();
|
||||
check(TOK.semicolon);
|
||||
auto a = new Dsymbols();
|
||||
a.push(s);
|
||||
addComment(s, comment);
|
||||
return a;
|
||||
}
|
||||
}
|
||||
/* Look for:
|
||||
* alias identifier = type;
|
||||
* alias identifier(...) = type;
|
||||
* https://dlang.org/spec/declaration.html#alias
|
||||
*/
|
||||
if (token.value == TOK.identifier && hasOptionalParensThen(peek(&token), TOK.assign))
|
||||
{
|
||||
auto a = new AST.Dsymbols();
|
||||
while (1)
|
||||
{
|
||||
auto ident = token.ident;
|
||||
nextToken();
|
||||
AST.TemplateParameters* tpl = null;
|
||||
if (token.value == TOK.leftParenthesis)
|
||||
tpl = parseTemplateParameterList();
|
||||
check(TOK.assign);
|
||||
|
||||
bool hasParsedAttributes;
|
||||
void parseAttributes()
|
||||
{
|
||||
if (hasParsedAttributes) // only parse once
|
||||
return;
|
||||
hasParsedAttributes = true;
|
||||
udas = null;
|
||||
storage_class = STC.undefined_;
|
||||
link = linkage;
|
||||
linkloc = this.linkLoc;
|
||||
setAlignment = false;
|
||||
ealign = null;
|
||||
parseStorageClasses(storage_class, link, setAlignment, ealign, udas, linkloc);
|
||||
}
|
||||
|
||||
if (token.value == TOK.at)
|
||||
parseAttributes;
|
||||
|
||||
AST.Declaration v;
|
||||
AST.Dsymbol s;
|
||||
|
||||
// try to parse function type:
|
||||
// TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes
|
||||
bool attributesAppended;
|
||||
const StorageClass funcStc = parseTypeCtor();
|
||||
Token* tlu = &token;
|
||||
Token* tk;
|
||||
if (token.value != TOK.function_ &&
|
||||
token.value != TOK.delegate_ &&
|
||||
isBasicType(&tlu) && tlu &&
|
||||
tlu.value == TOK.leftParenthesis)
|
||||
{
|
||||
AST.Type tret = parseBasicType();
|
||||
auto parameterList = parseParameterList(null);
|
||||
|
||||
parseAttributes();
|
||||
if (udas)
|
||||
error("user-defined attributes not allowed for `alias` declarations");
|
||||
|
||||
attributesAppended = true;
|
||||
storage_class = appendStorageClass(storage_class, funcStc);
|
||||
AST.Type tf = new AST.TypeFunction(parameterList, tret, link, storage_class);
|
||||
v = new AST.AliasDeclaration(loc, ident, tf);
|
||||
}
|
||||
else if (token.value == TOK.function_ ||
|
||||
token.value == TOK.delegate_ ||
|
||||
token.value == TOK.leftParenthesis &&
|
||||
skipAttributes(peekPastParen(&token), &tk) &&
|
||||
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly) ||
|
||||
token.value == TOK.leftCurly ||
|
||||
token.value == TOK.identifier && peekNext() == TOK.goesTo ||
|
||||
token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis &&
|
||||
skipAttributes(peekPastParen(peek(&token)), &tk) &&
|
||||
(tk.value == TOK.goesTo || tk.value == TOK.leftCurly)
|
||||
)
|
||||
{
|
||||
// function (parameters) { statements... }
|
||||
// delegate (parameters) { statements... }
|
||||
// (parameters) { statements... }
|
||||
// (parameters) => expression
|
||||
// { statements... }
|
||||
// identifier => expression
|
||||
// ref (parameters) { statements... }
|
||||
// ref (parameters) => expression
|
||||
|
||||
s = parseFunctionLiteral();
|
||||
|
||||
if (udas !is null)
|
||||
{
|
||||
if (storage_class != 0)
|
||||
error("Cannot put a storage-class in an alias declaration.");
|
||||
// parseAttributes shouldn't have set these variables
|
||||
assert(link == linkage && !setAlignment && ealign is null);
|
||||
auto tpl_ = cast(AST.TemplateDeclaration) s;
|
||||
assert(tpl_ !is null && tpl_.members.dim == 1);
|
||||
auto fd = cast(AST.FuncLiteralDeclaration) (*tpl_.members)[0];
|
||||
auto tf = cast(AST.TypeFunction) fd.type;
|
||||
assert(tf.parameterList.parameters.dim > 0);
|
||||
auto as = new AST.Dsymbols();
|
||||
(*tf.parameterList.parameters)[0].userAttribDecl = new AST.UserAttributeDeclaration(udas, as);
|
||||
}
|
||||
|
||||
v = new AST.AliasDeclaration(loc, ident, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseAttributes();
|
||||
// type
|
||||
if (udas)
|
||||
error("user-defined attributes not allowed for alias declarations");
|
||||
|
||||
auto t = parseType();
|
||||
|
||||
// Disallow meaningless storage classes on type aliases
|
||||
if (storage_class)
|
||||
{
|
||||
// Don't raise errors for STC that are part of a function/delegate type, e.g.
|
||||
// `alias F = ref pure nothrow @nogc @safe int function();`
|
||||
auto tp = t.isTypePointer;
|
||||
const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate;
|
||||
const remStc = isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class;
|
||||
|
||||
if (remStc)
|
||||
{
|
||||
OutBuffer buf;
|
||||
AST.stcToBuffer(&buf, remStc);
|
||||
// @@@DEPRECATED_2.093@@@
|
||||
// Deprecated in 2020-07, can be made an error in 2.103
|
||||
deprecation("storage class `%s` has no effect in type aliases", buf.peekChars());
|
||||
}
|
||||
}
|
||||
|
||||
v = new AST.AliasDeclaration(loc, ident, t);
|
||||
}
|
||||
if (!attributesAppended)
|
||||
storage_class = appendStorageClass(storage_class, funcStc);
|
||||
v.storage_class = storage_class;
|
||||
|
||||
s = v;
|
||||
if (tpl)
|
||||
{
|
||||
auto a2 = new AST.Dsymbols();
|
||||
a2.push(s);
|
||||
auto tempdecl = new AST.TemplateDeclaration(loc, ident, tpl, null, a2);
|
||||
s = tempdecl;
|
||||
}
|
||||
if (link != linkage)
|
||||
{
|
||||
auto a2 = new AST.Dsymbols();
|
||||
a2.push(s);
|
||||
s = new AST.LinkDeclaration(linkloc, link, a2);
|
||||
}
|
||||
a.push(s);
|
||||
|
||||
switch (token.value)
|
||||
{
|
||||
case TOK.semicolon:
|
||||
nextToken();
|
||||
addComment(s, comment);
|
||||
break;
|
||||
|
||||
case TOK.comma:
|
||||
nextToken();
|
||||
addComment(s, comment);
|
||||
if (token.value != TOK.identifier)
|
||||
{
|
||||
error("identifier expected following comma, not `%s`", token.toChars());
|
||||
break;
|
||||
}
|
||||
if (peekNext() != TOK.assign && peekNext() != TOK.leftParenthesis)
|
||||
{
|
||||
error("`=` expected following identifier");
|
||||
nextToken();
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
||||
default:
|
||||
error("semicolon expected to close `alias` declaration");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// alias StorageClasses type ident;
|
||||
return null;
|
||||
}
|
||||
|
||||
private AST.Dsymbol parseFunctionLiteral()
|
||||
{
|
||||
const loc = token.loc;
|
||||
|
@ -5390,6 +5487,7 @@ class Parser(AST) : Lexer
|
|||
check(TOK.leftParenthesis);
|
||||
|
||||
auto parameters = new AST.Parameters();
|
||||
Identifier lastai;
|
||||
while (1)
|
||||
{
|
||||
Identifier ai = null;
|
||||
|
@ -5465,8 +5563,9 @@ class Parser(AST) : Lexer
|
|||
if (token.value == TOK.identifier)
|
||||
{
|
||||
const tv = peekNext();
|
||||
if (tv == TOK.comma || tv == TOK.semicolon)
|
||||
if (tv == TOK.comma || tv == TOK.semicolon || tv == TOK.rightParenthesis)
|
||||
{
|
||||
lastai = token.ident;
|
||||
ai = token.ident;
|
||||
at = null; // infer argument type
|
||||
nextToken();
|
||||
|
@ -5486,7 +5585,17 @@ class Parser(AST) : Lexer
|
|||
}
|
||||
break;
|
||||
}
|
||||
check(TOK.semicolon);
|
||||
if (token.value != TOK.semicolon)
|
||||
{
|
||||
error("missing `; expression` before `)` of `foreach`");
|
||||
nextToken();
|
||||
if (lastai && parameters.length >= 2)
|
||||
{
|
||||
errorSupplemental(loc, "perhaps the `;` goes before `%s`", lastai.toChars());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
nextToken();
|
||||
|
||||
AST.Expression aggr = parseExpression();
|
||||
if (token.value == TOK.slice && parameters.dim == 1)
|
||||
|
@ -8473,6 +8582,7 @@ LagainStc:
|
|||
e = new AST.FuncExp(loc, s);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
error("expression expected, not `%s`", token.toChars());
|
||||
Lerr:
|
||||
|
@ -8766,6 +8876,17 @@ LagainStc:
|
|||
e = parsePostExp(e);
|
||||
break;
|
||||
}
|
||||
case TOK.throw_:
|
||||
{
|
||||
nextToken();
|
||||
// Deviation from the DIP:
|
||||
// Parse AssignExpression instead of Expression to avoid conflicts for comma
|
||||
// separated lists, e.g. function arguments
|
||||
AST.Expression exp = parseAssignExp();
|
||||
e = new AST.ThrowExp(loc, exp);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
e = parsePrimaryExp();
|
||||
e = parsePostExp(e);
|
||||
|
|
|
@ -220,6 +220,7 @@ public:
|
|||
void visit(AST.CallExp e) { visit(cast(AST.UnaExp)e); }
|
||||
void visit(AST.DotIdExp e) { visit(cast(AST.UnaExp)e); }
|
||||
void visit(AST.AssertExp e) { visit(cast(AST.UnaExp)e); }
|
||||
void visit(AST.ThrowExp e) { visit(cast(AST.UnaExp)e); }
|
||||
void visit(AST.ImportExp e) { visit(cast(AST.UnaExp)e); }
|
||||
void visit(AST.DotTemplateInstanceExp e) { visit(cast(AST.UnaExp)e); }
|
||||
void visit(AST.ArrayExp e) { visit(cast(AST.UnaExp)e); }
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
| [hash.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/hash.d) | Calculate a hash for a byte array |
|
||||
| [longdouble.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/longdouble.d) | 80-bit floating point number implementation in case they are not natively supported |
|
||||
| [man.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/man.d) | Opens an online manual page |
|
||||
| [optional.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/optional.d) | Implementation of an 'Optional' type |
|
||||
| [port.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d) | Portable routines for functions that have different implementations on different platforms |
|
||||
| [region.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/region.d) | A region allocator |
|
||||
| [response.d](https://github.com/dlang/dmd/blob/master/src/dmd/root/response.d) | Parse command line arguments from response files |
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Optional implementation.
|
||||
* Implementation of an 'Optional' type
|
||||
*
|
||||
* Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
|
||||
* Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
|
||||
|
|
|
@ -94,8 +94,9 @@ extern (C++) bool hasSideEffect(Expression e, bool assumeImpureCalls = false)
|
|||
* Determine if the call of f, or function type or delegate type t1, has any side effects.
|
||||
* Returns:
|
||||
* 0 has any side effects
|
||||
* 1 nothrow + constant purity
|
||||
* 2 nothrow + strong purity
|
||||
* 1 nothrow + strongly pure
|
||||
* 2 nothrow + strongly pure + only immutable indirections in the return
|
||||
* type
|
||||
*/
|
||||
int callSideEffectLevel(FuncDeclaration f)
|
||||
{
|
||||
|
@ -106,15 +107,18 @@ int callSideEffectLevel(FuncDeclaration f)
|
|||
return 0;
|
||||
assert(f.type.ty == Tfunction);
|
||||
TypeFunction tf = cast(TypeFunction)f.type;
|
||||
if (tf.isnothrow)
|
||||
if (!tf.isnothrow)
|
||||
return 0;
|
||||
final switch (f.isPure())
|
||||
{
|
||||
PURE purity = f.isPure();
|
||||
if (purity == PURE.strong)
|
||||
return 2;
|
||||
if (purity == PURE.const_)
|
||||
return 1;
|
||||
case PURE.impure:
|
||||
case PURE.fwdref:
|
||||
case PURE.weak:
|
||||
return 0;
|
||||
|
||||
case PURE.const_:
|
||||
return mutabilityOfType(tf.isref, tf.next) == 2 ? 2 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int callSideEffectLevel(Type t)
|
||||
|
@ -141,10 +145,9 @@ int callSideEffectLevel(Type t)
|
|||
purity = PURE.const_;
|
||||
}
|
||||
|
||||
if (purity == PURE.strong)
|
||||
return 2;
|
||||
if (purity == PURE.const_)
|
||||
return 1;
|
||||
return mutabilityOfType(tf.isref, tf.next) == 2 ? 2 : 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -178,6 +181,7 @@ private bool lambdaHasSideEffect(Expression e, bool assumeImpureCalls = false)
|
|||
case EXP.remove:
|
||||
case EXP.assert_:
|
||||
case EXP.halt:
|
||||
case EXP.throw_:
|
||||
case EXP.delete_:
|
||||
case EXP.new_:
|
||||
case EXP.newAnonymousClass:
|
||||
|
|
|
@ -21,7 +21,6 @@ import dmd.arraytypes;
|
|||
import dmd.astenums;
|
||||
import dmd.ast_node;
|
||||
import dmd.gluelayer;
|
||||
import dmd.canthrow;
|
||||
import dmd.cond;
|
||||
import dmd.dclass;
|
||||
import dmd.declaration;
|
||||
|
|
|
@ -45,7 +45,7 @@ struct code;
|
|||
|
||||
/* How a statement exits; this is returned by blockExit()
|
||||
*/
|
||||
enum BE
|
||||
enum BE : int32_t
|
||||
{
|
||||
BEnone = 0,
|
||||
BEfallthru = 1,
|
||||
|
|
|
@ -122,8 +122,10 @@ private LabelStatement checkLabeledLoop(Scope* sc, Statement statement)
|
|||
* Returns:
|
||||
* `e` or ErrorExp.
|
||||
*/
|
||||
private Expression checkAssignmentAsCondition(Expression e)
|
||||
private Expression checkAssignmentAsCondition(Expression e, Scope* sc)
|
||||
{
|
||||
if (sc.flags & SCOPE.Cfile)
|
||||
return e;
|
||||
auto ec = lastComma(e);
|
||||
if (ec.op == EXP.assign)
|
||||
{
|
||||
|
@ -148,7 +150,7 @@ extern(C++) Statement statementSemantic(Statement s, Scope* sc)
|
|||
return v.result;
|
||||
}
|
||||
|
||||
private extern (C++) final class StatementSemanticVisitor : Visitor
|
||||
package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
||||
{
|
||||
alias visit = Visitor.visit;
|
||||
|
||||
|
@ -550,7 +552,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
(cast(DotIdExp)ds.condition).noderef = true;
|
||||
|
||||
// check in syntax level
|
||||
ds.condition = checkAssignmentAsCondition(ds.condition);
|
||||
ds.condition = checkAssignmentAsCondition(ds.condition, sc);
|
||||
|
||||
ds.condition = ds.condition.expressionSemantic(sc);
|
||||
ds.condition = resolveProperties(sc, ds.condition);
|
||||
|
@ -623,7 +625,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
(cast(DotIdExp)fs.condition).noderef = true;
|
||||
|
||||
// check in syntax level
|
||||
fs.condition = checkAssignmentAsCondition(fs.condition);
|
||||
fs.condition = checkAssignmentAsCondition(fs.condition, sc);
|
||||
|
||||
fs.condition = fs.condition.expressionSemantic(sc);
|
||||
fs.condition = resolveProperties(sc, fs.condition);
|
||||
|
@ -1867,7 +1869,7 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
*/
|
||||
|
||||
// check in syntax level
|
||||
ifs.condition = checkAssignmentAsCondition(ifs.condition);
|
||||
ifs.condition = checkAssignmentAsCondition(ifs.condition, sc);
|
||||
|
||||
auto sym = new ScopeDsymbol();
|
||||
sym.parent = sc.scopesym;
|
||||
|
@ -3732,44 +3734,61 @@ private extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
*/
|
||||
|
||||
//printf("ThrowStatement::semantic()\n");
|
||||
if (throwSemantic(ts.loc, ts.exp, sc))
|
||||
result = ts;
|
||||
else
|
||||
setError();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Run semantic on `throw <exp>`.
|
||||
*
|
||||
* Params:
|
||||
* loc = location of the `throw`
|
||||
* exp = value to be thrown
|
||||
* sc = enclosing scope
|
||||
*
|
||||
* Returns: true if the `throw` is valid, or false if an error was found
|
||||
*/
|
||||
extern(D) static bool throwSemantic(const ref Loc loc, ref Expression exp, Scope* sc)
|
||||
{
|
||||
if (!global.params.useExceptions)
|
||||
{
|
||||
ts.error("Cannot use `throw` statements with -betterC");
|
||||
return setError();
|
||||
loc.error("Cannot use `throw` statements with -betterC");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ClassDeclaration.throwable)
|
||||
{
|
||||
ts.error("Cannot use `throw` statements because `object.Throwable` was not declared");
|
||||
return setError();
|
||||
loc.error("Cannot use `throw` statements because `object.Throwable` was not declared");
|
||||
return false;
|
||||
}
|
||||
|
||||
FuncDeclaration fd = sc.parent.isFuncDeclaration();
|
||||
fd.hasReturnExp |= 2;
|
||||
if (FuncDeclaration fd = sc.parent.isFuncDeclaration())
|
||||
fd.hasReturnExp |= 2;
|
||||
|
||||
if (ts.exp.op == EXP.new_)
|
||||
if (exp.op == EXP.new_)
|
||||
{
|
||||
NewExp ne = cast(NewExp)ts.exp;
|
||||
NewExp ne = cast(NewExp) exp;
|
||||
ne.thrownew = true;
|
||||
}
|
||||
|
||||
ts.exp = ts.exp.expressionSemantic(sc);
|
||||
ts.exp = resolveProperties(sc, ts.exp);
|
||||
ts.exp = checkGC(sc, ts.exp);
|
||||
if (ts.exp.op == EXP.error)
|
||||
return setError();
|
||||
exp = exp.expressionSemantic(sc);
|
||||
exp = resolveProperties(sc, exp);
|
||||
exp = checkGC(sc, exp);
|
||||
if (exp.op == EXP.error)
|
||||
return false;
|
||||
|
||||
checkThrowEscape(sc, ts.exp, false);
|
||||
checkThrowEscape(sc, exp, false);
|
||||
|
||||
ClassDeclaration cd = ts.exp.type.toBasetype().isClassHandle();
|
||||
ClassDeclaration cd = exp.type.toBasetype().isClassHandle();
|
||||
if (!cd || ((cd != ClassDeclaration.throwable) && !ClassDeclaration.throwable.isBaseOf(cd, null)))
|
||||
{
|
||||
ts.error("can only throw class objects derived from `Throwable`, not type `%s`", ts.exp.type.toChars());
|
||||
return setError();
|
||||
loc.error("can only throw class objects derived from `Throwable`, not type `%s`", exp.type.toChars());
|
||||
return false;
|
||||
}
|
||||
|
||||
result = ts;
|
||||
return true;
|
||||
}
|
||||
|
||||
override void visit(DebugStatement ds)
|
||||
|
|
|
@ -109,18 +109,16 @@ bool evalStaticCondition(Scope* sc, Expression original, Expression e, out bool
|
|||
e = e.ctfeInterpret();
|
||||
|
||||
const opt = e.toBool();
|
||||
if (opt.hasValue(true))
|
||||
return true;
|
||||
else if (opt.hasValue(false))
|
||||
if (opt.isEmpty())
|
||||
{
|
||||
if (negatives)
|
||||
negatives.push(before);
|
||||
e.error("expression `%s` is not constant", e.toChars());
|
||||
errors = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
e.error("expression `%s` is not constant", e.toChars());
|
||||
errors = true;
|
||||
return false;
|
||||
if (negatives && !opt.get())
|
||||
negatives.push(before);
|
||||
return opt.get();
|
||||
}
|
||||
return impl(e);
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@ extern (C++) struct Target
|
|||
import dmd.dscope : Scope;
|
||||
import dmd.expression : Expression;
|
||||
import dmd.func : FuncDeclaration;
|
||||
import dmd.globals : LINK, Loc, d_int64;
|
||||
import dmd.astenums : TY;
|
||||
import dmd.globals : Loc, d_int64;
|
||||
import dmd.astenums : LINK, TY;
|
||||
import dmd.mtype : Type, TypeFunction, TypeTuple;
|
||||
import dmd.root.ctfloat : real_t;
|
||||
import dmd.statement : Statement;
|
||||
|
@ -119,7 +119,7 @@ extern (C++) struct Target
|
|||
const(char)[] lib_ext; /// extension for static library files
|
||||
const(char)[] dll_ext; /// extension for dynamic library files
|
||||
bool run_noext; /// allow -run sources without extensions
|
||||
bool mscoff = false; // for Win32: write MsCoff object files instead of OMF
|
||||
bool omfobj = false; // for Win32: write OMF object files instead of MsCoff
|
||||
/**
|
||||
* Values representing all properties for floating point types
|
||||
*/
|
||||
|
@ -293,6 +293,13 @@ extern (C++) struct Target
|
|||
* `false` if the target backend handles synchronizing monitors.
|
||||
*/
|
||||
extern (C++) bool libraryObjectMonitors(FuncDeclaration fd, Statement fbody);
|
||||
|
||||
/**
|
||||
* Returns true if the target supports `pragma(linkerDirective)`.
|
||||
* Returns:
|
||||
* `false` if the target does not support `pragma(linkerDirective)`.
|
||||
*/
|
||||
extern (C++) bool supportsLinkerDirective() const;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -340,7 +347,7 @@ struct TargetCPP
|
|||
import dmd.dsymbol : Dsymbol;
|
||||
import dmd.dclass : ClassDeclaration;
|
||||
import dmd.func : FuncDeclaration;
|
||||
import dmd.mtype : Parameter, Type;
|
||||
import dmd.mtype : Type;
|
||||
|
||||
enum Runtime : ubyte
|
||||
{
|
||||
|
@ -354,6 +361,7 @@ struct TargetCPP
|
|||
bool reverseOverloads; /// set if overloaded functions are grouped and in reverse order (such as in dmc and cl)
|
||||
bool exceptions; /// set if catching C++ exceptions is supported
|
||||
bool twoDtorInVtable; /// target C++ ABI puts deleting and non-deleting destructor into vtable
|
||||
bool splitVBasetable; /// set if C++ ABI uses separate tables for virtual functions and virtual bases
|
||||
bool wrapDtorInExternD; /// set if C++ dtors require a D wrapper to be callable from runtime
|
||||
Runtime runtime; /// vendor of the C++ runtime to link against
|
||||
|
||||
|
@ -398,13 +406,13 @@ struct TargetCPP
|
|||
|
||||
/**
|
||||
* Get the type that will really be used for passing the given argument
|
||||
* to an `extern(C++)` function.
|
||||
* to an `extern(C++)` function, or `null` if unhandled.
|
||||
* Params:
|
||||
* p = parameter to be passed.
|
||||
* t = type to be passed.
|
||||
* Returns:
|
||||
* `Type` to use for parameter `p`.
|
||||
* `Type` to use for type `t`.
|
||||
*/
|
||||
extern (C++) Type parameterType(Parameter p);
|
||||
extern (C++) Type parameterType(Type t);
|
||||
|
||||
/**
|
||||
* Checks whether type is a vendor-specific fundamental type.
|
||||
|
|
|
@ -20,7 +20,6 @@ class ClassDeclaration;
|
|||
class Dsymbol;
|
||||
class Expression;
|
||||
class FuncDeclaration;
|
||||
class Parameter;
|
||||
class Statement;
|
||||
class Type;
|
||||
class TypeTuple;
|
||||
|
@ -92,6 +91,7 @@ struct TargetCPP
|
|||
bool reverseOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order
|
||||
bool exceptions; // set if catching C++ exceptions is supported
|
||||
bool twoDtorInVtable; // target C++ ABI puts deleting and non-deleting destructor into vtable
|
||||
bool splitVBasetable; // set if C++ ABI uses separate tables for virtual functions and virtual bases
|
||||
bool wrapDtorInExternD; // set if C++ dtors require a D wrapper to be callable from runtime
|
||||
Runtime runtime;
|
||||
|
||||
|
@ -99,7 +99,7 @@ struct TargetCPP
|
|||
const char *typeInfoMangle(ClassDeclaration *cd);
|
||||
const char *thunkMangle(FuncDeclaration *fd, int offset);
|
||||
const char *typeMangle(Type *t);
|
||||
Type *parameterType(Parameter *p);
|
||||
Type *parameterType(Type *p);
|
||||
bool fundamentalType(const Type *t, bool& isFundamental);
|
||||
unsigned derivedClassOffset(ClassDeclaration *baseClass);
|
||||
};
|
||||
|
@ -160,7 +160,7 @@ struct Target
|
|||
DString lib_ext; /// extension for static library files
|
||||
DString dll_ext; /// extension for dynamic library files
|
||||
bool run_noext; /// allow -run sources without extensions
|
||||
bool mscoff; /// for Win32: write COFF object files instead of OMF
|
||||
bool omfobj; /// for Win32: write OMF object files instead of COFF
|
||||
|
||||
template <typename T>
|
||||
struct FPTypeProperties
|
||||
|
@ -205,6 +205,7 @@ public:
|
|||
Expression *getTargetInfo(const char* name, const Loc& loc);
|
||||
bool isCalleeDestroyingArgs(TypeFunction* tf);
|
||||
bool libraryObjectMonitors(FuncDeclaration *fd, Statement *fbody);
|
||||
bool supportsLinkerDirective() const;
|
||||
void addPredefinedGlobalIdentifiers() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -284,6 +284,7 @@ public:
|
|||
Identifier *getIdent();
|
||||
hash_t toHash();
|
||||
|
||||
bool isDiscardable();
|
||||
bool needsCodegen();
|
||||
|
||||
TemplateInstance *isTemplateInstance() { return this; }
|
||||
|
|
|
@ -278,6 +278,7 @@ enum TOK : ubyte
|
|||
_Thread_local,
|
||||
|
||||
// C only extended keywords
|
||||
_import,
|
||||
__cdecl,
|
||||
__declspec,
|
||||
__attribute__,
|
||||
|
@ -585,6 +586,7 @@ private immutable TOK[] keywords =
|
|||
TOK._Thread_local,
|
||||
|
||||
// C only extended keywords
|
||||
TOK._import,
|
||||
TOK.__cdecl,
|
||||
TOK.__declspec,
|
||||
TOK.__attribute__,
|
||||
|
@ -615,7 +617,7 @@ static immutable TOK[TOK.max + 1] Ckeywords =
|
|||
restrict, return_, int16, signed, sizeof_, static_, struct_, switch_, typedef_,
|
||||
union_, unsigned, void_, volatile, while_, asm_,
|
||||
_Alignas, _Alignof, _Atomic, _Bool, _Complex, _Generic, _Imaginary, _Noreturn,
|
||||
_Static_assert, _Thread_local, __cdecl, __declspec, __attribute__ ];
|
||||
_Static_assert, _Thread_local, _import, __cdecl, __declspec, __attribute__ ];
|
||||
|
||||
foreach (kw; Ckwds)
|
||||
tab[kw] = cast(TOK) kw;
|
||||
|
@ -891,6 +893,7 @@ extern (C++) struct Token
|
|||
TOK._Thread_local : "_Thread_local",
|
||||
|
||||
// C only extended keywords
|
||||
TOK._import : "__import",
|
||||
TOK.__cdecl : "__cdecl",
|
||||
TOK.__declspec : "__declspec",
|
||||
TOK.__attribute__ : "__attribute__",
|
||||
|
|
|
@ -287,6 +287,7 @@ enum class TOK : unsigned char
|
|||
_Thread_local_,
|
||||
|
||||
// C only extended keywords
|
||||
_import,
|
||||
cdecl,
|
||||
declspec,
|
||||
attribute__,
|
||||
|
|
|
@ -150,6 +150,7 @@ shared static this()
|
|||
"hasPostblit",
|
||||
"hasCopyConstructor",
|
||||
"isCopyable",
|
||||
"parameters"
|
||||
];
|
||||
|
||||
StringTable!(bool)* stringTable = cast(StringTable!(bool)*) &traitsStringTable;
|
||||
|
@ -998,7 +999,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
e.error("`bool` expected as third argument of `__traits(getOverloads)`, not `%s` of type `%s`", b.toChars(), b.type.toChars());
|
||||
return ErrorExp.get();
|
||||
}
|
||||
includeTemplates = b.toBool().hasValue(true);
|
||||
includeTemplates = b.toBool().get();
|
||||
}
|
||||
|
||||
StringExp se = ex.toStringExp();
|
||||
|
@ -2090,7 +2091,43 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
|
|||
auto tup = new TupleExp(e.loc, exps);
|
||||
return tup.expressionSemantic(sc);
|
||||
}
|
||||
//https://issues.dlang.org/show_bug.cgi?id=22291
|
||||
if (e.ident == Id.parameters)
|
||||
{
|
||||
//No args are valid
|
||||
if (e.args)
|
||||
{
|
||||
char[] contents = cast(char[]) e.args.toString();
|
||||
contents = contents[1..$];
|
||||
contents[$-1] = '\0';
|
||||
e.error("`__traits(parameters)` cannot have arguments, but `%s` was supplied", contents.ptr);
|
||||
return ErrorExp.get();
|
||||
}
|
||||
|
||||
if (sc.func is null)
|
||||
{
|
||||
e.error("`__traits(parameters)` may only be used inside a function");
|
||||
return ErrorExp.get();
|
||||
}
|
||||
assert(sc.func && sc.parent.isFuncDeclaration());
|
||||
auto tf = sc.parent.isFuncDeclaration.type.isTypeFunction();
|
||||
assert(tf);
|
||||
auto exps = new Expressions(0);
|
||||
int addParameterDG(size_t idx, Parameter x)
|
||||
{
|
||||
assert(x.ident);
|
||||
exps.push(new IdentifierExp(e.loc, x.ident));
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
This is required since not all "parameters" actually have a name
|
||||
until they (tuples) are expanded e.g. an anonymous tuple parameter's
|
||||
contents get given names but not the tuple itself.
|
||||
*/
|
||||
Parameter._foreach(tf.parameterList.parameters, &addParameterDG);
|
||||
auto tup = new TupleExp(e.loc, exps);
|
||||
return tup.expressionSemantic(sc);
|
||||
}
|
||||
static const(char)[] trait_search_fp(const(char)[] seed, out int cost)
|
||||
{
|
||||
//printf("trait_search_fp('%s')\n", seed);
|
||||
|
|
|
@ -1141,6 +1141,12 @@ package mixin template ParseVisitMethods(AST)
|
|||
}
|
||||
}
|
||||
|
||||
override void visit(AST.ThrowExp e)
|
||||
{
|
||||
//printf("Visiting ThrowExp\n");
|
||||
e.e1.accept(this);
|
||||
}
|
||||
|
||||
// Template Parameter
|
||||
//===========================================================
|
||||
|
||||
|
|
|
@ -2062,7 +2062,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
|
|||
switch (mtype.tok)
|
||||
{
|
||||
case TOK.enum_:
|
||||
auto ed = new EnumDeclaration(mtype.loc, mtype.id, Type.tint32);
|
||||
auto ed = new EnumDeclaration(mtype.loc, mtype.id, mtype.base);
|
||||
declare(ed);
|
||||
mtype.resolved = visitEnum(new TypeEnum(ed));
|
||||
break;
|
||||
|
@ -3940,7 +3940,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
|
|||
|
||||
e = new TupleExp(e.loc, e0, exps);
|
||||
Scope* sc2 = sc.push();
|
||||
sc2.flags |= global.params.useDIP1000 == FeatureState.enabled ? SCOPE.onlysafeaccess : SCOPE.noaccesscheck;
|
||||
sc2.flags |= SCOPE.noaccesscheck;
|
||||
e = e.expressionSemantic(sc2);
|
||||
sc2.pop();
|
||||
return e;
|
||||
|
@ -4201,7 +4201,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, int flag)
|
|||
|
||||
e = new TupleExp(e.loc, e0, exps);
|
||||
Scope* sc2 = sc.push();
|
||||
sc2.flags |= global.params.useDIP1000 == FeatureState.enabled ? SCOPE.onlysafeaccess : SCOPE.noaccesscheck;
|
||||
sc2.flags |= SCOPE.noaccesscheck;
|
||||
e = e.expressionSemantic(sc2);
|
||||
sc2.pop();
|
||||
return e;
|
||||
|
|
|
@ -220,6 +220,7 @@ class BinAssignExp;
|
|||
class MixinExp;
|
||||
class ImportExp;
|
||||
class AssertExp;
|
||||
class ThrowExp;
|
||||
class DotIdExp;
|
||||
class DotTemplateExp;
|
||||
class DotVarExp;
|
||||
|
@ -511,6 +512,7 @@ public:
|
|||
virtual void visit(CallExp *e) { visit((UnaExp *)e); }
|
||||
virtual void visit(DotIdExp *e) { visit((UnaExp *)e); }
|
||||
virtual void visit(AssertExp *e) { visit((UnaExp *)e); }
|
||||
virtual void visit(ThrowExp *e) { visit((UnaExp *)e); }
|
||||
virtual void visit(ImportExp *e) { visit((UnaExp *)e); }
|
||||
virtual void visit(DotTemplateInstanceExp *e) { visit((UnaExp *)e); }
|
||||
virtual void visit(ArrayExp *e) { visit((UnaExp *)e); }
|
||||
|
|
|
@ -1186,6 +1186,14 @@ public:
|
|||
this->result_ = build_assign (modifycode, t1, t2);
|
||||
}
|
||||
|
||||
/* Build a throw expression. */
|
||||
|
||||
void visit (ThrowExp *e)
|
||||
{
|
||||
tree arg = build_expr_dtor (e->e1);
|
||||
this->result_ = build_libcall (LIBCALL_THROW, Type::tvoid, 1, arg);
|
||||
}
|
||||
|
||||
/* Build a postfix expression. */
|
||||
|
||||
void visit (PostExp *e)
|
||||
|
|
|
@ -274,6 +274,72 @@ insert_aggregate_field (tree type, tree field, size_t offset)
|
|||
TYPE_FIELDS (type) = chainon (TYPE_FIELDS (type), field);
|
||||
}
|
||||
|
||||
/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
|
||||
|
||||
static tree
|
||||
d_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
|
||||
{
|
||||
/* Same as d_type_for_size, but uses exact match for size. */
|
||||
if (width == TYPE_PRECISION (d_byte_type))
|
||||
return unsignedp ? d_ubyte_type : d_byte_type;
|
||||
|
||||
if (width == TYPE_PRECISION (d_short_type))
|
||||
return unsignedp ? d_ushort_type : d_short_type;
|
||||
|
||||
if (width == TYPE_PRECISION (d_int_type))
|
||||
return unsignedp ? d_uint_type : d_int_type;
|
||||
|
||||
if (width == TYPE_PRECISION (d_long_type))
|
||||
return unsignedp ? d_ulong_type : d_long_type;
|
||||
|
||||
if (width == TYPE_PRECISION (d_cent_type))
|
||||
return unsignedp ? d_ucent_type : d_cent_type;
|
||||
|
||||
for (int i = 0; i < NUM_INT_N_ENTS; i ++)
|
||||
{
|
||||
if (int_n_enabled_p[i] && width == int_n_data[i].bitsize)
|
||||
{
|
||||
if (unsignedp)
|
||||
return int_n_trees[i].unsigned_type;
|
||||
else
|
||||
return int_n_trees[i].signed_type;
|
||||
}
|
||||
}
|
||||
|
||||
return build_nonstandard_integer_type (width, unsignedp);
|
||||
}
|
||||
|
||||
/* Adds BITFIELD into the aggregate TYPE at OFFSET+BITOFFSET. */
|
||||
|
||||
static void
|
||||
insert_aggregate_bitfield (tree type, tree bitfield, size_t width,
|
||||
size_t offset, size_t bitoffset)
|
||||
{
|
||||
DECL_FIELD_CONTEXT (bitfield) = type;
|
||||
SET_DECL_OFFSET_ALIGN (bitfield, TYPE_ALIGN (TREE_TYPE (bitfield)));
|
||||
DECL_SIZE (bitfield) = bitsize_int (width);
|
||||
DECL_FIELD_OFFSET (bitfield) = size_int (offset);
|
||||
DECL_FIELD_BIT_OFFSET (bitfield) = bitsize_int (bitoffset);
|
||||
|
||||
TREE_ADDRESSABLE (bitfield) = TYPE_SHARED (TREE_TYPE (bitfield));
|
||||
|
||||
DECL_BIT_FIELD (bitfield) = 1;
|
||||
DECL_BIT_FIELD_TYPE (bitfield) = TREE_TYPE (bitfield);
|
||||
|
||||
layout_decl (bitfield, 0);
|
||||
|
||||
/* Give bit-field its proper type after layout_decl. */
|
||||
tree orig_type = DECL_BIT_FIELD_TYPE (bitfield);
|
||||
if (width != TYPE_PRECISION (orig_type))
|
||||
{
|
||||
TREE_TYPE (bitfield)
|
||||
= d_build_bitfield_integer_type (width, TYPE_UNSIGNED (orig_type));
|
||||
SET_DECL_MODE (bitfield, TYPE_MODE (TREE_TYPE (bitfield)));
|
||||
}
|
||||
|
||||
TYPE_FIELDS (type) = chainon (TYPE_FIELDS (type), bitfield);
|
||||
}
|
||||
|
||||
/* For all decls in the FIELDS chain, adjust their field offset by OFFSET.
|
||||
This is done as the frontend puts fields into the outer struct, and so
|
||||
their offset is from the beginning of the aggregate.
|
||||
|
@ -356,7 +422,16 @@ layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p)
|
|||
tree field = create_field_decl (declaration_type (var), ident,
|
||||
inherited_p, inherited_p);
|
||||
apply_user_attributes (var, field);
|
||||
insert_aggregate_field (context, field, var->offset);
|
||||
|
||||
if (BitFieldDeclaration *bf = var->isBitFieldDeclaration ())
|
||||
{
|
||||
/* Bit-fields come from an ImportC context, and require the
|
||||
field be correctly adjusted. */
|
||||
insert_aggregate_bitfield (context, field, bf->fieldWidth,
|
||||
bf->offset, bf->bitOffset);
|
||||
}
|
||||
else
|
||||
insert_aggregate_field (context, field, var->offset);
|
||||
|
||||
/* Because the front-end shares field decls across classes, don't
|
||||
create the corresponding back-end symbol unless we are adding
|
||||
|
|
31
gcc/testsuite/gdc.test/compilable/casttuple.d
Normal file
31
gcc/testsuite/gdc.test/compilable/casttuple.d
Normal file
|
@ -0,0 +1,31 @@
|
|||
alias tuple(T...) = T;
|
||||
|
||||
void exactMatch()
|
||||
{
|
||||
tuple!int tup_1;
|
||||
|
||||
auto i = cast() tup_1;
|
||||
static assert(is(typeof(i) == int));
|
||||
const i_const = cast(const) tup_1;
|
||||
static assert(is(typeof(i_const) == const int));
|
||||
|
||||
auto totup_1 = cast(tuple!int) tup_1;
|
||||
static assert(is(typeof(totup_1) == tuple!int));
|
||||
|
||||
tuple!(int, int) tup_2;
|
||||
auto totup_2 = cast(tuple!(int, int)) tup_2;
|
||||
static assert(is(typeof(totup_2) == tuple!(int, int)));
|
||||
}
|
||||
|
||||
void implicitConv()
|
||||
{
|
||||
tuple!short tup_1;
|
||||
auto totup_1 = cast(tuple!int) tup_1;
|
||||
static assert(is(typeof(tup_1) == tuple!short));
|
||||
static assert(is(typeof(totup_1) == tuple!int));
|
||||
|
||||
tuple!(short, short) tup_2;
|
||||
auto totup_2 = cast(tuple!(int, int)) tup_2;
|
||||
static assert(is(typeof(tup_2) == tuple!(short, short)));
|
||||
static assert(is(typeof(totup_2) == tuple!(int, int)));
|
||||
}
|
97
gcc/testsuite/gdc.test/compilable/deprecated_override.d
Normal file
97
gcc/testsuite/gdc.test/compilable/deprecated_override.d
Normal file
|
@ -0,0 +1,97 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=22668
|
||||
|
||||
// Overrides with same deprecated'ness are allowed
|
||||
|
||||
class SameParent
|
||||
{
|
||||
deprecated void foo() {}
|
||||
void foo(int) {}
|
||||
|
||||
void bar(int) {}
|
||||
deprecated void bar() {}
|
||||
}
|
||||
|
||||
class SameChild : SameParent
|
||||
{
|
||||
deprecated override void foo() {}
|
||||
override void foo(int) {}
|
||||
|
||||
override void bar(int) {}
|
||||
deprecated override void bar() {}
|
||||
}
|
||||
|
||||
/**
|
||||
Only the parent declaration is deprecated
|
||||
|
||||
TEST_OUTPUT:
|
||||
----
|
||||
compilable/deprecated_override.d(44): Deprecation: `deprecated_override.IntroducingChild.foo` is overriding the deprecated method `deprecated_override.IntroducingParent.foo`
|
||||
compilable/deprecated_override.d(48): Deprecation: `deprecated_override.IntroducingChild.bar` is overriding the deprecated method `deprecated_override.IntroducingParent.bar`
|
||||
----
|
||||
**/
|
||||
|
||||
class IntroducingParent
|
||||
{
|
||||
deprecated void foo() {}
|
||||
void foo(int) {}
|
||||
|
||||
void bar(int) {}
|
||||
deprecated void bar() {}
|
||||
}
|
||||
|
||||
class IntroducingChild : IntroducingParent
|
||||
{
|
||||
override void foo() {}
|
||||
override void foo(int) {}
|
||||
|
||||
override void bar(int) {}
|
||||
override void bar() {}
|
||||
}
|
||||
|
||||
// Unrelated to this path but should this error as well?
|
||||
|
||||
class IntroducingGrandchild : IntroducingChild
|
||||
{
|
||||
override void foo() {}
|
||||
override void foo(int) {}
|
||||
|
||||
override void bar(int) {}
|
||||
override void bar() {}
|
||||
}
|
||||
|
||||
/**
|
||||
Only the overriding declaration is deprecated
|
||||
|
||||
TEST_OUTPUT:
|
||||
----
|
||||
compilable/deprecated_override.d(83): Deprecation: `deprecated_override.OverrideChild.foo` cannot be marked as `deprecated` because it is overriding a function in the base class
|
||||
compilable/deprecated_override.d(87): Deprecation: `deprecated_override.OverrideChild.bar` cannot be marked as `deprecated` because it is overriding a function in the base class
|
||||
----
|
||||
**/
|
||||
|
||||
class OverrideParent
|
||||
{
|
||||
void foo() {}
|
||||
void foo(int) {}
|
||||
|
||||
void bar(int) {}
|
||||
void bar() {}
|
||||
}
|
||||
|
||||
class OverrideChild : OverrideParent
|
||||
{
|
||||
deprecated override void foo() {}
|
||||
override void foo(int) {}
|
||||
|
||||
override void bar(int) {}
|
||||
deprecated override void bar() {}
|
||||
}
|
||||
|
||||
class OverrideGrandChild : OverrideChild
|
||||
{
|
||||
deprecated override void foo() {}
|
||||
override void foo(int) {}
|
||||
|
||||
override void bar(int) {}
|
||||
deprecated override void bar() {}
|
||||
}
|
|
@ -600,3 +600,9 @@ struct Test14UDA4(string v){}
|
|||
void test14x(@Test14UDA1 int, @Test14UDA2("1") int, @test14uda3("2") int, @Test14UDA4!"3" int) {}
|
||||
|
||||
void test15x(@(20) void delegate(int) @safe dg){}
|
||||
|
||||
T throwStuff(T)(T t)
|
||||
{
|
||||
if (false) test13x(1, throw new Exception(""), 2);
|
||||
return t ? t : throw new Exception("Bad stuff happens!");
|
||||
}
|
||||
|
|
16
gcc/testsuite/gdc.test/compilable/fix17635.d
Normal file
16
gcc/testsuite/gdc.test/compilable/fix17635.d
Normal file
|
@ -0,0 +1,16 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=17635
|
||||
|
||||
alias T = immutable int;
|
||||
|
||||
T** f(const T** input) pure
|
||||
{
|
||||
T** output;
|
||||
return output;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
T i;
|
||||
T* p = &i;
|
||||
immutable T** r = f(&p);
|
||||
}
|
134
gcc/testsuite/gdc.test/compilable/fix22291.d
Normal file
134
gcc/testsuite/gdc.test/compilable/fix22291.d
Normal file
|
@ -0,0 +1,134 @@
|
|||
//https://issues.dlang.org/show_bug.cgi?id=22291
|
||||
|
||||
alias AliasSeq(T...) = T;
|
||||
void noParameters()
|
||||
{
|
||||
static assert(typeof(__traits(parameters)).length == 0);
|
||||
}
|
||||
void noArgs()
|
||||
{
|
||||
//Arguments are not valid, this should not compile
|
||||
static assert(!__traits(compiles, __traits(parameters, 456)));
|
||||
}
|
||||
shared static this()
|
||||
{
|
||||
static assert(typeof(__traits(parameters)).length == 0);
|
||||
}
|
||||
int echoPlusOne(int x)
|
||||
{
|
||||
__traits(parameters)[0] += 1;
|
||||
return x;
|
||||
}
|
||||
static assert(echoPlusOne(1) == 2);
|
||||
class Tree {
|
||||
int opApply(int delegate(size_t, Tree) dg) {
|
||||
if (dg(0, this)) return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void useOpApply(Tree top, int x)
|
||||
{
|
||||
foreach(idx; 0..5)
|
||||
{
|
||||
static assert(is(typeof(__traits(parameters)) == AliasSeq!(Tree, int)));
|
||||
}
|
||||
foreach(idx, elem; top)
|
||||
{
|
||||
static assert(is(typeof(__traits(parameters)) == AliasSeq!(size_t, Tree)));
|
||||
}
|
||||
}
|
||||
class Test
|
||||
{
|
||||
static assert(!__traits(compiles, __traits(parameters)));
|
||||
void handle(int x)
|
||||
{
|
||||
static assert(typeof(__traits(parameters)).length == 1);
|
||||
}
|
||||
}
|
||||
|
||||
int add(int x, int y)
|
||||
{
|
||||
return x + y;
|
||||
}
|
||||
|
||||
auto forwardToAdd(int x, int y)
|
||||
{
|
||||
return add(__traits(parameters));
|
||||
}
|
||||
static assert(forwardToAdd(2, 3) == 5);
|
||||
struct TestConstructor
|
||||
{
|
||||
int x;
|
||||
string y;
|
||||
//This parameter will not have a name but it's (tuple) members
|
||||
//will
|
||||
this(typeof(this.tupleof))
|
||||
{
|
||||
this.tupleof = __traits(parameters);
|
||||
}
|
||||
}
|
||||
bool test(int x, string y)
|
||||
{
|
||||
auto s = TestConstructor(2, "pi");
|
||||
return s.x == x && s.y == y;
|
||||
}
|
||||
static assert(test(2, "pi"));
|
||||
int testNested(int x)
|
||||
{
|
||||
static assert(typeof(__traits(parameters)).length == 1);
|
||||
int add(int x, int y)
|
||||
{
|
||||
static assert(typeof(__traits(parameters)).length == 2);
|
||||
return x + y;
|
||||
}
|
||||
return add(x + 2, x + 3);
|
||||
}
|
||||
void testPack(Pack...)(Pack x)
|
||||
{
|
||||
static assert(is(typeof(__traits(parameters)) == typeof(AliasSeq!(x))));
|
||||
}
|
||||
|
||||
ref int forwardTest(return ref int x)
|
||||
{
|
||||
static assert(__traits(isRef, x) == __traits(isRef, __traits(parameters)[0]));
|
||||
return x;
|
||||
}
|
||||
|
||||
int testRefness(int x, ref int monkey)
|
||||
{
|
||||
{
|
||||
//monkey = x;
|
||||
__traits(parameters)[1] = __traits(parameters)[0];
|
||||
}
|
||||
return x;
|
||||
}
|
||||
int refTest()
|
||||
{
|
||||
int x;
|
||||
testRefness(45, x);
|
||||
return x;
|
||||
}
|
||||
auto packLength(Pack...)(Pack x)
|
||||
{
|
||||
return typeof(__traits(parameters)).length;
|
||||
}
|
||||
static assert(packLength(2, 3) == 2);
|
||||
alias lambda = (x) => typeof(__traits(parameters)).stringof;
|
||||
static assert(lambda(1) == "(int)");
|
||||
static assert(refTest() == 45);
|
||||
|
||||
T testTemplate(T)(scope T input)
|
||||
{
|
||||
void chimpInASuit(float set)
|
||||
{
|
||||
static assert(is(typeof(__traits(parameters)) == AliasSeq!(float)));
|
||||
}
|
||||
{
|
||||
__traits(parameters) = AliasSeq!(T.max);
|
||||
}
|
||||
__traits(parameters) = AliasSeq!(T.init);
|
||||
return input;
|
||||
}
|
||||
|
||||
static assert(testTemplate!long(420) == 0);
|
||||
|
6
gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
Normal file
6
gcc/testsuite/gdc.test/compilable/imports/cstuff3.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
// check bugs in importing C files
|
||||
|
||||
int squared(int a)
|
||||
{
|
||||
return a * a;
|
||||
}
|
1
gcc/testsuite/gdc.test/compilable/imports/imp22625.c
Normal file
1
gcc/testsuite/gdc.test/compilable/imports/imp22625.c
Normal file
|
@ -0,0 +1 @@
|
|||
typedef struct S { int x; } T;
|
1
gcc/testsuite/gdc.test/compilable/imports/imp22665.c
Normal file
1
gcc/testsuite/gdc.test/compilable/imports/imp22665.c
Normal file
|
@ -0,0 +1 @@
|
|||
enum E { A };
|
5
gcc/testsuite/gdc.test/compilable/imports/test22685b.d
Normal file
5
gcc/testsuite/gdc.test/compilable/imports/test22685b.d
Normal file
|
@ -0,0 +1,5 @@
|
|||
module imports.test22685b;
|
||||
|
||||
import imports.test22685c : overloaded;
|
||||
|
||||
void overloaded()() { }
|
3
gcc/testsuite/gdc.test/compilable/imports/test22685c.d
Normal file
3
gcc/testsuite/gdc.test/compilable/imports/test22685c.d
Normal file
|
@ -0,0 +1,3 @@
|
|||
module imports.test22685c;
|
||||
|
||||
void overloaded()() { }
|
12
gcc/testsuite/gdc.test/compilable/issue22130.d
Normal file
12
gcc/testsuite/gdc.test/compilable/issue22130.d
Normal file
|
@ -0,0 +1,12 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=22130
|
||||
|
||||
int* f(const int* input) pure nothrow @safe
|
||||
{
|
||||
int* output;
|
||||
return output;
|
||||
}
|
||||
void main() pure nothrow @safe
|
||||
{
|
||||
int* c = new int;
|
||||
immutable int* i = f(c);
|
||||
}
|
|
@ -20,8 +20,7 @@ static assert(!is(noreturn == void));
|
|||
|
||||
static assert(is( typeof(assert(0)) == noreturn ));
|
||||
|
||||
// Does not parse yet
|
||||
// static assert(is( typeof(throw new Exception()) == noreturn ));
|
||||
static assert(is( typeof(throw new Exception("")) == noreturn ));
|
||||
|
||||
static assert(is(noreturn == noreturn));
|
||||
static assert(!is(noreturn == const noreturn));
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// REQUIRED_ARGS: -o-
|
||||
// PERMUTE_ARGS: -d -de -dw
|
||||
/*
|
||||
TEST_OUTPUT*
|
||||
---
|
||||
---
|
||||
*/
|
||||
|
||||
deprecated class Dep { }
|
||||
deprecated Dep depFunc1(); // error
|
||||
deprecated void depFunc2(Dep); // error
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// REQUIRED_ARGS : -c
|
||||
// REQUIRED_ARGS: -c
|
||||
// EXTRA_FILES: imports/test18771a.d imports/test18771b.d imports/test18771c.d imports/test18771d.d
|
||||
// https://issues.dlang.org/show_bug.cgi?id=18771
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=19609
|
||||
// EXTRA_FILES: imports/test19609a.d imports/test19609b.d imports/test19609c.d
|
||||
/*
|
||||
TEST_OUTPUT
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
compilable/test19609.d(11): Deprecation: module `imports.test19609a` is deprecated -
|
||||
compilable/test19609.d(12): Deprecation: module `imports.test19609b` is deprecated - hello
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// PERMUTE_ARGS -preview=dip1000
|
||||
// PERMUTE_ARGS: -preview=dip1000
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19873
|
||||
int* ed(scope int* x)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// EXTRA_SOURCES: imports/test21299/mtype.d imports/test21299/func.d imports/test21299/rootstringtable.d
|
||||
// REQUIRED_ARGS: -main
|
||||
// LINK
|
||||
// LINK:
|
||||
module test21299a;
|
||||
|
|
11
gcc/testsuite/gdc.test/compilable/test22619.d
Normal file
11
gcc/testsuite/gdc.test/compilable/test22619.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=22619
|
||||
|
||||
struct W1 {
|
||||
int x;
|
||||
this(ref inout W1 rhs) inout { this.x = rhs.x; }
|
||||
}
|
||||
|
||||
inout(W1) f(inout W1 x) { return x; }
|
||||
void g(W1 x) {
|
||||
auto r = f(x);
|
||||
}
|
4
gcc/testsuite/gdc.test/compilable/test22625.d
Normal file
4
gcc/testsuite/gdc.test/compilable/test22625.d
Normal file
|
@ -0,0 +1,4 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=22625
|
||||
// EXTRA_FILES: imports/imp22625.c
|
||||
|
||||
import imports.imp22625 : S, T;
|
21
gcc/testsuite/gdc.test/compilable/test22646.d
Normal file
21
gcc/testsuite/gdc.test/compilable/test22646.d
Normal file
|
@ -0,0 +1,21 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=22646
|
||||
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
true
|
||||
true
|
||||
false
|
||||
false
|
||||
---
|
||||
*/
|
||||
|
||||
static template Bug(string name)
|
||||
{
|
||||
enum bool ok = name.length < 3 || name[0..3] != "pad";
|
||||
}
|
||||
|
||||
pragma(msg, Bug!"x".ok);
|
||||
pragma(msg, Bug!"foo".ok);
|
||||
pragma(msg, Bug!"pad".ok);
|
||||
pragma(msg, Bug!"pad123".ok);
|
22
gcc/testsuite/gdc.test/compilable/test22665.d
Normal file
22
gcc/testsuite/gdc.test/compilable/test22665.d
Normal file
|
@ -0,0 +1,22 @@
|
|||
// EXTRA_FILES: imports/imp22665.c
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22665
|
||||
|
||||
import imports.imp22665;
|
||||
|
||||
E foo1(E e)
|
||||
{
|
||||
return e.A; // with qualification, it is an enum
|
||||
}
|
||||
|
||||
int foo2()
|
||||
{
|
||||
return A; // without qualification, it is an int
|
||||
}
|
||||
|
||||
E foo3(E e)
|
||||
{
|
||||
return E.A; // with qualification, it is an enum
|
||||
}
|
||||
|
||||
|
25
gcc/testsuite/gdc.test/compilable/test22676.d
Normal file
25
gcc/testsuite/gdc.test/compilable/test22676.d
Normal file
|
@ -0,0 +1,25 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=22676
|
||||
template fullyQualifiedName(T)
|
||||
{
|
||||
static if (is(T : real))
|
||||
enum fullyQualifiedName;
|
||||
|
||||
enum fullyQualifiedName = null;
|
||||
}
|
||||
|
||||
static auto _inst()
|
||||
{
|
||||
return fullyQualifiedName!(frop);
|
||||
}
|
||||
|
||||
alias attr = __traits(getAttributes, _inst);
|
||||
|
||||
class frop
|
||||
{
|
||||
alias type_id = registry!frop;
|
||||
}
|
||||
|
||||
template registry(T)
|
||||
{
|
||||
enum string FOO = fullyQualifiedName!T;
|
||||
}
|
11
gcc/testsuite/gdc.test/compilable/test22685.d
Normal file
11
gcc/testsuite/gdc.test/compilable/test22685.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
// EXTRA_FILES: imports/test22685b.d imports/test22685c.d
|
||||
|
||||
module test22685;
|
||||
|
||||
import imports.test22685b;
|
||||
|
||||
void twoArgs(alias a, alias b)() { }
|
||||
|
||||
void main() {
|
||||
twoArgs!(a => 1, overloaded);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// COMPILE_SEPARATELY
|
||||
// COMPILE_SEPARATELY:
|
||||
// COMPILED_IMPORTS: imports/test55a.d
|
||||
// PERMUTE_ARGS: -dw
|
||||
// REQUIRED_ARGS: -d
|
||||
|
@ -17,4 +17,3 @@ class Queue2 {
|
|||
alias int ListHead;
|
||||
Arm2 a;
|
||||
}
|
||||
|
||||
|
|
4
gcc/testsuite/gdc.test/compilable/testcstuff3.d
Normal file
4
gcc/testsuite/gdc.test/compilable/testcstuff3.d
Normal file
|
@ -0,0 +1,4 @@
|
|||
// EXTRA_FILES: imports/cstuff3.c
|
||||
import imports.cstuff3;
|
||||
|
||||
static assert(squared(4) == 16);
|
7
gcc/testsuite/gdc.test/compilable/testos.d
Normal file
7
gcc/testsuite/gdc.test/compilable/testos.d
Normal file
|
@ -0,0 +1,7 @@
|
|||
/* PERMUTE_ARGS: -os=host -os=linux -os=osx -os=freebsd -os=solaris
|
||||
* DISABLED: win32 win64
|
||||
*/
|
||||
|
||||
void test()
|
||||
{
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* REQUIRED_ARGS: -c
|
||||
* TEST_OUTPUT:
|
||||
---
|
||||
compilable/b16967.d(16): Deprecation: switch case fallthrough - use 'goto default;' if intended
|
||||
compilable/b16967.d(26): Deprecation: switch case fallthrough - use 'goto default;' if intended
|
||||
fail_compilation/b16967.d(15): Error: switch case fallthrough - use 'goto default;' if intended
|
||||
fail_compilation/b16967.d(25): Error: switch case fallthrough - use 'goto default;' if intended
|
||||
---
|
||||
*/
|
||||
int foo(int x)
|
14
gcc/testsuite/gdc.test/fail_compilation/bug5096.d
Normal file
14
gcc/testsuite/gdc.test/fail_compilation/bug5096.d
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/bug5096.d(13): Error: unmatched closing brace
|
||||
---
|
||||
*/
|
||||
void foo(int x)
|
||||
in {
|
||||
assert(x > 0);
|
||||
} do {
|
||||
x++;
|
||||
}
|
||||
}
|
||||
void main() {}
|
|
@ -91,9 +91,9 @@ TEST_OUTPUT:
|
|||
---
|
||||
fail_compilation/bug9631.d(106): Error: function `bug9631.targ.ft!().ft(S _param_0)` is not callable using argument types `(S)`
|
||||
fail_compilation/bug9631.d(106): cannot pass argument `x` of type `bug9631.S` to parameter `bug9631.tem!().S _param_0`
|
||||
fail_compilation/bug9631.d(107): Error: template `bug9631.targ.ft` cannot deduce function from argument types `!()(S)`
|
||||
fail_compilation/bug9631.d(107): Error: none of the overloads of template `bug9631.targ.ft` are callable using argument types `!()(S)`
|
||||
fail_compilation/bug9631.d(105): Candidate is: `ft()(tem!().S)`
|
||||
fail_compilation/bug9631.d(109): Error: template `bug9631.targ.ft2` cannot deduce function from argument types `!()(S, int)`
|
||||
fail_compilation/bug9631.d(109): Error: none of the overloads of template `bug9631.targ.ft2` are callable using argument types `!()(S, int)`
|
||||
fail_compilation/bug9631.d(108): Candidate is: `ft2(T)(S, T)`
|
||||
---
|
||||
*/
|
||||
|
|
25
gcc/testsuite/gdc.test/fail_compilation/casttuple.d
Normal file
25
gcc/testsuite/gdc.test/fail_compilation/casttuple.d
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/casttuple.d(104): Error: cannot cast `__tup1_field_0` of type `int` to tuple type `(string)`
|
||||
fail_compilation/casttuple.d(107): Error: cannot cast `tuple(__tup2_field_0, __tup2_field_1)` of type `(int, int)` to tuple type `(string, string)`
|
||||
fail_compilation/casttuple.d(111): Error: cannot cast `tuple(foo, 123)` of type `(int, int)` to tuple type `(string, string)`
|
||||
---
|
||||
*/
|
||||
|
||||
alias tuple(T...) = T;
|
||||
|
||||
#line 100
|
||||
|
||||
void nomatch()
|
||||
{
|
||||
tuple!int tup1;
|
||||
auto x = cast(tuple!string) tup1;
|
||||
|
||||
tuple!(int, int) tup2;
|
||||
auto y = cast(tuple!(string, string)) tup2;
|
||||
|
||||
int foo;
|
||||
alias tup3 = tuple!(foo, 123);
|
||||
auto z = cast(tuple!(string, string)) tup3;
|
||||
}
|
|
@ -2,12 +2,12 @@
|
|||
EXTRA_FILES: imports/constraints.d
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/constraints_aggr.d(32): Error: template `imports.constraints.C.f` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_aggr.d(32): Error: none of the overloads of template `imports.constraints.C.f` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(60): Candidate is: `f(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` !P!T`
|
||||
fail_compilation/constraints_aggr.d(33): Error: template `imports.constraints.C.g` cannot deduce function from argument types `!()()`
|
||||
fail_compilation/constraints_aggr.d(33): Error: none of the overloads of template `imports.constraints.C.g` are callable using argument types `!()()`
|
||||
fail_compilation/imports/constraints.d(63): Candidate is: `g(this T)()`
|
||||
with `T = imports.constraints.C`
|
||||
must satisfy the following constraint:
|
||||
|
|
|
@ -2,72 +2,72 @@
|
|||
EXTRA_FILES: imports/constraints.d
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/constraints_func1.d(79): Error: template `imports.constraints.test1` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(79): Error: none of the overloads of template `imports.constraints.test1` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(9): Candidate is: `test1(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` N!T`
|
||||
fail_compilation/constraints_func1.d(80): Error: template `imports.constraints.test2` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(80): Error: none of the overloads of template `imports.constraints.test2` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(10): Candidate is: `test2(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` !P!T`
|
||||
fail_compilation/constraints_func1.d(81): Error: template `imports.constraints.test3` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(81): Error: none of the overloads of template `imports.constraints.test3` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(11): Candidate is: `test3(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` N!T`
|
||||
fail_compilation/constraints_func1.d(82): Error: template `imports.constraints.test4` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(82): Error: none of the overloads of template `imports.constraints.test4` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(12): Candidate is: `test4(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` N!T`
|
||||
fail_compilation/constraints_func1.d(83): Error: template `imports.constraints.test5` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(83): Error: none of the overloads of template `imports.constraints.test5` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(13): Candidate is: `test5(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
N!T`
|
||||
fail_compilation/constraints_func1.d(84): Error: template `imports.constraints.test6` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(84): Error: none of the overloads of template `imports.constraints.test6` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(14): Candidate is: `test6(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
N!T
|
||||
!P!T`
|
||||
fail_compilation/constraints_func1.d(85): Error: template `imports.constraints.test7` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(85): Error: none of the overloads of template `imports.constraints.test7` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(15): Candidate is: `test7(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
N!T`
|
||||
fail_compilation/constraints_func1.d(86): Error: template `imports.constraints.test8` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(86): Error: none of the overloads of template `imports.constraints.test8` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(16): Candidate is: `test8(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` N!T`
|
||||
fail_compilation/constraints_func1.d(87): Error: template `imports.constraints.test9` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(87): Error: none of the overloads of template `imports.constraints.test9` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(17): Candidate is: `test9(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` !P!T`
|
||||
fail_compilation/constraints_func1.d(88): Error: template `imports.constraints.test10` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(88): Error: none of the overloads of template `imports.constraints.test10` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(18): Candidate is: `test10(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` !P!T`
|
||||
fail_compilation/constraints_func1.d(89): Error: template `imports.constraints.test11` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(89): Error: none of the overloads of template `imports.constraints.test11` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(19): Candidate is: `test11(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
!P!T`
|
||||
fail_compilation/constraints_func1.d(90): Error: template `imports.constraints.test12` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func1.d(90): Error: none of the overloads of template `imports.constraints.test12` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(20): Candidate is: `test12(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` !P!T`
|
||||
fail_compilation/constraints_func1.d(92): Error: template `imports.constraints.test1` cannot deduce function from argument types `!()(int, int)`
|
||||
fail_compilation/constraints_func1.d(92): Error: none of the overloads of template `imports.constraints.test1` are callable using argument types `!()(int, int)`
|
||||
fail_compilation/imports/constraints.d(9): Candidate is: `test1(T)(T v)`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -2,83 +2,83 @@
|
|||
EXTRA_FILES: imports/constraints.d
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/constraints_func2.d(94): Error: template `imports.constraints.test13` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(94): Error: none of the overloads of template `imports.constraints.test13` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(23): Candidate is: `test13(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
!P!T`
|
||||
fail_compilation/constraints_func2.d(95): Error: template `imports.constraints.test14` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(95): Error: none of the overloads of template `imports.constraints.test14` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(24): Candidate is: `test14(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` !P!T
|
||||
N!T`
|
||||
fail_compilation/constraints_func2.d(96): Error: template `imports.constraints.test15` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(96): Error: none of the overloads of template `imports.constraints.test15` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(25): Candidate is: `test15(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` !P!T
|
||||
!P!T`
|
||||
fail_compilation/constraints_func2.d(97): Error: template `imports.constraints.test16` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(97): Error: none of the overloads of template `imports.constraints.test16` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(26): Candidate is: `test16(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
N!T`
|
||||
fail_compilation/constraints_func2.d(98): Error: template `imports.constraints.test17` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(98): Error: none of the overloads of template `imports.constraints.test17` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(27): Candidate is: `test17(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` N!T`
|
||||
fail_compilation/constraints_func2.d(99): Error: template `imports.constraints.test18` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(99): Error: none of the overloads of template `imports.constraints.test18` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(28): Candidate is: `test18(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
N!T`
|
||||
fail_compilation/constraints_func2.d(100): Error: template `imports.constraints.test19` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(100): Error: none of the overloads of template `imports.constraints.test19` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(29): Candidate is: `test19(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
!P!T
|
||||
N!T`
|
||||
fail_compilation/constraints_func2.d(101): Error: template `imports.constraints.test20` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(101): Error: none of the overloads of template `imports.constraints.test20` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(30): Candidate is: `test20(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` N!T`
|
||||
fail_compilation/constraints_func2.d(102): Error: template `imports.constraints.test21` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(102): Error: none of the overloads of template `imports.constraints.test21` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(31): Candidate is: `test21(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
N!T`
|
||||
fail_compilation/constraints_func2.d(103): Error: template `imports.constraints.test22` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(103): Error: none of the overloads of template `imports.constraints.test22` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(32): Candidate is: `test22(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` !P!T
|
||||
!P!T`
|
||||
fail_compilation/constraints_func2.d(104): Error: template `imports.constraints.test23` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(104): Error: none of the overloads of template `imports.constraints.test23` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(33): Candidate is: `test23(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy one of the following constraints:
|
||||
` !P!T
|
||||
N!T
|
||||
!P!T`
|
||||
fail_compilation/constraints_func2.d(105): Error: template `imports.constraints.test24` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(105): Error: none of the overloads of template `imports.constraints.test24` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(34): Candidate is: `test24(R)(R r)`
|
||||
with `R = int`
|
||||
must satisfy the following constraint:
|
||||
` __traits(hasMember, R, "stuff")`
|
||||
fail_compilation/constraints_func2.d(106): Error: template `imports.constraints.test25` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func2.d(106): Error: none of the overloads of template `imports.constraints.test25` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(35): Candidate is: `test25(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
` N!T`
|
||||
fail_compilation/constraints_func2.d(107): Error: template `imports.constraints.test26` cannot deduce function from argument types `!(float)(int)`
|
||||
fail_compilation/constraints_func2.d(107): Error: none of the overloads of template `imports.constraints.test26` are callable using argument types `!(float)(int)`
|
||||
fail_compilation/imports/constraints.d(36): Candidate is: `test26(T, U)(U u)`
|
||||
with `T = float,
|
||||
U = int`
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
EXTRA_FILES: imports/constraints.d
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/constraints_func3.d(53): Error: template `imports.constraints.overload` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func3.d(53): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(39): Candidates are: `overload(T)(T v)`
|
||||
with `T = int`
|
||||
must satisfy the following constraint:
|
||||
|
@ -13,7 +13,7 @@ fail_compilation/imports/constraints.d(40): `overload(T)(
|
|||
` !P!T`
|
||||
fail_compilation/imports/constraints.d(41): `overload(T)(T v1, T v2)`
|
||||
fail_compilation/imports/constraints.d(42): `overload(T, V)(T v1, V v2)`
|
||||
fail_compilation/constraints_func3.d(54): Error: template `imports.constraints.overload` cannot deduce function from argument types `!()(int, string)`
|
||||
fail_compilation/constraints_func3.d(54): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int, string)`
|
||||
fail_compilation/imports/constraints.d(39): Candidates are: `overload(T)(T v)`
|
||||
fail_compilation/imports/constraints.d(40): `overload(T)(T v)`
|
||||
fail_compilation/imports/constraints.d(41): `overload(T)(T v1, T v2)`
|
||||
|
@ -23,21 +23,21 @@ fail_compilation/imports/constraints.d(42): `overload(T,
|
|||
must satisfy one of the following constraints:
|
||||
` N!T
|
||||
N!V`
|
||||
fail_compilation/constraints_func3.d(56): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()()`
|
||||
fail_compilation/constraints_func3.d(56): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()()`
|
||||
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
|
||||
fail_compilation/constraints_func3.d(57): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func3.d(57): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int)`
|
||||
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
|
||||
with `A = int,
|
||||
T = ()`
|
||||
must satisfy the following constraint:
|
||||
` N!int`
|
||||
fail_compilation/constraints_func3.d(58): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int, int)`
|
||||
fail_compilation/constraints_func3.d(58): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int, int)`
|
||||
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
|
||||
with `A = int,
|
||||
T = (int)`
|
||||
must satisfy the following constraint:
|
||||
` N!int`
|
||||
fail_compilation/constraints_func3.d(59): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int, int, int)`
|
||||
fail_compilation/constraints_func3.d(59): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int, int, int)`
|
||||
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
|
||||
with `A = int,
|
||||
T = (int, int)`
|
||||
|
|
|
@ -3,7 +3,7 @@ EXTRA_FILES: imports/constraints.d
|
|||
REQUIRED_ARGS: -verrors=context
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/constraints_func4.d(90): Error: template `imports.constraints.overload` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func4.d(90): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int)`
|
||||
overload(0);
|
||||
^
|
||||
fail_compilation/imports/constraints.d(39): Candidates are: `overload(T)(T v)`
|
||||
|
@ -24,7 +24,7 @@ void overload(T)(T v1, T v2) if (N!T);
|
|||
fail_compilation/imports/constraints.d(42): `overload(T, V)(T v1, V v2)`
|
||||
void overload(T, V)(T v1, V v2) if (N!T || N!V);
|
||||
^
|
||||
fail_compilation/constraints_func4.d(91): Error: template `imports.constraints.overload` cannot deduce function from argument types `!()(int, string)`
|
||||
fail_compilation/constraints_func4.d(91): Error: none of the overloads of template `imports.constraints.overload` are callable using argument types `!()(int, string)`
|
||||
overload(0, "");
|
||||
^
|
||||
fail_compilation/imports/constraints.d(39): Candidates are: `overload(T)(T v)`
|
||||
|
@ -44,13 +44,13 @@ fail_compilation/imports/constraints.d(42): `overload(T,
|
|||
N!V`
|
||||
void overload(T, V)(T v1, V v2) if (N!T || N!V);
|
||||
^
|
||||
fail_compilation/constraints_func4.d(93): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()()`
|
||||
fail_compilation/constraints_func4.d(93): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()()`
|
||||
variadic();
|
||||
^
|
||||
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
|
||||
void variadic(A, T...)(A a, T v) if (N!int);
|
||||
^
|
||||
fail_compilation/constraints_func4.d(94): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/constraints_func4.d(94): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int)`
|
||||
variadic(0);
|
||||
^
|
||||
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
|
||||
|
@ -60,7 +60,7 @@ fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T.
|
|||
` N!int`
|
||||
void variadic(A, T...)(A a, T v) if (N!int);
|
||||
^
|
||||
fail_compilation/constraints_func4.d(95): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int, int)`
|
||||
fail_compilation/constraints_func4.d(95): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int, int)`
|
||||
variadic(0, 1);
|
||||
^
|
||||
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
|
||||
|
@ -70,7 +70,7 @@ fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T.
|
|||
` N!int`
|
||||
void variadic(A, T...)(A a, T v) if (N!int);
|
||||
^
|
||||
fail_compilation/constraints_func4.d(96): Error: template `imports.constraints.variadic` cannot deduce function from argument types `!()(int, int, int)`
|
||||
fail_compilation/constraints_func4.d(96): Error: none of the overloads of template `imports.constraints.variadic` are callable using argument types `!()(int, int, int)`
|
||||
variadic(0, 1, 2);
|
||||
^
|
||||
fail_compilation/imports/constraints.d(43): Candidate is: `variadic(A, T...)(A a, T v)`
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/diag11819b.d(28): Error: unrecognized trait `HasMember`, did you mean `hasMember`?
|
||||
fail_compilation/diag11819b.d(29): Error: unrecognized trait `Identifier`, did you mean `identifier`?
|
||||
fail_compilation/diag11819b.d(30): Error: unrecognized trait `GetProtection`, did you mean `getProtection`?
|
||||
fail_compilation/diag11819b.d(31): Error: unrecognized trait `Parent`, did you mean `parent`?
|
||||
fail_compilation/diag11819b.d(32): Error: unrecognized trait `GetMember`, did you mean `getMember`?
|
||||
fail_compilation/diag11819b.d(33): Error: unrecognized trait `GetOverloads`, did you mean `getOverloads`?
|
||||
fail_compilation/diag11819b.d(34): Error: unrecognized trait `GetVirtualFunctions`, did you mean `getVirtualFunctions`?
|
||||
fail_compilation/diag11819b.d(35): Error: unrecognized trait `GetVirtualMethods`, did you mean `getVirtualMethods`?
|
||||
fail_compilation/diag11819b.d(36): Error: unrecognized trait `ClassInstanceSize`, did you mean `classInstanceSize`?
|
||||
fail_compilation/diag11819b.d(37): Error: unrecognized trait `AllMembers`, did you mean `allMembers`?
|
||||
fail_compilation/diag11819b.d(38): Error: unrecognized trait `DerivedMembers`, did you mean `derivedMembers`?
|
||||
fail_compilation/diag11819b.d(39): Error: unrecognized trait `IsSame`, did you mean `isSame`?
|
||||
fail_compilation/diag11819b.d(40): Error: unrecognized trait `Compiles`, did you mean `compiles`?
|
||||
fail_compilation/diag11819b.d(41): Error: unrecognized trait `Parameters`
|
||||
fail_compilation/diag11819b.d(42): Error: unrecognized trait `GetAliasThis`, did you mean `getAliasThis`?
|
||||
fail_compilation/diag11819b.d(43): Error: unrecognized trait `GetAttributes`, did you mean `getAttributes`?
|
||||
fail_compilation/diag11819b.d(44): Error: unrecognized trait `GetFunctionAttributes`, did you mean `getFunctionAttributes`?
|
||||
fail_compilation/diag11819b.d(45): Error: unrecognized trait `GetUnitTests`, did you mean `getUnitTests`?
|
||||
fail_compilation/diag11819b.d(46): Error: unrecognized trait `GetVirtualIndex`, did you mean `getVirtualIndex`?
|
||||
fail_compilation/diag11819b.d(27): Error: unrecognized trait `HasMember`, did you mean `hasMember`?
|
||||
fail_compilation/diag11819b.d(28): Error: unrecognized trait `Identifier`, did you mean `identifier`?
|
||||
fail_compilation/diag11819b.d(29): Error: unrecognized trait `GetProtection`, did you mean `getProtection`?
|
||||
fail_compilation/diag11819b.d(30): Error: unrecognized trait `Parent`, did you mean `parent`?
|
||||
fail_compilation/diag11819b.d(31): Error: unrecognized trait `GetMember`, did you mean `getMember`?
|
||||
fail_compilation/diag11819b.d(32): Error: unrecognized trait `GetOverloads`, did you mean `getOverloads`?
|
||||
fail_compilation/diag11819b.d(33): Error: unrecognized trait `GetVirtualFunctions`, did you mean `getVirtualFunctions`?
|
||||
fail_compilation/diag11819b.d(34): Error: unrecognized trait `GetVirtualMethods`, did you mean `getVirtualMethods`?
|
||||
fail_compilation/diag11819b.d(35): Error: unrecognized trait `ClassInstanceSize`, did you mean `classInstanceSize`?
|
||||
fail_compilation/diag11819b.d(36): Error: unrecognized trait `AllMembers`, did you mean `allMembers`?
|
||||
fail_compilation/diag11819b.d(37): Error: unrecognized trait `DerivedMembers`, did you mean `derivedMembers`?
|
||||
fail_compilation/diag11819b.d(38): Error: unrecognized trait `IsSame`, did you mean `isSame`?
|
||||
fail_compilation/diag11819b.d(39): Error: unrecognized trait `Compiles`, did you mean `compiles`?
|
||||
fail_compilation/diag11819b.d(40): Error: unrecognized trait `GetAliasThis`, did you mean `getAliasThis`?
|
||||
fail_compilation/diag11819b.d(41): Error: unrecognized trait `GetAttributes`, did you mean `getAttributes`?
|
||||
fail_compilation/diag11819b.d(42): Error: unrecognized trait `GetFunctionAttributes`, did you mean `getFunctionAttributes`?
|
||||
fail_compilation/diag11819b.d(43): Error: unrecognized trait `GetUnitTests`, did you mean `getUnitTests`?
|
||||
fail_compilation/diag11819b.d(44): Error: unrecognized trait `GetVirtualIndex`, did you mean `getVirtualIndex`?
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -38,7 +37,6 @@ void main()
|
|||
if (__traits(DerivedMembers)) { }
|
||||
if (__traits(IsSame)) { }
|
||||
if (__traits(Compiles)) { }
|
||||
if (__traits(Parameters)) { }
|
||||
if (__traits(GetAliasThis)) { }
|
||||
if (__traits(GetAttributes)) { }
|
||||
if (__traits(GetFunctionAttributes)) { }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
TEST_OUTPUT*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/diag13333.d(29): Error: template instance `VariantN!(maxSize!(S), T)` recursive template expansion
|
||||
fail_compilation/diag13333.d(29): Error: template instance `diag13333.maxSize!(S)` error instantiating
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/diag13942.d(18): Error: template instance `isRawStaticArray!()` does not match template declaration `isRawStaticArray(T, A...)`
|
||||
fail_compilation/diag13942.d(26): Error: template `diag13942.to!double.to` cannot deduce function from argument types `!()()`
|
||||
fail_compilation/diag13942.d(26): Error: none of the overloads of template `diag13942.to!double.to` are callable using argument types `!()()`
|
||||
fail_compilation/diag13942.d(17): Candidate is: `to(A...)(A args)`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
TEST_OUTPUT
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/diag16271.d(10): Error: found `x` when expecting function literal following `ref`
|
||||
---
|
||||
|
|
|
@ -3,7 +3,7 @@ TEST_OUTPUT:
|
|||
---
|
||||
fail_compilation/diag16977.d(25): Error: undefined identifier `undefined`, did you mean function `undefinedId`?
|
||||
fail_compilation/diag16977.d(26): Error: cannot implicitly convert expression `"\x01string"` of type `string` to `int`
|
||||
fail_compilation/diag16977.d(27): Error: template `diag16977.templ` cannot deduce function from argument types `!()(int)`
|
||||
fail_compilation/diag16977.d(27): Error: none of the overloads of template `diag16977.templ` are callable using argument types `!()(int)`
|
||||
fail_compilation/diag16977.d(20): Candidate is: `templ(S)(S s)`
|
||||
with `S = int`
|
||||
must satisfy the following constraint:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue