From 8e480a56f514284d919e894c103288dda67ea243 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sun, 12 Jun 2016 01:07:18 -0700 Subject: [PATCH] fix Issue 13536 - Union of delegates breaks @safety --- src/expression.d | 54 ++++++++++++++++++++++++------- test/fail_compilation/test13536.d | 22 +++++++++++++ 2 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 test/fail_compilation/test13536.d diff --git a/src/expression.d b/src/expression.d index bcc453ee9e73..8cf74fd3a3fd 100644 --- a/src/expression.d +++ b/src/expression.d @@ -79,6 +79,39 @@ void emplaceExp(T : UnionExp)(T* p, Expression e) memcpy(p, cast(void*)e, e.size); } +/************************************************************* + * Check if e is a DotVarExp representing an overlapped pointer. + * Print error if overlapped pointer and in @safe. + * Params: + * sc = scope + * e = expression to check + * msg = error message string + * Returns: + * true if error + */ + +bool checkOverlappedPointer(Scope* sc, Expression e, string msg) +{ + if (e.op != TOKdotvar) + return false; + DotVarExp dve = cast(DotVarExp)e; + if (VarDeclaration v = dve.var.isVarDeclaration()) + { + if (v.overlapped && !sc.intypeof && sc.func && v.type.hasPointers()) + { + if (auto ad = v.toParent2().isAggregateDeclaration()) + { + if (sc.func.setUnsafe()) + { + e.error(msg.ptr, ad.toChars(), v.toChars()); + return true; + } + } + } + } + return false; +} + /************************************************************* * Given var, we need to get the * right 'this' pointer if var is in an outer class, but our @@ -250,7 +283,7 @@ extern (C++) bool isNeedThisScope(Scope* sc, Declaration d) */ extern (C++) Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null) { - //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL); + //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token.toChars(e1.op), e1.toChars(), e2 ? e2.toChars() : null); Loc loc = e1.loc; OverloadSet os; @@ -466,22 +499,21 @@ extern (C++) Expression resolvePropertiesX(Scope* sc, Expression e1, Expression else if (e1.op == TOKdotvar) { // Check for reading overlapped pointer field in @safe code. - VarDeclaration v = (cast(DotVarExp)e1).var.isVarDeclaration(); - if (v && v.overlapped && sc.func && !sc.intypeof) - { - AggregateDeclaration ad = v.toParent2().isAggregateDeclaration(); - if (ad && e1.type.hasPointers() && sc.func.setUnsafe()) - { - e1.error("field %s.%s cannot be accessed in @safe code because it overlaps with a pointer", ad.toChars(), v.toChars()); - return new ErrorExp(); - } - } + if (checkOverlappedPointer(sc, e1, "field %s.%s cannot be accessed in @safe code because it overlaps with a pointer")) + return new ErrorExp(); } else if (e1.op == TOKdot) { e1.error("expression has no value"); return new ErrorExp(); } + else if (e1.op == TOKcall) + { + CallExp ce = cast(CallExp)e1; + // Check for reading overlapped pointer field in @safe code. + if (checkOverlappedPointer(sc, ce.e1, "field %s.%s cannot be accessed in @safe code because it overlaps with a pointer")) + return new ErrorExp(); + } } if (!e1.type) diff --git a/test/fail_compilation/test13536.d b/test/fail_compilation/test13536.d new file mode 100644 index 000000000000..b351f8e10223 --- /dev/null +++ b/test/fail_compilation/test13536.d @@ -0,0 +1,22 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/test13536.d(20): Error: field U.safeDg cannot be accessed in @safe code because it overlaps with a pointer +--- +*/ +// https://issues.dlang.org/show_bug.cgi?id=13536 + +struct S { + void sysMethod() @system {} +} +void fun() @safe { + union U { + void delegate() @system sysDg; + void delegate() @safe safeDg; + } + U u; + S s; + u.sysDg = &s.sysMethod; + u.safeDg(); +} +