d: Merge upstream dmd, druntime e4f8919591, phobos 3ad507b51.
D front-end changes: - Import dmd v2.101.0-beta.1. - Add predefined version `D_Optimized' when compiling with `-O'. - Shortened method syntax (DIP1043) is now enabled by default. - Array literals assigned to `scope' array variables are now allocated on the stack. - Implement `@system' variables (DIP1035), available behind the preview feature flag `-fpreview=systemvariables'. D runtime changes: - Import druntime v2.101.0-beta.1. Phobos changes: - Import phobos v2.101.0-beta.1. - Added `std.typecons.SafeRefCounted', that can be used in `@safe' code with `-fpreview=dip1000'. gcc/d/ChangeLog: * d-attribs.cc (apply_user_attributes): Update for new front-end interface. * d-builtins.cc (d_init_versions): Predefine `D_Optimized' with compiling with optimizations enabled. * d-lang.cc (d_handle_option): Update for new front-end interface. Handle new option `-fpreview=systemvariables'. * dmd/MERGE: Merge upstream dmd e4f8919591. * dmd/VERSION: Bump version to v2.101.0-beta.1. * expr.cc (ExprVisitor::visit (AssignExp *)): Treat construction of static arrays from a call expression as a simple assignment. (ExprVisitor::visit (ArrayLiteralExp *)): Handle array literals with `scope' storage. * gdc.texi: Update documentation of `-fpreview=' options. * lang.opt (fpreview=shortenedmethods): Remove. (fpreview=systemvariables): New option. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime e4f8919591. * src/MERGE: Merge upstream phobos 3ad507b51. gcc/testsuite/ChangeLog: * gdc.dg/simd19630.d: Move tests with errors to ... * gdc.dg/simd19630b.d: ... here. New test. * gdc.dg/simd19630c.d: New test. * gdc.dg/simd_ctfe.d: Removed. * gdc.dg/simd18867.d: New test. * gdc.dg/simd19788.d: New test. * gdc.dg/simd21469.d: New test. * gdc.dg/simd21672.d: New test. * gdc.dg/simd23077.d: New test. * gdc.dg/simd23084.d: New test. * gdc.dg/simd23085.d: New test. * gdc.dg/torture/simd19632.d: New test. * gdc.dg/torture/simd20041.d: New test. * gdc.dg/torture/simd21673.d: New test. * gdc.dg/torture/simd21676.d: New test. * gdc.dg/torture/simd22438.d: New test. * gdc.dg/torture/simd23009.d: New test. * gdc.dg/torture/simd23077.d: New test. * gdc.dg/torture/simd8.d: New test. * gdc.dg/torture/simd9.d: New test. * gdc.dg/torture/simd_prefetch.d: New test.
This commit is contained in:
parent
cfd8541805
commit
7e7ebe3e35
380 changed files with 3837 additions and 1994 deletions
|
@ -426,7 +426,8 @@ build_attributes (Expressions *eattrs)
|
|||
void
|
||||
apply_user_attributes (Dsymbol *sym, tree node)
|
||||
{
|
||||
if (!sym->userAttribDecl)
|
||||
UserAttributeDeclaration *uda = sym->userAttribDecl ();
|
||||
if (uda == NULL)
|
||||
return;
|
||||
|
||||
location_t saved_location = input_location;
|
||||
|
@ -436,7 +437,7 @@ apply_user_attributes (Dsymbol *sym, tree node)
|
|||
if (TYPE_P (node) && !COMPLETE_TYPE_P (node))
|
||||
attr_flags |= ATTR_FLAG_TYPE_IN_PLACE;
|
||||
|
||||
Expressions *attrs = sym->userAttribDecl->getAttributes ();
|
||||
Expressions *attrs = uda->getAttributes ();
|
||||
decl_attributes (&node, build_attributes (attrs), attr_flags);
|
||||
|
||||
input_location = saved_location;
|
||||
|
|
|
@ -505,6 +505,9 @@ d_init_versions (void)
|
|||
VersionCondition::addPredefinedGlobalIdent ("D_TypeInfo");
|
||||
}
|
||||
|
||||
if (optimize)
|
||||
VersionCondition::addPredefinedGlobalIdent ("D_Optimized");
|
||||
|
||||
VersionCondition::addPredefinedGlobalIdent ("all");
|
||||
|
||||
/* Emit all target-specific version identifiers. */
|
||||
|
|
|
@ -567,10 +567,10 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
global.params.fixAliasThis = value;
|
||||
global.params.previewIn = value;
|
||||
global.params.fix16997 = value;
|
||||
global.params.noSharedAccess = value;
|
||||
global.params.noSharedAccess = FeatureState::enabled;
|
||||
global.params.rvalueRefParam = FeatureState::enabled;
|
||||
global.params.inclusiveInContracts = value;
|
||||
global.params.shortenedMethods = value;
|
||||
global.params.systemVariables = FeatureState::enabled;
|
||||
global.params.fixImmutableConv = value;
|
||||
break;
|
||||
|
||||
|
@ -619,15 +619,15 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
|
|||
break;
|
||||
|
||||
case OPT_fpreview_nosharedaccess:
|
||||
global.params.noSharedAccess = value;
|
||||
global.params.noSharedAccess = FeatureState::enabled;
|
||||
break;
|
||||
|
||||
case OPT_fpreview_rvaluerefparam:
|
||||
global.params.rvalueRefParam = FeatureState::enabled;
|
||||
break;
|
||||
|
||||
case OPT_fpreview_shortenedmethods:
|
||||
global.params.shortenedMethods = value;
|
||||
case OPT_fpreview_systemvariables:
|
||||
global.params.systemVariables = FeatureState::enabled;
|
||||
break;
|
||||
|
||||
case OPT_frelease:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
4219ba670ce9ff92f3e874f0f048f2c28134c008
|
||||
e4f89195913be1dc638707b1abb24c4f3ae7e0bf
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the dlang/dmd repository.
|
||||
|
|
|
@ -1 +1 @@
|
|||
v2.100.1
|
||||
v2.101.0-beta.1
|
||||
|
|
|
@ -109,7 +109,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
|
|||
CPPMANGLE cppmangle;
|
||||
|
||||
/// overridden symbol with pragma(mangle, "...") if not null
|
||||
MangleOverride* mangleOverride;
|
||||
MangleOverride* pMangleOverride;
|
||||
|
||||
/**
|
||||
* !=null if is nested
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
CPPMANGLE cppmangle;
|
||||
|
||||
// overridden symbol with pragma(mangle, "...")
|
||||
MangleOverride *mangleOverride;
|
||||
MangleOverride *pMangleOverride;
|
||||
/* !=NULL if is nested
|
||||
* pointing to the dsymbol that directly enclosing it.
|
||||
* 1. The function that enclosing it (nested struct and class)
|
||||
|
@ -174,7 +174,7 @@ public:
|
|||
structalign_t alignment; // alignment applied outside of the struct
|
||||
ThreeState ispod; // if struct is POD
|
||||
private:
|
||||
uint8_t bitFields;
|
||||
uint16_t bitFields;
|
||||
public:
|
||||
static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject);
|
||||
StructDeclaration *syntaxCopy(Dsymbol *s) override;
|
||||
|
|
|
@ -894,50 +894,9 @@ extern (C++) final class PragmaDeclaration : AttribDeclaration
|
|||
// then it's evaluated on demand in function semantic
|
||||
return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.visibility, sc.explicitVisibility, sc.aligndecl, this);
|
||||
}
|
||||
if (ident == Id.printf || ident == Id.scanf)
|
||||
{
|
||||
auto sc2 = sc.push();
|
||||
|
||||
if (ident == Id.printf)
|
||||
// Override previous setting, never let both be set
|
||||
sc2.flags = (sc2.flags & ~SCOPE.scanf) | SCOPE.printf;
|
||||
else
|
||||
sc2.flags = (sc2.flags & ~SCOPE.printf) | SCOPE.scanf;
|
||||
|
||||
return sc2;
|
||||
}
|
||||
return sc;
|
||||
}
|
||||
|
||||
PINLINE evalPragmaInline(Scope* sc)
|
||||
{
|
||||
if (!args || args.dim == 0)
|
||||
return PINLINE.default_;
|
||||
|
||||
Expression e = (*args)[0];
|
||||
if (!e.type)
|
||||
{
|
||||
|
||||
sc = sc.startCTFE();
|
||||
e = e.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
e = e.ctfeInterpret();
|
||||
e = e.toBoolean(sc);
|
||||
if (e.isErrorExp())
|
||||
error("pragma(`inline`, `true` or `false`) expected, not `%s`", (*args)[0].toChars());
|
||||
(*args)[0] = e;
|
||||
}
|
||||
|
||||
const opt = e.toBool();
|
||||
if (opt.isEmpty())
|
||||
return PINLINE.default_;
|
||||
else if (opt.get())
|
||||
return PINLINE.always;
|
||||
else
|
||||
return PINLINE.never;
|
||||
}
|
||||
|
||||
override const(char)* kind() const
|
||||
{
|
||||
return "pragma";
|
||||
|
|
|
@ -154,7 +154,6 @@ public:
|
|||
|
||||
PragmaDeclaration *syntaxCopy(Dsymbol *s) override;
|
||||
Scope *newScope(Scope *sc) override;
|
||||
PINLINE evalPragmaInline(Scope* sc);
|
||||
const char *kind() const override;
|
||||
void accept(Visitor *v) override { v->visit(this); }
|
||||
};
|
||||
|
|
|
@ -300,7 +300,7 @@ FuncDeclaration buildOpAssign(StructDeclaration sd, Scope* sc)
|
|||
auto tf = new TypeFunction(ParameterList(fparams), sd.handleType(), LINK.d, stc | STC.ref_);
|
||||
auto fop = new FuncDeclaration(declLoc, Loc.initial, Id.assign, stc, tf);
|
||||
fop.storage_class |= STC.inference;
|
||||
fop.flags |= FUNCFLAG.generated;
|
||||
fop.isGenerated = true;
|
||||
Expression e;
|
||||
if (stc & STC.disable)
|
||||
{
|
||||
|
@ -581,7 +581,7 @@ FuncDeclaration buildXopEquals(StructDeclaration sd, Scope* sc)
|
|||
tf = tf.addSTC(STC.const_).toTypeFunction();
|
||||
Identifier id = Id.xopEquals;
|
||||
auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf);
|
||||
fop.flags |= FUNCFLAG.generated;
|
||||
fop.isGenerated = true;
|
||||
fop.parent = sd;
|
||||
Expression e1 = new IdentifierExp(loc, Id.This);
|
||||
Expression e2 = new IdentifierExp(loc, Id.p);
|
||||
|
@ -705,7 +705,7 @@ FuncDeclaration buildXopCmp(StructDeclaration sd, Scope* sc)
|
|||
tf = tf.addSTC(STC.const_).toTypeFunction();
|
||||
Identifier id = Id.xopCmp;
|
||||
auto fop = new FuncDeclaration(declLoc, Loc.initial, id, 0, tf);
|
||||
fop.flags |= FUNCFLAG.generated;
|
||||
fop.isGenerated = true;
|
||||
fop.parent = sd;
|
||||
Expression e1 = new IdentifierExp(loc, Id.This);
|
||||
Expression e2 = new IdentifierExp(loc, Id.p);
|
||||
|
@ -823,7 +823,7 @@ FuncDeclaration buildXtoHash(StructDeclaration sd, Scope* sc)
|
|||
auto tf = new TypeFunction(ParameterList(parameters), Type.thash_t, LINK.d, STC.nothrow_ | STC.trusted);
|
||||
Identifier id = Id.xtoHash;
|
||||
auto fop = new FuncDeclaration(declLoc, Loc.initial, id, STC.static_, tf);
|
||||
fop.flags |= FUNCFLAG.generated;
|
||||
fop.isGenerated = true;
|
||||
|
||||
/* Do memberwise hashing.
|
||||
*
|
||||
|
@ -961,7 +961,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc)
|
|||
{
|
||||
//printf("Building __fieldDtor(), %s\n", e.toChars());
|
||||
auto dd = new DtorDeclaration(declLoc, Loc.initial, stc, Id.__fieldDtor);
|
||||
dd.flags |= FUNCFLAG.generated;
|
||||
dd.isGenerated = true;
|
||||
dd.storage_class |= STC.inference;
|
||||
dd.fbody = new ExpStatement(loc, e);
|
||||
ad.members.push(dd);
|
||||
|
@ -1017,7 +1017,7 @@ void buildDtors(AggregateDeclaration ad, Scope* sc)
|
|||
e = Expression.combine(e, ce);
|
||||
}
|
||||
auto dd = new DtorDeclaration(declLoc, Loc.initial, stc, Id.__aggrDtor);
|
||||
dd.flags |= FUNCFLAG.generated;
|
||||
dd.isGenerated = true;
|
||||
dd.storage_class |= STC.inference;
|
||||
dd.fbody = new ExpStatement(loc, e);
|
||||
ad.members.push(dd);
|
||||
|
@ -1088,7 +1088,7 @@ private DtorDeclaration buildWindowsCppDtor(AggregateDeclaration ad, DtorDeclara
|
|||
stmts.push(new ExpStatement(loc, call));
|
||||
stmts.push(new ReturnStatement(loc, new CastExp(loc, new ThisExp(loc), Type.tvoidptr)));
|
||||
func.fbody = new CompoundStatement(loc, stmts);
|
||||
func.flags |= FUNCFLAG.generated;
|
||||
func.isGenerated = true;
|
||||
|
||||
auto sc2 = sc.push();
|
||||
sc2.stc &= ~STC.static_; // not a static destructor
|
||||
|
@ -1140,7 +1140,7 @@ private DtorDeclaration buildExternDDtor(AggregateDeclaration ad, Scope* sc)
|
|||
auto call = new CallExp(dtor.loc, dtor, null);
|
||||
call.directcall = true; // non-virtual call Class.__dtor();
|
||||
func.fbody = new ExpStatement(dtor.loc, call);
|
||||
func.flags |= FUNCFLAG.generated;
|
||||
func.isGenerated = true;
|
||||
func.storage_class |= STC.inference;
|
||||
|
||||
auto sc2 = sc.push();
|
||||
|
@ -1416,7 +1416,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
|
|||
//printf("Building __fieldPostBlit()\n");
|
||||
checkShared();
|
||||
auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__fieldPostblit);
|
||||
dd.flags |= FUNCFLAG.generated;
|
||||
dd.isGenerated = true;
|
||||
dd.storage_class |= STC.inference | STC.scope_;
|
||||
dd.fbody = (stc & STC.disable) ? null : new CompoundStatement(loc, postblitCalls);
|
||||
sd.postblits.shift(dd);
|
||||
|
@ -1454,7 +1454,7 @@ FuncDeclaration buildPostBlit(StructDeclaration sd, Scope* sc)
|
|||
|
||||
checkShared();
|
||||
auto dd = new PostBlitDeclaration(declLoc, Loc.initial, stc, Id.__aggrPostblit);
|
||||
dd.flags |= FUNCFLAG.generated;
|
||||
dd.isGenerated = true;
|
||||
dd.storage_class |= STC.inference;
|
||||
dd.fbody = new ExpStatement(loc, e);
|
||||
sd.members.push(dd);
|
||||
|
@ -1517,7 +1517,7 @@ private CtorDeclaration generateCopyCtorDeclaration(StructDeclaration sd, const
|
|||
auto ccd = new CtorDeclaration(sd.loc, Loc.initial, STC.ref_, tf, true);
|
||||
ccd.storage_class |= funcStc;
|
||||
ccd.storage_class |= STC.inference;
|
||||
ccd.flags |= FUNCFLAG.generated;
|
||||
ccd.isGenerated = true;
|
||||
return ccd;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ if (__traits(isUnsigned, T))
|
|||
string result = "extern (C++) pure nothrow @nogc @safe final {";
|
||||
enum structName = __traits(identifier, S);
|
||||
|
||||
string initialValue = "";
|
||||
foreach (size_t i, mem; __traits(allMembers, S))
|
||||
{
|
||||
static assert(is(typeof(__traits(getMember, S, mem)) == bool));
|
||||
|
@ -37,8 +38,10 @@ if (__traits(isUnsigned, T))
|
|||
v ? (bitFields |= "~mask~") : (bitFields &= ~"~mask~");
|
||||
return v;
|
||||
}";
|
||||
|
||||
initialValue = (__traits(getMember, S.init, mem) ? "1" : "0") ~ initialValue;
|
||||
}
|
||||
return result ~ "}\n private "~T.stringof~" bitFields;\n";
|
||||
return result ~ "}\n private "~T.stringof~" bitFields = 0b" ~ initialValue ~ ";\n";
|
||||
}
|
||||
|
||||
///
|
||||
|
@ -48,7 +51,7 @@ unittest
|
|||
{
|
||||
bool x;
|
||||
bool y;
|
||||
bool z;
|
||||
bool z = 1;
|
||||
}
|
||||
|
||||
static struct S
|
||||
|
@ -66,5 +69,5 @@ unittest
|
|||
s.y = true;
|
||||
assert(s.y);
|
||||
assert(!s.x);
|
||||
assert(!s.z);
|
||||
assert(s.z);
|
||||
}
|
||||
|
|
|
@ -144,9 +144,14 @@ struct FileMapping(Datum)
|
|||
import core.stdc.string : strlen;
|
||||
import core.stdc.stdlib : malloc;
|
||||
import core.stdc.string : memcpy;
|
||||
auto totalNameLength = filename.strlen() + 1;
|
||||
name = cast(char*) memcpy(malloc(totalNameLength), filename, totalNameLength);
|
||||
name || assert(0, "FileMapping: Out of memory.");
|
||||
const totalNameLength = filename.strlen() + 1;
|
||||
auto namex = cast(char*) malloc(totalNameLength);
|
||||
if (!namex)
|
||||
{
|
||||
fprintf(stderr, "FileMapping: Out of memory.");
|
||||
exit(1);
|
||||
}
|
||||
name = cast(char*) memcpy(namex, filename, totalNameLength);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1906,6 +1906,8 @@ final class CParser(AST) : Parser!AST
|
|||
{
|
||||
auto str = asmName.peekString();
|
||||
p.mangleOverride = str;
|
||||
// p.adFlags |= AST.VarDeclaration.nounderscore;
|
||||
p.adFlags |= 4; // cannot get above line to compile on Ubuntu
|
||||
}
|
||||
}
|
||||
s = applySpecifier(s, specifier);
|
||||
|
@ -5164,18 +5166,40 @@ final class CParser(AST) : Parser!AST
|
|||
if (n.value == TOK.identifier && n.ident == Id.pop)
|
||||
{
|
||||
scan(&n);
|
||||
while (n.value == TOK.comma)
|
||||
size_t len = this.records.length;
|
||||
if (n.value == TOK.rightParenthesis) // #pragma pack ( pop )
|
||||
{
|
||||
if (len == 0) // nothing to pop
|
||||
return closingParen();
|
||||
|
||||
this.records.setDim(len - 1);
|
||||
this.packs.setDim(len - 1);
|
||||
if (len == 1) // stack is now empty
|
||||
packalign.setDefault();
|
||||
else
|
||||
packalign = (*this.packs)[len - 1];
|
||||
return closingParen();
|
||||
}
|
||||
while (n.value == TOK.comma) // #pragma pack ( pop ,
|
||||
{
|
||||
scan(&n);
|
||||
if (n.value == TOK.identifier)
|
||||
{
|
||||
for (size_t len = this.records.length; len; --len)
|
||||
/* pragma pack(pop, identifier
|
||||
* Pop until identifier is found, pop that one too, and set
|
||||
* alignment to the new top of the stack.
|
||||
* If identifier is not found, do nothing.
|
||||
*/
|
||||
for ( ; len; --len)
|
||||
{
|
||||
if ((*this.records)[len - 1] == n.ident)
|
||||
{
|
||||
packalign = (*this.packs)[len - 1];
|
||||
this.records.setDim(len - 1);
|
||||
this.packs.setDim(len - 1);
|
||||
if (len > 1)
|
||||
packalign = (*this.packs)[len - 2];
|
||||
else
|
||||
packalign.setDefault(); // stack empty, use default
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5184,14 +5208,18 @@ final class CParser(AST) : Parser!AST
|
|||
else if (n.value == TOK.int32Literal)
|
||||
{
|
||||
setPackAlign(n);
|
||||
this.records.push(null);
|
||||
this.packs.push(packalign);
|
||||
scan(&n);
|
||||
}
|
||||
else
|
||||
{
|
||||
error(loc, "identifier or alignment value expected following `#pragma pack(pop,` not `%s`", n.toChars());
|
||||
scan(&n);
|
||||
}
|
||||
}
|
||||
return closingParen();
|
||||
}
|
||||
/* # pragma pack ( integer )
|
||||
* Sets alignment to integer
|
||||
*/
|
||||
if (n.value == TOK.int32Literal)
|
||||
{
|
||||
|
@ -5200,6 +5228,7 @@ final class CParser(AST) : Parser!AST
|
|||
return closingParen();
|
||||
}
|
||||
/* # pragma pack ( )
|
||||
* Sets alignment to default
|
||||
*/
|
||||
if (n.value == TOK.rightParenthesis)
|
||||
{
|
||||
|
|
|
@ -615,7 +615,7 @@ private final class CppMangleVisitor : Visitor
|
|||
if (!ti)
|
||||
{
|
||||
auto ag = s.isAggregateDeclaration();
|
||||
const ident = (ag && ag.mangleOverride) ? ag.mangleOverride.id : s.ident;
|
||||
const ident = (ag && ag.pMangleOverride) ? ag.pMangleOverride.id : s.ident;
|
||||
this.writeNamespace(s.cppnamespace, () {
|
||||
this.writeIdentifier(ident);
|
||||
this.abiTags.writeSymbol(s, this);
|
||||
|
@ -654,14 +654,14 @@ private final class CppMangleVisitor : Visitor
|
|||
}
|
||||
|
||||
auto ag = ti.aliasdecl ? ti.aliasdecl.isAggregateDeclaration() : null;
|
||||
if (ag && ag.mangleOverride)
|
||||
if (ag && ag.pMangleOverride)
|
||||
{
|
||||
this.writeNamespace(
|
||||
ti.toAlias().cppnamespace, () {
|
||||
this.writeIdentifier(ag.mangleOverride.id);
|
||||
if (ag.mangleOverride.agg && ag.mangleOverride.agg.isInstantiated())
|
||||
this.writeIdentifier(ag.pMangleOverride.id);
|
||||
if (ag.pMangleOverride.agg && ag.pMangleOverride.agg.isInstantiated())
|
||||
{
|
||||
auto to = ag.mangleOverride.agg.isInstantiated();
|
||||
auto to = ag.pMangleOverride.agg.isInstantiated();
|
||||
append(to);
|
||||
this.abiTags.writeSymbol(to.tempdecl, this);
|
||||
template_args(to);
|
||||
|
|
|
@ -327,6 +327,45 @@ MATCH implicitConvTo(Expression e, Type t)
|
|||
return MATCH.nomatch;
|
||||
}
|
||||
|
||||
// Apply mod bits to each function parameter,
|
||||
// and see if we can convert the function argument to the modded type
|
||||
static bool parametersModMatch(Expressions* args, TypeFunction tf, MOD mod)
|
||||
{
|
||||
const size_t nparams = tf.parameterList.length;
|
||||
const size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended
|
||||
foreach (const i; j .. args.dim)
|
||||
{
|
||||
Expression earg = (*args)[i];
|
||||
Type targ = earg.type.toBasetype();
|
||||
static if (LOG)
|
||||
{
|
||||
printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
|
||||
}
|
||||
if (i - j < nparams)
|
||||
{
|
||||
Parameter fparam = tf.parameterList[i - j];
|
||||
if (fparam.isLazy())
|
||||
return false; // not sure what to do with this
|
||||
Type tparam = fparam.type;
|
||||
if (!tparam)
|
||||
continue;
|
||||
if (fparam.isReference())
|
||||
{
|
||||
if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
static if (LOG)
|
||||
{
|
||||
printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
|
||||
}
|
||||
if (implicitMod(earg, targ, mod) == MATCH.nomatch)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MATCH visitAdd(AddExp e)
|
||||
{
|
||||
version (none)
|
||||
|
@ -894,9 +933,6 @@ MATCH implicitConvTo(Expression e, Type t)
|
|||
/* Apply mod bits to each function parameter,
|
||||
* and see if we can convert the function argument to the modded type
|
||||
*/
|
||||
|
||||
size_t nparams = tf.parameterList.length;
|
||||
size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended
|
||||
if (auto dve = e.e1.isDotVarExp())
|
||||
{
|
||||
/* Treat 'this' as just another function argument
|
||||
|
@ -905,36 +941,9 @@ MATCH implicitConvTo(Expression e, Type t)
|
|||
if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
|
||||
return result;
|
||||
}
|
||||
foreach (const i; j .. e.arguments.dim)
|
||||
{
|
||||
Expression earg = (*e.arguments)[i];
|
||||
Type targ = earg.type.toBasetype();
|
||||
static if (LOG)
|
||||
{
|
||||
printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
|
||||
}
|
||||
if (i - j < nparams)
|
||||
{
|
||||
Parameter fparam = tf.parameterList[i - j];
|
||||
if (fparam.isLazy())
|
||||
return result; // not sure what to do with this
|
||||
Type tparam = fparam.type;
|
||||
if (!tparam)
|
||||
continue;
|
||||
if (fparam.isReference())
|
||||
{
|
||||
if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
|
||||
return result;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
static if (LOG)
|
||||
{
|
||||
printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
|
||||
}
|
||||
if (implicitMod(earg, targ, mod) == MATCH.nomatch)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!parametersModMatch(e.arguments, tf, mod))
|
||||
return result;
|
||||
|
||||
/* Success
|
||||
*/
|
||||
|
@ -1206,47 +1215,16 @@ MATCH implicitConvTo(Expression e, Type t)
|
|||
if (tf.purity == PURE.impure)
|
||||
return MATCH.nomatch; // impure
|
||||
|
||||
// Allow a conversion to immutable type, or
|
||||
// conversions of mutable types between thread-local and shared.
|
||||
if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
|
||||
{
|
||||
return MATCH.nomatch;
|
||||
}
|
||||
// Allow a conversion to immutable type, or
|
||||
// conversions of mutable types between thread-local and shared.
|
||||
|
||||
Expressions* args = e.arguments;
|
||||
|
||||
size_t nparams = tf.parameterList.length;
|
||||
// if TypeInfoArray was prepended
|
||||
size_t j = tf.isDstyleVariadic();
|
||||
for (size_t i = j; i < e.arguments.dim; ++i)
|
||||
if (!parametersModMatch(e.arguments, tf, mod))
|
||||
{
|
||||
Expression earg = (*args)[i];
|
||||
Type targ = earg.type.toBasetype();
|
||||
static if (LOG)
|
||||
{
|
||||
printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
|
||||
}
|
||||
if (i - j < nparams)
|
||||
{
|
||||
Parameter fparam = tf.parameterList[i - j];
|
||||
if (fparam.isLazy())
|
||||
return MATCH.nomatch; // not sure what to do with this
|
||||
Type tparam = fparam.type;
|
||||
if (!tparam)
|
||||
continue;
|
||||
if (fparam.isReference())
|
||||
{
|
||||
if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
|
||||
return MATCH.nomatch;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
static if (LOG)
|
||||
{
|
||||
printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
|
||||
}
|
||||
if (implicitMod(earg, targ, mod) == MATCH.nomatch)
|
||||
return MATCH.nomatch;
|
||||
return MATCH.nomatch;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -227,6 +227,7 @@ extern (C++) abstract class Declaration : Dsymbol
|
|||
ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons)
|
||||
enum wasRead = 1; // set if AliasDeclaration was read
|
||||
enum ignoreRead = 2; // ignore any reads of AliasDeclaration
|
||||
enum nounderscore = 4; // don't prepend _ to mangled name
|
||||
|
||||
Symbol* isym; // import version of csym
|
||||
|
||||
|
@ -481,6 +482,11 @@ extern (C++) abstract class Declaration : Dsymbol
|
|||
return (storage_class & STC.scope_) != 0;
|
||||
}
|
||||
|
||||
final bool isReturn() const pure nothrow @nogc @safe
|
||||
{
|
||||
return (storage_class & STC.return_) != 0;
|
||||
}
|
||||
|
||||
final bool isSynchronized() const pure nothrow @nogc @safe
|
||||
{
|
||||
return (storage_class & STC.synchronized_) != 0;
|
||||
|
@ -542,6 +548,11 @@ extern (C++) abstract class Declaration : Dsymbol
|
|||
return (storage_class & STC.future) != 0;
|
||||
}
|
||||
|
||||
final extern(D) bool isSystem() const pure nothrow @nogc @safe
|
||||
{
|
||||
return (storage_class & STC.system) != 0;
|
||||
}
|
||||
|
||||
override final Visibility visible() pure nothrow @nogc @safe
|
||||
{
|
||||
return visibility;
|
||||
|
@ -780,7 +791,17 @@ extern (C++) final class AliasDeclaration : Declaration
|
|||
* is not overloadable.
|
||||
*/
|
||||
if (type)
|
||||
return false;
|
||||
{
|
||||
/*
|
||||
If type has been resolved already we could
|
||||
still be inserting an alias from an import.
|
||||
|
||||
If we are handling an alias then pretend
|
||||
it was inserting and return true, if not then
|
||||
false since we didn't even pretend to insert something.
|
||||
*/
|
||||
return this._import && this.equals(s);
|
||||
}
|
||||
|
||||
/* When s is added in member scope by static if, mixin("code") or others,
|
||||
* aliassym is determined already. See the case in: test/compilable/test61.d
|
||||
|
@ -1634,7 +1655,7 @@ extern (C++) class VarDeclaration : Declaration
|
|||
// Add this VarDeclaration to fdv.closureVars[] if not already there
|
||||
if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
|
||||
// https://issues.dlang.org/show_bug.cgi?id=17605
|
||||
(fdv.flags & FUNCFLAG.compileTimeOnly || !(fdthis.flags & FUNCFLAG.compileTimeOnly))
|
||||
(fdv.isCompileTimeOnly || !fdthis.isCompileTimeOnly)
|
||||
)
|
||||
{
|
||||
if (!fdv.closureVars.contains(this))
|
||||
|
@ -1754,16 +1775,21 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
|
|||
|
||||
override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
|
||||
{
|
||||
//printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
|
||||
static void print(const ref FieldState fieldState)
|
||||
enum log = false;
|
||||
static if (log)
|
||||
{
|
||||
printf("FieldState.offset = %d bytes\n", fieldState.offset);
|
||||
printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
|
||||
printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
|
||||
printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
|
||||
printf(" .inFlight = %d\n\n", fieldState.inFlight);
|
||||
printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars());
|
||||
void print(const ref FieldState fieldState)
|
||||
{
|
||||
printf("FieldState.offset = %d bytes\n", fieldState.offset);
|
||||
printf(" .fieldOffset = %d bytes\n", fieldState.fieldOffset);
|
||||
printf(" .bitOffset = %d bits\n", fieldState.bitOffset);
|
||||
printf(" .fieldSize = %d bytes\n", fieldState.fieldSize);
|
||||
printf(" .inFlight = %d\n", fieldState.inFlight);
|
||||
printf(" fieldWidth = %d bits\n", fieldWidth);
|
||||
}
|
||||
print(fieldState);
|
||||
}
|
||||
//print(fieldState);
|
||||
|
||||
Type t = type.toBasetype();
|
||||
const bool anon = isAnonymous();
|
||||
|
@ -1780,6 +1806,7 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
|
|||
assert(sz != SIZE_INVALID && sz < uint.max);
|
||||
uint memsize = cast(uint)sz; // size of member
|
||||
uint memalignsize = target.fieldalign(t); // size of member for alignment purposes
|
||||
if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize);
|
||||
|
||||
if (fieldWidth == 0 && !anon)
|
||||
error(loc, "named bit fields cannot have 0 width");
|
||||
|
@ -1790,6 +1817,7 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
|
|||
|
||||
void startNewField()
|
||||
{
|
||||
if (log) printf("startNewField()\n");
|
||||
uint alignsize;
|
||||
if (style == TargetC.BitFieldStyle.Gcc_Clang)
|
||||
{
|
||||
|
@ -1881,15 +1909,15 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
|
|||
|
||||
if (!fieldState.inFlight)
|
||||
{
|
||||
//printf("not in flight\n");
|
||||
startNewField();
|
||||
}
|
||||
else if (style == TargetC.BitFieldStyle.Gcc_Clang)
|
||||
{
|
||||
if (fieldState.bitOffset + fieldWidth > memsize * 8)
|
||||
{
|
||||
//printf("start1 fieldState.bitOffset:%u fieldWidth:%u memsize:%u\n", fieldState.bitOffset, fieldWidth, memsize);
|
||||
startNewField();
|
||||
}
|
||||
// If the bit-field spans more units of alignment than its type,
|
||||
// start a new field at the next alignment boundary.
|
||||
if (fieldState.bitOffset == fieldState.fieldSize * 8)
|
||||
startNewField(); // the bit field is full
|
||||
else
|
||||
{
|
||||
// if alignment boundary is crossed
|
||||
|
@ -1909,6 +1937,7 @@ extern (C++) class BitFieldDeclaration : VarDeclaration
|
|||
if (memsize != fieldState.fieldSize ||
|
||||
fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8)
|
||||
{
|
||||
//printf("new field\n");
|
||||
startNewField();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,7 @@ public:
|
|||
bool isWild() const { return (storage_class & STCwild) != 0; }
|
||||
bool isAuto() const { return (storage_class & STCauto) != 0; }
|
||||
bool isScope() const { return (storage_class & STCscope) != 0; }
|
||||
bool isReturn() const { return (storage_class & STCreturn) != 0; }
|
||||
bool isSynchronized() const { return (storage_class & STCsynchronized) != 0; }
|
||||
bool isParameter() const { return (storage_class & STCparameter) != 0; }
|
||||
bool isDeprecated() const override final { return (storage_class & STCdeprecated) != 0; }
|
||||
|
@ -615,7 +616,54 @@ public:
|
|||
|
||||
AttributeViolation* safetyViolation;
|
||||
|
||||
unsigned flags; // FUNCFLAGxxxxx
|
||||
// Formerly FUNCFLAGS
|
||||
uint32_t flags;
|
||||
bool purityInprocess() const;
|
||||
bool purityInprocess(bool v);
|
||||
bool safetyInprocess() const;
|
||||
bool safetyInprocess(bool v);
|
||||
bool nothrowInprocess() const;
|
||||
bool nothrowInprocess(bool v);
|
||||
bool nogcInprocess() const;
|
||||
bool nogcInprocess(bool v);
|
||||
bool returnInprocess() const;
|
||||
bool returnInprocess(bool v);
|
||||
bool inlineScanned() const;
|
||||
bool inlineScanned(bool v);
|
||||
bool inferScope() const;
|
||||
bool inferScope(bool v);
|
||||
bool hasCatches() const;
|
||||
bool hasCatches(bool v);
|
||||
bool isCompileTimeOnly() const;
|
||||
bool isCompileTimeOnly(bool v);
|
||||
bool printf() const;
|
||||
bool printf(bool v);
|
||||
bool scanf() const;
|
||||
bool scanf(bool v);
|
||||
bool noreturn() const;
|
||||
bool noreturn(bool v);
|
||||
bool isNRVO() const;
|
||||
bool isNRVO(bool v);
|
||||
bool isNaked() const;
|
||||
bool isNaked(bool v);
|
||||
bool isGenerated() const;
|
||||
bool isGenerated(bool v);
|
||||
bool isIntroducing() const;
|
||||
bool isIntroducing(bool v);
|
||||
bool hasSemantic3Errors() const;
|
||||
bool hasSemantic3Errors(bool v);
|
||||
bool hasNoEH() const;
|
||||
bool hasNoEH(bool v);
|
||||
bool inferRetType() const;
|
||||
bool inferRetType(bool v);
|
||||
bool hasDualContext() const;
|
||||
bool hasDualContext(bool v);
|
||||
bool hasAlwaysInlines() const;
|
||||
bool hasAlwaysInlines(bool v);
|
||||
bool isCrtCtor() const;
|
||||
bool isCrtCtor(bool v);
|
||||
bool isCrtDtor() const;
|
||||
bool isCrtDtor(bool v);
|
||||
|
||||
// Data for a function declaration that is needed for the Objective-C
|
||||
// integration.
|
||||
|
@ -655,22 +703,6 @@ public:
|
|||
|
||||
bool isNogc();
|
||||
bool isNogcBypassingInference();
|
||||
bool isNRVO() const;
|
||||
void isNRVO(bool v);
|
||||
bool isNaked() const;
|
||||
void isNaked(bool v);
|
||||
bool isGenerated() const;
|
||||
void isGenerated(bool v);
|
||||
bool isIntroducing() const;
|
||||
bool hasSemantic3Errors() const;
|
||||
bool hasNoEH() const;
|
||||
bool inferRetType() const;
|
||||
bool hasDualContext() const;
|
||||
bool hasAlwaysInlines() const;
|
||||
bool isCrtCtor() const;
|
||||
void isCrtCtor(bool v);
|
||||
bool isCrtDtor() const;
|
||||
void isCrtDtor(bool v);
|
||||
|
||||
virtual bool isNested() const;
|
||||
AggregateDeclaration *isThis() override;
|
||||
|
|
|
@ -2872,6 +2872,12 @@ public:
|
|||
else
|
||||
m = v.getConstInitializer(true);
|
||||
}
|
||||
else if (v.type.isTypeNoreturn())
|
||||
{
|
||||
// Noreturn field with default initializer
|
||||
(*elems)[fieldsSoFar + i] = null;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
m = v.type.defaultInitLiteral(e.loc);
|
||||
if (exceptionOrCant(m))
|
||||
|
|
|
@ -98,13 +98,13 @@ private const(char)[] getFilename(Identifier[] packages, Identifier ident) nothr
|
|||
{
|
||||
const(char)[] filename = ident.toString();
|
||||
|
||||
if (packages.length == 0)
|
||||
return filename;
|
||||
|
||||
OutBuffer buf;
|
||||
OutBuffer dotmods;
|
||||
auto modAliases = &global.params.modFileAliasStrings;
|
||||
|
||||
if (packages.length == 0 && modAliases.length == 0)
|
||||
return filename;
|
||||
|
||||
void checkModFileAlias(const(char)[] p)
|
||||
{
|
||||
/* Check and replace the contents of buf[] with
|
||||
|
@ -308,7 +308,7 @@ extern (C++) class Package : ScopeDsymbol
|
|||
packages ~= s.ident;
|
||||
reverse(packages);
|
||||
|
||||
if (FileManager.lookForSourceFile(getFilename(packages, ident), global.path ? (*global.path)[] : null))
|
||||
if (Module.find(getFilename(packages, ident)))
|
||||
Module.load(Loc.initial, packages, this.ident);
|
||||
else
|
||||
isPkgMod = PKG.package_;
|
||||
|
@ -492,6 +492,16 @@ extern (C++) final class Module : Package
|
|||
return new Module(Loc.initial, filename, ident, doDocComment, doHdrGen);
|
||||
}
|
||||
|
||||
static const(char)* find(const(char)* filename)
|
||||
{
|
||||
return find(filename.toDString).ptr;
|
||||
}
|
||||
|
||||
extern (D) static const(char)[] find(const(char)[] filename)
|
||||
{
|
||||
return FileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null);
|
||||
}
|
||||
|
||||
extern (C++) static Module load(const ref Loc loc, Identifiers* packages, Identifier ident)
|
||||
{
|
||||
return load(loc, packages ? (*packages)[] : null, ident);
|
||||
|
@ -506,7 +516,7 @@ extern (C++) final class Module : Package
|
|||
// foo\bar\baz
|
||||
const(char)[] filename = getFilename(packages, ident);
|
||||
// Look for the source file
|
||||
if (const result = FileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null))
|
||||
if (const result = find(filename))
|
||||
filename = result; // leaks
|
||||
|
||||
auto m = new Module(loc, filename, ident, 0, 0);
|
||||
|
@ -703,232 +713,12 @@ extern (C++) final class Module : Package
|
|||
/// ditto
|
||||
extern (D) Module parseModule(AST)()
|
||||
{
|
||||
enum Endian { little, big}
|
||||
enum SourceEncoding { utf16, utf32}
|
||||
|
||||
/*
|
||||
* Convert a buffer from UTF32 to UTF8
|
||||
* Params:
|
||||
* Endian = is the buffer big/little endian
|
||||
* buf = buffer of UTF32 data
|
||||
* Returns:
|
||||
* input buffer reencoded as UTF8
|
||||
*/
|
||||
|
||||
char[] UTF32ToUTF8(Endian endian)(const(char)[] buf)
|
||||
{
|
||||
static if (endian == Endian.little)
|
||||
alias readNext = Port.readlongLE;
|
||||
else
|
||||
alias readNext = Port.readlongBE;
|
||||
|
||||
if (buf.length & 3)
|
||||
{
|
||||
error("odd length of UTF-32 char source %llu", cast(ulong) buf.length);
|
||||
return null;
|
||||
}
|
||||
|
||||
const (uint)[] eBuf = cast(const(uint)[])buf;
|
||||
|
||||
OutBuffer dbuf;
|
||||
dbuf.reserve(eBuf.length);
|
||||
|
||||
foreach (i; 0 .. eBuf.length)
|
||||
{
|
||||
const u = readNext(&eBuf[i]);
|
||||
if (u & ~0x7F)
|
||||
{
|
||||
if (u > 0x10FFFF)
|
||||
{
|
||||
error("UTF-32 value %08x greater than 0x10FFFF", u);
|
||||
return null;
|
||||
}
|
||||
dbuf.writeUTF8(u);
|
||||
}
|
||||
else
|
||||
dbuf.writeByte(u);
|
||||
}
|
||||
dbuf.writeByte(0); //add null terminator
|
||||
return dbuf.extractSlice();
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a buffer from UTF16 to UTF8
|
||||
* Params:
|
||||
* Endian = is the buffer big/little endian
|
||||
* buf = buffer of UTF16 data
|
||||
* Returns:
|
||||
* input buffer reencoded as UTF8
|
||||
*/
|
||||
|
||||
char[] UTF16ToUTF8(Endian endian)(const(char)[] buf)
|
||||
{
|
||||
static if (endian == Endian.little)
|
||||
alias readNext = Port.readwordLE;
|
||||
else
|
||||
alias readNext = Port.readwordBE;
|
||||
|
||||
if (buf.length & 1)
|
||||
{
|
||||
error("odd length of UTF-16 char source %llu", cast(ulong) buf.length);
|
||||
return null;
|
||||
}
|
||||
|
||||
const (ushort)[] eBuf = cast(const(ushort)[])buf;
|
||||
|
||||
OutBuffer dbuf;
|
||||
dbuf.reserve(eBuf.length);
|
||||
|
||||
//i will be incremented in the loop for high codepoints
|
||||
foreach (ref i; 0 .. eBuf.length)
|
||||
{
|
||||
uint u = readNext(&eBuf[i]);
|
||||
if (u & ~0x7F)
|
||||
{
|
||||
if (0xD800 <= u && u < 0xDC00)
|
||||
{
|
||||
i++;
|
||||
if (i >= eBuf.length)
|
||||
{
|
||||
error("surrogate UTF-16 high value %04x at end of file", u);
|
||||
return null;
|
||||
}
|
||||
const u2 = readNext(&eBuf[i]);
|
||||
if (u2 < 0xDC00 || 0xE000 <= u2)
|
||||
{
|
||||
error("surrogate UTF-16 low value %04x out of range", u2);
|
||||
return null;
|
||||
}
|
||||
u = (u - 0xD7C0) << 10;
|
||||
u |= (u2 - 0xDC00);
|
||||
}
|
||||
else if (u >= 0xDC00 && u <= 0xDFFF)
|
||||
{
|
||||
error("unpaired surrogate UTF-16 value %04x", u);
|
||||
return null;
|
||||
}
|
||||
else if (u == 0xFFFE || u == 0xFFFF)
|
||||
{
|
||||
error("illegal UTF-16 value %04x", u);
|
||||
return null;
|
||||
}
|
||||
dbuf.writeUTF8(u);
|
||||
}
|
||||
else
|
||||
dbuf.writeByte(u);
|
||||
}
|
||||
dbuf.writeByte(0); //add a terminating null byte
|
||||
return dbuf.extractSlice();
|
||||
}
|
||||
|
||||
const(char)* srcname = srcfile.toChars();
|
||||
//printf("Module::parse(srcname = '%s')\n", srcname);
|
||||
isPackageFile = isPackageFileName(srcfile);
|
||||
const(char)[] buf = cast(const(char)[]) this.src;
|
||||
|
||||
bool needsReencoding = true;
|
||||
bool hasBOM = true; //assume there's a BOM
|
||||
Endian endian;
|
||||
SourceEncoding sourceEncoding;
|
||||
|
||||
if (buf.length >= 2)
|
||||
{
|
||||
/* Convert all non-UTF-8 formats to UTF-8.
|
||||
* BOM : https://www.unicode.org/faq/utf_bom.html
|
||||
* 00 00 FE FF UTF-32BE, big-endian
|
||||
* FF FE 00 00 UTF-32LE, little-endian
|
||||
* FE FF UTF-16BE, big-endian
|
||||
* FF FE UTF-16LE, little-endian
|
||||
* EF BB BF UTF-8
|
||||
*/
|
||||
if (buf[0] == 0xFF && buf[1] == 0xFE)
|
||||
{
|
||||
endian = Endian.little;
|
||||
|
||||
sourceEncoding = buf.length >= 4 && buf[2] == 0 && buf[3] == 0
|
||||
? SourceEncoding.utf32
|
||||
: SourceEncoding.utf16;
|
||||
}
|
||||
else if (buf[0] == 0xFE && buf[1] == 0xFF)
|
||||
{
|
||||
endian = Endian.big;
|
||||
sourceEncoding = SourceEncoding.utf16;
|
||||
}
|
||||
else if (buf.length >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
|
||||
{
|
||||
endian = Endian.big;
|
||||
sourceEncoding = SourceEncoding.utf32;
|
||||
}
|
||||
else if (buf.length >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
|
||||
{
|
||||
needsReencoding = false;//utf8 with BOM
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no BOM. Make use of Arcane Jill's insight that
|
||||
* the first char of D source must be ASCII to
|
||||
* figure out the encoding.
|
||||
*/
|
||||
hasBOM = false;
|
||||
if (buf.length >= 4 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
|
||||
{
|
||||
endian = Endian.little;
|
||||
sourceEncoding = SourceEncoding.utf32;
|
||||
}
|
||||
else if (buf.length >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
|
||||
{
|
||||
endian = Endian.big;
|
||||
sourceEncoding = SourceEncoding.utf32;
|
||||
}
|
||||
else if (buf.length >= 2 && buf[1] == 0) //try to check for UTF-16
|
||||
{
|
||||
endian = Endian.little;
|
||||
sourceEncoding = SourceEncoding.utf16;
|
||||
}
|
||||
else if (buf[0] == 0)
|
||||
{
|
||||
endian = Endian.big;
|
||||
sourceEncoding = SourceEncoding.utf16;
|
||||
}
|
||||
else {
|
||||
// It's UTF-8
|
||||
needsReencoding = false;
|
||||
if (buf[0] >= 0x80)
|
||||
{
|
||||
error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
//throw away BOM
|
||||
if (hasBOM)
|
||||
{
|
||||
if (!needsReencoding) buf = buf[3..$];// utf-8 already
|
||||
else if (sourceEncoding == SourceEncoding.utf32) buf = buf[4..$];
|
||||
else buf = buf[2..$]; //utf 16
|
||||
}
|
||||
}
|
||||
// Assume the buffer is from memory and has not be read from disk. Assume UTF-8.
|
||||
else if (buf.length >= 1 && (buf[0] == '\0' || buf[0] == 0x1A))
|
||||
needsReencoding = false;
|
||||
//printf("%s, %d, %d, %d\n", srcfile.name.toChars(), needsReencoding, endian == Endian.little, sourceEncoding == SourceEncoding.utf16);
|
||||
if (needsReencoding)
|
||||
{
|
||||
if (sourceEncoding == SourceEncoding.utf16)
|
||||
{
|
||||
buf = endian == Endian.little
|
||||
? UTF16ToUTF8!(Endian.little)(buf)
|
||||
: UTF16ToUTF8!(Endian.big)(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = endian == Endian.little
|
||||
? UTF32ToUTF8!(Endian.little)(buf)
|
||||
: UTF32ToUTF8!(Endian.big)(buf);
|
||||
}
|
||||
// an error happened on UTF conversion
|
||||
if (buf is null) return null;
|
||||
}
|
||||
const(char)[] buf = processSource(src, this);
|
||||
// an error happened on UTF conversion
|
||||
if (buf is null) return null;
|
||||
|
||||
/* If it starts with the string "Ddoc", then it's a documentation
|
||||
* source file.
|
||||
|
@ -1533,3 +1323,192 @@ extern (C++) struct ModuleDeclaration
|
|||
return this.toChars().toDString;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the content of a source file
|
||||
*
|
||||
* Attempts to find which encoding it is using, if it has BOM,
|
||||
* and then normalize the source to UTF-8. If no encoding is required,
|
||||
* a slice of `src` will be returned without extra allocation.
|
||||
*
|
||||
* Params:
|
||||
* src = Content of the source file to process
|
||||
* mod = Module matching `src`, used for error handling
|
||||
*
|
||||
* Returns:
|
||||
* UTF-8 encoded variant of `src`, stripped of any BOM,
|
||||
* or `null` if an error happened.
|
||||
*/
|
||||
private const(char)[] processSource (const(ubyte)[] src, Module mod)
|
||||
{
|
||||
enum SourceEncoding { utf16, utf32}
|
||||
enum Endian { little, big}
|
||||
|
||||
/*
|
||||
* Convert a buffer from UTF32 to UTF8
|
||||
* Params:
|
||||
* Endian = is the buffer big/little endian
|
||||
* buf = buffer of UTF32 data
|
||||
* Returns:
|
||||
* input buffer reencoded as UTF8
|
||||
*/
|
||||
|
||||
char[] UTF32ToUTF8(Endian endian)(const(char)[] buf)
|
||||
{
|
||||
static if (endian == Endian.little)
|
||||
alias readNext = Port.readlongLE;
|
||||
else
|
||||
alias readNext = Port.readlongBE;
|
||||
|
||||
if (buf.length & 3)
|
||||
{
|
||||
mod.error("odd length of UTF-32 char source %llu", cast(ulong) buf.length);
|
||||
return null;
|
||||
}
|
||||
|
||||
const (uint)[] eBuf = cast(const(uint)[])buf;
|
||||
|
||||
OutBuffer dbuf;
|
||||
dbuf.reserve(eBuf.length);
|
||||
|
||||
foreach (i; 0 .. eBuf.length)
|
||||
{
|
||||
const u = readNext(&eBuf[i]);
|
||||
if (u & ~0x7F)
|
||||
{
|
||||
if (u > 0x10FFFF)
|
||||
{
|
||||
mod.error("UTF-32 value %08x greater than 0x10FFFF", u);
|
||||
return null;
|
||||
}
|
||||
dbuf.writeUTF8(u);
|
||||
}
|
||||
else
|
||||
dbuf.writeByte(u);
|
||||
}
|
||||
dbuf.writeByte(0); //add null terminator
|
||||
return dbuf.extractSlice();
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a buffer from UTF16 to UTF8
|
||||
* Params:
|
||||
* Endian = is the buffer big/little endian
|
||||
* buf = buffer of UTF16 data
|
||||
* Returns:
|
||||
* input buffer reencoded as UTF8
|
||||
*/
|
||||
|
||||
char[] UTF16ToUTF8(Endian endian)(const(char)[] buf)
|
||||
{
|
||||
static if (endian == Endian.little)
|
||||
alias readNext = Port.readwordLE;
|
||||
else
|
||||
alias readNext = Port.readwordBE;
|
||||
|
||||
if (buf.length & 1)
|
||||
{
|
||||
mod.error("odd length of UTF-16 char source %llu", cast(ulong) buf.length);
|
||||
return null;
|
||||
}
|
||||
|
||||
const (ushort)[] eBuf = cast(const(ushort)[])buf;
|
||||
|
||||
OutBuffer dbuf;
|
||||
dbuf.reserve(eBuf.length);
|
||||
|
||||
//i will be incremented in the loop for high codepoints
|
||||
foreach (ref i; 0 .. eBuf.length)
|
||||
{
|
||||
uint u = readNext(&eBuf[i]);
|
||||
if (u & ~0x7F)
|
||||
{
|
||||
if (0xD800 <= u && u < 0xDC00)
|
||||
{
|
||||
i++;
|
||||
if (i >= eBuf.length)
|
||||
{
|
||||
mod.error("surrogate UTF-16 high value %04x at end of file", u);
|
||||
return null;
|
||||
}
|
||||
const u2 = readNext(&eBuf[i]);
|
||||
if (u2 < 0xDC00 || 0xE000 <= u2)
|
||||
{
|
||||
mod.error("surrogate UTF-16 low value %04x out of range", u2);
|
||||
return null;
|
||||
}
|
||||
u = (u - 0xD7C0) << 10;
|
||||
u |= (u2 - 0xDC00);
|
||||
}
|
||||
else if (u >= 0xDC00 && u <= 0xDFFF)
|
||||
{
|
||||
mod.error("unpaired surrogate UTF-16 value %04x", u);
|
||||
return null;
|
||||
}
|
||||
else if (u == 0xFFFE || u == 0xFFFF)
|
||||
{
|
||||
mod.error("illegal UTF-16 value %04x", u);
|
||||
return null;
|
||||
}
|
||||
dbuf.writeUTF8(u);
|
||||
}
|
||||
else
|
||||
dbuf.writeByte(u);
|
||||
}
|
||||
dbuf.writeByte(0); //add a terminating null byte
|
||||
return dbuf.extractSlice();
|
||||
}
|
||||
|
||||
const(char)[] buf = cast(const(char)[]) src;
|
||||
|
||||
// Assume the buffer is from memory and has not be read from disk. Assume UTF-8.
|
||||
if (buf.length < 2)
|
||||
return buf;
|
||||
|
||||
/* Convert all non-UTF-8 formats to UTF-8.
|
||||
* BOM : https://www.unicode.org/faq/utf_bom.html
|
||||
* 00 00 FE FF UTF-32BE, big-endian
|
||||
* FF FE 00 00 UTF-32LE, little-endian
|
||||
* FE FF UTF-16BE, big-endian
|
||||
* FF FE UTF-16LE, little-endian
|
||||
* EF BB BF UTF-8
|
||||
*/
|
||||
if (buf[0] == 0xFF && buf[1] == 0xFE)
|
||||
{
|
||||
if (buf.length >= 4 && buf[2] == 0 && buf[3] == 0)
|
||||
return UTF32ToUTF8!(Endian.little)(buf[4 .. $]);
|
||||
return UTF16ToUTF8!(Endian.little)(buf[2 .. $]);
|
||||
}
|
||||
|
||||
if (buf[0] == 0xFE && buf[1] == 0xFF)
|
||||
return UTF16ToUTF8!(Endian.big)(buf[2 .. $]);
|
||||
|
||||
if (buf.length >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
|
||||
return UTF32ToUTF8!(Endian.big)(buf[4 .. $]);
|
||||
|
||||
if (buf.length >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
|
||||
return buf[3 .. $];
|
||||
|
||||
/* There is no BOM. Make use of Arcane Jill's insight that
|
||||
* the first char of D source must be ASCII to
|
||||
* figure out the encoding.
|
||||
*/
|
||||
if (buf.length >= 4 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
|
||||
return UTF32ToUTF8!(Endian.little)(buf);
|
||||
if (buf.length >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
|
||||
return UTF32ToUTF8!(Endian.big)(buf);
|
||||
// try to check for UTF-16
|
||||
if (buf.length >= 2 && buf[1] == 0)
|
||||
return UTF16ToUTF8!(Endian.little)(buf);
|
||||
if (buf[0] == 0)
|
||||
return UTF16ToUTF8!(Endian.big)(buf);
|
||||
|
||||
// It's UTF-8
|
||||
if (buf[0] >= 0x80)
|
||||
{
|
||||
mod.error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
|
||||
return null;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -63,17 +63,13 @@ enum SCOPE
|
|||
free = 0x8000, /// is on free list
|
||||
|
||||
fullinst = 0x10000, /// fully instantiate templates
|
||||
|
||||
// The following are mutually exclusive
|
||||
printf = 0x4_0000, /// printf-style function
|
||||
scanf = 0x8_0000, /// scanf-style function
|
||||
}
|
||||
|
||||
/// 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.ignoresymbolvisibility |
|
||||
SCOPE.printf | SCOPE.scanf | SCOPE.Cfile;
|
||||
SCOPE.Cfile;
|
||||
|
||||
struct Scope
|
||||
{
|
||||
|
|
|
@ -216,6 +216,11 @@ extern (C++) class StructDeclaration : AggregateDeclaration
|
|||
bool hasIdentityEquals; // true if has identity opEquals
|
||||
bool hasNoFields; // has no fields
|
||||
bool hasCopyCtor; // copy constructor
|
||||
bool hasPointerField; // members with indirections
|
||||
bool hasVoidInitPointers; // void-initialized unsafe fields
|
||||
bool hasSystemFields; // @system members
|
||||
bool hasFieldWithInvariant; // invariants
|
||||
bool computedTypeProperties;// the above 3 fields are computed
|
||||
// Even if struct is defined as non-root symbol, some built-in operations
|
||||
// (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo.
|
||||
// For those, today TypeInfo_Struct is generated in COMDAT.
|
||||
|
@ -223,7 +228,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration
|
|||
}
|
||||
|
||||
import dmd.common.bitfields : generateBitFields;
|
||||
mixin(generateBitFields!(BitFields, ubyte));
|
||||
mixin(generateBitFields!(BitFields, ushort));
|
||||
|
||||
extern (D) this(const ref Loc loc, Identifier id, bool inObject)
|
||||
{
|
||||
|
@ -391,9 +396,35 @@ extern (C++) class StructDeclaration : AggregateDeclaration
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
argTypes = target.toArgTypes(type);
|
||||
}
|
||||
|
||||
/// Compute cached type properties for `TypeStruct`
|
||||
extern(D) final void determineTypeProperties()
|
||||
{
|
||||
if (computedTypeProperties)
|
||||
return;
|
||||
foreach (vd; fields)
|
||||
{
|
||||
if (vd.storage_class & STC.ref_ || vd.hasPointers())
|
||||
hasPointerField = true;
|
||||
|
||||
if (vd._init && vd._init.isVoidInitializer() && vd.type.hasPointers())
|
||||
hasVoidInitPointers = true;
|
||||
|
||||
if (vd.storage_class & STC.system || vd.type.hasSystemFields())
|
||||
hasSystemFields = true;
|
||||
|
||||
if (!vd._init && vd.type.hasVoidInitPointers())
|
||||
hasVoidInitPointers = true;
|
||||
|
||||
if (vd.type.hasInvariant())
|
||||
hasFieldWithInvariant = true;
|
||||
}
|
||||
computedTypeProperties = true;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Determine if struct is POD (Plain Old Data).
|
||||
*
|
||||
|
|
|
@ -236,25 +236,33 @@ struct FieldState
|
|||
bool inFlight; /// bit field is in flight
|
||||
}
|
||||
|
||||
// 99.9% of Dsymbols don't have attributes (at least in druntime and Phobos),
|
||||
// so save memory by grouping them into a separate struct
|
||||
private struct DsymbolAttributes
|
||||
{
|
||||
/// C++ namespace this symbol belongs to
|
||||
CPPNamespaceDeclaration cppnamespace;
|
||||
/// customized deprecation message
|
||||
DeprecatedDeclaration depdecl_;
|
||||
/// user defined attributes
|
||||
UserAttributeDeclaration userAttribDecl;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
*/
|
||||
extern (C++) class Dsymbol : ASTNode
|
||||
{
|
||||
Identifier ident;
|
||||
Dsymbol parent;
|
||||
/// C++ namespace this symbol belongs to
|
||||
CPPNamespaceDeclaration cppnamespace;
|
||||
Symbol* csym; // symbol for code generator
|
||||
const Loc loc; // where defined
|
||||
Scope* _scope; // !=null means context to use for semantic()
|
||||
const(char)* prettystring; // cached value of toPrettyChars()
|
||||
private DsymbolAttributes* atts; /// attached attribute declarations
|
||||
bool errors; // this symbol failed to pass semantic()
|
||||
PASS semanticRun = PASS.initial;
|
||||
ushort localNum; /// perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
|
||||
|
||||
DeprecatedDeclaration depdecl; // customized deprecation message
|
||||
UserAttributeDeclaration userAttribDecl; // user defined attributes
|
||||
|
||||
final extern (D) this() nothrow
|
||||
{
|
||||
//printf("Dsymbol::Dsymbol(%p)\n", this);
|
||||
|
@ -285,6 +293,42 @@ extern (C++) class Dsymbol : ASTNode
|
|||
return ident ? ident.toChars() : "__anonymous";
|
||||
}
|
||||
|
||||
// Getters / setters for fields stored in `DsymbolAttributes`
|
||||
final nothrow pure @safe
|
||||
{
|
||||
private ref DsymbolAttributes getAtts()
|
||||
{
|
||||
if (!atts)
|
||||
atts = new DsymbolAttributes();
|
||||
return *atts;
|
||||
}
|
||||
|
||||
inout(DeprecatedDeclaration) depdecl() inout { return atts ? atts.depdecl_ : null; }
|
||||
inout(CPPNamespaceDeclaration) cppnamespace() inout { return atts ? atts.cppnamespace : null; }
|
||||
inout(UserAttributeDeclaration) userAttribDecl() inout { return atts ? atts.userAttribDecl : null; }
|
||||
|
||||
DeprecatedDeclaration depdecl(DeprecatedDeclaration dd)
|
||||
{
|
||||
if (!dd && !atts)
|
||||
return null;
|
||||
return getAtts().depdecl_ = dd;
|
||||
}
|
||||
|
||||
CPPNamespaceDeclaration cppnamespace(CPPNamespaceDeclaration ns)
|
||||
{
|
||||
if (!ns && !atts)
|
||||
return null;
|
||||
return getAtts().cppnamespace = ns;
|
||||
}
|
||||
|
||||
UserAttributeDeclaration userAttribDecl(UserAttributeDeclaration uad)
|
||||
{
|
||||
if (!uad && !atts)
|
||||
return null;
|
||||
return getAtts().userAttribDecl = uad;
|
||||
}
|
||||
}
|
||||
|
||||
// helper to print fully qualified (template) arguments
|
||||
const(char)* toPrettyCharsHelper()
|
||||
{
|
||||
|
|
|
@ -167,25 +167,31 @@ struct FieldState
|
|||
bool inFlight;
|
||||
};
|
||||
|
||||
struct DsymbolAttributes;
|
||||
|
||||
class Dsymbol : public ASTNode
|
||||
{
|
||||
public:
|
||||
Identifier *ident;
|
||||
Dsymbol *parent;
|
||||
/// C++ namespace this symbol belongs to
|
||||
CPPNamespaceDeclaration *namespace_;
|
||||
Symbol *csym; // symbol for code generator
|
||||
Loc loc; // where defined
|
||||
Scope *_scope; // !=NULL means context to use for semantic()
|
||||
const utf8_t *prettystring;
|
||||
private:
|
||||
DsymbolAttributes* atts;
|
||||
public:
|
||||
bool errors; // this symbol failed to pass semantic()
|
||||
PASS semanticRun;
|
||||
unsigned short localNum; // perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab
|
||||
DeprecatedDeclaration *depdecl; // customized deprecation message
|
||||
UserAttributeDeclaration *userAttribDecl; // user defined attributes
|
||||
|
||||
static Dsymbol *create(Identifier *);
|
||||
const char *toChars() const override;
|
||||
DeprecatedDeclaration* depdecl();
|
||||
CPPNamespaceDeclaration* cppnamespace();
|
||||
UserAttributeDeclaration* userAttribDecl();
|
||||
DeprecatedDeclaration* depdecl(DeprecatedDeclaration* dd);
|
||||
CPPNamespaceDeclaration* cppnamespace(CPPNamespaceDeclaration* ns);
|
||||
UserAttributeDeclaration* userAttribDecl(UserAttributeDeclaration* uad);
|
||||
virtual const char *toPrettyCharsHelper(); // helper to print fully qualified (template) arguments
|
||||
Loc getLoc();
|
||||
const char *locToChars();
|
||||
|
|
|
@ -98,6 +98,29 @@ private uint setMangleOverride(Dsymbol s, const(char)[] sym)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply pragma printf/scanf to FuncDeclarations under `s`,
|
||||
* poking through attribute declarations such as `extern(C)`
|
||||
* but not through aggregates or function bodies.
|
||||
*
|
||||
* Params:
|
||||
* s = symbol to apply
|
||||
* printf = `true` for printf, `false` for scanf
|
||||
*/
|
||||
private void setPragmaPrintf(Dsymbol s, bool printf)
|
||||
{
|
||||
if (auto fd = s.isFuncDeclaration())
|
||||
{
|
||||
fd.printf = printf;
|
||||
fd.scanf = !printf;
|
||||
}
|
||||
|
||||
if (auto ad = s.isAttribDeclaration())
|
||||
{
|
||||
ad.include(null).foreachDsymbol( (s) { setPragmaPrintf(s, printf); } );
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************
|
||||
* Does semantic analysis on the public face of declarations.
|
||||
*/
|
||||
|
@ -855,17 +878,20 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
}
|
||||
|
||||
// Calculate type size + safety checks
|
||||
if (1)
|
||||
if (sc && sc.func)
|
||||
{
|
||||
if (dsym._init && dsym._init.isVoidInitializer() &&
|
||||
(dsym.type.hasPointers() || dsym.type.hasInvariant())) // also computes type size
|
||||
if (dsym._init && dsym._init.isVoidInitializer())
|
||||
{
|
||||
if (dsym.type.hasPointers())
|
||||
|
||||
if (dsym.type.hasPointers()) // also computes type size
|
||||
sc.setUnsafe(false, dsym.loc,
|
||||
"`void` initializers for pointers not allowed in safe functions");
|
||||
else
|
||||
else if (dsym.type.hasInvariant())
|
||||
sc.setUnsafe(false, dsym.loc,
|
||||
"`void` initializers for structs with invariants are not allowed in safe functions");
|
||||
else if (dsym.type.hasSystemFields())
|
||||
sc.setUnsafePreview(global.params.systemVariables, false, dsym.loc,
|
||||
"`void` initializers for `@system` variables not allowed in safe functions");
|
||||
}
|
||||
else if (!dsym._init &&
|
||||
!(dsym.storage_class & (STC.static_ | STC.extern_ | STC.gshared | STC.manifest | STC.field | STC.parameter)) &&
|
||||
|
@ -1036,6 +1062,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
if (f.tookAddressOf)
|
||||
f.tookAddressOf--;
|
||||
}
|
||||
else if (auto ale = ex.isArrayLiteralExp())
|
||||
{
|
||||
// or an array literal assigned to a `scope` variable
|
||||
if (!dsym.type.nextOf().needsDestruction())
|
||||
ale.onstack = true;
|
||||
}
|
||||
}
|
||||
|
||||
Expression exp = ei.exp;
|
||||
|
@ -1200,7 +1232,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
override void visit(BitFieldDeclaration dsym)
|
||||
{
|
||||
//printf("BitField::semantic('%s') %s\n", toPrettyChars(), id.toChars());
|
||||
//printf("BitField::semantic('%s')\n", dsym.toChars());
|
||||
if (dsym.semanticRun >= PASS.semanticdone)
|
||||
return;
|
||||
|
||||
|
@ -1558,6 +1590,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
foreach (s; (*pd.decl)[])
|
||||
{
|
||||
if (pd.ident == Id.printf || pd.ident == Id.scanf)
|
||||
{
|
||||
s.setPragmaPrintf(pd.ident == Id.printf);
|
||||
continue;
|
||||
}
|
||||
|
||||
s.dsymbolSemantic(sc2);
|
||||
if (pd.ident != Id.mangle)
|
||||
continue;
|
||||
|
@ -1574,13 +1612,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
agg = tc.sym;
|
||||
else if (auto ts = e.type.isTypeStruct())
|
||||
agg = ts.sym;
|
||||
ad.mangleOverride = new MangleOverride;
|
||||
ad.pMangleOverride = new MangleOverride;
|
||||
void setString(ref Expression e)
|
||||
{
|
||||
if (auto se = verifyMangleString(e))
|
||||
{
|
||||
const name = (cast(const(char)[])se.peekData()).xarraydup;
|
||||
ad.mangleOverride.id = Identifier.idPool(name);
|
||||
ad.pMangleOverride.id = Identifier.idPool(name);
|
||||
e = se;
|
||||
}
|
||||
else
|
||||
|
@ -1588,13 +1626,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
}
|
||||
if (agg)
|
||||
{
|
||||
ad.mangleOverride.agg = agg;
|
||||
ad.pMangleOverride.agg = agg;
|
||||
if (pd.args.dim == 2)
|
||||
{
|
||||
setString((*pd.args)[1]);
|
||||
}
|
||||
else
|
||||
ad.mangleOverride.id = agg.ident;
|
||||
ad.pMangleOverride.id = agg.ident;
|
||||
}
|
||||
else
|
||||
setString((*pd.args)[0]);
|
||||
|
@ -1649,29 +1687,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
if (!pd.args)
|
||||
return noDeclarations();
|
||||
|
||||
for (size_t i = 0; i < pd.args.dim; i++)
|
||||
{
|
||||
Expression e = (*pd.args)[i];
|
||||
sc = sc.startCTFE();
|
||||
e = e.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
e = ctfeInterpretForPragmaMsg(e);
|
||||
if (e.op == EXP.error)
|
||||
{
|
||||
errorSupplemental(pd.loc, "while evaluating `pragma(msg, %s)`", (*pd.args)[i].toChars());
|
||||
return;
|
||||
}
|
||||
StringExp se = e.toStringExp();
|
||||
if (se)
|
||||
{
|
||||
se = se.toUTF8(sc);
|
||||
fprintf(stderr, "%.*s", cast(int)se.len, se.peekString().ptr);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s", e.toChars());
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
if (!pragmaMsgSemantic(pd.loc, sc, pd.args))
|
||||
return;
|
||||
|
||||
return noDeclarations();
|
||||
}
|
||||
|
@ -1707,33 +1724,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
}
|
||||
else if (pd.ident == Id.startaddress)
|
||||
{
|
||||
if (!pd.args || pd.args.dim != 1)
|
||||
pd.error("function name expected for start address");
|
||||
else
|
||||
{
|
||||
/* https://issues.dlang.org/show_bug.cgi?id=11980
|
||||
* resolveProperties and ctfeInterpret call are not necessary.
|
||||
*/
|
||||
Expression e = (*pd.args)[0];
|
||||
sc = sc.startCTFE();
|
||||
e = e.expressionSemantic(sc);
|
||||
sc = sc.endCTFE();
|
||||
(*pd.args)[0] = e;
|
||||
Dsymbol sa = getDsymbol(e);
|
||||
if (!sa || !sa.isFuncDeclaration())
|
||||
pd.error("function name expected for start address, not `%s`", e.toChars());
|
||||
}
|
||||
pragmaStartAddressSemantic(pd.loc, sc, pd.args);
|
||||
return noDeclarations();
|
||||
}
|
||||
else if (pd.ident == Id.Pinline)
|
||||
{
|
||||
if (pd.args && pd.args.dim > 1)
|
||||
{
|
||||
pd.error("one boolean expression expected for `pragma(inline)`, not %llu", cast(ulong) pd.args.dim);
|
||||
pd.args.setDim(1);
|
||||
(*pd.args)[0] = ErrorExp.get();
|
||||
}
|
||||
|
||||
// this pragma now gets evaluated on demand in function semantic
|
||||
|
||||
return declarations();
|
||||
|
@ -1774,7 +1769,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
}
|
||||
else if (auto f = s.isFuncDeclaration())
|
||||
{
|
||||
f.flags |= isCtor ? FUNCFLAG.CRTCtor : FUNCFLAG.CRTDtor;
|
||||
if (isCtor)
|
||||
f.isCrtCtor = true;
|
||||
else
|
||||
f.isCrtDtor = true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
@ -3048,7 +3047,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
//printf("function storage_class = x%llx, sc.stc = x%llx, %x\n", storage_class, sc.stc, Declaration.isFinal());
|
||||
|
||||
if (sc.flags & SCOPE.compile)
|
||||
funcdecl.flags |= FUNCFLAG.compileTimeOnly; // don't emit code for this function
|
||||
funcdecl.isCompileTimeOnly = true; // don't emit code for this function
|
||||
|
||||
funcdecl._linkage = sc.linkage;
|
||||
if (auto fld = funcdecl.isFuncLiteralDeclaration())
|
||||
|
@ -3069,7 +3068,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
// evaluate pragma(inline)
|
||||
if (auto pragmadecl = sc.inlining)
|
||||
funcdecl.inlining = pragmadecl.evalPragmaInline(sc);
|
||||
funcdecl.inlining = evalPragmaInline(pragmadecl.loc, sc, pragmadecl.args);
|
||||
|
||||
funcdecl.visibility = sc.visibility;
|
||||
funcdecl.userAttribDecl = sc.userAttribDecl;
|
||||
|
@ -3269,9 +3268,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
}
|
||||
|
||||
// check pragma(crt_constructor) signature
|
||||
if (funcdecl.flags & (FUNCFLAG.CRTCtor | FUNCFLAG.CRTDtor))
|
||||
if (funcdecl.isCrtCtor || funcdecl.isCrtDtor)
|
||||
{
|
||||
const idStr = (funcdecl.flags & FUNCFLAG.CRTCtor) ? "crt_constructor" : "crt_destructor";
|
||||
const idStr = funcdecl.isCrtCtor ? "crt_constructor" : "crt_destructor";
|
||||
if (f.nextOf().ty != Tvoid)
|
||||
funcdecl.error("must return `void` for `pragma(%s)`", idStr.ptr);
|
||||
if (funcdecl._linkage != LINK.c && f.parameterList.length != 0)
|
||||
|
@ -3351,7 +3350,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
}
|
||||
}
|
||||
|
||||
if (const pors = sc.flags & (SCOPE.printf | SCOPE.scanf))
|
||||
if (funcdecl.printf || funcdecl.scanf)
|
||||
{
|
||||
/* printf/scanf-like functions must be of the form:
|
||||
* extern (C/C++) T printf([parameters...], const(char)* format, ...);
|
||||
|
@ -3387,11 +3386,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
)
|
||||
)
|
||||
{
|
||||
funcdecl.flags |= (pors == SCOPE.printf) ? FUNCFLAG.printf : FUNCFLAG.scanf;
|
||||
// the signature is valid for printf/scanf, no error
|
||||
}
|
||||
else
|
||||
{
|
||||
const p = (pors == SCOPE.printf ? Id.printf : Id.scanf).toChars();
|
||||
const p = (funcdecl.printf ? Id.printf : Id.scanf).toChars();
|
||||
if (f.parameterList.varargs == VarArg.variadic)
|
||||
{
|
||||
funcdecl.error("`pragma(%s)` functions must be `extern(C) %s %s([parameters...], const(char)*, ...)`"
|
||||
|
@ -3538,7 +3537,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
else
|
||||
{
|
||||
//printf("\tintroducing function %s\n", funcdecl.toChars());
|
||||
funcdecl.flags |= FUNCFLAG.introducing;
|
||||
funcdecl.isIntroducing = true;
|
||||
if (cd.classKind == ClassKind.cpp && target.cpp.reverseOverloads)
|
||||
{
|
||||
/* Overloaded functions with same name are grouped and in reverse order.
|
||||
|
@ -4555,13 +4554,16 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
if (sd.semanticRun == PASS.initial)
|
||||
sd.type = sd.type.addSTC(sc.stc | sd.storage_class);
|
||||
sd.type = sd.type.typeSemantic(sd.loc, sc);
|
||||
if (auto ts = sd.type.isTypeStruct())
|
||||
auto ts = sd.type.isTypeStruct();
|
||||
if (ts)
|
||||
{
|
||||
if (ts.sym != sd)
|
||||
{
|
||||
auto ti = ts.sym.isInstantiated();
|
||||
if (ti && isError(ti))
|
||||
ts.sym = sd;
|
||||
}
|
||||
}
|
||||
|
||||
// Ungag errors when not speculative
|
||||
Ungag ungag = sd.ungagSpeculative();
|
||||
|
@ -4699,16 +4701,26 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
}
|
||||
}
|
||||
|
||||
if (sd.type.ty == Tstruct && (cast(TypeStruct)sd.type).sym != sd)
|
||||
if (ts && ts.sym != sd)
|
||||
{
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19024
|
||||
StructDeclaration sym = (cast(TypeStruct)sd.type).sym;
|
||||
version (none)
|
||||
StructDeclaration sym = ts.sym;
|
||||
if (sd.isCsymbol() && sym.isCsymbol())
|
||||
{
|
||||
printf("this = %p %s\n", sd, sd.toChars());
|
||||
printf("type = %d sym = %p, %s\n", sd.type.ty, sym, sym.toPrettyChars());
|
||||
/* This is two structs imported from different C files.
|
||||
* Just ignore sd, the second one. The first one will always
|
||||
* be found when going through the type.
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
version (none)
|
||||
{
|
||||
printf("this = %p %s\n", sd, sd.toChars());
|
||||
printf("type = %d sym = %p, %s\n", sd.type.ty, sym, sym.toPrettyChars());
|
||||
}
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19024
|
||||
sd.error("already exists at %s. Perhaps in another function with the same name?", sym.loc.toChars());
|
||||
}
|
||||
sd.error("already exists at %s. Perhaps in another function with the same name?", sym.loc.toChars());
|
||||
}
|
||||
|
||||
if (global.errors != errors)
|
||||
|
@ -5291,7 +5303,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
auto ctor = new CtorDeclaration(cldec.loc, Loc.initial, 0, tf);
|
||||
ctor.storage_class |= STC.inference;
|
||||
ctor.flags |= FUNCFLAG.generated;
|
||||
ctor.isGenerated = true;
|
||||
ctor.fbody = new CompoundStatement(Loc.initial, new Statements());
|
||||
|
||||
cldec.members.push(ctor);
|
||||
|
@ -7099,3 +7111,47 @@ private CallExp doAtomicOp (string op, Identifier var, Expression arg)
|
|||
|
||||
return CallExp.create(loc, dti, args);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Interpret a `pragma(inline, x)`
|
||||
*
|
||||
* Params:
|
||||
* loc = location for error messages
|
||||
* sc = scope for evaluation of argument
|
||||
* args = pragma arguments
|
||||
* Returns: corresponding `PINLINE` state
|
||||
*/
|
||||
PINLINE evalPragmaInline(Loc loc, Scope* sc, Expressions* args)
|
||||
{
|
||||
if (!args || args.dim == 0)
|
||||
return PINLINE.default_;
|
||||
|
||||
if (args && args.dim > 1)
|
||||
{
|
||||
.error(loc, "one boolean expression expected for `pragma(inline)`, not %llu", cast(ulong) args.dim);
|
||||
args.setDim(1);
|
||||
(*args)[0] = ErrorExp.get();
|
||||
}
|
||||
|
||||
Expression e = (*args)[0];
|
||||
if (!e.type)
|
||||
{
|
||||
sc = sc.startCTFE();
|
||||
e = e.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
e = e.ctfeInterpret();
|
||||
e = e.toBoolean(sc);
|
||||
if (e.isErrorExp())
|
||||
.error(loc, "pragma(`inline`, `true` or `false`) expected, not `%s`", (*args)[0].toChars());
|
||||
(*args)[0] = e;
|
||||
}
|
||||
|
||||
const opt = e.toBool();
|
||||
if (opt.isEmpty())
|
||||
return PINLINE.default_;
|
||||
else if (opt.get())
|
||||
return PINLINE.always;
|
||||
else
|
||||
return PINLINE.never;
|
||||
}
|
||||
|
|
|
@ -1173,7 +1173,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
|
|||
|
||||
fd = new FuncDeclaration(fd.loc, fd.endloc, fd.ident, fd.storage_class, tf);
|
||||
fd.parent = ti;
|
||||
fd.flags |= FUNCFLAG.inferRetType;
|
||||
fd.inferRetType = true;
|
||||
|
||||
// Shouldn't run semantic on default arguments and return type.
|
||||
foreach (ref param; *tf.parameterList.parameters)
|
||||
|
@ -3901,7 +3901,7 @@ MATCH deduceType(RootObject o, Scope* sc, Type tparam, TemplateParameters* param
|
|||
// https://issues.dlang.org/show_bug.cgi?id=2579
|
||||
// Apply function parameter storage classes to parameter types
|
||||
fparam.type = fparam.type.addStorageClass(fparam.storageClass);
|
||||
fparam.storageClass &= ~(STC.TYPECTOR | STC.in_);
|
||||
fparam.storageClass &= ~STC.TYPECTOR;
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=15243
|
||||
// Resolve parameter type if it's not related with template parameters
|
||||
|
|
|
@ -25,7 +25,7 @@ nothrow:
|
|||
* code point corresponding to the named entity
|
||||
* ~0 for not recognized as a named entity
|
||||
*/
|
||||
public uint HtmlNamedEntity(scope const char[] name) pure @nogc @safe
|
||||
public uint[2] HtmlNamedEntity(scope const char[] name) pure @nogc @safe
|
||||
{
|
||||
const firstC = tolower(name[0]);
|
||||
if (firstC >= 'a' && firstC <= 'z')
|
||||
|
@ -34,10 +34,10 @@ public uint HtmlNamedEntity(scope const char[] name) pure @nogc @safe
|
|||
foreach (entity; namesTable[firstC - 'a'])
|
||||
{
|
||||
if (entity.name == name)
|
||||
return entity.value;
|
||||
return [entity.value, entity.value2];
|
||||
}
|
||||
}
|
||||
return ~0;
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -52,6 +52,7 @@ struct NameId
|
|||
{
|
||||
string name;
|
||||
uint value;
|
||||
uint value2;
|
||||
}
|
||||
|
||||
// @todo@ order namesTable and names? by frequency
|
||||
|
@ -72,7 +73,7 @@ immutable NameId[] namesA =
|
|||
{"abreve", 0x00103}, // LATIN SMALL LETTER A WITH BREVE
|
||||
{"ac", 0x0223E}, // INVERTED LAZY S
|
||||
{"acd", 0x0223F}, // SINE WAVE
|
||||
// {"acE", 0x0223E;0x00333}, // INVERTED LAZY S with double underline
|
||||
{"acE", 0x0223E, 0x00333}, // INVERTED LAZY S with double underline
|
||||
{"Acirc", 0x000C2}, // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
|
||||
{"acirc", 0x000E2}, // LATIN SMALL LETTER A WITH CIRCUMFLEX
|
||||
{"acute", 0x000B4}, // ACUTE ACCENT
|
||||
|
@ -157,42 +158,30 @@ immutable NameId[] namesB =
|
|||
{"backsim", 0x0223D}, // REVERSED TILDE
|
||||
{"backsimeq", 0x022CD}, // REVERSED TILDE EQUALS
|
||||
{"Backslash", 0x02216}, // SET MINUS
|
||||
// "b.alpha", 0x1D6C2}, // MATHEMATICAL BOLD SMALL ALPHA
|
||||
{"Barv", 0x02AE7}, // SHORT DOWN TACK WITH OVERBAR
|
||||
{"barvee", 0x022BD}, // NOR
|
||||
{"barwed", 0x02305}, // PROJECTIVE
|
||||
{"Barwed", 0x02306}, // PERSPECTIVE
|
||||
{"barwedge", 0x02305}, // PROJECTIVE
|
||||
// "b.beta", 0x1D6C3}, // MATHEMATICAL BOLD SMALL BETA
|
||||
{"bbrk", 0x023B5}, // BOTTOM SQUARE BRACKET
|
||||
{"bbrktbrk", 0x023B6}, // BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET
|
||||
// "b.chi", 0x1D6D8}, // MATHEMATICAL BOLD SMALL CHI
|
||||
{"bcong", 0x0224C}, // ALL EQUAL TO
|
||||
{"Bcy", 0x00411}, // CYRILLIC CAPITAL LETTER BE
|
||||
{"bcy", 0x00431}, // CYRILLIC SMALL LETTER BE
|
||||
// "b.Delta", 0x1D6AB}, // MATHEMATICAL BOLD CAPITAL DELTA
|
||||
// "b.delta", 0x1D6C5}, // MATHEMATICAL BOLD SMALL DELTA
|
||||
{"bdquo", 0x0201E}, // DOUBLE LOW-9 QUOTATION MARK
|
||||
{"becaus", 0x02235}, // BECAUSE
|
||||
{"because", 0x02235}, // BECAUSE
|
||||
{"Because", 0x02235}, // BECAUSE
|
||||
{"bemptyv", 0x029B0}, // REVERSED EMPTY SET
|
||||
{"bepsi", 0x003F6}, // GREEK REVERSED LUNATE EPSILON SYMBOL
|
||||
// "b.epsi", 0x1D6C6}, // MATHEMATICAL BOLD SMALL EPSILON
|
||||
// "b.epsiv", 0x1D6DC}, // MATHEMATICAL BOLD EPSILON SYMBOL
|
||||
{"bernou", 0x0212C}, // SCRIPT CAPITAL B
|
||||
{"Bernoullis", 0x0212C}, // SCRIPT CAPITAL B
|
||||
{"Beta", 0x00392}, // GREEK CAPITAL LETTER BETA
|
||||
{"beta", 0x003B2}, // GREEK SMALL LETTER BETA
|
||||
// "b.eta", 0x1D6C8}, // MATHEMATICAL BOLD SMALL ETA
|
||||
{"beth", 0x02136}, // BET SYMBOL
|
||||
{"between", 0x0226C}, // BETWEEN
|
||||
{"Bfr", 0x1D505}, // MATHEMATICAL FRAKTUR CAPITAL B
|
||||
{"bfr", 0x1D51F}, // MATHEMATICAL FRAKTUR SMALL B
|
||||
// "b.Gamma", 0x1D6AA}, // MATHEMATICAL BOLD CAPITAL GAMMA
|
||||
// "b.gamma", 0x1D6C4}, // MATHEMATICAL BOLD SMALL GAMMA
|
||||
// "b.Gammad", 0x1D7CA}, // MATHEMATICAL BOLD CAPITAL DIGAMMA
|
||||
// "b.gammad", 0x1D7CB}, // MATHEMATICAL BOLD SMALL DIGAMMA
|
||||
{"Bgr", 0x00392}, // GREEK CAPITAL LETTER BETA
|
||||
{"bgr", 0x003B2}, // GREEK SMALL LETTER BETA
|
||||
{"bigcap", 0x022C2}, // N-ARY INTERSECTION
|
||||
|
@ -208,9 +197,6 @@ immutable NameId[] namesB =
|
|||
{"biguplus", 0x02A04}, // N-ARY UNION OPERATOR WITH PLUS
|
||||
{"bigvee", 0x022C1}, // N-ARY LOGICAL OR
|
||||
{"bigwedge", 0x022C0}, // N-ARY LOGICAL AND
|
||||
// "b.iota", 0x1D6CA}, // MATHEMATICAL BOLD SMALL IOTA
|
||||
// "b.kappa", 0x1D6CB}, // MATHEMATICAL BOLD SMALL KAPPA
|
||||
// "b.kappav", 0x1D6DE}, // MATHEMATICAL BOLD KAPPA SYMBOL
|
||||
{"bkarow", 0x0290D}, // RIGHTWARDS DOUBLE DASH ARROW
|
||||
{"blacklozenge", 0x029EB}, // BLACK LOZENGE
|
||||
{"blacksquare", 0x025AA}, // BLACK SMALL SQUARE
|
||||
|
@ -218,21 +204,15 @@ immutable NameId[] namesB =
|
|||
{"blacktriangledown", 0x025BE}, // BLACK DOWN-POINTING SMALL TRIANGLE
|
||||
{"blacktriangleleft", 0x025C2}, // BLACK LEFT-POINTING SMALL TRIANGLE
|
||||
{"blacktriangleright", 0x025B8}, // BLACK RIGHT-POINTING SMALL TRIANGLE
|
||||
// "b.Lambda", 0x1D6B2}, // MATHEMATICAL BOLD CAPITAL LAMDA
|
||||
// "b.lambda", 0x1D6CC}, // MATHEMATICAL BOLD SMALL LAMDA
|
||||
{"blank", 0x02423}, // OPEN BOX
|
||||
{"blk12", 0x02592}, // MEDIUM SHADE
|
||||
{"blk14", 0x02591}, // LIGHT SHADE
|
||||
{"blk34", 0x02593}, // DARK SHADE
|
||||
{"block", 0x02588}, // FULL BLOCK
|
||||
// "b.mu", 0x1D6CD}, // MATHEMATICAL BOLD SMALL MU
|
||||
// "bne", 0x0003D;0x020E5}, // EQUALS SIGN with reverse slash
|
||||
// "bnequiv", 0x02261;0x020E5}, // IDENTICAL TO with reverse slash
|
||||
{"bne", 0x0003D, 0x020E5}, // EQUALS SIGN with reverse slash
|
||||
{"bnequiv", 0x02261, 0x020E5}, // IDENTICAL TO with reverse slash
|
||||
{"bnot", 0x02310}, // REVERSED NOT SIGN
|
||||
{"bNot", 0x02AED}, // REVERSED DOUBLE STROKE NOT SIGN
|
||||
// "b.nu", 0x1D6CE}, // MATHEMATICAL BOLD SMALL NU
|
||||
// "b.Omega", 0x1D6C0}, // MATHEMATICAL BOLD CAPITAL OMEGA
|
||||
// "b.omega", 0x1D6DA}, // MATHEMATICAL BOLD SMALL OMEGA
|
||||
{"Bopf", 0x1D539}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL B
|
||||
{"bopf", 0x1D553}, // MATHEMATICAL DOUBLE-STRUCK SMALL B
|
||||
{"bot", 0x022A5}, // UP TACK
|
||||
|
@ -282,35 +262,18 @@ immutable NameId[] namesB =
|
|||
{"boxvR", 0x0255E}, // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
|
||||
{"boxVr", 0x0255F}, // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
|
||||
{"boxVR", 0x02560}, // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
|
||||
// "b.Phi", 0x1D6BD}, // MATHEMATICAL BOLD CAPITAL PHI
|
||||
// "b.phi", 0x1D6D7}, // MATHEMATICAL BOLD SMALL PHI
|
||||
// "b.phiv", 0x1D6DF}, // MATHEMATICAL BOLD PHI SYMBOL
|
||||
// "b.Pi", 0x1D6B7}, // MATHEMATICAL BOLD CAPITAL PI
|
||||
// "b.pi", 0x1D6D1}, // MATHEMATICAL BOLD SMALL PI
|
||||
// "b.piv", 0x1D6E1}, // MATHEMATICAL BOLD PI SYMBOL
|
||||
{"bprime", 0x02035}, // REVERSED PRIME
|
||||
// "b.Psi", 0x1D6BF}, // MATHEMATICAL BOLD CAPITAL PSI
|
||||
// "b.psi", 0x1D6D9}, // MATHEMATICAL BOLD SMALL PSI
|
||||
{"breve", 0x002D8}, // BREVE
|
||||
{"Breve", 0x002D8}, // BREVE
|
||||
// "b.rho", 0x1D6D2}, // MATHEMATICAL BOLD SMALL RHO
|
||||
// "b.rhov", 0x1D6E0}, // MATHEMATICAL BOLD RHO SYMBOL
|
||||
{"brvbar", 0x000A6}, // BROKEN BAR
|
||||
{"Bscr", 0x0212C}, // SCRIPT CAPITAL B
|
||||
{"bscr", 0x1D4B7}, // MATHEMATICAL SCRIPT SMALL B
|
||||
{"bsemi", 0x0204F}, // REVERSED SEMICOLON
|
||||
// "b.Sigma", 0x1D6BA}, // MATHEMATICAL BOLD CAPITAL SIGMA
|
||||
// "b.sigma", 0x1D6D4}, // MATHEMATICAL BOLD SMALL SIGMA
|
||||
// "b.sigmav", 0x1D6D3}, // MATHEMATICAL BOLD SMALL FINAL SIGMA
|
||||
{"bsim", 0x0223D}, // REVERSED TILDE
|
||||
{"bsime", 0x022CD}, // REVERSED TILDE EQUALS
|
||||
{"bsol", 0x0005C}, // REVERSE SOLIDUS
|
||||
{"bsolb", 0x029C5}, // SQUARED FALLING DIAGONAL SLASH
|
||||
{"bsolhsub", 0x027C8}, // REVERSE SOLIDUS PRECEDING SUBSET
|
||||
// "b.tau", 0x1D6D5}, // MATHEMATICAL BOLD SMALL TAU
|
||||
// "b.Theta", 0x1D6AF}, // MATHEMATICAL BOLD CAPITAL THETA
|
||||
// "b.thetas", 0x1D6C9}, // MATHEMATICAL BOLD SMALL THETA
|
||||
// "b.thetav", 0x1D6DD}, // MATHEMATICAL BOLD THETA SYMBOL
|
||||
{"bull", 0x02022}, // BULLET
|
||||
{"bullet", 0x02022}, // BULLET
|
||||
{"bump", 0x0224E}, // GEOMETRICALLY EQUIVALENT TO
|
||||
|
@ -318,11 +281,6 @@ immutable NameId[] namesB =
|
|||
{"bumpE", 0x02AAE}, // EQUALS SIGN WITH BUMPY ABOVE
|
||||
{"Bumpeq", 0x0224E}, // GEOMETRICALLY EQUIVALENT TO
|
||||
{"bumpeq", 0x0224F}, // DIFFERENCE BETWEEN
|
||||
// "b.Upsi", 0x1D6BC}, // MATHEMATICAL BOLD CAPITAL UPSILON
|
||||
// "b.upsi", 0x1D6D6}, // MATHEMATICAL BOLD SMALL UPSILON
|
||||
// "b.Xi", 0x1D6B5}, // MATHEMATICAL BOLD CAPITAL XI
|
||||
// "b.xi", 0x1D6CF}, // MATHEMATICAL BOLD SMALL XI
|
||||
// "b.zeta", 0x1D6C7}, // MATHEMATICAL BOLD SMALL ZETA
|
||||
];
|
||||
|
||||
immutable NameId[] namesC =
|
||||
|
@ -337,7 +295,7 @@ immutable NameId[] namesC =
|
|||
{"capcup", 0x02A47}, // INTERSECTION ABOVE UNION
|
||||
{"capdot", 0x02A40}, // INTERSECTION WITH DOT
|
||||
{"CapitalDifferentialD", 0x02145}, // DOUBLE-STRUCK ITALIC CAPITAL D
|
||||
// "caps", 0x02229;0x0FE00}, // INTERSECTION with serifs
|
||||
{"caps", 0x02229, 0x0FE00}, // INTERSECTION with serifs
|
||||
{"caret", 0x02041}, // CARET INSERTION POINT
|
||||
{"caron", 0x002C7}, // CARON
|
||||
{"Cayleys", 0x0212D}, // BLACK-LETTER CAPITAL C
|
||||
|
@ -440,7 +398,7 @@ immutable NameId[] namesC =
|
|||
{"cupcup", 0x02A4A}, // UNION BESIDE AND JOINED WITH UNION
|
||||
{"cupdot", 0x0228D}, // MULTISET MULTIPLICATION
|
||||
{"cupor", 0x02A45}, // UNION WITH LOGICAL OR
|
||||
// "cups", 0x0222A;0x0FE00}, // UNION with serifs
|
||||
{"cups", 0x0222A, 0x0FE00}, // UNION with serifs
|
||||
{"curarr", 0x021B7}, // CLOCKWISE TOP SEMICIRCLE ARROW
|
||||
{"curarrm", 0x0293C}, // TOP ARC CLOCKWISE ARROW WITH MINUS
|
||||
{"curlyeqprec", 0x022DE}, // EQUAL TO OR PRECEDES
|
||||
|
@ -694,7 +652,7 @@ immutable NameId[] namesF =
|
|||
{"filig", 0x0FB01}, // LATIN SMALL LIGATURE FI
|
||||
{"FilledSmallSquare", 0x025FC}, // BLACK MEDIUM SQUARE
|
||||
{"FilledVerySmallSquare", 0x025AA}, // BLACK SMALL SQUARE
|
||||
// "fjlig", 0x00066;0x0006A}, // fj ligature
|
||||
{"fjlig", 0x00066, 0x0006A}, // fj ligature
|
||||
{"flat", 0x0266D}, // MUSIC FLAT SIGN
|
||||
{"fllig", 0x0FB02}, // LATIN SMALL LIGATURE FL
|
||||
{"fltns", 0x025B1}, // WHITE PARALLELOGRAM
|
||||
|
@ -757,7 +715,7 @@ immutable NameId[] namesG =
|
|||
{"gesdot", 0x02A80}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
|
||||
{"gesdoto", 0x02A82}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
|
||||
{"gesdotol", 0x02A84}, // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT
|
||||
// "gesl", 0x022DB;0x0FE00}, // GREATER-THAN slanted EQUAL TO OR LESS-THAN
|
||||
{"gesl", 0x022DB, 0x0FE00}, // GREATER-THAN slanted EQUAL TO OR LESS-THAN
|
||||
{"gesles", 0x02A94}, // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL
|
||||
{"Gfr", 0x1D50A}, // MATHEMATICAL FRAKTUR CAPITAL G
|
||||
{"gfr", 0x1D524}, // MATHEMATICAL FRAKTUR SMALL G
|
||||
|
@ -810,8 +768,8 @@ immutable NameId[] namesG =
|
|||
{"gtreqqless", 0x02A8C}, // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
|
||||
{"gtrless", 0x02277}, // GREATER-THAN OR LESS-THAN
|
||||
{"gtrsim", 0x02273}, // GREATER-THAN OR EQUIVALENT TO
|
||||
// "gvertneqq", 0x02269;0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke
|
||||
// "gvnE", 0x02269;0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke
|
||||
{"gvertneqq", 0x02269, 0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke
|
||||
{"gvnE", 0x02269, 0x0FE00}, // GREATER-THAN BUT NOT EQUAL TO - with vertical stroke
|
||||
];
|
||||
|
||||
immutable NameId[] namesH =
|
||||
|
@ -1020,7 +978,7 @@ immutable NameId[] namesL =
|
|||
{"latail", 0x02919}, // LEFTWARDS ARROW-TAIL
|
||||
{"lAtail", 0x0291B}, // LEFTWARDS DOUBLE ARROW-TAIL
|
||||
{"late", 0x02AAD}, // LARGER THAN OR EQUAL TO
|
||||
// "lates", 0x02AAD;0x0FE00}, // LARGER THAN OR slanted EQUAL
|
||||
{"lates", 0x02AAD, 0x0FE00}, // LARGER THAN OR slanted EQUAL
|
||||
{"lbarr", 0x0290C}, // LEFTWARDS DOUBLE DASH ARROW
|
||||
{"lBarr", 0x0290E}, // LEFTWARDS TRIPLE DASH ARROW
|
||||
{"lbbrk", 0x02772}, // LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT
|
||||
|
@ -1091,7 +1049,7 @@ immutable NameId[] namesL =
|
|||
{"lesdot", 0x02A7F}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
|
||||
{"lesdoto", 0x02A81}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
|
||||
{"lesdotor", 0x02A83}, // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT
|
||||
// "lesg", 0x022DA;0x0FE00}, // LESS-THAN slanted EQUAL TO OR GREATER-THAN
|
||||
{"lesg", 0x022DA, 0x0FE00}, // LESS-THAN slanted EQUAL TO OR GREATER-THAN
|
||||
{"lesges", 0x02A93}, // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL
|
||||
{"lessapprox", 0x02A85}, // LESS-THAN OR APPROXIMATE
|
||||
{"lessdot", 0x022D6}, // LESS-THAN WITH DOT
|
||||
|
@ -1202,8 +1160,8 @@ immutable NameId[] namesL =
|
|||
{"ltrPar", 0x02996}, // DOUBLE RIGHT ARC LESS-THAN BRACKET
|
||||
{"lurdshar", 0x0294A}, // LEFT BARB UP RIGHT BARB DOWN HARPOON
|
||||
{"luruhar", 0x02966}, // LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP
|
||||
// "lvertneqq", 0x02268;0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke
|
||||
// "lvnE", 0x02268;0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke
|
||||
{"lvertneqq", 0x02268, 0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke
|
||||
{"lvnE", 0x02268, 0x0FE00}, // LESS-THAN BUT NOT EQUAL TO - with vertical stroke
|
||||
];
|
||||
|
||||
immutable NameId[] namesM =
|
||||
|
@ -1263,25 +1221,25 @@ immutable NameId[] namesN =
|
|||
{"nabla", 0x02207}, // NABLA
|
||||
{"Nacute", 0x00143}, // LATIN CAPITAL LETTER N WITH ACUTE
|
||||
{"nacute", 0x00144}, // LATIN SMALL LETTER N WITH ACUTE
|
||||
// "nang", 0x02220;0x020D2}, // ANGLE with vertical line
|
||||
{"nang", 0x02220, 0x020D2}, // ANGLE with vertical line
|
||||
{"nap", 0x02249}, // NOT ALMOST EQUAL TO
|
||||
// "napE", 0x02A70;0x00338}, // APPROXIMATELY EQUAL OR EQUAL TO with slash
|
||||
// "napid", 0x0224B;0x00338}, // TRIPLE TILDE with slash
|
||||
{"napE", 0x02A70, 0x00338}, // APPROXIMATELY EQUAL OR EQUAL TO with slash
|
||||
{"napid", 0x0224B, 0x00338}, // TRIPLE TILDE with slash
|
||||
{"napos", 0x00149}, // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
|
||||
{"napprox", 0x02249}, // NOT ALMOST EQUAL TO
|
||||
{"natur", 0x0266E}, // MUSIC NATURAL SIGN
|
||||
{"natural", 0x0266E}, // MUSIC NATURAL SIGN
|
||||
{"naturals", 0x02115}, // DOUBLE-STRUCK CAPITAL N
|
||||
{"nbsp", 0x000A0}, // NO-BREAK SPACE
|
||||
// "nbump", 0x0224E;0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash
|
||||
// "nbumpe", 0x0224F;0x00338}, // DIFFERENCE BETWEEN with slash
|
||||
{"nbump", 0x0224E, 0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash
|
||||
{"nbumpe", 0x0224F, 0x00338}, // DIFFERENCE BETWEEN with slash
|
||||
{"ncap", 0x02A43}, // INTERSECTION WITH OVERBAR
|
||||
{"Ncaron", 0x00147}, // LATIN CAPITAL LETTER N WITH CARON
|
||||
{"ncaron", 0x00148}, // LATIN SMALL LETTER N WITH CARON
|
||||
{"Ncedil", 0x00145}, // LATIN CAPITAL LETTER N WITH CEDILLA
|
||||
{"ncedil", 0x00146}, // LATIN SMALL LETTER N WITH CEDILLA
|
||||
{"ncong", 0x02247}, // NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
|
||||
// "ncongdot", 0x02A6D;0x00338}, // CONGRUENT WITH DOT ABOVE with slash
|
||||
{"ncongdot", 0x02A6D, 0x00338}, // CONGRUENT WITH DOT ABOVE with slash
|
||||
{"ncup", 0x02A42}, // UNION WITH OVERBAR
|
||||
{"Ncy", 0x0041D}, // CYRILLIC CAPITAL LETTER EN
|
||||
{"ncy", 0x0043D}, // CYRILLIC SMALL LETTER EN
|
||||
|
@ -1291,14 +1249,14 @@ immutable NameId[] namesN =
|
|||
{"nearr", 0x02197}, // NORTH EAST ARROW
|
||||
{"neArr", 0x021D7}, // NORTH EAST DOUBLE ARROW
|
||||
{"nearrow", 0x02197}, // NORTH EAST ARROW
|
||||
// "nedot", 0x02250;0x00338}, // APPROACHES THE LIMIT with slash
|
||||
{"nedot", 0x02250, 0x00338}, // APPROACHES THE LIMIT with slash
|
||||
{"NegativeMediumSpace", 0x0200B}, // ZERO WIDTH SPACE
|
||||
{"NegativeThickSpace", 0x0200B}, // ZERO WIDTH SPACE
|
||||
{"NegativeThinSpace", 0x0200B}, // ZERO WIDTH SPACE
|
||||
{"NegativeVeryThinSpace", 0x0200B}, // ZERO WIDTH SPACE
|
||||
{"nequiv", 0x02262}, // NOT IDENTICAL TO
|
||||
{"nesear", 0x02928}, // NORTH EAST ARROW AND SOUTH EAST ARROW
|
||||
// "nesim", 0x02242;0x00338}, // MINUS TILDE with slash
|
||||
{"nesim", 0x02242, 0x00338}, // MINUS TILDE with slash
|
||||
{"NestedGreaterGreater", 0x0226B}, // MUCH GREATER-THAN
|
||||
{"NestedLessLess", 0x0226A}, // MUCH LESS-THAN
|
||||
{"NewLine", 0x0000A}, // LINE FEED (LF)
|
||||
|
@ -1306,20 +1264,20 @@ immutable NameId[] namesN =
|
|||
{"nexists", 0x02204}, // THERE DOES NOT EXIST
|
||||
{"Nfr", 0x1D511}, // MATHEMATICAL FRAKTUR CAPITAL N
|
||||
{"nfr", 0x1D52B}, // MATHEMATICAL FRAKTUR SMALL N
|
||||
// "ngE", 0x02267;0x00338}, // GREATER-THAN OVER EQUAL TO with slash
|
||||
{"ngE", 0x02267, 0x00338}, // GREATER-THAN OVER EQUAL TO with slash
|
||||
{"nge", 0x02271}, // NEITHER GREATER-THAN NOR EQUAL TO
|
||||
{"ngeq", 0x02271}, // NEITHER GREATER-THAN NOR EQUAL TO
|
||||
// "ngeqq", 0x02267;0x00338}, // GREATER-THAN OVER EQUAL TO with slash
|
||||
// "ngeqslant", 0x02A7E;0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash
|
||||
// "nges", 0x02A7E;0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash
|
||||
// "nGg", 0x022D9;0x00338}, // VERY MUCH GREATER-THAN with slash
|
||||
{"ngeqq", 0x02267, 0x00338}, // GREATER-THAN OVER EQUAL TO with slash
|
||||
{"ngeqslant", 0x02A7E, 0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash
|
||||
{"nges", 0x02A7E, 0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash
|
||||
{"nGg", 0x022D9, 0x00338}, // VERY MUCH GREATER-THAN with slash
|
||||
{"Ngr", 0x0039D}, // GREEK CAPITAL LETTER NU
|
||||
{"ngr", 0x003BD}, // GREEK SMALL LETTER NU
|
||||
{"ngsim", 0x02275}, // NEITHER GREATER-THAN NOR EQUIVALENT TO
|
||||
// "nGt", 0x0226B;0x020D2}, // MUCH GREATER THAN with vertical line
|
||||
{"nGt", 0x0226B, 0x020D2}, // MUCH GREATER THAN with vertical line
|
||||
{"ngt", 0x0226F}, // NOT GREATER-THAN
|
||||
{"ngtr", 0x0226F}, // NOT GREATER-THAN
|
||||
// "nGtv", 0x0226B;0x00338}, // MUCH GREATER THAN with slash
|
||||
{"nGtv", 0x0226B, 0x00338}, // MUCH GREATER THAN with slash
|
||||
{"nharr", 0x021AE}, // LEFT RIGHT ARROW WITH STROKE
|
||||
{"nhArr", 0x021CE}, // LEFT RIGHT DOUBLE ARROW WITH STROKE
|
||||
{"nhpar", 0x02AF2}, // PARALLEL WITH HORIZONTAL STROKE
|
||||
|
@ -1332,24 +1290,24 @@ immutable NameId[] namesN =
|
|||
{"nlarr", 0x0219A}, // LEFTWARDS ARROW WITH STROKE
|
||||
{"nlArr", 0x021CD}, // LEFTWARDS DOUBLE ARROW WITH STROKE
|
||||
{"nldr", 0x02025}, // TWO DOT LEADER
|
||||
// "nlE", 0x02266;0x00338}, // LESS-THAN OVER EQUAL TO with slash
|
||||
{"nlE", 0x02266, 0x00338}, // LESS-THAN OVER EQUAL TO with slash
|
||||
{"nle", 0x02270}, // NEITHER LESS-THAN NOR EQUAL TO
|
||||
{"nleftarrow", 0x0219A}, // LEFTWARDS ARROW WITH STROKE
|
||||
{"nLeftarrow", 0x021CD}, // LEFTWARDS DOUBLE ARROW WITH STROKE
|
||||
{"nleftrightarrow", 0x021AE}, // LEFT RIGHT ARROW WITH STROKE
|
||||
{"nLeftrightarrow", 0x021CE}, // LEFT RIGHT DOUBLE ARROW WITH STROKE
|
||||
{"nleq", 0x02270}, // NEITHER LESS-THAN NOR EQUAL TO
|
||||
// "nleqq", 0x02266;0x00338}, // LESS-THAN OVER EQUAL TO with slash
|
||||
// "nleqslant", 0x02A7D;0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash
|
||||
// "nles", 0x02A7D;0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash
|
||||
{"nleqq", 0x02266, 0x00338}, // LESS-THAN OVER EQUAL TO with slash
|
||||
{"nleqslant", 0x02A7D, 0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash
|
||||
{"nles", 0x02A7D, 0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash
|
||||
{"nless", 0x0226E}, // NOT LESS-THAN
|
||||
// "nLl", 0x022D8;0x00338}, // VERY MUCH LESS-THAN with slash
|
||||
{"nLl", 0x022D8, 0x00338}, // VERY MUCH LESS-THAN with slash
|
||||
{"nlsim", 0x02274}, // NEITHER LESS-THAN NOR EQUIVALENT TO
|
||||
// "nLt", 0x0226A;0x020D2}, // MUCH LESS THAN with vertical line
|
||||
{"nLt", 0x0226A, 0x020D2}, // MUCH LESS THAN with vertical line
|
||||
{"nlt", 0x0226E}, // NOT LESS-THAN
|
||||
{"nltri", 0x022EA}, // NOT NORMAL SUBGROUP OF
|
||||
{"nltrie", 0x022EC}, // NOT NORMAL SUBGROUP OF OR EQUAL TO
|
||||
// "nLtv", 0x0226A;0x00338}, // MUCH LESS THAN with slash
|
||||
{"nLtv", 0x0226A, 0x00338}, // MUCH LESS THAN with slash
|
||||
{"nmid", 0x02224}, // DOES NOT DIVIDE
|
||||
{"NoBreak", 0x02060}, // WORD JOINER
|
||||
{"NonBreakingSpace", 0x000A0}, // NO-BREAK SPACE
|
||||
|
@ -1362,56 +1320,56 @@ immutable NameId[] namesN =
|
|||
{"NotDoubleVerticalBar", 0x02226}, // NOT PARALLEL TO
|
||||
{"NotElement", 0x02209}, // NOT AN ELEMENT OF
|
||||
{"NotEqual", 0x02260}, // NOT EQUAL TO
|
||||
// "NotEqualTilde", 0x02242;0x00338}, // MINUS TILDE with slash
|
||||
{"NotEqualTilde", 0x02242, 0x00338}, // MINUS TILDE with slash
|
||||
{"NotExists", 0x02204}, // THERE DOES NOT EXIST
|
||||
{"NotGreater", 0x0226F}, // NOT GREATER-THAN
|
||||
{"NotGreaterEqual", 0x02271}, // NEITHER GREATER-THAN NOR EQUAL TO
|
||||
// "NotGreaterFullEqual", 0x02267;0x00338}, // GREATER-THAN OVER EQUAL TO with slash
|
||||
// "NotGreaterGreater", 0x0226B;0x00338}, // MUCH GREATER THAN with slash
|
||||
{"NotGreaterFullEqual", 0x02267, 0x00338}, // GREATER-THAN OVER EQUAL TO with slash
|
||||
{"NotGreaterGreater", 0x0226B, 0x00338}, // MUCH GREATER THAN with slash
|
||||
{"NotGreaterLess", 0x02279}, // NEITHER GREATER-THAN NOR LESS-THAN
|
||||
// "NotGreaterSlantEqual", 0x02A7E;0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash
|
||||
{"NotGreaterSlantEqual", 0x02A7E, 0x00338}, // GREATER-THAN OR SLANTED EQUAL TO with slash
|
||||
{"NotGreaterTilde", 0x02275}, // NEITHER GREATER-THAN NOR EQUIVALENT TO
|
||||
// "NotHumpDownHump", 0x0224E;0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash
|
||||
// "NotHumpEqual", 0x0224F;0x00338}, // DIFFERENCE BETWEEN with slash
|
||||
{"NotHumpDownHump", 0x0224E, 0x00338}, // GEOMETRICALLY EQUIVALENT TO with slash
|
||||
{"NotHumpEqual", 0x0224F, 0x00338}, // DIFFERENCE BETWEEN with slash
|
||||
{"notin", 0x02209}, // NOT AN ELEMENT OF
|
||||
// "notindot", 0x022F5;0x00338}, // ELEMENT OF WITH DOT ABOVE with slash
|
||||
// "notinE", 0x022F9;0x00338}, // ELEMENT OF WITH TWO HORIZONTAL STROKES with slash
|
||||
{"notindot", 0x022F5, 0x00338}, // ELEMENT OF WITH DOT ABOVE with slash
|
||||
{"notinE", 0x022F9, 0x00338}, // ELEMENT OF WITH TWO HORIZONTAL STROKES with slash
|
||||
{"notinva", 0x02209}, // NOT AN ELEMENT OF
|
||||
{"notinvb", 0x022F7}, // SMALL ELEMENT OF WITH OVERBAR
|
||||
{"notinvc", 0x022F6}, // ELEMENT OF WITH OVERBAR
|
||||
{"NotLeftTriangle", 0x022EA}, // NOT NORMAL SUBGROUP OF
|
||||
// "NotLeftTriangleBar", 0x029CF;0x00338}, // LEFT TRIANGLE BESIDE VERTICAL BAR with slash
|
||||
{"NotLeftTriangleBar", 0x029CF, 0x00338}, // LEFT TRIANGLE BESIDE VERTICAL BAR with slash
|
||||
{"NotLeftTriangleEqual", 0x022EC}, // NOT NORMAL SUBGROUP OF OR EQUAL TO
|
||||
{"NotLess", 0x0226E}, // NOT LESS-THAN
|
||||
{"NotLessEqual", 0x02270}, // NEITHER LESS-THAN NOR EQUAL TO
|
||||
{"NotLessGreater", 0x02278}, // NEITHER LESS-THAN NOR GREATER-THAN
|
||||
// "NotLessLess", 0x0226A;0x00338}, // MUCH LESS THAN with slash
|
||||
// "NotLessSlantEqual", 0x02A7D;0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash
|
||||
{"NotLessLess", 0x0226A, 0x00338}, // MUCH LESS THAN with slash
|
||||
{"NotLessSlantEqual", 0x02A7D, 0x00338}, // LESS-THAN OR SLANTED EQUAL TO with slash
|
||||
{"NotLessTilde", 0x02274}, // NEITHER LESS-THAN NOR EQUIVALENT TO
|
||||
// "NotNestedGreaterGreater", 0x02AA2;0x00338}, // DOUBLE NESTED GREATER-THAN with slash
|
||||
// "NotNestedLessLess", 0x02AA1;0x00338}, // DOUBLE NESTED LESS-THAN with slash
|
||||
{"NotNestedGreaterGreater", 0x02AA2, 0x00338}, // DOUBLE NESTED GREATER-THAN with slash
|
||||
{"NotNestedLessLess", 0x02AA1, 0x00338}, // DOUBLE NESTED LESS-THAN with slash
|
||||
{"notni", 0x0220C}, // DOES NOT CONTAIN AS MEMBER
|
||||
{"notniva", 0x0220C}, // DOES NOT CONTAIN AS MEMBER
|
||||
{"notnivb", 0x022FE}, // SMALL CONTAINS WITH OVERBAR
|
||||
{"notnivc", 0x022FD}, // CONTAINS WITH OVERBAR
|
||||
{"NotPrecedes", 0x02280}, // DOES NOT PRECEDE
|
||||
// "NotPrecedesEqual", 0x02AAF;0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"NotPrecedesEqual", 0x02AAF, 0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"NotPrecedesSlantEqual", 0x022E0}, // DOES NOT PRECEDE OR EQUAL
|
||||
{"NotReverseElement", 0x0220C}, // DOES NOT CONTAIN AS MEMBER
|
||||
{"NotRightTriangle", 0x022EB}, // DOES NOT CONTAIN AS NORMAL SUBGROUP
|
||||
// "NotRightTriangleBar", 0x029D0;0x00338}, // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash
|
||||
{"NotRightTriangleBar", 0x029D0, 0x00338}, // VERTICAL BAR BESIDE RIGHT TRIANGLE with slash
|
||||
{"NotRightTriangleEqual", 0x022ED}, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
|
||||
// "NotSquareSubset", 0x0228F;0x00338}, // SQUARE IMAGE OF with slash
|
||||
{"NotSquareSubset", 0x0228F, 0x00338}, // SQUARE IMAGE OF with slash
|
||||
{"NotSquareSubsetEqual", 0x022E2}, // NOT SQUARE IMAGE OF OR EQUAL TO
|
||||
// "NotSquareSuperset", 0x02290;0x00338}, // SQUARE ORIGINAL OF with slash
|
||||
{"NotSquareSuperset", 0x02290, 0x00338}, // SQUARE ORIGINAL OF with slash
|
||||
{"NotSquareSupersetEqual", 0x022E3}, // NOT SQUARE ORIGINAL OF OR EQUAL TO
|
||||
// "NotSubset", 0x02282;0x020D2}, // SUBSET OF with vertical line
|
||||
{"NotSubset", 0x02282, 0x020D2}, // SUBSET OF with vertical line
|
||||
{"NotSubsetEqual", 0x02288}, // NEITHER A SUBSET OF NOR EQUAL TO
|
||||
{"NotSucceeds", 0x02281}, // DOES NOT SUCCEED
|
||||
// "NotSucceedsEqual", 0x02AB0;0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"NotSucceedsEqual", 0x02AB0, 0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"NotSucceedsSlantEqual", 0x022E1}, // DOES NOT SUCCEED OR EQUAL
|
||||
// "NotSucceedsTilde", 0x0227F;0x00338}, // SUCCEEDS OR EQUIVALENT TO with slash
|
||||
// "NotSuperset", 0x02283;0x020D2}, // SUPERSET OF with vertical line
|
||||
{"NotSucceedsTilde", 0x0227F, 0x00338}, // SUCCEEDS OR EQUIVALENT TO with slash
|
||||
{"NotSuperset", 0x02283, 0x020D2}, // SUPERSET OF with vertical line
|
||||
{"NotSupersetEqual", 0x02289}, // NEITHER A SUPERSET OF NOR EQUAL TO
|
||||
{"NotTilde", 0x02241}, // NOT TILDE
|
||||
{"NotTildeEqual", 0x02244}, // NOT ASYMPTOTICALLY EQUAL TO
|
||||
|
@ -1420,25 +1378,25 @@ immutable NameId[] namesN =
|
|||
{"NotVerticalBar", 0x02224}, // DOES NOT DIVIDE
|
||||
{"npar", 0x02226}, // NOT PARALLEL TO
|
||||
{"nparallel", 0x02226}, // NOT PARALLEL TO
|
||||
// "nparsl", 0x02AFD;0x020E5}, // DOUBLE SOLIDUS OPERATOR with reverse slash
|
||||
// "npart", 0x02202;0x00338}, // PARTIAL DIFFERENTIAL with slash
|
||||
{"nparsl", 0x02AFD, 0x020E5}, // DOUBLE SOLIDUS OPERATOR with reverse slash
|
||||
{"npart", 0x02202, 0x00338}, // PARTIAL DIFFERENTIAL with slash
|
||||
{"npolint", 0x02A14}, // LINE INTEGRATION NOT INCLUDING THE POLE
|
||||
{"npr", 0x02280}, // DOES NOT PRECEDE
|
||||
{"nprcue", 0x022E0}, // DOES NOT PRECEDE OR EQUAL
|
||||
// "npre", 0x02AAF;0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"npre", 0x02AAF, 0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"nprec", 0x02280}, // DOES NOT PRECEDE
|
||||
// "npreceq", 0x02AAF;0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"npreceq", 0x02AAF, 0x00338}, // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"nrarr", 0x0219B}, // RIGHTWARDS ARROW WITH STROKE
|
||||
{"nrArr", 0x021CF}, // RIGHTWARDS DOUBLE ARROW WITH STROKE
|
||||
// "nrarrc", 0x02933;0x00338}, // WAVE ARROW POINTING DIRECTLY RIGHT with slash
|
||||
// "nrarrw", 0x0219D;0x00338}, // RIGHTWARDS WAVE ARROW with slash
|
||||
{"nrarrc", 0x02933, 0x00338}, // WAVE ARROW POINTING DIRECTLY RIGHT with slash
|
||||
{"nrarrw", 0x0219D, 0x00338}, // RIGHTWARDS WAVE ARROW with slash
|
||||
{"nrightarrow", 0x0219B}, // RIGHTWARDS ARROW WITH STROKE
|
||||
{"nRightarrow", 0x021CF}, // RIGHTWARDS DOUBLE ARROW WITH STROKE
|
||||
{"nrtri", 0x022EB}, // DOES NOT CONTAIN AS NORMAL SUBGROUP
|
||||
{"nrtrie", 0x022ED}, // DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
|
||||
{"nsc", 0x02281}, // DOES NOT SUCCEED
|
||||
{"nsccue", 0x022E1}, // DOES NOT SUCCEED OR EQUAL
|
||||
// "nsce", 0x02AB0;0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"nsce", 0x02AB0, 0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"Nscr", 0x1D4A9}, // MATHEMATICAL SCRIPT CAPITAL N
|
||||
{"nscr", 0x1D4C3}, // MATHEMATICAL SCRIPT SMALL N
|
||||
{"nshortmid", 0x02224}, // DOES NOT DIVIDE
|
||||
|
@ -1452,18 +1410,18 @@ immutable NameId[] namesN =
|
|||
{"nsqsupe", 0x022E3}, // NOT SQUARE ORIGINAL OF OR EQUAL TO
|
||||
{"nsub", 0x02284}, // NOT A SUBSET OF
|
||||
{"nsube", 0x02288}, // NEITHER A SUBSET OF NOR EQUAL TO
|
||||
// "nsubE", 0x02AC5;0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash
|
||||
// "nsubset", 0x02282;0x020D2}, // SUBSET OF with vertical line
|
||||
{"nsubE", 0x02AC5, 0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash
|
||||
{"nsubset", 0x02282, 0x020D2}, // SUBSET OF with vertical line
|
||||
{"nsubseteq", 0x02288}, // NEITHER A SUBSET OF NOR EQUAL TO
|
||||
// "nsubseteqq", 0x02AC5;0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash
|
||||
{"nsubseteqq", 0x02AC5, 0x00338}, // SUBSET OF ABOVE EQUALS SIGN with slash
|
||||
{"nsucc", 0x02281}, // DOES NOT SUCCEED
|
||||
// "nsucceq", 0x02AB0;0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"nsucceq", 0x02AB0, 0x00338}, // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN with slash
|
||||
{"nsup", 0x02285}, // NOT A SUPERSET OF
|
||||
{"nsupe", 0x02289}, // NEITHER A SUPERSET OF NOR EQUAL TO
|
||||
// "nsupE", 0x02AC6;0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash
|
||||
// "nsupset", 0x02283;0x020D2}, // SUPERSET OF with vertical line
|
||||
{"nsupE", 0x02AC6, 0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash
|
||||
{"nsupset", 0x02283, 0x020D2}, // SUPERSET OF with vertical line
|
||||
{"nsupseteq", 0x02289}, // NEITHER A SUPERSET OF NOR EQUAL TO
|
||||
// "nsupseteqq", 0x02AC6;0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash
|
||||
{"nsupseteqq", 0x02AC6, 0x00338}, // SUPERSET OF ABOVE EQUALS SIGN with slash
|
||||
{"ntgl", 0x02279}, // NEITHER GREATER-THAN NOR LESS-THAN
|
||||
{"Ntilde", 0x000D1}, // LATIN CAPITAL LETTER N WITH TILDE
|
||||
{"ntilde", 0x000F1}, // LATIN SMALL LETTER N WITH TILDE
|
||||
|
@ -1477,22 +1435,22 @@ immutable NameId[] namesN =
|
|||
{"num", 0x00023}, // NUMBER SIGN
|
||||
{"numero", 0x02116}, // NUMERO SIGN
|
||||
{"numsp", 0x02007}, // FIGURE SPACE
|
||||
// "nvap", 0x0224D;0x020D2}, // EQUIVALENT TO with vertical line
|
||||
{"nvap", 0x0224D, 0x020D2}, // EQUIVALENT TO with vertical line
|
||||
{"nvdash", 0x022AC}, // DOES NOT PROVE
|
||||
{"nvDash", 0x022AD}, // NOT TRUE
|
||||
{"nVdash", 0x022AE}, // DOES NOT FORCE
|
||||
{"nVDash", 0x022AF}, // NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
|
||||
// "nvge", 0x02265;0x020D2}, // GREATER-THAN OR EQUAL TO with vertical line
|
||||
// "nvgt", 0x0003E;0x020D2}, // GREATER-THAN SIGN with vertical line
|
||||
{"nvge", 0x02265, 0x020D2}, // GREATER-THAN OR EQUAL TO with vertical line
|
||||
{"nvgt", 0x0003E, 0x020D2}, // GREATER-THAN SIGN with vertical line
|
||||
{"nvHarr", 0x02904}, // LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE
|
||||
{"nvinfin", 0x029DE}, // INFINITY NEGATED WITH VERTICAL BAR
|
||||
{"nvlArr", 0x02902}, // LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE
|
||||
// "nvle", 0x02264;0x020D2}, // LESS-THAN OR EQUAL TO with vertical line
|
||||
// "nvlt", 0x0003C;0x020D2}, // LESS-THAN SIGN with vertical line
|
||||
// "nvltrie", 0x022B4;0x020D2}, // NORMAL SUBGROUP OF OR EQUAL TO with vertical line
|
||||
{"nvle", 0x02264, 0x020D2}, // LESS-THAN OR EQUAL TO with vertical line
|
||||
{"nvlt", 0x0003C, 0x020D2}, // LESS-THAN SIGN with vertical line
|
||||
{"nvltrie", 0x022B4, 0x020D2}, // NORMAL SUBGROUP OF OR EQUAL TO with vertical line
|
||||
{"nvrArr", 0x02903}, // RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE
|
||||
// "nvrtrie", 0x022B5;0x020D2}, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line
|
||||
// "nvsim", 0x0223C;0x020D2}, // TILDE OPERATOR with vertical line
|
||||
{"nvrtrie", 0x022B5, 0x020D2}, // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO with vertical line
|
||||
{"nvsim", 0x0223C, 0x020D2}, // TILDE OPERATOR with vertical line
|
||||
{"nwarhk", 0x02923}, // NORTH WEST ARROW WITH HOOK
|
||||
{"nwarr", 0x02196}, // NORTH WEST ARROW
|
||||
{"nwArr", 0x021D6}, // NORTH WEST DOUBLE ARROW
|
||||
|
@ -1704,7 +1662,7 @@ immutable NameId[] namesQ =
|
|||
immutable NameId[] namesR =
|
||||
[
|
||||
{"rAarr", 0x021DB}, // RIGHTWARDS TRIPLE ARROW
|
||||
// "race", 0x0223D;0x00331}, // REVERSED TILDE with underline
|
||||
{"race", 0x0223D, 0x00331}, // REVERSED TILDE with underline
|
||||
{"Racute", 0x00154}, // LATIN CAPITAL LETTER R WITH ACUTE
|
||||
{"racute", 0x00155}, // LATIN SMALL LETTER R WITH ACUTE
|
||||
{"radic", 0x0221A}, // SQUARE ROOT
|
||||
|
@ -1932,7 +1890,7 @@ immutable NameId[] namesS =
|
|||
{"smile", 0x02323}, // SMILE
|
||||
{"smt", 0x02AAA}, // SMALLER THAN
|
||||
{"smte", 0x02AAC}, // SMALLER THAN OR EQUAL TO
|
||||
// "smtes", 0x02AAC;0x0FE00}, // SMALLER THAN OR slanted EQUAL
|
||||
{"smtes", 0x02AAC, 0x0FE00}, // SMALLER THAN OR slanted EQUAL
|
||||
{"SOFTcy", 0x0042C}, // CYRILLIC CAPITAL LETTER SOFT SIGN
|
||||
{"softcy", 0x0044C}, // CYRILLIC SMALL LETTER SOFT SIGN
|
||||
{"sol", 0x0002F}, // SOLIDUS
|
||||
|
@ -1944,9 +1902,9 @@ immutable NameId[] namesS =
|
|||
{"spadesuit", 0x02660}, // BLACK SPADE SUIT
|
||||
{"spar", 0x02225}, // PARALLEL TO
|
||||
{"sqcap", 0x02293}, // SQUARE CAP
|
||||
// "sqcaps", 0x02293;0x0FE00}, // SQUARE CAP with serifs
|
||||
{"sqcaps", 0x02293, 0x0FE00}, // SQUARE CAP with serifs
|
||||
{"sqcup", 0x02294}, // SQUARE CUP
|
||||
// "sqcups", 0x02294;0x0FE00}, // SQUARE CUP with serifs
|
||||
{"sqcups", 0x02294, 0x0FE00}, // SQUARE CUP with serifs
|
||||
{"Sqrt", 0x0221A}, // SQUARE ROOT
|
||||
{"sqsub", 0x0228F}, // SQUARE IMAGE OF
|
||||
{"sqsube", 0x02291}, // SQUARE IMAGE OF OR EQUAL TO
|
||||
|
@ -2082,7 +2040,7 @@ immutable NameId[] namesT =
|
|||
{"thgr", 0x003B8}, // GREEK SMALL LETTER THETA
|
||||
{"thickapprox", 0x02248}, // ALMOST EQUAL TO
|
||||
{"thicksim", 0x0223C}, // TILDE OPERATOR
|
||||
// "ThickSpace", 0x0205F;0x0200A}, // space of width 5/18 em
|
||||
{"ThickSpace", 0x0205F, 0x0200A}, // space of width 5/18 em
|
||||
{"thinsp", 0x02009}, // THIN SPACE
|
||||
{"ThinSpace", 0x02009}, // THIN SPACE
|
||||
{"thkap", 0x02248}, // ALMOST EQUAL TO
|
||||
|
@ -2245,10 +2203,10 @@ immutable NameId[] namesV =
|
|||
{"vArr", 0x021D5}, // UP DOWN DOUBLE ARROW
|
||||
{"varrho", 0x003F1}, // GREEK RHO SYMBOL
|
||||
{"varsigma", 0x003C2}, // GREEK SMALL LETTER FINAL SIGMA
|
||||
// "varsubsetneq", 0x0228A;0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
|
||||
// "varsubsetneqq", 0x02ACB;0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
|
||||
// "varsupsetneq", 0x0228B;0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
|
||||
// "varsupsetneqq", 0x02ACC;0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"varsubsetneq", 0x0228A, 0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"varsubsetneqq", 0x02ACB, 0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"varsupsetneq", 0x0228B, 0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"varsupsetneqq", 0x02ACC, 0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"vartheta", 0x003D1}, // GREEK THETA SYMBOL
|
||||
{"vartriangleleft", 0x022B2}, // NORMAL SUBGROUP OF
|
||||
{"vartriangleright", 0x022B3}, // CONTAINS AS NORMAL SUBGROUP
|
||||
|
@ -2279,18 +2237,18 @@ immutable NameId[] namesV =
|
|||
{"Vfr", 0x1D519}, // MATHEMATICAL FRAKTUR CAPITAL V
|
||||
{"vfr", 0x1D533}, // MATHEMATICAL FRAKTUR SMALL V
|
||||
{"vltri", 0x022B2}, // NORMAL SUBGROUP OF
|
||||
// "vnsub", 0x02282;0x020D2}, // SUBSET OF with vertical line
|
||||
// "vnsup", 0x02283;0x020D2}, // SUPERSET OF with vertical line
|
||||
{"vnsub", 0x02282, 0x020D2}, // SUBSET OF with vertical line
|
||||
{"vnsup", 0x02283, 0x020D2}, // SUPERSET OF with vertical line
|
||||
{"Vopf", 0x1D54D}, // MATHEMATICAL DOUBLE-STRUCK CAPITAL V
|
||||
{"vopf", 0x1D567}, // MATHEMATICAL DOUBLE-STRUCK SMALL V
|
||||
{"vprop", 0x0221D}, // PROPORTIONAL TO
|
||||
{"vrtri", 0x022B3}, // CONTAINS AS NORMAL SUBGROUP
|
||||
{"Vscr", 0x1D4B1}, // MATHEMATICAL SCRIPT CAPITAL V
|
||||
{"vscr", 0x1D4CB}, // MATHEMATICAL SCRIPT SMALL V
|
||||
// "vsubne", 0x0228A;0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
|
||||
// "vsubnE", 0x02ACB;0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
|
||||
// "vsupne", 0x0228B;0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
|
||||
// "vsupnE", 0x02ACC;0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"vsubne", 0x0228A, 0x0FE00}, // SUBSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"vsubnE", 0x02ACB, 0x0FE00}, // SUBSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"vsupne", 0x0228B, 0x0FE00}, // SUPERSET OF WITH NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"vsupnE", 0x02ACC, 0x0FE00}, // SUPERSET OF ABOVE NOT EQUAL TO - variant with stroke through bottom members
|
||||
{"Vvdash", 0x022AA}, // TRIPLE VERTICAL BAR RIGHT TURNSTILE
|
||||
{"vzigzag", 0x0299A}, // VERTICAL ZIGZAG LINE
|
||||
];
|
||||
|
|
|
@ -409,23 +409,9 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, Var
|
|||
{
|
||||
unsafeAssign!"scope variable"(v);
|
||||
}
|
||||
else if (v.isTypesafeVariadicParameter && p == sc.func)
|
||||
else if (v.isTypesafeVariadicArray && p == sc.func)
|
||||
{
|
||||
Type tb = v.type.toBasetype();
|
||||
if (tb.ty == Tarray || tb.ty == Tsarray)
|
||||
{
|
||||
unsafeAssign!"variadic variable"(v);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* v is not 'scope', and is assigned to a parameter that may escape.
|
||||
* Therefore, v can never be 'scope'.
|
||||
*/
|
||||
if (log) printf("no infer for %s in %s loc %s, fdc %s, %d\n",
|
||||
v.toChars(), sc.func.ident.toChars(), sc.func.loc.toChars(), fdc.ident.toChars(), __LINE__);
|
||||
|
||||
doNotInferScope(v, vPar);
|
||||
unsafeAssign!"variadic variable"(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -673,9 +659,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
|
|||
FuncDeclaration fd = sc.func;
|
||||
|
||||
|
||||
// Determine if va is a parameter that is an indirect reference
|
||||
const bool vaIsRef = va && va.storage_class & STC.parameter &&
|
||||
(va.isReference() || va.type.toBasetype().isTypeClass()); // ref, out, or class
|
||||
// Determine if va is a `ref` parameter, so it has a lifetime exceding the function scope
|
||||
const bool vaIsRef = va && va.isParameter() && va.isReference();
|
||||
if (log && vaIsRef) printf("va is ref `%s`\n", va.toChars());
|
||||
|
||||
/* Determine if va is the first parameter, through which other 'return' parameters
|
||||
|
@ -717,7 +702,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
|
|||
Dsymbol p = v.toParent2();
|
||||
|
||||
if (va && !vaIsRef && !va.isScope() && !v.isScope() &&
|
||||
!v.isTypesafeVariadicParameter && !va.isTypesafeVariadicParameter &&
|
||||
!v.isTypesafeVariadicArray && !va.isTypesafeVariadicArray &&
|
||||
(va.isParameter() && va.maybeScope && v.isParameter() && v.maybeScope) &&
|
||||
p == fd)
|
||||
{
|
||||
|
@ -727,16 +712,9 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (vaIsFirstRef &&
|
||||
(v.isScope() || v.maybeScope) &&
|
||||
!(v.storage_class & STC.return_) &&
|
||||
v.isParameter() &&
|
||||
fd.flags & FUNCFLAG.returnInprocess &&
|
||||
p == fd &&
|
||||
!v.isTypesafeVariadicParameter)
|
||||
if (vaIsFirstRef && p == fd)
|
||||
{
|
||||
if (log) printf("inferring 'return' for parameter %s in function %s\n", v.toChars(), fd.toChars());
|
||||
inferReturn(fd, v, /*returnScope:*/ true); // infer addition of 'return' to make `return scope`
|
||||
inferReturn(fd, v, /*returnScope:*/ true);
|
||||
}
|
||||
|
||||
if (!(va && va.isScope()) || vaIsRef)
|
||||
|
@ -744,82 +722,66 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
|
|||
|
||||
if (v.isScope())
|
||||
{
|
||||
if (vaIsFirstRef && v.isParameter() && v.storage_class & STC.return_)
|
||||
if (vaIsFirstRef && v.isParameter() && v.isReturn())
|
||||
{
|
||||
// va=v, where v is `return scope`
|
||||
if (va.isScope())
|
||||
if (inferScope(va))
|
||||
continue;
|
||||
|
||||
if (va.maybeScope)
|
||||
{
|
||||
if (log) printf("inferring scope for lvalue %s\n", va.toChars());
|
||||
va.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (va && va.isScope() && va.storage_class & STC.return_ && !(v.storage_class & STC.return_))
|
||||
{
|
||||
// va may return its value, but v does not allow that, so this is an error
|
||||
if (sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to return scope `%s`", v, va))
|
||||
{
|
||||
result = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If va's lifetime encloses v's, then error
|
||||
if (va && !va.isDataseg() &&
|
||||
((va.enclosesLifetimeOf(v) && !(v.storage_class & STC.temp)) || vaIsRef))
|
||||
if (EnclosedBy eb = va.enclosesLifetimeOf(v))
|
||||
{
|
||||
if (sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to `%s` with longer lifetime", v, va))
|
||||
const(char)* msg;
|
||||
final switch (eb)
|
||||
{
|
||||
case EnclosedBy.none: assert(0);
|
||||
case EnclosedBy.returnScope:
|
||||
msg = "scope variable `%s` assigned to return scope `%s`";
|
||||
break;
|
||||
case EnclosedBy.longerScope:
|
||||
if (v.storage_class & STC.temp)
|
||||
continue;
|
||||
msg = "scope variable `%s` assigned to `%s` with longer lifetime";
|
||||
break;
|
||||
case EnclosedBy.refVar:
|
||||
msg = "scope variable `%s` assigned to `ref` variable `%s` with longer lifetime";
|
||||
break;
|
||||
case EnclosedBy.global:
|
||||
msg = "scope variable `%s` assigned to global variable `%s`";
|
||||
break;
|
||||
}
|
||||
|
||||
if (sc.setUnsafeDIP1000(gag, ae.loc, msg, v, va))
|
||||
{
|
||||
result = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (va && !va.isDataseg() && (va.isScope() || va.maybeScope))
|
||||
// v = scope, va should be scope as well
|
||||
const vaWasScope = va && va.isScope();
|
||||
if (inferScope(va))
|
||||
{
|
||||
if (!va.isScope())
|
||||
{ /* v is scope, and va is not scope, so va needs to
|
||||
* infer scope
|
||||
*/
|
||||
if (log) printf("inferring scope for %s\n", va.toChars());
|
||||
va.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
/* v returns, and va does not return, so va needs
|
||||
* to infer return
|
||||
*/
|
||||
if (v.storage_class & STC.return_ &&
|
||||
!(va.storage_class & STC.return_))
|
||||
{
|
||||
if (log) printf("infer return for %s\n", va.toChars());
|
||||
va.storage_class |= STC.return_ | STC.returninferred;
|
||||
// In case of `scope local = returnScopeParam`, do not infer return scope for `x`
|
||||
if (!vaWasScope && v.isReturn() && !va.isReturn())
|
||||
{
|
||||
if (log) printf("infer return for %s\n", va.toChars());
|
||||
va.storage_class |= STC.return_ | STC.returninferred;
|
||||
|
||||
// Added "return scope" so don't confuse it with "return ref"
|
||||
if (isRefReturnScope(va.storage_class))
|
||||
va.storage_class |= STC.returnScope;
|
||||
}
|
||||
// Added "return scope" so don't confuse it with "return ref"
|
||||
if (isRefReturnScope(va.storage_class))
|
||||
va.storage_class |= STC.returnScope;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
result |= sc.setUnsafeDIP1000(gag, ae.loc, "scope variable `%s` assigned to non-scope `%s`", v, e1);
|
||||
}
|
||||
else if (v.isTypesafeVariadicParameter && p == fd)
|
||||
else if (v.isTypesafeVariadicArray && p == fd)
|
||||
{
|
||||
Type tb = v.type.toBasetype();
|
||||
if (tb.ty == Tarray || tb.ty == Tsarray)
|
||||
{
|
||||
if (va && !va.isDataseg() && (va.isScope() || va.maybeScope))
|
||||
{
|
||||
if (!va.isScope())
|
||||
{ //printf("inferring scope for %s\n", va.toChars());
|
||||
va.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
result |= sc.setUnsafeDIP1000(gag, ae.loc, "variadic variable `%s` assigned to non-scope `%s`", v, e1);
|
||||
}
|
||||
if (inferScope(va))
|
||||
continue;
|
||||
result |= sc.setUnsafeDIP1000(gag, ae.loc, "variadic variable `%s` assigned to non-scope `%s`", v, e1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -845,7 +807,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
|
|||
|
||||
if (va && va.isScope() && !v.isReference())
|
||||
{
|
||||
if (!(va.storage_class & STC.return_))
|
||||
if (!va.isReturn())
|
||||
{
|
||||
va.doNotInferReturn = true;
|
||||
}
|
||||
|
@ -858,19 +820,14 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
|
|||
|
||||
Dsymbol p = v.toParent2();
|
||||
|
||||
if (vaIsFirstRef && v.isParameter() &&
|
||||
!(v.storage_class & STC.return_) &&
|
||||
fd.flags & FUNCFLAG.returnInprocess &&
|
||||
p == fd)
|
||||
if (vaIsFirstRef && p == fd)
|
||||
{
|
||||
//if (log) printf("inferring 'return' for parameter %s in function %s\n", v.toChars(), fd.toChars());
|
||||
inferReturn(fd, v, /*returnScope:*/ false);
|
||||
}
|
||||
|
||||
// If va's lifetime encloses v's, then error
|
||||
if (va &&
|
||||
!(vaIsFirstRef && (v.storage_class & STC.return_)) &&
|
||||
(va.enclosesLifetimeOf(v) || (va.isReference() && !(va.storage_class & STC.temp)) || va.isDataseg()))
|
||||
if (va && !(vaIsFirstRef && v.isReturn()) && va.enclosesLifetimeOf(v))
|
||||
{
|
||||
if (sc.setUnsafeDIP1000(gag, ae.loc, "address of variable `%s` assigned to `%s` with longer lifetime", v, va))
|
||||
{
|
||||
|
@ -885,13 +842,9 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
|
|||
if (p != sc.func)
|
||||
continue;
|
||||
|
||||
if (va && !va.isDataseg() && (va.isScope() || va.maybeScope))
|
||||
if (inferScope(va))
|
||||
{
|
||||
if (!va.isScope())
|
||||
{ //printf("inferring scope for %s\n", va.toChars());
|
||||
va.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
}
|
||||
if (v.storage_class & STC.return_ && !(va.storage_class & STC.return_))
|
||||
if (v.isReturn() && !va.isReturn())
|
||||
va.storage_class |= STC.return_ | STC.returninferred;
|
||||
continue;
|
||||
}
|
||||
|
@ -912,7 +865,7 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
|
|||
* then uncount that address of. This is so it won't cause a
|
||||
* closure to be allocated.
|
||||
*/
|
||||
if (va && va.isScope() && !(va.storage_class & STC.return_) && func.tookAddressOf)
|
||||
if (va && va.isScope() && !va.isReturn() && func.tookAddressOf)
|
||||
--func.tookAddressOf;
|
||||
|
||||
foreach (v; vars)
|
||||
|
@ -978,14 +931,8 @@ bool checkAssignEscape(Scope* sc, Expression e, bool gag, bool byRef)
|
|||
}
|
||||
}
|
||||
|
||||
if (va && !va.isDataseg() && (va.isScope() || va.maybeScope))
|
||||
{
|
||||
if (!va.isScope())
|
||||
{ //printf("inferring scope for %s\n", va.toChars());
|
||||
va.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
}
|
||||
if (inferScope(va))
|
||||
continue;
|
||||
}
|
||||
|
||||
result |= sc.setUnsafeDIP1000(gag, ee.loc,
|
||||
"reference to stack allocated value returned by `%s` assigned to non-scope `%s`", ee, e1);
|
||||
|
@ -1091,14 +1038,10 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if (v.isTypesafeVariadicParameter && p == sc.func)
|
||||
else if (v.isTypesafeVariadicArray && p == sc.func)
|
||||
{
|
||||
Type tb = v.type.toBasetype();
|
||||
if (tb.ty == Tarray || tb.ty == Tsarray)
|
||||
{
|
||||
result |= sc.setUnsafeDIP1000(gag, e.loc,
|
||||
"copying `%s` into allocated memory escapes a reference to variadic parameter `%s`", e, v);
|
||||
}
|
||||
result |= sc.setUnsafeDIP1000(gag, e.loc,
|
||||
"copying `%s` into allocated memory escapes a reference to variadic parameter `%s`", e, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1258,15 +1201,8 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
|
|||
|
||||
Dsymbol p = v.toParent2();
|
||||
|
||||
if ((v.isScope() || v.maybeScope) &&
|
||||
!(v.storage_class & STC.return_) &&
|
||||
v.isParameter() &&
|
||||
!v.doNotInferReturn &&
|
||||
sc.func.flags & FUNCFLAG.returnInprocess &&
|
||||
p == sc.func &&
|
||||
!v.isTypesafeVariadicParameter)
|
||||
if (p == sc.func && inferReturn(sc.func, v, /*returnScope:*/ true))
|
||||
{
|
||||
inferReturn(sc.func, v, /*returnScope:*/ true); // infer addition of 'return'
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1300,7 +1236,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
|
|||
!(!refs && sc.func.isFuncDeclaration().getLevel(pfunc, sc.intypeof) > 0)
|
||||
)
|
||||
{
|
||||
if (v.isParameter() && !(v.storage_class & STC.return_))
|
||||
if (v.isParameter() && !v.isReturn())
|
||||
{
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23191
|
||||
if (!gag)
|
||||
|
@ -1320,15 +1256,11 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (v.isTypesafeVariadicParameter && p == sc.func)
|
||||
else if (v.isTypesafeVariadicArray && p == sc.func)
|
||||
{
|
||||
Type tb = v.type.toBasetype();
|
||||
if (tb.ty == Tarray || tb.ty == Tsarray)
|
||||
{
|
||||
if (!gag)
|
||||
error(e.loc, "returning `%s` escapes a reference to variadic parameter `%s`", e.toChars(), v.toChars());
|
||||
result = false;
|
||||
}
|
||||
if (!gag)
|
||||
error(e.loc, "returning `%s` escapes a reference to variadic parameter `%s`", e.toChars(), v.toChars());
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1414,7 +1346,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
|
|||
continue;
|
||||
}
|
||||
FuncDeclaration fd = p.isFuncDeclaration();
|
||||
if (fd && sc.func.flags & FUNCFLAG.returnInprocess)
|
||||
if (fd && sc.func.returnInprocess)
|
||||
{
|
||||
/* Code like:
|
||||
* int x;
|
||||
|
@ -1435,10 +1367,10 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
|
|||
vsr == ScopeRef.Ref_ReturnScope) &&
|
||||
!(v.storage_class & STC.foreach_))
|
||||
{
|
||||
if (sc.func.flags & FUNCFLAG.returnInprocess && p == sc.func &&
|
||||
(vsr == ScopeRef.Ref || vsr == ScopeRef.RefScope))
|
||||
if (p == sc.func && (vsr == ScopeRef.Ref || vsr == ScopeRef.RefScope) &&
|
||||
inferReturn(sc.func, v, /*returnScope:*/ false))
|
||||
{
|
||||
inferReturn(sc.func, v, /*returnScope:*/ false); // infer addition of 'return'
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1488,6 +1420,26 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
|
|||
return result;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Infer `scope` for a variable
|
||||
*
|
||||
* Params:
|
||||
* va = variable to infer scope for
|
||||
* Returns: `true` if succesful or already `scope`
|
||||
*/
|
||||
bool inferScope(VarDeclaration va)
|
||||
{
|
||||
if (!va)
|
||||
return false;
|
||||
if (!va.isDataseg() && va.maybeScope && !va.isScope())
|
||||
{
|
||||
//printf("inferring scope for %s\n", va.toChars());
|
||||
va.maybeScope = false;
|
||||
va.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
return true;
|
||||
}
|
||||
return va.isScope();
|
||||
}
|
||||
|
||||
/*************************************
|
||||
* Variable v needs to have 'return' inferred for it.
|
||||
|
@ -1495,10 +1447,22 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag)
|
|||
* fd = function that v is a parameter to
|
||||
* v = parameter that needs to be STC.return_
|
||||
* returnScope = infer `return scope` instead of `return ref`
|
||||
*
|
||||
* Returns: whether the inference on `v` was successful or `v` already was `return`
|
||||
*/
|
||||
private void inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
|
||||
private bool inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
|
||||
{
|
||||
// v is a local in the current function
|
||||
if (v.isReturn())
|
||||
return !!(v.storage_class & STC.returnScope) == returnScope;
|
||||
|
||||
if (!v.isParameter() || v.isTypesafeVariadicArray || (returnScope && v.doNotInferReturn))
|
||||
return false;
|
||||
|
||||
if (!fd.returnInprocess)
|
||||
return false;
|
||||
|
||||
if (returnScope && !(v.isScope() || v.maybeScope))
|
||||
return false;
|
||||
|
||||
//printf("for function '%s' inferring 'return' for variable '%s', returnScope: %d\n", fd.toChars(), v.toChars(), returnScope);
|
||||
auto newStcs = STC.return_ | STC.returninferred | (returnScope ? STC.returnScope : 0);
|
||||
|
@ -1532,6 +1496,7 @@ private void inferReturn(FuncDeclaration fd, VarDeclaration v, bool returnScope)
|
|||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1694,7 +1659,7 @@ void escapeByValue(Expression e, EscapeByResults* er, bool live = false, bool re
|
|||
{
|
||||
if (tb.ty == Tsarray)
|
||||
return;
|
||||
if (v.isTypesafeVariadicParameter)
|
||||
if (v.isTypesafeVariadicArray)
|
||||
{
|
||||
er.byvalue.push(v);
|
||||
return;
|
||||
|
@ -2008,13 +1973,10 @@ void escapeByRef(Expression e, EscapeByResults* er, bool live = false, bool retR
|
|||
if (auto ve = e.e1.isVarExp())
|
||||
{
|
||||
VarDeclaration v = ve.var.isVarDeclaration();
|
||||
if (tb.ty == Tarray || tb.ty == Tsarray)
|
||||
if (v && v.isTypesafeVariadicArray)
|
||||
{
|
||||
if (v && v.isTypesafeVariadicParameter)
|
||||
{
|
||||
er.pushRef(v, retRefTransition);
|
||||
return;
|
||||
}
|
||||
er.pushRef(v, retRefTransition);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (tb.ty == Tsarray)
|
||||
|
@ -2339,9 +2301,9 @@ private void doNotInferScope(VarDeclaration v, RootObject o)
|
|||
void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f)
|
||||
{
|
||||
|
||||
if (funcdecl.flags & FUNCFLAG.returnInprocess)
|
||||
if (funcdecl.returnInprocess)
|
||||
{
|
||||
funcdecl.flags &= ~FUNCFLAG.returnInprocess;
|
||||
funcdecl.returnInprocess = false;
|
||||
if (funcdecl.storage_class & STC.return_)
|
||||
{
|
||||
if (funcdecl.type == f)
|
||||
|
@ -2353,9 +2315,9 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(funcdecl.flags & FUNCFLAG.inferScope))
|
||||
if (!funcdecl.inferScope)
|
||||
return;
|
||||
funcdecl.flags &= ~FUNCFLAG.inferScope;
|
||||
funcdecl.inferScope = false;
|
||||
|
||||
// Eliminate maybescope's
|
||||
{
|
||||
|
@ -2387,22 +2349,19 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f)
|
|||
foreach (u, p; f.parameterList)
|
||||
{
|
||||
auto v = (*funcdecl.parameters)[u];
|
||||
if (v.maybeScope)
|
||||
if (!v.isScope() && inferScope(v))
|
||||
{
|
||||
//printf("Inferring scope for %s\n", v.toChars());
|
||||
notMaybeScope(v, null);
|
||||
v.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
p.storageClass |= STC.scope_ | STC.scopeinferred;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (funcdecl.vthis && funcdecl.vthis.maybeScope)
|
||||
if (funcdecl.vthis)
|
||||
{
|
||||
notMaybeScope(funcdecl.vthis, null);
|
||||
funcdecl.vthis.storage_class |= STC.scope_ | STC.scopeinferred;
|
||||
f.isScopeQual = true;
|
||||
f.isscopeinferred = true;
|
||||
inferScope(funcdecl.vthis);
|
||||
f.isScopeQual = funcdecl.vthis.isScope();
|
||||
f.isscopeinferred = !!(funcdecl.vthis.storage_class & STC.scopeinferred);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2542,20 +2501,45 @@ bool isReferenceToMutable(Parameter p, Type t)
|
|||
return isReferenceToMutable(p.type);
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Determine if `va` has a lifetime that lasts past
|
||||
* the destruction of `v`
|
||||
* Params:
|
||||
* va = variable assigned to
|
||||
* v = variable being assigned
|
||||
* Returns:
|
||||
* true if it does
|
||||
*/
|
||||
private bool enclosesLifetimeOf(const VarDeclaration va, const VarDeclaration v) pure
|
||||
/// When checking lifetime for assignment `va=v`, the way `va` encloses `v`
|
||||
private enum EnclosedBy
|
||||
{
|
||||
none = 0,
|
||||
refVar, // `va` is a `ref` variable, which may link to a global variable
|
||||
global, // `va` is a global variable
|
||||
returnScope, // `va` is a scope variable that may be returned
|
||||
longerScope, // `va` is another scope variable declared earlier than `v`
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Determine if `va` has a lifetime that lasts past
|
||||
* the destruction of `v`
|
||||
* Params:
|
||||
* va = variable assigned to
|
||||
* v = variable being assigned
|
||||
* Returns:
|
||||
* The way `va` encloses `v` (if any)
|
||||
*/
|
||||
private EnclosedBy enclosesLifetimeOf(VarDeclaration va, VarDeclaration v)
|
||||
{
|
||||
if (!va)
|
||||
return EnclosedBy.none;
|
||||
|
||||
if (va.isDataseg())
|
||||
return EnclosedBy.global;
|
||||
|
||||
if (va.isScope() && va.isReturn() && !v.isReturn())
|
||||
return EnclosedBy.returnScope;
|
||||
|
||||
if (va.isReference() && va.isParameter())
|
||||
return EnclosedBy.refVar;
|
||||
|
||||
assert(va.sequenceNumber != va.sequenceNumber.init);
|
||||
assert(v.sequenceNumber != v.sequenceNumber.init);
|
||||
return va.sequenceNumber < v.sequenceNumber;
|
||||
if (va.sequenceNumber < v.sequenceNumber)
|
||||
return EnclosedBy.longerScope;
|
||||
|
||||
return EnclosedBy.none;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
|
@ -2576,53 +2560,6 @@ private void addMaybe(VarDeclaration va, VarDeclaration v)
|
|||
va.maybes.push(v);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Like `FuncDeclaration.setUnsafe`, but modified for dip25 / dip1000 by default transitions
|
||||
*
|
||||
* With `-preview=dip1000` it actually sets the function as unsafe / prints an error, while
|
||||
* without it, it only prints a deprecation in a `@safe` function.
|
||||
* With `-revert=preview=dip1000`, it doesn't do anything.
|
||||
*
|
||||
* Params:
|
||||
* sc = used for checking whether we are in a deprecated scope
|
||||
* fs = command line setting of dip1000 / dip25
|
||||
* gag = surpress error message
|
||||
* loc = location of error
|
||||
* fmt = printf-style format string
|
||||
* arg0 = (optional) argument for first %s format specifier
|
||||
* arg1 = (optional) argument for second %s format specifier
|
||||
* arg2 = (optional) argument for third %s format specifier
|
||||
* Returns: whether an actual safe error (not deprecation) occured
|
||||
*/
|
||||
private bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg,
|
||||
RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
|
||||
{
|
||||
if (fs == FeatureState.disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (fs == FeatureState.enabled)
|
||||
{
|
||||
return sc.setUnsafe(gag, loc, msg, arg0, arg1, arg2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sc.func.isSafeBypassingInference())
|
||||
{
|
||||
if (!gag)
|
||||
previewErrorFunc(sc.isDeprecated(), fs)(
|
||||
loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""
|
||||
);
|
||||
}
|
||||
else if (!sc.func.safetyViolation)
|
||||
{
|
||||
import dmd.func : AttributeViolation;
|
||||
sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// `setUnsafePreview` partially evaluated for dip1000
|
||||
private bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg,
|
||||
RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
|
||||
|
@ -2671,13 +2608,19 @@ private bool checkScopeVarAddr(VarDeclaration v, Expression e, Scope* sc, bool g
|
|||
}
|
||||
|
||||
/****************************
|
||||
* Determine if `v` is a typesafe variadic parameter.
|
||||
* Determine if `v` is a typesafe variadic array, which is implicitly `scope`
|
||||
* Params:
|
||||
* v = variable to check
|
||||
* Returns:
|
||||
* true if `v` is a variadic parameter
|
||||
*/
|
||||
bool isTypesafeVariadicParameter(VarDeclaration v)
|
||||
private bool isTypesafeVariadicArray(VarDeclaration v)
|
||||
{
|
||||
return !!(v.storage_class & STC.variadic);
|
||||
if (v.storage_class & STC.variadic)
|
||||
{
|
||||
Type tb = v.type.toBasetype();
|
||||
if (tb.ty == Tarray || tb.ty == Tsarray)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -2949,7 +2949,7 @@ extern (C++) final class ArrayLiteralExp : Expression
|
|||
|
||||
Expressions* elements;
|
||||
OwnedBy ownedByCtfe = OwnedBy.code;
|
||||
|
||||
bool onstack = false;
|
||||
|
||||
extern (D) this(const ref Loc loc, Type type, Expressions* elements)
|
||||
{
|
||||
|
|
|
@ -419,6 +419,7 @@ public:
|
|||
Expression *basis;
|
||||
Expressions *elements;
|
||||
OwnedBy ownedByCtfe;
|
||||
bool onstack;
|
||||
|
||||
static ArrayLiteralExp *create(const Loc &loc, Expressions *elements);
|
||||
static void emplace(UnionExp *pue, const Loc &loc, Expressions *elements);
|
||||
|
|
|
@ -353,6 +353,37 @@ extern(D) bool arrayExpressionSemantic(
|
|||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
Checks if `exp` contains a direct access to a `noreturn`
|
||||
variable. If that is the case, an `assert(0)` expression
|
||||
is generated and returned. This function should be called
|
||||
only after semantic analysis has been performed on `exp`.
|
||||
|
||||
Params:
|
||||
exp = expression that is checked
|
||||
|
||||
Returns:
|
||||
An `assert(0)` expression if `exp` contains a `noreturn`
|
||||
variable access, `exp` otherwise.
|
||||
*/
|
||||
|
||||
Expression checkNoreturnVarAccess(Expression exp)
|
||||
{
|
||||
assert(exp.type);
|
||||
|
||||
Expression result = exp;
|
||||
if (exp.type.isTypeNoreturn() && !exp.isAssertExp() &&
|
||||
!exp.isThrowExp() && !exp.isCallExp())
|
||||
{
|
||||
auto msg = new StringExp(exp.loc, "Accessed expression of type `noreturn`");
|
||||
msg.type = Type.tstring;
|
||||
result = new AssertExp(exp.loc, IntegerExp.literal!0, msg);
|
||||
result.type = exp.type;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/******************************
|
||||
* Check the tail CallExp is really property function call.
|
||||
* Bugs:
|
||||
|
@ -848,6 +879,18 @@ Lagain:
|
|||
if (d)
|
||||
d.checkDisabled(loc, sc);
|
||||
}
|
||||
|
||||
if (auto sd = s.isDeclaration())
|
||||
{
|
||||
if (sd.isSystem())
|
||||
{
|
||||
if (sc.setUnsafePreview(global.params.systemVariables, false, loc,
|
||||
"cannot access `@system` variable `%s` in @safe code", sd))
|
||||
{
|
||||
return ErrorExp.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto em = s.isEnumMember())
|
||||
|
@ -1714,7 +1757,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
if (sc._module)
|
||||
sc._module.hasAlwaysInlines = true;
|
||||
if (sc.func)
|
||||
sc.func.flags |= FUNCFLAG.hasAlwaysInline;
|
||||
sc.func.hasAlwaysInlines = true;
|
||||
}
|
||||
|
||||
const isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
|
||||
|
@ -2200,14 +2243,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
|
|||
/* If calling C scanf(), printf(), or any variants, check the format string against the arguments
|
||||
*/
|
||||
const isVa_list = tf.parameterList.varargs == VarArg.none;
|
||||
if (fd && fd.flags & FUNCFLAG.printf)
|
||||
if (fd && fd.printf)
|
||||
{
|
||||
if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
|
||||
{
|
||||
checkPrintfFormat(se.loc, se.peekString(), (*arguments)[nparams .. nargs], isVa_list);
|
||||
}
|
||||
}
|
||||
else if (fd && fd.flags & FUNCFLAG.scanf)
|
||||
else if (fd && fd.scanf)
|
||||
{
|
||||
if (auto se = (*arguments)[nparams - 1 - isVa_list].isStringExp())
|
||||
{
|
||||
|
@ -4628,8 +4671,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
else if (exp.arguments.dim == 1)
|
||||
{
|
||||
e = (*exp.arguments)[0];
|
||||
e = e.implicitCastTo(sc, t1);
|
||||
e = new CastExp(exp.loc, e, t1);
|
||||
if (!e.type.isTypeNoreturn())
|
||||
e = e.implicitCastTo(sc, t1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -7474,6 +7517,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
return;
|
||||
}
|
||||
|
||||
if (exp.e1.type.isTypeNoreturn() && (!exp.to || !exp.to.isTypeNoreturn()))
|
||||
{
|
||||
result = exp.e1;
|
||||
return;
|
||||
}
|
||||
if (exp.to && !exp.to.isTypeSArray() && !exp.to.isTypeFunction())
|
||||
exp.e1 = exp.e1.arrayFuncConv(sc);
|
||||
|
||||
|
@ -7889,7 +7937,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
return setError();
|
||||
}
|
||||
}
|
||||
else if (t1b.ty == Tvector)
|
||||
else if (t1b.ty == Tvector && exp.e1.isLvalue())
|
||||
{
|
||||
// Convert e1 to corresponding static array
|
||||
TypeVector tv1 = cast(TypeVector)t1b;
|
||||
|
@ -8896,7 +8944,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
exp.e1 = e1x;
|
||||
assert(exp.e1.type);
|
||||
}
|
||||
Type t1 = exp.e1.type.toBasetype();
|
||||
Type t1 = exp.e1.type.isTypeEnum() ? exp.e1.type : exp.e1.type.toBasetype();
|
||||
|
||||
/* Run this.e2 semantic.
|
||||
* Different from other binary expressions, the analysis of e2
|
||||
|
@ -8918,14 +8966,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
e2x.checkSharedAccess(sc))
|
||||
return setError();
|
||||
|
||||
if (e2x.type.isTypeNoreturn() && !e2x.isAssertExp() && !e2x.isThrowExp() && !e2x.isCallExp())
|
||||
{
|
||||
auto msg = new StringExp(e2x.loc, "Accessed expression of type `noreturn`");
|
||||
msg.type = Type.tstring;
|
||||
e2x = new AssertExp(e2x.loc, IntegerExp.literal!0, msg);
|
||||
e2x.type = Type.tnoreturn;
|
||||
return setResult(e2x);
|
||||
}
|
||||
auto etmp = checkNoreturnVarAccess(e2x);
|
||||
if (etmp != e2x)
|
||||
return setResult(etmp);
|
||||
|
||||
exp.e2 = e2x;
|
||||
}
|
||||
|
||||
|
@ -9890,14 +9934,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
|
||||
exp.type = exp.e1.type;
|
||||
assert(exp.type);
|
||||
auto assignElem = exp.e2;
|
||||
auto res = exp.op == EXP.assign ? exp.reorderSettingAAElem(sc) : exp;
|
||||
Expression tmp;
|
||||
/* https://issues.dlang.org/show_bug.cgi?id=22366
|
||||
*
|
||||
* `reorderSettingAAElem` creates a tree of comma expressions, however,
|
||||
* `checkAssignExp` expects only AssignExps.
|
||||
*/
|
||||
checkAssignEscape(sc, Expression.extractLast(res, tmp), false, false);
|
||||
if (res == exp) // no `AA[k] = v` rewrite was performed
|
||||
checkAssignEscape(sc, res, false, false);
|
||||
else
|
||||
checkNewEscape(sc, assignElem, false); // assigning to AA puts it on heap
|
||||
|
||||
if (auto ae = res.isConstructExp())
|
||||
{
|
||||
|
@ -9905,40 +9952,48 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
if (t1b.ty != Tsarray && t1b.ty != Tarray)
|
||||
return setResult(res);
|
||||
|
||||
/* Do not lower Rvalues and references, as they need to be moved,
|
||||
* not copied.
|
||||
* Skip the lowering when the RHS is an array literal, as e2ir
|
||||
* already handles such cases more elegantly.
|
||||
*/
|
||||
const isArrayCtor =
|
||||
(ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
|
||||
ae.e2.isLvalue &&
|
||||
!(ae.e1.isVarExp &&
|
||||
ae.e1.isVarExp.var.isVarDeclaration.isReference) &&
|
||||
(ae.e2.isVarExp ||
|
||||
ae.e2.isSliceExp ||
|
||||
(ae.e2.type.ty == Tsarray && !ae.e2.isArrayLiteralExp)) &&
|
||||
ae.e1.type.nextOf &&
|
||||
ae.e2.type.nextOf &&
|
||||
ae.e1.type.nextOf.mutableOf.equals(ae.e2.type.nextOf.mutableOf);
|
||||
// only non-trivial array constructions may need to be lowered (non-POD elements basically)
|
||||
Type t1e = t1b.nextOf();
|
||||
TypeStruct ts = t1e.baseElemOf().isTypeStruct();
|
||||
if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor))
|
||||
return setResult(res);
|
||||
|
||||
/* Unlike isArrayCtor above, lower all Rvalues. If the RHS is a literal,
|
||||
* then we do want to make a temporary for it and call its destructor.
|
||||
*/
|
||||
const isArraySetCtor =
|
||||
(ae.e1.isSliceExp || ae.e1.type.ty == Tsarray) &&
|
||||
(ae.e2.type.ty == Tstruct || ae.e2.type.ty == Tsarray) &&
|
||||
ae.e1.type.nextOf &&
|
||||
ae.e1.type.nextOf.equivalent(ae.e2.type);
|
||||
// don't lower ref-constructions etc.
|
||||
if (!(t1b.ty == Tsarray || ae.e1.isSliceExp) ||
|
||||
(ae.e1.isVarExp && ae.e1.isVarExp.var.isVarDeclaration.isReference))
|
||||
return setResult(res);
|
||||
|
||||
if (isArrayCtor || isArraySetCtor)
|
||||
// Construction from an equivalent other array?
|
||||
// Only lower with lvalue RHS elements; let the glue layer move rvalue elements.
|
||||
Type t2b = ae.e2.type.toBasetype();
|
||||
// skip over a (possibly implicit) cast of a static array RHS to a slice
|
||||
Expression rhs = ae.e2;
|
||||
Type rhsType = t2b;
|
||||
if (t2b.ty == Tarray)
|
||||
{
|
||||
const ts = t1b.nextOf().baseElemOf().isTypeStruct();
|
||||
if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor))
|
||||
return setResult(res);
|
||||
if (auto ce = rhs.isCastExp())
|
||||
{
|
||||
auto ct = ce.e1.type.toBasetype();
|
||||
if (ct.ty == Tsarray)
|
||||
{
|
||||
rhs = ce.e1;
|
||||
rhsType = ct;
|
||||
}
|
||||
}
|
||||
}
|
||||
const lowerToArrayCtor =
|
||||
( (rhsType.ty == Tarray && !rhs.isArrayLiteralExp) ||
|
||||
(rhsType.ty == Tsarray && rhs.isLvalue) ) &&
|
||||
t1e.equivalent(t2b.nextOf);
|
||||
|
||||
auto func = isArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor;
|
||||
const other = isArrayCtor ? "other array" : "value";
|
||||
// Construction from a single element?
|
||||
// If the RHS is an rvalue, then we'll need to make a temporary for it (copied multiple times).
|
||||
const lowerToArraySetCtor = !lowerToArrayCtor && t1e.equivalent(t2b);
|
||||
|
||||
if (lowerToArrayCtor || lowerToArraySetCtor)
|
||||
{
|
||||
auto func = lowerToArrayCtor ? Id._d_arrayctor : Id._d_arraysetctor;
|
||||
const other = lowerToArrayCtor ? "other array" : "value";
|
||||
if (!verifyHookExist(exp.loc, *sc, func, "construct array with " ~ other, Id.object))
|
||||
return setError();
|
||||
|
||||
|
@ -9948,18 +10003,18 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
id = new DotIdExp(exp.loc, id, func);
|
||||
|
||||
auto arguments = new Expressions();
|
||||
arguments.push(new CastExp(ae.loc, ae.e1, ae.e1.type.nextOf.arrayOf).expressionSemantic(sc));
|
||||
if (isArrayCtor)
|
||||
arguments.push(new CastExp(ae.loc, ae.e1, t1e.arrayOf).expressionSemantic(sc));
|
||||
if (lowerToArrayCtor)
|
||||
{
|
||||
arguments.push(new CastExp(ae.loc, ae.e2, ae.e2.type.nextOf.arrayOf).expressionSemantic(sc));
|
||||
arguments.push(new CastExp(ae.loc, rhs, t2b.nextOf.arrayOf).expressionSemantic(sc));
|
||||
Expression ce = new CallExp(exp.loc, id, arguments);
|
||||
res = ce.expressionSemantic(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression e0;
|
||||
// If ae.e2 is not a variable, construct a temp variable, as _d_arraysetctor requires `ref` access
|
||||
if (!ae.e2.isVarExp)
|
||||
// promote an rvalue RHS element to a temporary, it's passed by ref to _d_arraysetctor
|
||||
if (!ae.e2.isLvalue)
|
||||
{
|
||||
auto vd = copyToTemp(STC.scope_, "__setctor", ae.e2);
|
||||
e0 = new DeclarationExp(vd.loc, vd).expressionSemantic(sc);
|
||||
|
@ -11759,6 +11814,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
result = arrayLowering;
|
||||
return;
|
||||
}
|
||||
|
||||
if (t1.isTypeVector())
|
||||
exp.type = t1;
|
||||
|
||||
result = exp;
|
||||
return;
|
||||
}
|
||||
|
@ -12038,6 +12097,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
|
|||
return;
|
||||
}
|
||||
|
||||
if (t1.isTypeVector())
|
||||
exp.type = t1;
|
||||
|
||||
result = exp;
|
||||
}
|
||||
|
||||
|
@ -12490,8 +12552,7 @@ Expression semanticX(DotIdExp exp, Scope* sc)
|
|||
if (f.checkForwardRef(loc))
|
||||
return ErrorExp.get();
|
||||
|
||||
if (f.flags & (FUNCFLAG.purityInprocess | FUNCFLAG.safetyInprocess |
|
||||
FUNCFLAG.nothrowInprocess | FUNCFLAG.nogcInprocess))
|
||||
if (f.purityInprocess || f.safetyInprocess || f.nothrowInprocess || f.nogcInprocess)
|
||||
{
|
||||
f.error(loc, "cannot retrieve its `.mangleof` while inferring attributes");
|
||||
return ErrorExp.get();
|
||||
|
@ -13099,7 +13160,7 @@ Lerr:
|
|||
*/
|
||||
bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false)
|
||||
{
|
||||
if (!global.params.noSharedAccess ||
|
||||
if (global.params.noSharedAccess != FeatureState.enabled ||
|
||||
sc.intypeof ||
|
||||
sc.flags & SCOPE.ctfe)
|
||||
{
|
||||
|
|
276
gcc/d/dmd/func.d
276
gcc/d/dmd/func.d
|
@ -182,7 +182,7 @@ public:
|
|||
catches.push(ctch);
|
||||
|
||||
Statement s2 = new TryCatchStatement(Loc.initial, s._body, catches);
|
||||
fd.flags &= ~FUNCFLAG.noEH;
|
||||
fd.hasNoEH = false;
|
||||
replaceCurrent(s2);
|
||||
s2.accept(this);
|
||||
}
|
||||
|
@ -191,31 +191,31 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
enum FUNCFLAG : uint
|
||||
private struct FUNCFLAG
|
||||
{
|
||||
purityInprocess = 1, /// working on determining purity
|
||||
safetyInprocess = 2, /// working on determining safety
|
||||
nothrowInprocess = 4, /// working on determining nothrow
|
||||
nogcInprocess = 8, /// working on determining @nogc
|
||||
returnInprocess = 0x10, /// working on inferring 'return' for parameters
|
||||
inlineScanned = 0x20, /// function has been scanned for inline possibilities
|
||||
inferScope = 0x40, /// infer 'scope' for parameters
|
||||
hasCatches = 0x80, /// function has try-catch statements
|
||||
compileTimeOnly = 0x100, /// is a compile time only function; no code will be generated for it
|
||||
printf = 0x200, /// is a printf-like function
|
||||
scanf = 0x400, /// is a scanf-like function
|
||||
noreturn = 0x800, /// the function does not return
|
||||
NRVO = 0x1000, /// Support for named return value optimization
|
||||
naked = 0x2000, /// The function is 'naked' (see inline ASM)
|
||||
generated = 0x4000, /// The function is compiler generated (e.g. `opCmp`)
|
||||
introducing = 0x8000, /// If this function introduces the overload set
|
||||
semantic3Errors = 0x10000, /// If errors in semantic3 this function's frame ptr
|
||||
noEH = 0x20000, /// No exception unwinding is needed
|
||||
inferRetType = 0x40000, /// Return type is to be inferred
|
||||
dualContext = 0x80000, /// has a dual-context 'this' parameter
|
||||
hasAlwaysInline = 0x100000, /// Contains references to functions that must be inlined
|
||||
CRTCtor = 0x200000, /// Has attribute pragma(crt_constructor)
|
||||
CRTDtor = 0x400000, /// Has attribute pragma(crt_destructor)
|
||||
bool purityInprocess; /// working on determining purity
|
||||
bool safetyInprocess; /// working on determining safety
|
||||
bool nothrowInprocess; /// working on determining nothrow
|
||||
bool nogcInprocess; /// working on determining @nogc
|
||||
bool returnInprocess; /// working on inferring 'return' for parameters
|
||||
bool inlineScanned; /// function has been scanned for inline possibilities
|
||||
bool inferScope; /// infer 'scope' for parameters
|
||||
bool hasCatches; /// function has try-catch statements
|
||||
bool isCompileTimeOnly; /// is a compile time only function; no code will be generated for it
|
||||
bool printf; /// is a printf-like function
|
||||
bool scanf; /// is a scanf-like function
|
||||
bool noreturn; /// the function does not return
|
||||
bool isNRVO = true; /// Support for named return value optimization
|
||||
bool isNaked; /// The function is 'naked' (see inline ASM)
|
||||
bool isGenerated; /// The function is compiler generated (e.g. `opCmp`)
|
||||
bool isIntroducing; /// If this function introduces the overload set
|
||||
bool hasSemantic3Errors; /// If errors in semantic3 this function's frame ptr
|
||||
bool hasNoEH; /// No exception unwinding is needed
|
||||
bool inferRetType; /// Return type is to be inferred
|
||||
bool hasDualContext; /// has a dual-context 'this' parameter
|
||||
bool hasAlwaysInlines; /// Contains references to functions that must be inlined
|
||||
bool isCrtCtor; /// Has attribute pragma(crt_constructor)
|
||||
bool isCrtDtor; /// Has attribute pragma(crt_destructor)
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
|
@ -348,9 +348,9 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
/// better diagnostics
|
||||
AttributeViolation* safetyViolation;
|
||||
|
||||
/// Function flags: A collection of boolean packed for memory efficiency
|
||||
/// See the `FUNCFLAG` enum
|
||||
uint flags = FUNCFLAG.NRVO;
|
||||
/// See the `FUNCFLAG` struct
|
||||
import dmd.common.bitfields;
|
||||
mixin(generateBitFields!(FUNCFLAG, uint));
|
||||
|
||||
/**
|
||||
* Data for a function declaration that is needed for the Objective-C
|
||||
|
@ -373,13 +373,13 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
}
|
||||
this.endloc = endloc;
|
||||
if (noreturn)
|
||||
this.flags |= FUNCFLAG.noreturn;
|
||||
this.noreturn = true;
|
||||
|
||||
/* The type given for "infer the return type" is a TypeFunction with
|
||||
* NULL for the return type.
|
||||
*/
|
||||
if (type && type.nextOf() is null)
|
||||
this.flags |= FUNCFLAG.inferRetType;
|
||||
this.inferRetType = true;
|
||||
}
|
||||
|
||||
static FuncDeclaration create(const ref Loc loc, const ref Loc endloc, Identifier id, StorageClass storage_class, Type type, bool noreturn = false)
|
||||
|
@ -391,7 +391,7 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
{
|
||||
//printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
|
||||
FuncDeclaration f = s ? cast(FuncDeclaration)s
|
||||
: new FuncDeclaration(loc, endloc, ident, storage_class, type.syntaxCopy(), (flags & FUNCFLAG.noreturn) != 0);
|
||||
: new FuncDeclaration(loc, endloc, ident, storage_class, type.syntaxCopy(), this.noreturn != 0);
|
||||
f.frequires = frequires ? Statement.arraySyntaxCopy(frequires) : null;
|
||||
f.fensures = fensures ? Ensure.arraySyntaxCopy(fensures) : null;
|
||||
f.fbody = fbody ? fbody.syntaxCopy() : null;
|
||||
|
@ -522,7 +522,7 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
{
|
||||
const bool dualCtx = (toParent2() != toParentLocal());
|
||||
if (dualCtx)
|
||||
this.flags |= FUNCFLAG.dualContext;
|
||||
this.hasDualContext = true;
|
||||
auto ad = isThis();
|
||||
if (!dualCtx && !ad && !isNested())
|
||||
{
|
||||
|
@ -1376,29 +1376,29 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
//printf("initInferAttributes() for %s (%s)\n", toPrettyChars(), ident.toChars());
|
||||
TypeFunction tf = type.toTypeFunction();
|
||||
if (tf.purity == PURE.impure) // purity not specified
|
||||
flags |= FUNCFLAG.purityInprocess;
|
||||
purityInprocess = true;
|
||||
|
||||
if (tf.trust == TRUST.default_)
|
||||
flags |= FUNCFLAG.safetyInprocess;
|
||||
safetyInprocess = true;
|
||||
|
||||
if (!tf.isnothrow)
|
||||
flags |= FUNCFLAG.nothrowInprocess;
|
||||
nothrowInprocess = true;
|
||||
|
||||
if (!tf.isnogc)
|
||||
flags |= FUNCFLAG.nogcInprocess;
|
||||
nogcInprocess = true;
|
||||
|
||||
if (!isVirtual() || this.isIntroducing())
|
||||
flags |= FUNCFLAG.returnInprocess;
|
||||
returnInprocess = true;
|
||||
|
||||
// Initialize for inferring STC.scope_
|
||||
flags |= FUNCFLAG.inferScope;
|
||||
inferScope = true;
|
||||
}
|
||||
|
||||
final PURE isPure()
|
||||
{
|
||||
//printf("FuncDeclaration::isPure() '%s'\n", toChars());
|
||||
TypeFunction tf = type.toTypeFunction();
|
||||
if (flags & FUNCFLAG.purityInprocess)
|
||||
if (purityInprocess)
|
||||
setImpure();
|
||||
if (tf.purity == PURE.fwdref)
|
||||
tf.purityLevel();
|
||||
|
@ -1424,7 +1424,7 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
|
||||
final PURE isPureBypassingInference()
|
||||
{
|
||||
if (flags & FUNCFLAG.purityInprocess)
|
||||
if (purityInprocess)
|
||||
return PURE.fwdref;
|
||||
else
|
||||
return isPure();
|
||||
|
@ -1437,9 +1437,9 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
*/
|
||||
extern (D) final bool setImpure()
|
||||
{
|
||||
if (flags & FUNCFLAG.purityInprocess)
|
||||
if (purityInprocess)
|
||||
{
|
||||
flags &= ~FUNCFLAG.purityInprocess;
|
||||
purityInprocess = false;
|
||||
if (fes)
|
||||
fes.func.setImpure();
|
||||
}
|
||||
|
@ -1448,21 +1448,32 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
return false;
|
||||
}
|
||||
|
||||
extern (D) final uint flags()
|
||||
{
|
||||
return bitFields;
|
||||
}
|
||||
|
||||
extern (D) final uint flags(uint f)
|
||||
{
|
||||
bitFields = f;
|
||||
return bitFields;
|
||||
}
|
||||
|
||||
final bool isSafe()
|
||||
{
|
||||
if (flags & FUNCFLAG.safetyInprocess)
|
||||
if (safetyInprocess)
|
||||
setUnsafe();
|
||||
return type.toTypeFunction().trust == TRUST.safe;
|
||||
}
|
||||
|
||||
final bool isSafeBypassingInference()
|
||||
{
|
||||
return !(flags & FUNCFLAG.safetyInprocess) && isSafe();
|
||||
return !(safetyInprocess) && isSafe();
|
||||
}
|
||||
|
||||
final bool isTrusted()
|
||||
{
|
||||
if (flags & FUNCFLAG.safetyInprocess)
|
||||
if (safetyInprocess)
|
||||
setUnsafe();
|
||||
return type.toTypeFunction().trust == TRUST.trusted;
|
||||
}
|
||||
|
@ -1483,9 +1494,9 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
bool gag = false, Loc loc = Loc.init, const(char)* fmt = null,
|
||||
RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
|
||||
{
|
||||
if (flags & FUNCFLAG.safetyInprocess)
|
||||
if (safetyInprocess)
|
||||
{
|
||||
flags &= ~FUNCFLAG.safetyInprocess;
|
||||
safetyInprocess = false;
|
||||
type.toTypeFunction().trust = TRUST.system;
|
||||
if (fmt || arg0)
|
||||
safetyViolation = new AttributeViolation(loc, fmt, arg0, arg1, arg2);
|
||||
|
@ -1518,99 +1529,14 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
final bool isNogc()
|
||||
{
|
||||
//printf("isNogc() %s, inprocess: %d\n", toChars(), !!(flags & FUNCFLAG.nogcInprocess));
|
||||
if (flags & FUNCFLAG.nogcInprocess)
|
||||
if (nogcInprocess)
|
||||
setGC();
|
||||
return type.toTypeFunction().isnogc;
|
||||
}
|
||||
|
||||
final bool isNogcBypassingInference()
|
||||
{
|
||||
return !(flags & FUNCFLAG.nogcInprocess) && isNogc();
|
||||
}
|
||||
|
||||
final bool isNRVO() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.NRVO);
|
||||
}
|
||||
|
||||
final void isNRVO(bool v) pure nothrow @safe @nogc
|
||||
{
|
||||
if (v) this.flags |= FUNCFLAG.NRVO;
|
||||
else this.flags &= ~FUNCFLAG.NRVO;
|
||||
}
|
||||
|
||||
final bool isNaked() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.naked);
|
||||
}
|
||||
|
||||
final void isNaked(bool v) @safe pure nothrow @nogc
|
||||
{
|
||||
if (v) this.flags |= FUNCFLAG.naked;
|
||||
else this.flags &= ~FUNCFLAG.naked;
|
||||
}
|
||||
|
||||
final bool isGenerated() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.generated);
|
||||
}
|
||||
|
||||
final void isGenerated(bool v) pure nothrow @safe @nogc
|
||||
{
|
||||
if (v) this.flags |= FUNCFLAG.generated;
|
||||
else this.flags &= ~FUNCFLAG.generated;
|
||||
}
|
||||
|
||||
final bool isIntroducing() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.introducing);
|
||||
}
|
||||
|
||||
final bool hasSemantic3Errors() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.semantic3Errors);
|
||||
}
|
||||
|
||||
final bool hasNoEH() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.noEH);
|
||||
}
|
||||
|
||||
final bool inferRetType() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.inferRetType);
|
||||
}
|
||||
|
||||
final bool hasDualContext() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.dualContext);
|
||||
}
|
||||
|
||||
final bool hasAlwaysInlines() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.hasAlwaysInline);
|
||||
}
|
||||
|
||||
final bool isCrtCtor() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.CRTCtor);
|
||||
}
|
||||
|
||||
final void isCrtCtor(bool v) @safe pure nothrow @nogc
|
||||
{
|
||||
if (v) this.flags |= FUNCFLAG.CRTCtor;
|
||||
else this.flags &= ~FUNCFLAG.CRTCtor;
|
||||
}
|
||||
|
||||
final bool isCrtDtor() const scope @safe pure nothrow @nogc
|
||||
{
|
||||
return !!(this.flags & FUNCFLAG.CRTDtor);
|
||||
}
|
||||
|
||||
final void isCrtDtor(bool v) @safe pure nothrow @nogc
|
||||
{
|
||||
if (v) this.flags |= FUNCFLAG.CRTDtor;
|
||||
else this.flags &= ~FUNCFLAG.CRTDtor;
|
||||
return !nogcInprocess && isNogc();
|
||||
}
|
||||
|
||||
/**************************************
|
||||
|
@ -1622,15 +1548,15 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
extern (D) final bool setGC()
|
||||
{
|
||||
//printf("setGC() %s\n", toChars());
|
||||
if (flags & FUNCFLAG.nogcInprocess && semanticRun < PASS.semantic3 && _scope)
|
||||
if (nogcInprocess && semanticRun < PASS.semantic3 && _scope)
|
||||
{
|
||||
this.semantic2(_scope);
|
||||
this.semantic3(_scope);
|
||||
}
|
||||
|
||||
if (flags & FUNCFLAG.nogcInprocess)
|
||||
if (nogcInprocess)
|
||||
{
|
||||
flags &= ~FUNCFLAG.nogcInprocess;
|
||||
nogcInprocess = false;
|
||||
type.toTypeFunction().isnogc = false;
|
||||
if (fes)
|
||||
fes.func.setGC();
|
||||
|
@ -3384,6 +3310,28 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
|
|||
// re-resolve to check for supplemental message
|
||||
if (!global.gag || global.params.showGaggedErrors)
|
||||
{
|
||||
if (tthis)
|
||||
{
|
||||
if (auto classType = tthis.isTypeClass())
|
||||
{
|
||||
if (auto baseClass = classType.sym.baseClass)
|
||||
{
|
||||
if (auto baseFunction = baseClass.search(baseClass.loc, fd.ident))
|
||||
{
|
||||
MatchAccumulator mErr;
|
||||
functionResolve(mErr, baseFunction, loc, sc, tiargs, baseClass.type, fargs, null);
|
||||
if (mErr.last > MATCH.nomatch && mErr.lastf)
|
||||
{
|
||||
errorSupplemental(loc, "%s `%s` hides base class function `%s`",
|
||||
fd.kind, fd.toPrettyChars(), mErr.lastf.toPrettyChars());
|
||||
errorSupplemental(loc, "add `alias %s = %s` to `%s`'s body to merge the overload sets",
|
||||
fd.toChars(), mErr.lastf.toPrettyChars(), tthis.toChars());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const(char)* failMessage;
|
||||
functionResolve(m, orig_s, loc, sc, tiargs, tthis, fargs, &failMessage);
|
||||
if (failMessage)
|
||||
|
@ -3767,7 +3715,7 @@ extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
|
|||
this.fes = fes;
|
||||
// Always infer scope for function literals
|
||||
// See https://issues.dlang.org/show_bug.cgi?id=20362
|
||||
this.flags |= FUNCFLAG.inferScope;
|
||||
this.inferScope = true;
|
||||
//printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this.ident.toChars(), type.toChars());
|
||||
}
|
||||
|
||||
|
@ -4431,6 +4379,58 @@ bool setUnsafe(Scope* sc,
|
|||
return sc.func.setUnsafe(gag, loc, fmt, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Like `setUnsafe`, but for safety errors still behind preview switches
|
||||
*
|
||||
* Given a `FeatureState fs`, for example dip1000 / dip25 / systemVariables,
|
||||
* the behavior changes based on the setting:
|
||||
*
|
||||
* - In case of `-revert=fs`, it does nothing.
|
||||
* - In case of `-preview=fs`, it's the same as `setUnsafe`
|
||||
* - By default, print a deprecation in `@safe` functions, or store an attribute violation in inferred functions.
|
||||
*
|
||||
* Params:
|
||||
* sc = used to find affected function/variable, and for checking whether we are in a deprecated / speculative scope
|
||||
* fs = feature state from the preview flag
|
||||
* gag = surpress error message
|
||||
* loc = location of error
|
||||
* msg = printf-style format string
|
||||
* arg0 = (optional) argument for first %s format specifier
|
||||
* arg1 = (optional) argument for second %s format specifier
|
||||
* arg2 = (optional) argument for third %s format specifier
|
||||
* Returns: whether an actual safe error (not deprecation) occured
|
||||
*/
|
||||
bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char)* msg,
|
||||
RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
|
||||
{
|
||||
if (fs == FeatureState.disabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (fs == FeatureState.enabled)
|
||||
{
|
||||
return sc.setUnsafe(gag, loc, msg, arg0, arg1, arg2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sc.func)
|
||||
return false;
|
||||
if (sc.func.isSafeBypassingInference())
|
||||
{
|
||||
if (!gag)
|
||||
previewErrorFunc(sc.isDeprecated(), fs)(
|
||||
loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""
|
||||
);
|
||||
}
|
||||
else if (!sc.func.safetyViolation)
|
||||
{
|
||||
import dmd.func : AttributeViolation;
|
||||
sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores a reason why a function failed to infer a function attribute like `@safe` or `pure`
|
||||
///
|
||||
/// Has two modes:
|
||||
|
|
|
@ -160,15 +160,16 @@ extern (C++) struct Param
|
|||
// https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
|
||||
// https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html
|
||||
// Implementation: https://github.com/dlang/dmd/pull/9817
|
||||
bool noSharedAccess; // read/write access to shared memory objects
|
||||
FeatureState noSharedAccess; // read/write access to shared memory objects
|
||||
bool previewIn; // `in` means `[ref] scope const`, accepts rvalues
|
||||
bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract
|
||||
bool shortenedMethods; // allow => in normal function declarations
|
||||
bool shortenedMethods = true; // allow => in normal function declarations
|
||||
bool fixImmutableConv; // error on unsound immutable conversion - https://github.com/dlang/dmd/pull/14070
|
||||
bool fix16997 = true; // fix integral promotions for unary + - ~ operators
|
||||
// https://issues.dlang.org/show_bug.cgi?id=16997
|
||||
FeatureState dtorFields; // destruct fields of partially constructed objects
|
||||
// https://issues.dlang.org/show_bug.cgi?id=14246
|
||||
FeatureState systemVariables; // limit access to variables marked @system from @safe code
|
||||
|
||||
CHECKENABLE useInvariants = CHECKENABLE._default; // generate class invariant checks
|
||||
CHECKENABLE useIn = CHECKENABLE._default; // generate precondition checks
|
||||
|
|
|
@ -158,7 +158,7 @@ struct Param
|
|||
// https://gist.github.com/andralex/e5405a5d773f07f73196c05f8339435a
|
||||
// https://digitalmars.com/d/archives/digitalmars/D/Binding_rvalues_to_ref_parameters_redux_325087.html
|
||||
// Implementation: https://github.com/dlang/dmd/pull/9817
|
||||
bool noSharedAccess; // read/write access to shared memory objects
|
||||
FeatureState noSharedAccess; // read/write access to shared memory objects
|
||||
bool previewIn; // `in` means `[ref] scope const`, accepts rvalues
|
||||
bool inclusiveInContracts; // 'in' contracts of overridden methods must be a superset of parent contract
|
||||
bool shortenedMethods; // allow => in normal function declarations
|
||||
|
@ -166,7 +166,9 @@ struct Param
|
|||
bool fix16997; // fix integral promotions for unary + - ~ operators
|
||||
// https://issues.dlang.org/show_bug.cgi?id=16997
|
||||
FeatureState dtorFields; // destruct fields of partially constructed objects
|
||||
// https://issues.dlang.org/show_bug.cgi?id=14246
|
||||
// https://issues.dlang.org/show_bug.cgi?id=14246
|
||||
FeatureState systemVariables; // limit access to variables marked @system from @safe code
|
||||
|
||||
CHECKENABLE useInvariants; // generate class invariant checks
|
||||
CHECKENABLE useIn; // generate precondition checks
|
||||
CHECKENABLE useOut; // generate postcondition checks
|
||||
|
|
|
@ -64,6 +64,7 @@ struct HdrGenState
|
|||
int tpltMember;
|
||||
int autoMember;
|
||||
int forStmtInit;
|
||||
int insideFuncBody;
|
||||
|
||||
bool declstring; // set while declaring alias for string,wstring or dstring
|
||||
EnumDeclaration inEnumDecl;
|
||||
|
@ -1045,8 +1046,18 @@ public:
|
|||
buf.writestring(", ");
|
||||
argsToBuffer(d.args, buf, hgs);
|
||||
}
|
||||
|
||||
buf.writeByte(')');
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=14690
|
||||
// Unconditionally perform a full output dump
|
||||
// for `pragma(inline)` declarations.
|
||||
bool savedFullDump = global.params.dihdr.fullOutput;
|
||||
if (d.ident == Id.Pinline)
|
||||
global.params.dihdr.fullOutput = true;
|
||||
|
||||
visit(cast(AttribDeclaration)d);
|
||||
global.params.dihdr.fullOutput = savedFullDump;
|
||||
}
|
||||
|
||||
override void visit(ConditionalDeclaration d)
|
||||
|
@ -1549,7 +1560,7 @@ public:
|
|||
bodyToBuffer(f);
|
||||
hgs.autoMember--;
|
||||
}
|
||||
else if (hgs.tpltMember == 0 && global.params.dihdr.fullOutput == false)
|
||||
else if (hgs.tpltMember == 0 && global.params.dihdr.fullOutput == false && !hgs.insideFuncBody)
|
||||
{
|
||||
if (!f.fbody)
|
||||
{
|
||||
|
@ -1634,7 +1645,7 @@ public:
|
|||
|
||||
void bodyToBuffer(FuncDeclaration f)
|
||||
{
|
||||
if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember))
|
||||
if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember && !hgs.insideFuncBody))
|
||||
{
|
||||
if (!f.fbody && (f.fensures || f.frequires))
|
||||
{
|
||||
|
@ -1645,6 +1656,18 @@ public:
|
|||
buf.writenl();
|
||||
return;
|
||||
}
|
||||
|
||||
// there is no way to know if a function is nested
|
||||
// or not after parsing. We need scope information
|
||||
// for that, which is avaible during semantic
|
||||
// analysis. To overcome that, a simple mechanism
|
||||
// is implemented: everytime we print a function
|
||||
// body (templated or not) we increment a counter.
|
||||
// We decredement the counter when we stop
|
||||
// printing the function body.
|
||||
++hgs.insideFuncBody;
|
||||
scope(exit) { --hgs.insideFuncBody; }
|
||||
|
||||
const savetlpt = hgs.tpltMember;
|
||||
const saveauto = hgs.autoMember;
|
||||
hgs.tpltMember = 0;
|
||||
|
|
|
@ -1197,9 +1197,9 @@ class Lexer
|
|||
/*******************************************
|
||||
* Parse escape sequence.
|
||||
*/
|
||||
private uint escapeSequence()
|
||||
private uint escapeSequence(out dchar c2)
|
||||
{
|
||||
return Lexer.escapeSequence(token.loc, p, Ccompile);
|
||||
return Lexer.escapeSequence(token.loc, p, Ccompile, c2);
|
||||
}
|
||||
|
||||
/********
|
||||
|
@ -1211,10 +1211,11 @@ class Lexer
|
|||
* sequence = pointer to string with escape sequence to parse. Updated to
|
||||
* point past the end of the escape sequence
|
||||
* Ccompile = true for compile C11 escape sequences
|
||||
* c2 = returns second `dchar` of html entity with 2 code units, otherwise stays `dchar.init`
|
||||
* Returns:
|
||||
* the escape sequence as a single character
|
||||
*/
|
||||
private dchar escapeSequence(const ref Loc loc, ref const(char)* sequence, bool Ccompile)
|
||||
private dchar escapeSequence(const ref Loc loc, ref const(char)* sequence, bool Ccompile, out dchar c2)
|
||||
{
|
||||
const(char)* p = sequence; // cache sequence reference on stack
|
||||
scope(exit) sequence = p;
|
||||
|
@ -1326,12 +1327,16 @@ class Lexer
|
|||
switch (*p)
|
||||
{
|
||||
case ';':
|
||||
c = HtmlNamedEntity(idstart[0 .. p - idstart]);
|
||||
if (c == ~0)
|
||||
auto entity = HtmlNamedEntity(idstart[0 .. p - idstart]);
|
||||
c = entity[0];
|
||||
if (entity == entity.init)
|
||||
{
|
||||
error(loc, "unnamed character entity &%.*s;", cast(int)(p - idstart), idstart);
|
||||
c = '?';
|
||||
}
|
||||
if (entity[1] != entity.init[1])
|
||||
c2 = entity[1];
|
||||
|
||||
p++;
|
||||
break;
|
||||
default:
|
||||
|
@ -1665,6 +1670,7 @@ class Lexer
|
|||
while (1)
|
||||
{
|
||||
dchar c = *p++;
|
||||
dchar c2;
|
||||
switch (c)
|
||||
{
|
||||
case '\\':
|
||||
|
@ -1673,15 +1679,19 @@ class Lexer
|
|||
case '&':
|
||||
if (Ccompile)
|
||||
goto default;
|
||||
goto case;
|
||||
|
||||
c = escapeSequence(c2);
|
||||
stringbuffer.writeUTF8(c);
|
||||
if (c2 != dchar.init)
|
||||
stringbuffer.writeUTF8(c2);
|
||||
continue;
|
||||
case 'u':
|
||||
case 'U':
|
||||
c = escapeSequence();
|
||||
c = escapeSequence(c2);
|
||||
stringbuffer.writeUTF8(c);
|
||||
continue;
|
||||
default:
|
||||
c = escapeSequence();
|
||||
c = escapeSequence(c2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -1746,22 +1756,26 @@ class Lexer
|
|||
//printf("Lexer::charConstant\n");
|
||||
p++;
|
||||
dchar c = *p++;
|
||||
dchar c2;
|
||||
switch (c)
|
||||
{
|
||||
case '\\':
|
||||
switch (*p)
|
||||
{
|
||||
case 'u':
|
||||
t.unsvalue = escapeSequence();
|
||||
tk = TOK.wcharLiteral;
|
||||
break;
|
||||
goto default;
|
||||
case 'U':
|
||||
case '&':
|
||||
t.unsvalue = escapeSequence();
|
||||
tk = TOK.dcharLiteral;
|
||||
break;
|
||||
goto default;
|
||||
default:
|
||||
t.unsvalue = escapeSequence();
|
||||
t.unsvalue = escapeSequence(c2);
|
||||
if (c2 != c2.init)
|
||||
{
|
||||
error("html entity requires 2 code units, use a string instead of a character");
|
||||
t.unsvalue = '?';
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -1978,8 +1992,6 @@ class Lexer
|
|||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
if (Ccompile)
|
||||
error("binary constants not allowed");
|
||||
++p;
|
||||
base = 2;
|
||||
break;
|
||||
|
@ -3185,8 +3197,9 @@ unittest
|
|||
static void test(T)(string sequence, T expected, bool Ccompile = false)
|
||||
{
|
||||
auto p = cast(const(char)*)sequence.ptr;
|
||||
dchar c2;
|
||||
Lexer lexer = new Lexer();
|
||||
assert(expected == lexer.escapeSequence(Loc.initial, p, Ccompile));
|
||||
assert(expected == lexer.escapeSequence(Loc.initial, p, Ccompile, c2));
|
||||
assert(p == sequence.ptr + sequence.length);
|
||||
}
|
||||
|
||||
|
@ -3253,7 +3266,8 @@ unittest
|
|||
expected = expectedError;
|
||||
auto p = cast(const(char)*)sequence.ptr;
|
||||
Lexer lexer = new Lexer();
|
||||
auto actualReturnValue = lexer.escapeSequence(Loc.initial, p, Ccompile);
|
||||
dchar c2;
|
||||
auto actualReturnValue = lexer.escapeSequence(Loc.initial, p, Ccompile, c2);
|
||||
assert(gotError);
|
||||
assert(expectedReturnValue == actualReturnValue);
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ public:
|
|||
size_t namelen; // length of module name in characters
|
||||
|
||||
static Module* create(const char *arg, Identifier *ident, int doDocComment, int doHdrGen);
|
||||
|
||||
static const char *find(const char *filename);
|
||||
static Module *load(const Loc &loc, Identifiers *packages, Identifier *ident);
|
||||
|
||||
const char *kind() const override;
|
||||
|
|
|
@ -2488,6 +2488,16 @@ extern (C++) abstract class Type : ASTNode
|
|||
return false;
|
||||
}
|
||||
|
||||
/*************************************
|
||||
* Detect if this is an unsafe type because of the presence of `@system` members
|
||||
* Returns:
|
||||
* true if so
|
||||
*/
|
||||
bool hasSystemFields()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Returns: true if type has any invariants
|
||||
*/
|
||||
|
@ -3821,6 +3831,16 @@ extern (C++) final class TypeSArray : TypeArray
|
|||
return next.hasPointers();
|
||||
}
|
||||
|
||||
override bool hasSystemFields()
|
||||
{
|
||||
return next.hasSystemFields();
|
||||
}
|
||||
|
||||
override bool hasVoidInitPointers()
|
||||
{
|
||||
return next.hasVoidInitPointers();
|
||||
}
|
||||
|
||||
override bool hasInvariant()
|
||||
{
|
||||
return next.hasInvariant();
|
||||
|
@ -5532,52 +5552,32 @@ extern (C++) final class TypeStruct : Type
|
|||
|
||||
override bool hasPointers()
|
||||
{
|
||||
// Probably should cache this information in sym rather than recompute
|
||||
StructDeclaration s = sym;
|
||||
|
||||
if (sym.members && !sym.determineFields() && sym.type != Type.terror)
|
||||
error(sym.loc, "no size because of forward references");
|
||||
|
||||
foreach (VarDeclaration v; s.fields)
|
||||
{
|
||||
if (v.storage_class & STC.ref_ || v.hasPointers())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
sym.determineTypeProperties();
|
||||
return sym.hasPointerField;
|
||||
}
|
||||
|
||||
override bool hasVoidInitPointers()
|
||||
{
|
||||
// Probably should cache this information in sym rather than recompute
|
||||
StructDeclaration s = sym;
|
||||
|
||||
sym.size(Loc.initial); // give error for forward references
|
||||
foreach (VarDeclaration v; s.fields)
|
||||
{
|
||||
if (v._init && v._init.isVoidInitializer() && v.type.hasPointers())
|
||||
return true;
|
||||
if (!v._init && v.type.hasVoidInitPointers())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
sym.determineTypeProperties();
|
||||
return sym.hasVoidInitPointers;
|
||||
}
|
||||
|
||||
override bool hasSystemFields()
|
||||
{
|
||||
sym.size(Loc.initial); // give error for forward references
|
||||
sym.determineTypeProperties();
|
||||
return sym.hasSystemFields;
|
||||
}
|
||||
|
||||
override bool hasInvariant()
|
||||
{
|
||||
// Probably should cache this information in sym rather than recompute
|
||||
StructDeclaration s = sym;
|
||||
|
||||
sym.size(Loc.initial); // give error for forward references
|
||||
|
||||
if (s.hasInvariant())
|
||||
return true;
|
||||
|
||||
foreach (VarDeclaration v; s.fields)
|
||||
{
|
||||
if (v.type.hasInvariant())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
sym.determineTypeProperties();
|
||||
return sym.hasInvariant() || sym.hasFieldWithInvariant;
|
||||
}
|
||||
|
||||
extern (D) MATCH implicitConvToWithoutAliasThis(Type to)
|
||||
|
@ -5857,6 +5857,11 @@ extern (C++) final class TypeEnum : Type
|
|||
return memType().hasVoidInitPointers();
|
||||
}
|
||||
|
||||
override bool hasSystemFields()
|
||||
{
|
||||
return memType().hasSystemFields();
|
||||
}
|
||||
|
||||
override bool hasInvariant()
|
||||
{
|
||||
return memType().hasInvariant();
|
||||
|
|
|
@ -311,6 +311,7 @@ public:
|
|||
virtual int hasWild() const;
|
||||
virtual bool hasPointers();
|
||||
virtual bool hasVoidInitPointers();
|
||||
virtual bool hasSystemFields();
|
||||
virtual bool hasInvariant();
|
||||
virtual Type *nextOf();
|
||||
Type *baseElemOf();
|
||||
|
@ -458,6 +459,8 @@ public:
|
|||
MATCH implicitConvTo(Type *to) override;
|
||||
Expression *defaultInitLiteral(const Loc &loc) override;
|
||||
bool hasPointers() override;
|
||||
bool hasSystemFields() override;
|
||||
bool hasVoidInitPointers() override;
|
||||
bool hasInvariant() override;
|
||||
bool needsDestruction() override;
|
||||
bool needsCopyOrPostblit() override;
|
||||
|
@ -794,6 +797,7 @@ public:
|
|||
bool needsNested() override;
|
||||
bool hasPointers() override;
|
||||
bool hasVoidInitPointers() override;
|
||||
bool hasSystemFields() override;
|
||||
bool hasInvariant() override;
|
||||
MATCH implicitConvTo(Type *to) override;
|
||||
MATCH constConv(Type *to) override;
|
||||
|
@ -832,6 +836,7 @@ public:
|
|||
bool isZeroInit(const Loc &loc) override;
|
||||
bool hasPointers() override;
|
||||
bool hasVoidInitPointers() override;
|
||||
bool hasSystemFields() override;
|
||||
bool hasInvariant() override;
|
||||
Type *nextOf() override;
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
|
||||
override void visit(ArrayLiteralExp e)
|
||||
{
|
||||
if (e.type.ty != Tarray || !e.elements || !e.elements.dim)
|
||||
if (e.type.ty != Tarray || !e.elements || !e.elements.dim || e.onstack)
|
||||
return;
|
||||
if (f.setGC())
|
||||
{
|
||||
|
@ -221,7 +221,7 @@ Expression checkGC(Scope* sc, Expression e)
|
|||
FuncDeclaration f = sc.func;
|
||||
if (e && e.op != EXP.error && f && sc.intypeof != 1 && !(sc.flags & SCOPE.ctfe) &&
|
||||
(f.type.ty == Tfunction &&
|
||||
(cast(TypeFunction)f.type).isnogc || (f.flags & FUNCFLAG.nogcInprocess) || global.params.vgc) &&
|
||||
(cast(TypeFunction)f.type).isnogc || f.nogcInprocess || global.params.vgc) &&
|
||||
!(sc.flags & SCOPE.debug_))
|
||||
{
|
||||
scope NOGCVisitor gcv = new NOGCVisitor(f);
|
||||
|
|
|
@ -888,6 +888,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
error("redundant visibility attribute `%s`", AST.visibilityToChars(prot));
|
||||
}
|
||||
pAttrs.visibility.kind = prot;
|
||||
const attrloc = token.loc;
|
||||
|
||||
nextToken();
|
||||
|
||||
|
@ -908,7 +909,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
}
|
||||
}
|
||||
|
||||
const attrloc = token.loc;
|
||||
a = parseBlock(pLastDecl, pAttrs);
|
||||
if (pAttrs.visibility.kind != AST.Visibility.Kind.undefined)
|
||||
{
|
||||
|
@ -3168,9 +3168,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
|
|||
|
||||
if (udas)
|
||||
{
|
||||
auto s = new AST.Dsymbols();
|
||||
s.push(em);
|
||||
auto uad = new AST.UserAttributeDeclaration(udas, s);
|
||||
auto uad = new AST.UserAttributeDeclaration(udas, new AST.Dsymbols());
|
||||
em.userAttribDecl = uad;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,6 +203,13 @@ extern (C++) final class PrintASTVisitor : Visitor
|
|||
printf(".func: %s\n", e.func ? e.func.toChars() : "");
|
||||
}
|
||||
|
||||
override void visit(CompoundLiteralExp e)
|
||||
{
|
||||
visit(cast(Expression)e);
|
||||
printIndent(indent + 2);
|
||||
printf(".init: %s\n", e.initializer ? e.initializer.toChars() : "");
|
||||
}
|
||||
|
||||
static void printIndent(int indent)
|
||||
{
|
||||
foreach (i; 0 .. indent)
|
||||
|
|
|
@ -288,7 +288,7 @@ bool isUniAlpha(dchar c)
|
|||
// Binary search
|
||||
while (low <= high)
|
||||
{
|
||||
size_t mid = (low + high) >> 1;
|
||||
const size_t mid = low + ((high - low) >> 1);
|
||||
if (c < ALPHA_TABLE[mid][0])
|
||||
high = mid - 1;
|
||||
else if (ALPHA_TABLE[mid][1] < c)
|
||||
|
|
|
@ -26,7 +26,7 @@ import dmd.identifier;
|
|||
import dmd.mtype;
|
||||
import dmd.target;
|
||||
import dmd.tokens;
|
||||
import dmd.func : setUnsafe;
|
||||
import dmd.func : setUnsafe, setUnsafePreview;
|
||||
|
||||
/*************************************************************
|
||||
* Check for unsafe access in @safe code:
|
||||
|
@ -57,6 +57,14 @@ bool checkUnsafeAccess(Scope* sc, Expression e, bool readonly, bool printmsg)
|
|||
if (!ad)
|
||||
return false;
|
||||
|
||||
import dmd.globals : global;
|
||||
if (v.isSystem())
|
||||
{
|
||||
if (sc.setUnsafePreview(global.params.systemVariables, !printmsg, e.loc,
|
||||
"cannot access `@system` field `%s.%s` in `@safe` code", ad, v))
|
||||
return true;
|
||||
}
|
||||
|
||||
// needed to set v.overlapped and v.overlapUnsafe
|
||||
if (ad.sizeok != Sizeok.done)
|
||||
ad.determineSize(ad.loc);
|
||||
|
|
|
@ -282,7 +282,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
// Disable generated opAssign, because some members forbid identity assignment.
|
||||
funcdecl.storage_class |= STC.disable;
|
||||
funcdecl.fbody = null; // remove fbody which contains the error
|
||||
funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
|
||||
funcdecl.hasSemantic3Errors = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
if (funcdecl.semanticRun >= PASS.semantic3)
|
||||
return;
|
||||
funcdecl.semanticRun = PASS.semantic3;
|
||||
funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
|
||||
funcdecl.hasSemantic3Errors = false;
|
||||
|
||||
if (!funcdecl.type || funcdecl.type.ty != Tfunction)
|
||||
return;
|
||||
|
@ -650,7 +650,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
|
||||
// handle NRVO
|
||||
if (!target.isReturnOnStack(f, funcdecl.needThis()) || !funcdecl.checkNRVO())
|
||||
funcdecl.flags &= ~FUNCFLAG.NRVO;
|
||||
funcdecl.isNRVO = false;
|
||||
|
||||
if (funcdecl.fbody.isErrorStatement())
|
||||
{
|
||||
|
@ -753,15 +753,15 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
if (f.isnothrow && blockexit & BE.throw_)
|
||||
error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
|
||||
|
||||
if (!(blockexit & (BE.throw_ | BE.halt) || funcdecl.flags & FUNCFLAG.hasCatches))
|
||||
if (!(blockexit & (BE.throw_ | BE.halt) || funcdecl.hasCatches))
|
||||
{
|
||||
/* Don't generate unwind tables for this function
|
||||
* https://issues.dlang.org/show_bug.cgi?id=17997
|
||||
*/
|
||||
funcdecl.flags |= FUNCFLAG.noEH;
|
||||
funcdecl.hasNoEH = true;
|
||||
}
|
||||
|
||||
if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
|
||||
if (funcdecl.nothrowInprocess)
|
||||
{
|
||||
if (funcdecl.type == f)
|
||||
f = cast(TypeFunction)f.copy();
|
||||
|
@ -976,7 +976,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
/* Do the semantic analysis on the [in] preconditions and
|
||||
* [out] postconditions.
|
||||
*/
|
||||
immutable bool isnothrow = f.isnothrow && !(funcdecl.flags & FUNCFLAG.nothrowInprocess);
|
||||
immutable bool isnothrow = f.isnothrow && !funcdecl.nothrowInprocess;
|
||||
if (freq)
|
||||
{
|
||||
/* frequire is composed of the [in] contracts
|
||||
|
@ -1001,11 +1001,11 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
// Deprecated in 2.101, can be made an error in 2.111
|
||||
deprecation(funcdecl.loc, "`%s`: `in` contract may throw but function is marked as `nothrow`",
|
||||
funcdecl.toPrettyChars());
|
||||
else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
|
||||
else if (funcdecl.nothrowInprocess)
|
||||
f.isnothrow = false;
|
||||
}
|
||||
|
||||
funcdecl.flags &= ~FUNCFLAG.noEH;
|
||||
funcdecl.hasNoEH = false;
|
||||
|
||||
sc2 = sc2.pop();
|
||||
|
||||
|
@ -1048,11 +1048,11 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
// Deprecated in 2.101, can be made an error in 2.111
|
||||
deprecation(funcdecl.loc, "`%s`: `out` contract may throw but function is marked as `nothrow`",
|
||||
funcdecl.toPrettyChars());
|
||||
else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
|
||||
else if (funcdecl.nothrowInprocess)
|
||||
f.isnothrow = false;
|
||||
}
|
||||
|
||||
funcdecl.flags &= ~FUNCFLAG.noEH;
|
||||
funcdecl.hasNoEH = false;
|
||||
|
||||
sc2 = sc2.pop();
|
||||
|
||||
|
@ -1180,10 +1180,10 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
const blockexit = s.blockExit(funcdecl, isnothrow);
|
||||
if (blockexit & BE.throw_)
|
||||
{
|
||||
funcdecl.flags &= ~FUNCFLAG.noEH;
|
||||
funcdecl.hasNoEH = false;
|
||||
if (isnothrow)
|
||||
error(funcdecl.loc, "%s `%s` may throw but is marked as `nothrow`", funcdecl.kind(), funcdecl.toPrettyChars());
|
||||
else if (funcdecl.flags & FUNCFLAG.nothrowInprocess)
|
||||
else if (funcdecl.nothrowInprocess)
|
||||
f.isnothrow = false;
|
||||
}
|
||||
|
||||
|
@ -1195,7 +1195,7 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
}
|
||||
}
|
||||
// from this point on all possible 'throwers' are checked
|
||||
funcdecl.flags &= ~FUNCFLAG.nothrowInprocess;
|
||||
funcdecl.nothrowInprocess = false;
|
||||
|
||||
if (funcdecl.isSynchronized())
|
||||
{
|
||||
|
@ -1274,25 +1274,25 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
|
||||
/* If function survived being marked as impure, then it is pure
|
||||
*/
|
||||
if (funcdecl.flags & FUNCFLAG.purityInprocess)
|
||||
if (funcdecl.purityInprocess)
|
||||
{
|
||||
funcdecl.flags &= ~FUNCFLAG.purityInprocess;
|
||||
funcdecl.purityInprocess = false;
|
||||
if (funcdecl.type == f)
|
||||
f = cast(TypeFunction)f.copy();
|
||||
f.purity = PURE.fwdref;
|
||||
}
|
||||
|
||||
if (funcdecl.flags & FUNCFLAG.safetyInprocess)
|
||||
if (funcdecl.safetyInprocess)
|
||||
{
|
||||
funcdecl.flags &= ~FUNCFLAG.safetyInprocess;
|
||||
funcdecl.safetyInprocess = false;
|
||||
if (funcdecl.type == f)
|
||||
f = cast(TypeFunction)f.copy();
|
||||
f.trust = TRUST.safe;
|
||||
}
|
||||
|
||||
if (funcdecl.flags & FUNCFLAG.nogcInprocess)
|
||||
if (funcdecl.nogcInprocess)
|
||||
{
|
||||
funcdecl.flags &= ~FUNCFLAG.nogcInprocess;
|
||||
funcdecl.nogcInprocess = false;
|
||||
if (funcdecl.type == f)
|
||||
f = cast(TypeFunction)f.copy();
|
||||
f.isnogc = true;
|
||||
|
@ -1395,9 +1395,9 @@ private extern(C++) final class Semantic3Visitor : Visitor
|
|||
*/
|
||||
funcdecl.semanticRun = PASS.semantic3done;
|
||||
if ((global.errors != oldErrors) || (funcdecl.fbody && funcdecl.fbody.isErrorStatement()))
|
||||
funcdecl.flags |= FUNCFLAG.semantic3Errors;
|
||||
funcdecl.hasSemantic3Errors = true;
|
||||
else
|
||||
funcdecl.flags &= ~FUNCFLAG.semantic3Errors;
|
||||
funcdecl.hasSemantic3Errors = false;
|
||||
if (funcdecl.type.ty == Terror)
|
||||
funcdecl.errors = true;
|
||||
//printf("-FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", funcdecl.parent.toChars(), funcdecl.toChars(), sc, funcdecl.loc.toChars());
|
||||
|
|
|
@ -2010,32 +2010,8 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
//printf("body = %p\n", ps._body);
|
||||
if (ps.ident == Id.msg)
|
||||
{
|
||||
if (ps.args)
|
||||
{
|
||||
foreach (arg; *ps.args)
|
||||
{
|
||||
sc = sc.startCTFE();
|
||||
auto e = arg.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
|
||||
// pragma(msg) is allowed to contain types as well as expressions
|
||||
e = ctfeInterpretForPragmaMsg(e);
|
||||
if (e.op == EXP.error)
|
||||
{
|
||||
errorSupplemental(ps.loc, "while evaluating `pragma(msg, %s)`", arg.toChars());
|
||||
return setError();
|
||||
}
|
||||
if (auto se = e.toStringExp())
|
||||
{
|
||||
const slice = se.toUTF8(sc).peekString();
|
||||
fprintf(stderr, "%.*s", cast(int)slice.length, slice.ptr);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s", e.toChars());
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
if (!pragmaMsgSemantic(ps.loc, sc, ps.args))
|
||||
return setError();
|
||||
}
|
||||
else if (ps.ident == Id.lib)
|
||||
{
|
||||
|
@ -2075,75 +2051,19 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
}
|
||||
else if (ps.ident == Id.startaddress)
|
||||
{
|
||||
if (!ps.args || ps.args.dim != 1)
|
||||
ps.error("function name expected for start address");
|
||||
else
|
||||
{
|
||||
Expression e = (*ps.args)[0];
|
||||
sc = sc.startCTFE();
|
||||
e = e.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
|
||||
e = e.ctfeInterpret();
|
||||
(*ps.args)[0] = e;
|
||||
Dsymbol sa = getDsymbol(e);
|
||||
if (!sa || !sa.isFuncDeclaration())
|
||||
{
|
||||
ps.error("function name expected for start address, not `%s`", e.toChars());
|
||||
return setError();
|
||||
}
|
||||
if (ps._body)
|
||||
{
|
||||
ps._body = ps._body.statementSemantic(sc);
|
||||
if (ps._body.isErrorStatement())
|
||||
{
|
||||
result = ps._body;
|
||||
return;
|
||||
}
|
||||
}
|
||||
result = ps;
|
||||
return;
|
||||
}
|
||||
if (!pragmaStartAddressSemantic(ps.loc, sc, ps.args))
|
||||
return setError();
|
||||
}
|
||||
else if (ps.ident == Id.Pinline)
|
||||
{
|
||||
PINLINE inlining = PINLINE.default_;
|
||||
if (!ps.args || ps.args.dim == 0)
|
||||
inlining = PINLINE.default_;
|
||||
else if (!ps.args || ps.args.dim != 1)
|
||||
if (auto fd = sc.func)
|
||||
{
|
||||
ps.error("boolean expression expected for `pragma(inline)`");
|
||||
return setError();
|
||||
fd.inlining = evalPragmaInline(ps.loc, sc, ps.args);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expression e = (*ps.args)[0];
|
||||
sc = sc.startCTFE();
|
||||
e = e.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
e = e.ctfeInterpret();
|
||||
e = e.toBoolean(sc);
|
||||
if (e.isErrorExp())
|
||||
{
|
||||
ps.error("pragma(`inline`, `true` or `false`) expected, not `%s`", (*ps.args)[0].toChars());
|
||||
return setError();
|
||||
}
|
||||
|
||||
const opt = e.toBool();
|
||||
if (opt.hasValue(true))
|
||||
inlining = PINLINE.always;
|
||||
else if (opt.hasValue(false))
|
||||
inlining = PINLINE.never;
|
||||
|
||||
FuncDeclaration fd = sc.func;
|
||||
if (!fd)
|
||||
{
|
||||
ps.error("`pragma(inline)` is not inside a function");
|
||||
return setError();
|
||||
}
|
||||
fd.inlining = inlining;
|
||||
ps.error("`pragma(inline)` is not inside a function");
|
||||
return setError();
|
||||
}
|
||||
}
|
||||
else if (!global.params.ignoreUnsupportedPragmas)
|
||||
|
@ -2932,13 +2852,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23063
|
||||
if (texp.isTypeNoreturn() && !rs.exp.isAssertExp() && !rs.exp.isThrowExp() && !rs.exp.isCallExp())
|
||||
{
|
||||
auto msg = new StringExp(rs.exp.loc, "Accessed expression of type `noreturn`");
|
||||
msg.type = Type.tstring;
|
||||
rs.exp = new AssertExp(rs.loc, IntegerExp.literal!0, msg);
|
||||
rs.exp.type = texp;
|
||||
}
|
||||
rs.exp = checkNoreturnVarAccess(rs.exp);
|
||||
|
||||
// @@@DEPRECATED_2.111@@@
|
||||
const olderrors = global.startGagging();
|
||||
|
@ -3022,7 +2936,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
|
||||
// If we previously assumed the function could be ref when
|
||||
// checking for `shared`, make sure we were right
|
||||
if (global.params.noSharedAccess && rs.exp.type.isShared())
|
||||
if (global.params.noSharedAccess == FeatureState.enabled && rs.exp.type.isShared())
|
||||
{
|
||||
fd.error("function returns `shared` but cannot be inferred `ref`");
|
||||
supplemental();
|
||||
|
@ -3648,7 +3562,7 @@ package (dmd) extern (C++) final class StatementSemanticVisitor : Visitor
|
|||
|
||||
if (sc.func)
|
||||
{
|
||||
sc.func.flags |= FUNCFLAG.hasCatches;
|
||||
sc.func.hasCatches = true;
|
||||
if (flags == (FLAGcpp | FLAGd))
|
||||
{
|
||||
tcs.error("cannot mix catching D and C++ exceptions in the same try-catch");
|
||||
|
@ -4925,3 +4839,83 @@ private void debugThrowWalker(Statement s)
|
|||
scope walker = new DebugWalker();
|
||||
s.accept(walker);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Evaluate and print a `pragma(msg, args)`
|
||||
*
|
||||
* Params:
|
||||
* loc = location for error messages
|
||||
* sc = scope for argument interpretation
|
||||
* args = expressions to print
|
||||
* Returns:
|
||||
* `true` on success
|
||||
*/
|
||||
bool pragmaMsgSemantic(Loc loc, Scope* sc, Expressions* args)
|
||||
{
|
||||
if (!args)
|
||||
return true;
|
||||
foreach (arg; *args)
|
||||
{
|
||||
sc = sc.startCTFE();
|
||||
auto e = arg.expressionSemantic(sc);
|
||||
e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
|
||||
// pragma(msg) is allowed to contain types as well as expressions
|
||||
e = ctfeInterpretForPragmaMsg(e);
|
||||
if (e.op == EXP.error)
|
||||
{
|
||||
errorSupplemental(loc, "while evaluating `pragma(msg, %s)`", arg.toChars());
|
||||
return false;
|
||||
}
|
||||
if (auto se = e.toStringExp())
|
||||
{
|
||||
const slice = se.toUTF8(sc).peekString();
|
||||
fprintf(stderr, "%.*s", cast(int)slice.length, slice.ptr);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s", e.toChars());
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Evaluate `pragma(startAddress, func)` and store the resolved symbol in `args`
|
||||
*
|
||||
* Params:
|
||||
* loc = location for error messages
|
||||
* sc = scope for argument interpretation
|
||||
* args = pragma arguments
|
||||
* Returns:
|
||||
* `true` on success
|
||||
*/
|
||||
bool pragmaStartAddressSemantic(Loc loc, Scope* sc, Expressions* args)
|
||||
{
|
||||
if (!args || args.dim != 1)
|
||||
{
|
||||
.error(loc, "function name expected for start address");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* https://issues.dlang.org/show_bug.cgi?id=11980
|
||||
* resolveProperties and ctfeInterpret call are not necessary.
|
||||
*/
|
||||
Expression e = (*args)[0];
|
||||
sc = sc.startCTFE();
|
||||
e = e.expressionSemantic(sc);
|
||||
// e = resolveProperties(sc, e);
|
||||
sc = sc.endCTFE();
|
||||
|
||||
// e = e.ctfeInterpret();
|
||||
(*args)[0] = e;
|
||||
Dsymbol sa = getDsymbol(e);
|
||||
if (!sa || !sa.isFuncDeclaration())
|
||||
{
|
||||
.error(loc, "function name expected for start address, not `%s`", e.toChars());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -73,6 +73,15 @@ private extern (C++) final class TemplateParameterSemanticVisitor : Visitor
|
|||
result = !(ttp.specType && isError(ttp.specType));
|
||||
}
|
||||
|
||||
override void visit(TemplateThisParameter ttp)
|
||||
{
|
||||
import dmd.errors;
|
||||
|
||||
if (!sc.getStructClassScope())
|
||||
error(ttp.loc, "cannot use `this` outside an aggregate type");
|
||||
visit(cast(TemplateTypeParameter)ttp);
|
||||
}
|
||||
|
||||
override void visit(TemplateValueParameter tvp)
|
||||
{
|
||||
tvp.valType = tvp.valType.typeSemantic(tvp.loc, sc);
|
||||
|
|
|
@ -799,6 +799,15 @@ package mixin template ParseVisitMethods(AST)
|
|||
s.accept(this);
|
||||
}
|
||||
|
||||
override void visit(AST.InterfaceDeclaration d)
|
||||
{
|
||||
//printf("Visiting InterfaceDeclaration\n");
|
||||
visitBaseClasses(d);
|
||||
if (d.members)
|
||||
foreach (s; *d.members)
|
||||
s.accept(this);
|
||||
}
|
||||
|
||||
override void visit(AST.AliasDeclaration d)
|
||||
{
|
||||
//printf("Visting AliasDeclaration\n");
|
||||
|
|
|
@ -1099,6 +1099,7 @@ public:
|
|||
this assignment should call dtors on old assigned elements. */
|
||||
if ((!postblit && !destructor)
|
||||
|| (e->op == EXP::construct && e->e2->op == EXP::arrayLiteral)
|
||||
|| (e->op == EXP::construct && e->e2->op == EXP::call)
|
||||
|| (e->op == EXP::construct && !lvalue && postblit)
|
||||
|| (e->op == EXP::blit || e->e1->type->size () == 0))
|
||||
{
|
||||
|
@ -2704,6 +2705,14 @@ public:
|
|||
|
||||
this->result_ = compound_expr (saved_elems, d_convert (type, ctor));
|
||||
}
|
||||
else if (e->onstack)
|
||||
{
|
||||
/* Array literal for a `scope' dynamic array. */
|
||||
gcc_assert (tb->ty == TY::Tarray);
|
||||
ctor = force_target_expr (ctor);
|
||||
this->result_ = d_array_value (type, size_int (e->elements->length),
|
||||
build_address (ctor));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate space on the memory managed heap. */
|
||||
|
|
|
@ -344,6 +344,9 @@ Turns on generation of struct equality to use field-wise comparisons.
|
|||
@item fixaliasthis
|
||||
Implements new lookup rules that check the current scope for @code{alias this}
|
||||
before searching in upper scopes.
|
||||
@item fiximmutableconv
|
||||
Disallows unsound immutable conversions that were formerly incorrectly
|
||||
permitted.
|
||||
@item in
|
||||
Implements @code{in} parameters to mean @code{scope const [ref]} and accepts
|
||||
rvalues.
|
||||
|
@ -357,9 +360,8 @@ expressions.
|
|||
Turns off and disallows all access to shared memory objects.
|
||||
@item rvaluerefparam
|
||||
Implements rvalue arguments to @code{ref} parameters.
|
||||
@item shortenedmethods
|
||||
Implements use of @code{=>} for methods and top-level functions in addition to
|
||||
lambdas.
|
||||
@item systemvariables
|
||||
Disables access to variables marked @code{@@system} from @code{@@safe} code.
|
||||
@end table
|
||||
|
||||
@item -frelease
|
||||
|
|
|
@ -396,9 +396,9 @@ fpreview=rvaluerefparam
|
|||
D RejectNegative
|
||||
Enable rvalue arguments to ref parameters.
|
||||
|
||||
fpreview=shortenedmethods
|
||||
fpreview=systemvariables
|
||||
D RejectNegative
|
||||
Allow use of '=>' for methods and top-level functions in addition to lambdas.
|
||||
Disable access to variables marked `@system' from @safe code.
|
||||
|
||||
frelease
|
||||
D
|
||||
|
|
11
gcc/testsuite/gdc.dg/simd18867.d
Normal file
11
gcc/testsuite/gdc.dg/simd18867.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=18867
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
import core.simd;
|
||||
|
||||
ulong2 test18867(ulong s)
|
||||
{
|
||||
ulong2 v;
|
||||
v[0] = s;
|
||||
return v;
|
||||
}
|
|
@ -3,19 +3,13 @@
|
|||
// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
import core.simd;
|
||||
|
||||
enum fail19630a = int4.init[1..2];
|
||||
enum fail19630b = int4.init.array[1..2];
|
||||
enum fail19630c = (cast(int[4])int4.init.array)[1..2];
|
||||
enum fail19630d = (cast(int[4])int4.init)[1..2];
|
||||
enum fail19630e = int4(0)[1..2];
|
||||
enum fail19630f = int4(0).array[1..2];
|
||||
enum fail19630g = (cast(int[4])int4(0).array)[1..2];
|
||||
enum fail19630h = (cast(int[4])int4(0))[1..2];
|
||||
|
||||
enum int4 v19630a = int4.init;
|
||||
enum slice19630a = v19630a[1..2];
|
||||
static assert(slice19630a == [0]);
|
||||
|
||||
enum int[4] v19630b = int4.init.array;
|
||||
enum slice19630b = v19630b[1..2];
|
||||
static assert(slice19630b == [0]);
|
||||
|
@ -28,10 +22,6 @@ enum int[4] v19630d = cast(int[4])int4.init;
|
|||
enum slice19630d = v19630d[1..2];
|
||||
static assert(slice19630d == [0]);
|
||||
|
||||
enum int4 v19630e = int4(0);
|
||||
enum slice19630e = v19630e[1..2];
|
||||
static assert(slice19630e == [0]);
|
||||
|
||||
enum int[4] v19630f = int4(0).array;
|
||||
enum slice19630f = v19630f[1..2];
|
||||
static assert(slice19630f == [0]);
|
||||
|
|
17
gcc/testsuite/gdc.dg/simd19630b.d
Normal file
17
gcc/testsuite/gdc.dg/simd19630b.d
Normal file
|
@ -0,0 +1,17 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=19630
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
import core.simd;
|
||||
|
||||
enum fail19630a = int4.init[1..2];
|
||||
// { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 }
|
||||
enum fail19630e = int4(0)[1..2];
|
||||
// { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 }
|
||||
|
||||
enum int4 v19630a = int4.init;
|
||||
enum slice19630a = v19630a[1..2];
|
||||
// { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 }
|
||||
|
||||
enum int4 v19630e = int4(0);
|
||||
enum slice19630e = v19630e[1..2];
|
||||
// { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 }
|
15
gcc/testsuite/gdc.dg/simd19630c.d
Normal file
15
gcc/testsuite/gdc.dg/simd19630c.d
Normal file
|
@ -0,0 +1,15 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=19630
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
import core.simd;
|
||||
|
||||
int4 testz19630()
|
||||
{
|
||||
return [0,0,0,0];
|
||||
}
|
||||
|
||||
void test19630()
|
||||
{
|
||||
assert(testz19630()[] == [0,0,0,0]);
|
||||
// { dg-error "'__vector\\\(int\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 }
|
||||
}
|
11
gcc/testsuite/gdc.dg/simd19788.d
Normal file
11
gcc/testsuite/gdc.dg/simd19788.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=19788
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
|
||||
void test19788()
|
||||
{
|
||||
enum v = __vector(float[4]).init;
|
||||
const(float)[] a = v[];
|
||||
// { dg-error "'__vector\\\(float\\\[4\\\]\\\)' cannot be sliced with '\\\[\\\]'" "" { target *-*-* } .-1 }
|
||||
}
|
9
gcc/testsuite/gdc.dg/simd21469.d
Normal file
9
gcc/testsuite/gdc.dg/simd21469.d
Normal file
|
@ -0,0 +1,9 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=18867
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
import core.simd;
|
||||
|
||||
int4 test21469(short a)
|
||||
{
|
||||
return cast(int4)(short8(a));
|
||||
}
|
17
gcc/testsuite/gdc.dg/simd21672.d
Normal file
17
gcc/testsuite/gdc.dg/simd21672.d
Normal file
|
@ -0,0 +1,17 @@
|
|||
// https://bugzilla.gdcproject.org/show_bug.cgi?id=213
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
|
||||
import core.simd;
|
||||
|
||||
struct S213
|
||||
{
|
||||
int4 vec;
|
||||
}
|
||||
|
||||
void test213()
|
||||
{
|
||||
S213 s, b;
|
||||
|
||||
assert(s == b);
|
||||
}
|
11
gcc/testsuite/gdc.dg/simd23077.d
Normal file
11
gcc/testsuite/gdc.dg/simd23077.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23077
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
|
||||
float test23077(float x)
|
||||
{
|
||||
short i = *cast(short*)&x;
|
||||
++i;
|
||||
return *cast(float*)&i; // this cast is not allowed in @safe code
|
||||
}
|
17
gcc/testsuite/gdc.dg/simd23084.d
Normal file
17
gcc/testsuite/gdc.dg/simd23084.d
Normal file
|
@ -0,0 +1,17 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23084
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
import core.simd;
|
||||
|
||||
__vector(int[4]) test23084a(__vector(int[4]) a)
|
||||
{
|
||||
__vector(short[8]) r = cast(short)(a.array[0]);
|
||||
return cast(__vector(int[4]))r;
|
||||
}
|
||||
|
||||
__vector(int[4]) test23084b(__vector(int[4]) a)
|
||||
{
|
||||
__vector(byte[16]) r = cast(byte)(a.array[0]);
|
||||
return cast(__vector(int[4]))r;
|
||||
}
|
11
gcc/testsuite/gdc.dg/simd23085.d
Normal file
11
gcc/testsuite/gdc.dg/simd23085.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23085
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
|
||||
float test23085(float x)
|
||||
{
|
||||
byte i = *cast(byte*)&x;
|
||||
++i;
|
||||
return *cast(float*)&i; // this cast is not allowed in @safe code
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
import core.simd;
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19627
|
||||
enum int[4] fail19627 = cast(int[4])int4(0);
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19628
|
||||
enum ice19628a = int4.init[0];
|
||||
enum ice19628b = int4.init.array[0];
|
||||
enum ice19628c = (cast(int[4])int4.init.array)[0];
|
||||
enum ice19628d = (cast(int[4])int4.init)[0];
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19629
|
||||
enum fail19629a = int4(0)[0];
|
||||
enum fail19629b = int4(0).array[0];
|
||||
enum fail19629c = (cast(int[4])int4(0).array)[0];
|
||||
enum fail19628d = (cast(int[4])int4(0))[0];
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=19630
|
||||
enum fail19630a = int4.init[1..2];
|
||||
enum fail19630b = int4.init.array[1..2];
|
||||
enum fail19630c = (cast(int[4])int4.init.array)[1..2];
|
||||
enum fail19630d = int4(0)[1..2];
|
||||
enum fail19630e = int4(0).array[1..2];
|
||||
enum fail19630f = (cast(int[4])int4(0).array)[1..2];
|
||||
enum fail19630g = (cast(int[4])int4.init)[1..2];
|
||||
enum fail19630h = (cast(int[4])int4(0))[1..2];
|
||||
|
||||
// Same tests as above, but use access via enum.
|
||||
enum int4 V1 = int4.init;
|
||||
enum int[4] V2 = int4.init.array;
|
||||
enum int[4] V3 = cast(int[4])int4.init;
|
||||
enum int[4] V4 = cast(int[4])int4.init.array;
|
||||
enum int4 V5 = int4(0);
|
||||
enum int[4] V6 = int4(0).array;
|
||||
enum int[4] V7 = cast(int[4])int4(0);
|
||||
enum int[4] V8 = cast(int[4])int4(0).array;
|
||||
|
||||
// CTFE index tests
|
||||
enum I1 = V1[0]; static assert(I1 == 0);
|
||||
enum I2 = V2[0]; static assert(I2 == 0);
|
||||
enum I3 = V3[0]; static assert(I3 == 0);
|
||||
enum I4 = V4[0]; static assert(I4 == 0);
|
||||
enum I5 = V5[0]; static assert(I5 == 0);
|
||||
enum I6 = V6[0]; static assert(I6 == 0);
|
||||
enum I7 = V7[0]; static assert(I7 == 0);
|
||||
enum I8 = V8[0]; static assert(I8 == 0);
|
||||
|
||||
// CTFE slice tests
|
||||
enum S1 = V1[1..2]; static assert(S1 == [0]);
|
||||
enum S2 = V2[1..2]; static assert(S2 == [0]);
|
||||
enum S3 = V3[1..2]; static assert(S3 == [0]);
|
||||
enum S4 = V4[1..2]; static assert(S4 == [0]);
|
||||
enum S5 = V5[1..2]; static assert(S5 == [0]);
|
||||
enum S6 = V6[1..2]; static assert(S6 == [0]);
|
||||
enum S7 = V7[1..2]; static assert(S7 == [0]);
|
||||
enum S8 = V8[1..2]; static assert(S8 == [0]);
|
||||
|
||||
// Same tests as above, but use access via immutable.
|
||||
//immutable int4 v1 = int4.init; // Cannot cast to immutable at compile time
|
||||
immutable int[4] v2 = int4.init.array;
|
||||
immutable int[4] v3 = cast(int[4])int4.init;
|
||||
immutable int[4] v4 = cast(int[4])int4.init.array;
|
||||
//immutable int4 v5 = int4(0); // Cannot cast to immutable at compile time
|
||||
immutable int[4] v6 = int4(0).array;
|
||||
immutable int[4] v7 = cast(int[4])int4(0);
|
||||
immutable int[4] v8 = cast(int[4])int4(0).array;
|
||||
|
||||
// CTFE index tests
|
||||
//immutable i1 = v1[0]; static assert(i1 == 0);
|
||||
immutable i2 = v2[0]; static assert(i2 == 0);
|
||||
immutable i3 = v3[0]; static assert(i3 == 0);
|
||||
immutable i4 = v4[0]; static assert(i4 == 0);
|
||||
//immutable i5 = v5[0]; static assert(i5 == 0);
|
||||
immutable i6 = v6[0]; static assert(i6 == 0);
|
||||
immutable i7 = v7[0]; static assert(i7 == 0);
|
||||
immutable i8 = v8[0]; static assert(i8 == 0);
|
||||
|
||||
// CTFE slice tests
|
||||
//immutable s1 = v1[1..2]; static assert(s1 == [0]);
|
||||
immutable s2 = v2[1..2]; static assert(s2 == [0]);
|
||||
immutable s3 = v3[1..2]; static assert(s3 == [0]);
|
||||
immutable s4 = v4[1..2]; static assert(s4 == [0]);
|
||||
//immutable s5 = v5[1..2]; static assert(s5 == [0]);
|
||||
immutable s6 = v6[1..2]; static assert(s6 == [0]);
|
||||
immutable s7 = v7[1..2]; static assert(s7 == [0]);
|
||||
immutable s8 = v8[1..2]; static assert(s8 == [0]);
|
15
gcc/testsuite/gdc.dg/torture/simd19632.d
Normal file
15
gcc/testsuite/gdc.dg/torture/simd19632.d
Normal file
|
@ -0,0 +1,15 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=19632
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
import core.simd;
|
||||
|
||||
void main()
|
||||
{
|
||||
int4 v = [1, 2, 3, 4];
|
||||
int sum = 0;
|
||||
foreach (ref e; v)
|
||||
sum += (e *= 2);
|
||||
assert(v.array[] == [2, 4, 6, 8]);
|
||||
assert(sum == 20);
|
||||
}
|
22
gcc/testsuite/gdc.dg/torture/simd20041.d
Normal file
22
gcc/testsuite/gdc.dg/torture/simd20041.d
Normal file
|
@ -0,0 +1,22 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=20041
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
import core.simd;
|
||||
|
||||
immutable(float4) test20041()
|
||||
{
|
||||
float4 raw = 2.0f;
|
||||
raw.array[0] = 1;
|
||||
return cast(immutable)raw;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
static immutable float4 v = test20041();
|
||||
|
||||
assert(v.array[0] == 1);
|
||||
assert(v.array[1] == 2);
|
||||
assert(v.array[2] == 2);
|
||||
assert(v.array[3] == 2);
|
||||
}
|
20
gcc/testsuite/gdc.dg/torture/simd21673.d
Normal file
20
gcc/testsuite/gdc.dg/torture/simd21673.d
Normal file
|
@ -0,0 +1,20 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=21673
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
import core.simd;
|
||||
|
||||
float4 _mm_move_ss(float4 a, float4 b)
|
||||
{
|
||||
a.ptr[0] = b.array[0];
|
||||
return a;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float4 A = [1.0f, 2.0f, 3.0f, 4.0f];
|
||||
float4 B = [5.0f, 6.0f, 7.0f, 8.0f];
|
||||
float4 R = _mm_move_ss(A, B);
|
||||
float[4] correct = [5.0f, 2.0f, 3.0f, 4.0f];
|
||||
assert(R.array == correct);
|
||||
}
|
36
gcc/testsuite/gdc.dg/torture/simd21676.d
Normal file
36
gcc/testsuite/gdc.dg/torture/simd21676.d
Normal file
|
@ -0,0 +1,36 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23009
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
import core.simd;
|
||||
|
||||
double2 loadUnaligned21676(const(double)* pvec)
|
||||
{
|
||||
double2 result;
|
||||
foreach(i; 0..2)
|
||||
{
|
||||
result[i] = pvec[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
double2 _mm_setr_pd(double e1, double e0)
|
||||
{
|
||||
double[2] result = [e1, e0];
|
||||
return loadUnaligned21676(result.ptr);
|
||||
}
|
||||
|
||||
double2 fun(double2 a, double2 b)
|
||||
{
|
||||
a[0] = (a[0] < b[0]) ? a[0] : b[0];
|
||||
return a;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
double2 A = _mm_setr_pd(1.0, 2.0);
|
||||
double2 B = _mm_setr_pd(4.0, 1.0);
|
||||
double2 C = fun(A, B);
|
||||
assert(C.array[0] == 1.0);
|
||||
assert(C.array[1] == 2.0);
|
||||
}
|
18
gcc/testsuite/gdc.dg/torture/simd22438.d
Normal file
18
gcc/testsuite/gdc.dg/torture/simd22438.d
Normal file
|
@ -0,0 +1,18 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=22438
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do run }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
|
||||
struct T22438 { int x; double d; }
|
||||
|
||||
T22438 foo22438(int x, double d) { return T22438(x, d); }
|
||||
|
||||
struct S22438 { T22438 t; string r; }
|
||||
|
||||
void main()
|
||||
{
|
||||
S22438 s = S22438(foo22438(10, 3.14), "str");
|
||||
assert(s.t.x == 10);
|
||||
assert(s.t.d == 3.14);
|
||||
assert(s.r == "str");
|
||||
}
|
22
gcc/testsuite/gdc.dg/torture/simd23009.d
Normal file
22
gcc/testsuite/gdc.dg/torture/simd23009.d
Normal file
|
@ -0,0 +1,22 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23009
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
import core.simd;
|
||||
|
||||
double2 _mm_loadl_pd(double2 a, const(double)* mem_addr)
|
||||
{
|
||||
a[0] = *mem_addr;
|
||||
return a;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
double A = 7.0;
|
||||
double2 B;
|
||||
B[0] = 4.0;
|
||||
B[1] = -5.0;
|
||||
double2 R = _mm_loadl_pd(B, &A);
|
||||
double[2] correct = [ 7.0, -5.0 ];
|
||||
assert(R.array == correct);
|
||||
}
|
11
gcc/testsuite/gdc.dg/torture/simd23077.d
Normal file
11
gcc/testsuite/gdc.dg/torture/simd23077.d
Normal file
|
@ -0,0 +1,11 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23077
|
||||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do compile }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
|
||||
float test23077(float x)
|
||||
{
|
||||
short i = *cast(short*)&x;
|
||||
++i;
|
||||
return *cast(float*)&i; // this cast is not allowed in @safe code
|
||||
}
|
26
gcc/testsuite/gdc.dg/torture/simd8.d
Normal file
26
gcc/testsuite/gdc.dg/torture/simd8.d
Normal file
|
@ -0,0 +1,26 @@
|
|||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do run { target { avx_runtime || vect_sizes_16B_8B } } }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
import gcc.simd;
|
||||
|
||||
alias __m128 = __vector(float[4]);
|
||||
|
||||
__m128 _mm_setr_ps (float e3, float e2, float e1, float e0) pure @trusted
|
||||
{
|
||||
float[4] result = [e3, e2, e1, e0];
|
||||
return loadUnaligned!(__m128)(cast(__m128*)result.ptr);
|
||||
}
|
||||
|
||||
__m128 _mm_movehdup_ps (__m128 a) pure @trusted
|
||||
{
|
||||
a.ptr[0] = a.array[1];
|
||||
a.ptr[2] = a.array[3];
|
||||
return a;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
__m128 A = _mm_movehdup_ps(_mm_setr_ps(1, 2, 3, 4));
|
||||
float[4] correct = [2.0f, 2, 4, 4 ];
|
||||
assert(A.array == correct);
|
||||
}
|
46
gcc/testsuite/gdc.dg/torture/simd9.d
Normal file
46
gcc/testsuite/gdc.dg/torture/simd9.d
Normal file
|
@ -0,0 +1,46 @@
|
|||
// { dg-additional-options "-mavx" { target avx_runtime } }
|
||||
// { dg-do run }
|
||||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
|
||||
__gshared int testsroa_x;
|
||||
|
||||
template SROA(T1, T2)
|
||||
{
|
||||
struct FPoint
|
||||
{
|
||||
T1 x;
|
||||
T2 y;
|
||||
}
|
||||
|
||||
void sroa(FPoint p1, ref FPoint quad)
|
||||
{
|
||||
quad = FPoint(p1.x, p1.y);
|
||||
}
|
||||
|
||||
void testit()
|
||||
{
|
||||
FPoint p1 = FPoint(1, 2);
|
||||
|
||||
FPoint quad;
|
||||
sroa(p1, quad);
|
||||
|
||||
if (quad != p1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
++testsroa_x;
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
SROA!(int, int ).testit();
|
||||
SROA!(int, float).testit();
|
||||
SROA!(float, float).testit();
|
||||
SROA!(float, int ).testit();
|
||||
|
||||
SROA!(long, long ).testit();
|
||||
SROA!(long, double).testit();
|
||||
SROA!(double, double).testit();
|
||||
SROA!(double, long ).testit();
|
||||
}
|
21
gcc/testsuite/gdc.dg/torture/simd_prefetch.d
Normal file
21
gcc/testsuite/gdc.dg/torture/simd_prefetch.d
Normal file
|
@ -0,0 +1,21 @@
|
|||
// { dg-skip-if "needs gcc/config.d" { ! d_runtime } }
|
||||
import gcc.simd;
|
||||
|
||||
int testprefetch(byte a)
|
||||
{
|
||||
prefetch!(false, 0)(&a);
|
||||
prefetch!(false, 1)(&a);
|
||||
prefetch!(false, 2)(&a);
|
||||
prefetch!(false, 3)(&a);
|
||||
prefetch!(true, 0)(&a);
|
||||
prefetch!(true, 1)(&a);
|
||||
prefetch!(true, 2)(&a);
|
||||
prefetch!(true, 3)(&a);
|
||||
return 3;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
int i = testprefetch(1);
|
||||
assert(i == 3);
|
||||
}
|
|
@ -60,20 +60,6 @@ bool test_nez(long x) { return x != 0; }
|
|||
bool test_gez(long x) { return x >= 0; }
|
||||
bool test_gtz(long x) { return x > 0; }
|
||||
|
||||
bool test_ltz(float x) { return x < 0; }
|
||||
bool test_lez(float x) { return x <= 0; }
|
||||
bool test_eqz(float x) { return x == 0; }
|
||||
bool test_nez(float x) { return x != 0; }
|
||||
bool test_gez(float x) { return x >= 0; }
|
||||
bool test_gtz(float x) { return x > 0; }
|
||||
|
||||
bool test_ltz(double x) { return x < 0; }
|
||||
bool test_lez(double x) { return x <= 0; }
|
||||
bool test_eqz(double x) { return x == 0; }
|
||||
bool test_nez(double x) { return x != 0; }
|
||||
bool test_gez(double x) { return x >= 0; }
|
||||
bool test_gtz(double x) { return x > 0; }
|
||||
|
||||
/* ----------------------------------- */
|
||||
|
||||
bool test_lt(ubyte x, ubyte y) { return x < y; }
|
||||
|
|
|
@ -162,6 +162,18 @@ align(2) struct S12200_2
|
|||
align(1):
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=14694
|
||||
inout(T)[] overlap(T)(inout(T)[] r1, inout(T)[] r2) @trusted pure nothrow
|
||||
{
|
||||
alias U = inout(T);
|
||||
static U* max(U* a, U* b) nothrow { return a > b ? a : b; }
|
||||
static U* min(U* a, U* b) nothrow { return a < b ? a : b; }
|
||||
|
||||
auto b = max(r1.ptr, r2.ptr);
|
||||
auto e = min(r1.ptr + r1.length, r2.ptr + r2.length);
|
||||
return b < e ? b[0 .. e - b] : null;
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=16140
|
||||
void gun()()
|
||||
{
|
||||
|
@ -173,6 +185,13 @@ void gun()()
|
|||
else break;
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=14690
|
||||
pragma(inline, true)
|
||||
int fun(int a, int b)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=16649
|
||||
void leFoo()()
|
||||
{
|
||||
|
|
|
@ -2,3 +2,10 @@ extern int xx;
|
|||
|
||||
typedef struct Foo *FooRef;
|
||||
FooRef make_foo(void);
|
||||
|
||||
|
||||
typedef struct Foo2 *FooRef2;
|
||||
struct Foo2 {
|
||||
int x;
|
||||
};
|
||||
FooRef2 make_foo2(void);
|
||||
|
|
|
@ -2,3 +2,11 @@ extern int xx;
|
|||
|
||||
typedef struct Foo *FooRef;
|
||||
void free_foo(FooRef foo);
|
||||
|
||||
/****************************/
|
||||
|
||||
typedef struct Foo2 *FooRef2;
|
||||
struct Foo2 {
|
||||
int x;
|
||||
};
|
||||
void free_foo2(FooRef2 foo);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
module lib;
|
257
gcc/testsuite/gdc.test/compilable/noreturn3.d
Normal file
257
gcc/testsuite/gdc.test/compilable/noreturn3.d
Normal file
|
@ -0,0 +1,257 @@
|
|||
/*
|
||||
REQUIRED_ARGS: -w -o- -d
|
||||
|
||||
More complex examples from the DIP
|
||||
https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1034.md
|
||||
*/
|
||||
|
||||
alias noreturn = typeof(*null);
|
||||
static assert (!is(noreturn == void));
|
||||
|
||||
void initialize()
|
||||
{
|
||||
noreturn a;
|
||||
noreturn b = noreturn.init;
|
||||
}
|
||||
|
||||
void foo(const noreturn);
|
||||
void foo(const int);
|
||||
|
||||
noreturn bar();
|
||||
|
||||
void overloads()
|
||||
{
|
||||
noreturn n;
|
||||
foo(n);
|
||||
|
||||
foo(bar());
|
||||
}
|
||||
|
||||
// /*****************************************************************************/
|
||||
|
||||
auto inferNoreturn(int i)
|
||||
{
|
||||
if (i < 0)
|
||||
return assert(false);
|
||||
else if (i == 0)
|
||||
return assert(false);
|
||||
else
|
||||
return assert(false);
|
||||
}
|
||||
|
||||
auto inferReturn(int i)
|
||||
{
|
||||
if (i < 0)
|
||||
return assert(false);
|
||||
else if (i == 0)
|
||||
return i;
|
||||
else
|
||||
return assert(false);
|
||||
}
|
||||
|
||||
// /*****************************************************************************/
|
||||
// // https://issues.dlang.org/show_bug.cgi?id=22004
|
||||
|
||||
alias fun22004 = _ => {}();
|
||||
alias gun22004 = _ => assert(0);
|
||||
auto bun22004(bool b)
|
||||
{
|
||||
if (b)
|
||||
return gun22004(0);
|
||||
else
|
||||
return fun22004(0);
|
||||
}
|
||||
|
||||
static assert(is(typeof(bun22004(true)) == void));
|
||||
|
||||
// // Reversed order
|
||||
auto bun22004_reversed(bool b)
|
||||
{
|
||||
if (b)
|
||||
return fun22004(0);
|
||||
else
|
||||
return gun22004(0);
|
||||
}
|
||||
|
||||
static assert(is(typeof(bun22004_reversed(true)) == void));
|
||||
|
||||
// /*****************************************************************************/
|
||||
|
||||
// // Also works fine with non-void types and ref inference
|
||||
|
||||
int global;
|
||||
|
||||
auto ref forwardOrExit(ref int num)
|
||||
{
|
||||
if (num)
|
||||
return num;
|
||||
else
|
||||
return assert(false);
|
||||
}
|
||||
|
||||
static assert( is(typeof(forwardOrExit(global)) == int));
|
||||
|
||||
// // Must not infer ref due to the noreturn rvalue
|
||||
static assert(!is(typeof(&forwardOrExit(global))));
|
||||
|
||||
auto ref forwardOrExit2(ref int num)
|
||||
{
|
||||
if (num)
|
||||
return assert(false);
|
||||
else
|
||||
return num;
|
||||
}
|
||||
|
||||
static assert( is(typeof(forwardOrExit2(global)) == int));
|
||||
|
||||
// // Must not infer ref due to the noreturn rvalue
|
||||
static assert(!is(typeof(&forwardOrExit2(global))));
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void inference()
|
||||
{
|
||||
auto inf = cast(noreturn) 1;
|
||||
static assert(is(typeof(inf) == noreturn));
|
||||
|
||||
noreturn n;
|
||||
auto c = cast(const shared noreturn) n;
|
||||
static assert(is(typeof(c) == const shared noreturn));
|
||||
static assert(is(typeof(n) == noreturn));
|
||||
|
||||
auto c2 = cast(immutable noreturn) n;
|
||||
static assert(is(typeof(c) == const shared noreturn));
|
||||
static assert(is(typeof(c2) == immutable noreturn));
|
||||
static assert(is(typeof(n) == noreturn));
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
// https://issues.dlang.org/show_bug.cgi?id=21957
|
||||
// Calculate proper alignment and size for noreturn members
|
||||
|
||||
enum longPad = long.alignof - int.sizeof;
|
||||
|
||||
struct BasicStruct
|
||||
{
|
||||
int firstInt;
|
||||
noreturn noRet;
|
||||
long lastLong;
|
||||
}
|
||||
|
||||
static assert(BasicStruct.sizeof == (int.sizeof + longPad + long.sizeof));
|
||||
|
||||
static assert(BasicStruct.firstInt.offsetof == 0);
|
||||
static assert(BasicStruct.noRet.offsetof == 4);
|
||||
static assert(BasicStruct.lastLong.offsetof == (4 + longPad));
|
||||
|
||||
struct AlignedStruct
|
||||
{
|
||||
int firstInt;
|
||||
align(16) noreturn noRet;
|
||||
long lastLong;
|
||||
}
|
||||
|
||||
static assert(AlignedStruct.sizeof == 32);
|
||||
|
||||
static assert(AlignedStruct.firstInt.offsetof == 0);
|
||||
static assert(AlignedStruct.noRet.offsetof == 16);
|
||||
static assert(AlignedStruct.lastLong.offsetof == 16);
|
||||
|
||||
union BasicUnion
|
||||
{
|
||||
int firstInt;
|
||||
noreturn noRet;
|
||||
long lastLong;
|
||||
}
|
||||
|
||||
static assert(BasicUnion.sizeof == 8);
|
||||
|
||||
static assert(BasicUnion.firstInt.offsetof == 0);
|
||||
static assert(BasicUnion.noRet.offsetof == 0);
|
||||
static assert(BasicUnion.lastLong.offsetof == 0);
|
||||
|
||||
union AlignedUnion
|
||||
{
|
||||
int firstInt;
|
||||
align(16) noreturn noRet;
|
||||
long lastLong;
|
||||
}
|
||||
|
||||
static assert(AlignedUnion.sizeof == 16);
|
||||
|
||||
static assert(AlignedUnion.firstInt.offsetof == 0);
|
||||
static assert(AlignedUnion.noRet.offsetof == 0);
|
||||
static assert(AlignedUnion.lastLong.offsetof == 0);
|
||||
|
||||
class BasicClass
|
||||
{
|
||||
int firstInt;
|
||||
noreturn noRet;
|
||||
long lastLong;
|
||||
}
|
||||
|
||||
enum objectMemberSize = __traits(classInstanceSize, Object);
|
||||
|
||||
static assert(__traits(classInstanceSize, BasicClass) == objectMemberSize + (int.sizeof + longPad + long.sizeof));
|
||||
|
||||
static assert(BasicClass.firstInt.offsetof == objectMemberSize + 0);
|
||||
static assert(BasicClass.noRet.offsetof == objectMemberSize + 4);
|
||||
static assert(BasicClass.lastLong.offsetof == objectMemberSize + (4 + longPad));
|
||||
|
||||
class AlignedClass
|
||||
{
|
||||
int firstInt;
|
||||
align(16) noreturn noRet;
|
||||
long lastLong;
|
||||
}
|
||||
|
||||
enum offset = (objectMemberSize + 4 + 16) & ~15;
|
||||
|
||||
static assert(__traits(classInstanceSize, AlignedClass) == offset + 8);
|
||||
|
||||
static assert(AlignedClass.firstInt.offsetof == objectMemberSize + 0);
|
||||
static assert(AlignedClass.noRet.offsetof == offset);
|
||||
static assert(AlignedClass.lastLong.offsetof == offset);
|
||||
|
||||
struct EmptyStruct
|
||||
{
|
||||
noreturn noRet;
|
||||
}
|
||||
|
||||
static assert(EmptyStruct.sizeof == 1);
|
||||
static assert(EmptyStruct.noRet.offsetof == 0);
|
||||
|
||||
struct EmptyStruct2
|
||||
{
|
||||
noreturn[4] noRet;
|
||||
}
|
||||
|
||||
static assert(EmptyStruct2.sizeof == 1);
|
||||
static assert(EmptyStruct2.noRet.offsetof == 0);
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22858
|
||||
// Shouldn't mess with the alignment of other zero-sized types.
|
||||
|
||||
struct S22858
|
||||
{
|
||||
int a;
|
||||
void*[0] arr;
|
||||
char c;
|
||||
noreturn[0] arr2;
|
||||
char c2;
|
||||
}
|
||||
|
||||
static assert (S22858.arr.offsetof % size_t.sizeof == 0);
|
||||
static assert (S22858.arr2.offsetof == S22858.c.offsetof + 1);
|
||||
static assert (S22858.arr2.offsetof == S22858.c2.offsetof);
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23331
|
||||
|
||||
auto fun() { return double(new noreturn[](0)[0]); }
|
||||
auto gun() { return double(assert(0)); }
|
||||
auto hun() { return int(assert(0)); }
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23379
|
||||
|
||||
void casting_noreturn() { auto b = cast(double)(assert(0)); }
|
21
gcc/testsuite/gdc.test/compilable/scope_tuple_expansion.d
Normal file
21
gcc/testsuite/gdc.test/compilable/scope_tuple_expansion.d
Normal file
|
@ -0,0 +1,21 @@
|
|||
// REQUIRED_ARGS: -preview=dip1000
|
||||
|
||||
// Reduced from `std.systime`.
|
||||
// Tuple expansion can trip up scope checking with errors like:
|
||||
// Error: scope variable `__tup4` assigned to `found` with longer lifetime
|
||||
|
||||
struct Tuple(T...)
|
||||
{
|
||||
T t;
|
||||
alias t this;
|
||||
}
|
||||
|
||||
Tuple!(int*, int) find(return scope int* x) @safe
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void fromISOExtString(scope int* str) @safe
|
||||
{
|
||||
int* found = str.find()[0];
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// REQUIRED_ARGS: -preview=shortenedMethods
|
||||
// N.B. Shortened methods are no longer under a preview flag
|
||||
class A {
|
||||
int _x = 34;
|
||||
// short syntax works in all contexts
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
void start() {}
|
||||
void start()
|
||||
{
|
||||
pragma(startaddress, start);
|
||||
}
|
||||
pragma(startaddress, start);
|
||||
|
|
|
@ -8,3 +8,10 @@ void do_foo(){
|
|||
FooRef f = make_foo(); // use_foo.d(5)
|
||||
free_foo(f); // use_foo.d(6)
|
||||
}
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23357
|
||||
|
||||
void do_foo2(){
|
||||
FooRef2 f = make_foo2();
|
||||
free_foo2(f);
|
||||
}
|
||||
|
|
10
gcc/testsuite/gdc.test/compilable/test22784.d
Normal file
10
gcc/testsuite/gdc.test/compilable/test22784.d
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Issue 22784 - pragma(printf) applies to nested functions
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22784
|
||||
|
||||
import core.stdc.stdarg;
|
||||
extern(C)
|
||||
pragma(printf)
|
||||
void fn(const(char)* fmt, ...)
|
||||
{
|
||||
void inner(){}
|
||||
}
|
10
gcc/testsuite/gdc.test/compilable/test22952.d
Normal file
10
gcc/testsuite/gdc.test/compilable/test22952.d
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
REQUIRED_ARGS: -Icompilable/imports -mv=lib=pkg22952
|
||||
EXTRA_FILES: imports/pkg22952/package.d
|
||||
*/
|
||||
|
||||
// Issue 22952 - Compiler fails to find package.d modules via -mv map
|
||||
// https://issues.dlang.org/show_bug.cgi?id=22952
|
||||
|
||||
module test22952;
|
||||
import lib;
|
9
gcc/testsuite/gdc.test/compilable/test23380.d
Normal file
9
gcc/testsuite/gdc.test/compilable/test23380.d
Normal file
|
@ -0,0 +1,9 @@
|
|||
// REQUIRED_ARGS: -preview=dip1000
|
||||
|
||||
// https://issues.dlang.org/show_bug.cgi?id=23380
|
||||
// Issue 23380 - [dip1000] class parameter should not be treated as ref qua lifetime
|
||||
|
||||
@safe void test(scope Object o0, scope Object o1)
|
||||
{
|
||||
o1 = o0;
|
||||
}
|
12
gcc/testsuite/gdc.test/compilable/test23386.d
Normal file
12
gcc/testsuite/gdc.test/compilable/test23386.d
Normal file
|
@ -0,0 +1,12 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23386
|
||||
// Segfault on enum member UDA inside template
|
||||
|
||||
template E()
|
||||
{
|
||||
enum E : byte
|
||||
{
|
||||
@(1) none,
|
||||
}
|
||||
}
|
||||
|
||||
alias T = E!();
|
29
gcc/testsuite/gdc.test/fail_compilation/diag23384.d
Normal file
29
gcc/testsuite/gdc.test/fail_compilation/diag23384.d
Normal file
|
@ -0,0 +1,29 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23384
|
||||
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/diag23384.d(28): Error: function `diag23384.Derived.fun(B b)` is not callable using argument types `(A)`
|
||||
fail_compilation/diag23384.d(28): function `diag23384.Derived.fun` hides base class function `diag23384.Base.fun`
|
||||
fail_compilation/diag23384.d(28): add `alias fun = diag23384.Base.fun` to `diag23384.Derived`'s body to merge the overload sets
|
||||
---
|
||||
*/
|
||||
|
||||
struct A {}
|
||||
struct B {}
|
||||
|
||||
class Base
|
||||
{
|
||||
void fun(A a) {}
|
||||
}
|
||||
|
||||
class Derived : Base
|
||||
{
|
||||
void fun(B b) {}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
Derived d;
|
||||
d.fun(A());
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
REQUIRED_ARGS: -m64
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail10905.d(20): Error: incompatible types for `(this.x) == (cast(const(__vector(long[2])))cast(__vector(long[2]))1L)`: both operands are of type `const(__vector(long[2]))`
|
||||
---
|
||||
*/
|
||||
|
||||
struct Foo
|
||||
{
|
||||
enum __vector(long[2]) y = 1;
|
||||
}
|
||||
|
||||
struct Bar
|
||||
{
|
||||
__vector(long[2]) x;
|
||||
|
||||
bool spam() const
|
||||
{
|
||||
return x == Foo.y;
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
REQUIRED_ARGS: -m64
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail19898a.d(10): Error: incompatible types for `(__key2) < (__limit3)`: both operands are of type `__vector(int[4])`
|
||||
fail_compilation/fail19898a.d(10): Error: expression `__key2 < __limit3` of type `__vector(int[4])` does not have a boolean value
|
||||
---
|
||||
*/
|
||||
void f (__vector(int[4]) n)
|
||||
|
|
|
@ -3,7 +3,7 @@ REQUIRED_ARGS: -m64
|
|||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail19898b.d(17): Error: cannot implicitly convert expression `m` of type `S` to `__vector(int[4])`
|
||||
fail_compilation/fail19898b.d(17): Error: incompatible types for `(__key2) != (__limit3)`: both operands are of type `__vector(int[4])`
|
||||
fail_compilation/fail19898b.d(17): Error: expression `__key2 != __limit3` of type `__vector(int[4])` does not have a boolean value
|
||||
fail_compilation/fail19898b.d(17): Error: cannot cast expression `__key2` of type `__vector(int[4])` to `S`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail22366.d(13): Error: scope variable `__aaval2` assigned to non-scope `aa[0]`
|
||||
fail_compilation/fail22366.d(13): Error: scope variable `x` may not be copied into allocated memory
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
40
gcc/testsuite/gdc.test/fail_compilation/fail23406.d
Normal file
40
gcc/testsuite/gdc.test/fail_compilation/fail23406.d
Normal file
|
@ -0,0 +1,40 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23406
|
||||
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/fail23406.d(39): Error: cannot implicitly convert expression `0` of type `int` to `alphakey`
|
||||
---
|
||||
*/
|
||||
|
||||
struct flagenum
|
||||
{
|
||||
int i = 1;
|
||||
alias i this;
|
||||
|
||||
auto opBinary(string s)(int j)
|
||||
{
|
||||
assert(j == 1);
|
||||
return typeof(this)(i*2);
|
||||
}
|
||||
|
||||
auto opEquals(int a)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum alphakey
|
||||
{
|
||||
a = flagenum(),
|
||||
b,c,d,e,f,g,h,i,
|
||||
k,l,m,n,o,p,q,r,
|
||||
s,t,u,v,w,x,y,z
|
||||
}
|
||||
|
||||
alphakey alpha;
|
||||
|
||||
void main()
|
||||
{
|
||||
alpha = 0;
|
||||
}
|
|
@ -3,7 +3,7 @@ TEST_OUTPUT:
|
|||
---
|
||||
fail_compilation/issue21378.d(13): Error: function `issue21378.fn` circular dependency. Functions cannot be interpreted while being compiled
|
||||
fail_compilation/issue21378.d(12): called from here: `fn()`
|
||||
fail_compilation/issue21378.d(12): Error: pragma `inline` pragma(`inline`, `true` or `false`) expected, not `fn()`
|
||||
fail_compilation/issue21378.d(12): Error: pragma(`inline`, `true` or `false`) expected, not `fn()`
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@ fail_compilation/lexer1.d(49): Error: unterminated named entity &*;
|
|||
fail_compilation/lexer1.d(50): Error: unterminated named entity &s1";
|
||||
fail_compilation/lexer1.d(51): Error: unterminated named entity &2;
|
||||
fail_compilation/lexer1.d(52): Error: escape octal sequence \400 is larger than \377
|
||||
fail_compilation/lexer1.d(53): Error: html entity requires 2 code units, use a string instead of a character
|
||||
---
|
||||
*/
|
||||
|
||||
// https://dlang.dawg.eu/coverage/src/lexer.c.gcov.html
|
||||
x"01 02 03"w;
|
||||
0x80000001;
|
||||
|
@ -50,3 +50,4 @@ static s5 = "\&*";
|
|||
static s6 = "\&s1";
|
||||
static s7 = "\&2;";
|
||||
static s7 = "\400;";
|
||||
dchar s8 = '\∾̳';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/pragmainline.d(8): Error: pragma `inline` one boolean expression expected for `pragma(inline)`, not 3
|
||||
fail_compilation/pragmainline.d(8): Error: one boolean expression expected for `pragma(inline)`, not 3
|
||||
---
|
||||
*/
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/pragmas.d(103): Error: boolean expression expected for `pragma(inline)`
|
||||
fail_compilation/pragmas.d(108): Error: boolean expression expected for `pragma(inline)`
|
||||
fail_compilation/pragmas.d(103): Error: one boolean expression expected for `pragma(inline)`, not 2
|
||||
fail_compilation/pragmas.d(108): Error: one boolean expression expected for `pragma(inline)`, not 2
|
||||
fail_compilation/pragmas.d(118): Error: unrecognized `pragma(unrecognized)`
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -8,10 +8,10 @@ fail_compilation/previewin.d(5): Error: function `previewin.takeFunction(void fu
|
|||
fail_compilation/previewin.d(5): cannot pass argument `__lambda2` of type `void function(const(real) x) pure nothrow @nogc @safe` to parameter `void function(in real) f`
|
||||
fail_compilation/previewin.d(6): Error: function `previewin.takeFunction(void function(in real) f)` is not callable using argument types `(void function(ref const(real) x) pure nothrow @nogc @safe)`
|
||||
fail_compilation/previewin.d(6): cannot pass argument `__lambda3` of type `void function(ref const(real) x) pure nothrow @nogc @safe` to parameter `void function(in real) f`
|
||||
fail_compilation/previewin.d(15): Error: scope variable `arg` assigned to non-scope `myGlobal`
|
||||
fail_compilation/previewin.d(16): Error: scope variable `arg` assigned to non-scope `myGlobal`
|
||||
fail_compilation/previewin.d(15): Error: scope variable `arg` assigned to global variable `myGlobal`
|
||||
fail_compilation/previewin.d(16): Error: scope variable `arg` assigned to global variable `myGlobal`
|
||||
fail_compilation/previewin.d(17): Error: scope parameter `arg` may not be returned
|
||||
fail_compilation/previewin.d(18): Error: scope variable `arg` assigned to `escape` with longer lifetime
|
||||
fail_compilation/previewin.d(18): Error: scope variable `arg` assigned to `ref` variable `escape` with longer lifetime
|
||||
fail_compilation/previewin.d(22): Error: returning `arg` escapes a reference to parameter `arg`
|
||||
fail_compilation/previewin.d(22): perhaps annotate the parameter with `return`
|
||||
---
|
||||
|
|
|
@ -117,6 +117,7 @@ fail_compilation/reserved_version.d(218): Error: version identifier `D_PreCondit
|
|||
fail_compilation/reserved_version.d(219): Error: version identifier `D_PostConditions` is reserved and cannot be set
|
||||
fail_compilation/reserved_version.d(220): Error: version identifier `D_ProfileGC` is reserved and cannot be set
|
||||
fail_compilation/reserved_version.d(221): Error: version identifier `D_Invariants` is reserved and cannot be set
|
||||
fail_compilation/reserved_version.d(222): Error: version identifier `D_Optimized` is reserved and cannot be set
|
||||
---
|
||||
*/
|
||||
|
||||
|
@ -240,6 +241,7 @@ version = D_PreConditions;
|
|||
version = D_PostConditions;
|
||||
version = D_ProfileGC;
|
||||
version = D_Invariants;
|
||||
version = D_Optimized;
|
||||
|
||||
// This should work though
|
||||
debug = DigitalMars;
|
||||
|
@ -351,3 +353,4 @@ debug = AVR;
|
|||
debug = D_PreConditions;
|
||||
debug = D_PostConditions;
|
||||
debug = D_ProfileGC;
|
||||
debug = D_Optimized;
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
// REQUIRED_ARGS: -version=D_PostConditions
|
||||
// REQUIRED_ARGS: -version=D_ProfileGC
|
||||
// REQUIRED_ARGS: -version=D_Invariants
|
||||
// REQUIRED_ARGS: -version=D_Optimized
|
||||
// REQUIRED_ARGS: -debug=DigitalMars
|
||||
// REQUIRED_ARGS: -debug=GNU
|
||||
// REQUIRED_ARGS: -debug=LDC
|
||||
|
@ -211,6 +212,7 @@
|
|||
// REQUIRED_ARGS: -debug=D_PostConditions
|
||||
// REQUIRED_ARGS: -debug=D_ProfileGC
|
||||
// REQUIRED_ARGS: -debug=D_Invariants
|
||||
// REQUIRED_ARGS: -debug=D_Optimized
|
||||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
|
@ -321,5 +323,6 @@ Error: version identifier `D_PreConditions` is reserved and cannot be set
|
|||
Error: version identifier `D_PostConditions` is reserved and cannot be set
|
||||
Error: version identifier `D_ProfileGC` is reserved and cannot be set
|
||||
Error: version identifier `D_Invariants` is reserved and cannot be set
|
||||
Error: version identifier `D_Optimized` is reserved and cannot be set
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -4,9 +4,9 @@ TEST_OUTPUT:
|
|||
---
|
||||
fail_compilation/retscope.d(22): Error: scope parameter `p` may not be returned
|
||||
fail_compilation/retscope.d(32): Error: returning `b ? nested1(& i) : nested2(& j)` escapes a reference to local variable `j`
|
||||
fail_compilation/retscope.d(45): Error: scope variable `p` assigned to non-scope `q`
|
||||
fail_compilation/retscope.d(45): Error: scope variable `p` assigned to global variable `q`
|
||||
fail_compilation/retscope.d(47): Error: address of variable `i` assigned to `q` with longer lifetime
|
||||
fail_compilation/retscope.d(48): Error: scope variable `a` assigned to non-scope `b`
|
||||
fail_compilation/retscope.d(48): Error: scope variable `a` assigned to global variable `b`
|
||||
fail_compilation/retscope.d(49): Error: address of struct temporary returned by `(*fp2)()` assigned to longer lived variable `q`
|
||||
---
|
||||
*/
|
||||
|
@ -662,7 +662,7 @@ int test21()
|
|||
/*********************************************
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/retscope.d(1907): Error: scope variable `x` assigned to `this` with longer lifetime
|
||||
fail_compilation/retscope.d(1907): Error: scope variable `x` assigned to `ref` variable `this` with longer lifetime
|
||||
fail_compilation/retscope.d(1913): Error: scope variable `x` may not be returned
|
||||
---
|
||||
*/
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
REQUIRED_ARGS: -preview=dip1000
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/retscope2.d(102): Error: scope variable `s` assigned to `p` with longer lifetime
|
||||
fail_compilation/retscope2.d(102): Error: scope variable `s` assigned to `ref` variable `p` with longer lifetime
|
||||
fail_compilation/retscope2.d(107): Error: address of variable `s` assigned to `p` with longer lifetime
|
||||
---
|
||||
*/
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue