--- /dev/null
+// CS0019: Operator `??' cannot be applied to operands of type `void' and `throw expression'
+// Line: 20
+
+class C
+{
+ public static void Main ()
+ {
+ var s = Main () ?? throw null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0155: The type caught or thrown must be derived from System.Exception
+// Line: 9
+
+class X
+{
+ public int Test () => throw "";
+}
--- /dev/null
+// CS0162: Unreachable code detected
+// Line: 12
+// Compiler options: -warnaserror -warn:2
+
+using System;
+
+class X
+{
+ void Test ()
+ {
+ var x = true ? throw new NullReferenceException () : 1;
+ x = 2;
+ return;
+ }
+
+ static void Main ()
+ {
+ }
+}
--- /dev/null
+// CS0173: Type of conditional expression cannot be determined because there is no implicit conversion between `throw expression' and `throw expression'
+// Line: 8
+
+class C
+{
+ public static void Test (bool b)
+ {
+ var s = b ? throw null : throw null;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0411: The type arguments for method `C.Foo<T>(System.Func<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly
+// Line: 10
+
+using System;
+
+public class C
+{
+ public static void Main ()
+ {
+ Foo (() => throw null);
+ }
+
+ static void Foo<T> (Func<T> arg)
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS1061: No overload for method `Call' takes `0' arguments
+// Line: 11
+
+using System;
+
+class Program
+{
+ static void Main ()
+ {
+ Action<dynamic, object> action = delegate { };
+ Foo (action).NoDynamicBinding ();
+ }
+
+ static T Foo<T>(Action<T, T> x)
+ {
+ throw new NotImplementedException ();
+ }
+}
\ No newline at end of file
-// CS1617: Invalid -langversion option `ISO'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 6
+// CS1617: Invalid -langversion option `ISO'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 7
// Line: 0
// Compiler options: -langversion:ISO
--- /dev/null
+// CS1644: Feature `throw expression' cannot be used because it is not part of the C# 6.0 language specification
+// Line: 5
+// Compiler options: -langversion:6
+
+static class Class
+{
+ int Prop => throw null;
+}
--- /dev/null
+// CS4001: Cannot await `void' expression
+// Line: 10
+
+using System;
+
+class A
+{
+ static async void Test ()
+ {
+ await Console.WriteLine;
+ }
+}
--- /dev/null
+// CS8188: An expression tree cannot not contain a throw expression
+// Line: 11
+
+using System;
+using System.Linq.Expressions;
+
+class C
+{
+ public static void Main ()
+ {
+ Expression<Func<object>> l = () => throw null;
+ }
+}
\ No newline at end of file
fc.TryFinally = prev_tf;
}
- public override void MarkReachable (Reachability rc)
+ public override Reachability MarkReachable (Reachability rc)
{
block.MarkReachable (rc);
+ return rc;
}
public void SetHasThisAccess ()
}
}
- public override void MarkReachable (Reachability rc)
+ public override Reachability MarkReachable (Reachability rc)
{
- var es = source as ExpressionStatement;
- if (es != null)
- es.MarkReachable (rc);
+ return source.MarkReachable (rc);
}
}
stmt.EmitStatement (ec);
}
- public override void MarkReachable (Reachability rc)
+ public override Reachability MarkReachable (Reachability rc)
{
- base.MarkReachable (rc);
- stmt.MarkReachable (rc);
+ return stmt.MarkReachable (rc);
}
public override object Accept (StructuralVisitor visitor)
ec.Emit (OpCodes.Ret);
}
- public override void MarkReachable (Reachability rc)
+ public override Reachability MarkReachable (Reachability rc)
{
//
// Reachability has been done in AsyncInitializerStatement
//
+ return rc;
}
}
if (expr_type == target_type)
return true;
+ if (expr_type == InternalType.ThrowExpr)
+ return target_type.Kind != MemberKind.InternalCompilerType;
+
if (target_type.IsNullableType)
return ImplicitNulableConversion (null, expr, target_type) != null;
Expression e;
if (expr_type == target_type) {
- if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod)
+ if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod && expr_type != InternalType.ThrowExpr)
return expr;
return null;
}
return null;
}
+ if (expr_type == InternalType.ThrowExpr) {
+ return target_type.Kind == MemberKind.InternalCompilerType ? null : EmptyCast.Create (expr, target_type);
+ }
+
if (target_type.IsNullableType)
return ImplicitNulableConversion (ec, expr, target_type);
%token STRUCT
%token SWITCH
%token THIS
-%token THROW
+%token THROW
%token TRUE
%token TRY
%token TYPEOF
%token WHEN
%token INTERPOLATED_STRING
%token INTERPOLATED_STRING_END
+%token THROW_EXPR
/* C# keywords which are not really keywords */
%token GET
$$ = new Await ((Expression) $2, GetLocation ($1));
}
+ | THROW_EXPR prefixed_unary_expression
+ {
+ if (lang_version < LanguageVersion.V_7)
+ FeatureIsNotAvailable (lexer.Location, "throw expression");
+
+ $$ = new ThrowExpression ((Expression) $2, GetLocation ($1));
+ }
| BANG error
{
Error_SyntaxError (yyToken);
;
throw_statement
- : THROW opt_expression SEMICOLON
+ : THROW expression SEMICOLON
{
$$ = new Throw ((Expression) $2, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($3));
}
+ | THROW SEMICOLON
+ {
+ $$ = new Throw (null, GetLocation ($1));
+ lbag.AddStatement ($$, GetLocation ($2));
+ }
| THROW expression error
{
Error_SyntaxError (yyToken);
case Token.THIS:
return "this";
case Token.THROW:
+ case Token.THROW_EXPR:
return "throw";
case Token.TRUE:
return "true";
if (parsing_block == 0)
res = -1;
+ break;
+ case Token.THROW:
+ switch (current_token) {
+ case Token.ARROW:
+ case Token.OP_COALESCING:
+ case Token.INTERR:
+ case Token.COLON:
+ res = Token.THROW_EXPR;
+ break;
+ }
+
break;
}
case Token.THIS:
case Token.NEW:
case Token.INTERPOLATED_STRING:
+ case Token.THROW:
next_token = Token.INTERR;
break;
{
}
+ public virtual Reachability MarkReachable (Reachability rc)
+ {
+ return rc;
+ }
+
//
// Special version of flow analysis for expressions which can return different
// on-true and on-false result. Used by &&, ||, ?: expressions
/// </summary>
public abstract class ExpressionStatement : Expression
{
- public virtual void MarkReachable (Reachability rc)
- {
- }
-
public virtual ExpressionStatement ResolveStatement (BlockContext ec)
{
Expression e = Resolve (ec);
#endif
}
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ return child.MarkReachable (rc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
// Nothing to clone
{
return orig_expr.MakeExpression (ctx);
}
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ return expr.MarkReachable (rc);
+ }
}
//
return value;
}
}
+
+ class ThrowExpression : ExpressionStatement
+ {
+ Expression expr;
+
+ public ThrowExpression (Expression expr, Location loc)
+ {
+ this.expr = expr;
+ this.loc = loc;
+ }
+
+ protected override void CloneTo (CloneContext clonectx, Expression t)
+ {
+ var target = (ThrowExpression)t;
+ target.expr = expr.Clone (clonectx);
+ }
+
+ public override bool ContainsEmitWithAwait ()
+ {
+ return expr.ContainsEmitWithAwait ();
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext rc)
+ {
+ rc.Report.Error (8188, loc, "An expression tree cannot not contain a throw expression");
+ return expr;
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ expr = expr.Resolve (rc, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+
+ if (expr == null)
+ return null;
+
+ expr = Throw.ConvertType (rc, expr);
+
+ eclass = ExprClass.Value;
+ type = InternalType.ThrowExpr;
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ EmitStatement (ec);
+ }
+
+ public override void EmitStatement (EmitContext ec)
+ {
+ expr.Emit (ec);
+
+ ec.Emit (OpCodes.Throw);
+ }
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ return Reachability.CreateUnreachable ();
+ }
+ }
}
// Some types cannot be used as type arguments
//
if ((bound.Type.Kind == MemberKind.Void && !voidAllowed) || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType ||
- bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod || bound.Type == InternalType.VarOutType)
+ bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod || bound.Type == InternalType.VarOutType ||
+ bound.Type == InternalType.ThrowExpr)
return;
var a = bounds [index];
type = ltype;
return this;
}
+ } else if (ltype == InternalType.ThrowExpr) {
+ //
+ // LAMESPEC: I am not really sure what's point of allowing throw on left side
+ //
+ return ReducedExpression.Create (right, this, false).Resolve (ec);
} else {
return null;
}
case LanguageVersion.V_6:
version = "6.0";
break;
+ case LanguageVersion.V_7:
+ version = "7.0";
+ break;
default:
throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version);
}
V_4 = 4,
V_5 = 5,
V_6 = 6,
+ V_7 = 7,
Experimental = 100,
- Default = LanguageVersion.V_6,
+ Default = V_7,
}
public enum RuntimeVersion
case "6":
settings.Version = LanguageVersion.V_6;
return ParseResult.Success;
+ case "7":
+ settings.Version = LanguageVersion.V_7;
+ return ParseResult.Success;
case "experimental":
settings.Version = LanguageVersion.Experimental;
return ParseResult.Success;
- case "future":
- report.Warning (8000, 1, "Language version `future' is no longer supported");
- goto case "6";
}
- report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 6", value);
+ report.Error (1617, "Invalid -langversion option `{0}'. It must be `ISO-1', `ISO-2', Default or value in range 1 to 7", value);
return ParseResult.Error;
case "/codepage":
public class Return : ExitStatement
{
Expression expr;
+ bool expr_returns;
public Return (Expression expr, Location l)
{
if (expr != null)
expr.FlowAnalysis (fc);
- base.DoFlowAnalysis (fc);
+ if (!expr_returns)
+ base.DoFlowAnalysis (fc);
+
return true;
}
public override Reachability MarkReachable (Reachability rc)
{
base.MarkReachable (rc);
+
+ if (Expr != null) {
+ rc = Expr.MarkReachable (rc);
+ expr_returns = rc.IsUnreachable;
+ }
+
return Reachability.CreateUnreachable ();
}
}
}
+ public static Expression ConvertType (ResolveContext rc, Expression expr)
+ {
+ var et = rc.BuiltinTypes.Exception;
+ if (Convert.ImplicitConversionExists (rc, expr, et))
+ expr = Convert.ImplicitConversion (rc, expr, et, expr.Location);
+ else {
+ rc.Report.Error (155, expr.Location, "The type caught or thrown must be derived from System.Exception");
+ expr = EmptyCast.Create (expr, et);
+ }
+
+ return expr;
+ }
+
public override bool Resolve (BlockContext ec)
{
if (expr == null) {
if (expr == null)
return false;
- var et = ec.BuiltinTypes.Exception;
- if (Convert.ImplicitConversionExists (ec, expr, et))
- expr = Convert.ImplicitConversion (ec, expr, et, loc);
- else
- ec.Report.Error (155, expr.Location, "The type caught or thrown must be derived from System.Exception");
+ expr = ConvertType (ec, expr);
return true;
}
public override Reachability MarkReachable (Reachability rc)
{
- var init = initializer as ExpressionStatement;
- if (init != null)
- init.MarkReachable (rc);
-
- return base.MarkReachable (rc);
+ base.MarkReachable (rc);
+ return initializer == null ? rc : initializer.MarkReachable (rc);
}
protected override void CloneTo (CloneContext clonectx, Statement target)
public static readonly InternalType Namespace = new InternalType ("<namespace>");
public static readonly InternalType ErrorType = new InternalType ("<error>");
public static readonly InternalType VarOutType = new InternalType ("var out");
+ public static readonly InternalType ThrowExpr = new InternalType ("throw expression");
readonly string name;
--- /dev/null
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+ Func<object> f = () => throw null;
+ }
+
+ public int Test () => throw null;
+
+ object Foo ()
+ {
+ return null;
+ }
+
+ public object Test2 () => Foo () ?? throw null;
+
+ static void Test3 (out int z) => throw null;
+
+ int this [int x] {
+ get => throw null;
+ }
+
+ public event Action Event {
+ add => throw null;
+ remove => throw null;
+ }
+
+ void TestExpr_1 (bool b)
+ {
+ int x = b ? throw new NullReferenceException () : 1;
+ }
+
+ void TestExpr_2 (bool b)
+ {
+ int x = b ? 2 : throw new NullReferenceException ();
+ }
+
+ void TestExpr_3 (string s)
+ {
+ s = s ?? throw new NullReferenceException ();
+ }
+
+ void TestExpr_4 ()
+ {
+ throw new ApplicationException () ?? throw new NullReferenceException() ?? throw null;
+ }
+
+ void TestExpr_5 ()
+ {
+ Action a = () => throw new ApplicationException () ?? throw new NullReferenceException() ?? throw null;
+ }
+
+ static int TestExpr_6 (out int z) => throw null;
+
+ int TestExpr_7 (out int z)
+ {
+ return true ? throw new NullReferenceException () : 1;
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+class Program
+{
+ public static int Main ()
+ {
+ Console.WriteLine (M (1));
+ try {
+ Console.WriteLine (M (null));
+ } catch (Exception) {
+ Console.WriteLine ("thrown");
+ return 0;
+ }
+
+ return 1;
+ }
+
+ static string M (object data)
+ {
+ return data?.ToString () ?? throw null;
+ }
+}
\ No newline at end of file
</method>
</type>
</test>
+ <test name="test-throw-expr-01.cs">
+ <type name="X">
+ <method name="Void Main()" attrs="150">
+ <size>32</size>
+ </method>
+ <method name="Int32 Test()" attrs="134">
+ <size>10</size>
+ </method>
+ <method name="System.Object Foo()" attrs="129">
+ <size>10</size>
+ </method>
+ <method name="System.Object Test2()" attrs="134">
+ <size>23</size>
+ </method>
+ <method name="Void Test3(Int32 ByRef)" attrs="145">
+ <size>3</size>
+ </method>
+ <method name="Int32 get_Item(Int32)" attrs="2177">
+ <size>10</size>
+ </method>
+ <method name="Void add_Event(System.Action)" attrs="2182">
+ <size>3</size>
+ </method>
+ <method name="Void remove_Event(System.Action)" attrs="2182">
+ <size>3</size>
+ </method>
+ <method name="Void TestExpr_1(Boolean)" attrs="129">
+ <size>21</size>
+ </method>
+ <method name="Void TestExpr_2(Boolean)" attrs="129">
+ <size>21</size>
+ </method>
+ <method name="Void TestExpr_3(System.String)" attrs="129">
+ <size>18</size>
+ </method>
+ <method name="Void TestExpr_4()" attrs="129">
+ <size>16</size>
+ </method>
+ <method name="Void TestExpr_5()" attrs="129">
+ <size>32</size>
+ </method>
+ <method name="System.Object <Main>m__0()" attrs="145">
+ <size>10</size>
+ </method>
+ <method name="Void <TestExpr_5>m__1()" attrs="145">
+ <size>3</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ <method name="Int32 TestExpr_6(Int32 ByRef)" attrs="145">
+ <size>10</size>
+ </method>
+ <method name="Int32 TestExpr_7(Int32 ByRef)" attrs="129">
+ <size>15</size>
+ </method>
+ </type>
+ </test>
+ <test name="test-throw-expr-02.cs">
+ <type name="Program">
+ <method name="Int32 Main()" attrs="150">
+ <size>63</size>
+ </method>
+ <method name="System.String M(System.Object)" attrs="145">
+ <size>33</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-var-01.cs">
<type name="Test">
<method name="Int32 Main()" attrs="150">