Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Safar <marek.safar@gmail.com>2014-12-04 16:18:18 +0300
committerMarek Safar <marek.safar@gmail.com>2014-12-04 16:18:18 +0300
commit336755ca9edfbb0dd5c395f59a398c76449f7fdc (patch)
treee141ff97fdb10097cb0d3a8de04b8057fbda88a5
parentb50017eba3a83ecbb495f4c698531696df043b78 (diff)
[mcs] Validate more nameof argument expressions
-rw-r--r--mcs/errors/cs0103-16.cs10
-rw-r--r--mcs/errors/cs7003-6.cs10
-rw-r--r--mcs/errors/cs7003-7.cs14
-rw-r--r--mcs/errors/cs7003-8.cs14
-rw-r--r--mcs/errors/cs8081-2.cs10
-rw-r--r--mcs/errors/cs8081.cs10
-rw-r--r--mcs/errors/cs8082.cs11
-rw-r--r--mcs/errors/cs8083.cs10
-rw-r--r--mcs/errors/cs8084-2.cs14
-rw-r--r--mcs/errors/cs8084.cs14
-rw-r--r--mcs/mcs/complete.cs2
-rw-r--r--mcs/mcs/constant.cs55
-rw-r--r--mcs/mcs/cs-parser.jay2
-rw-r--r--mcs/mcs/dynamic.cs2
-rw-r--r--mcs/mcs/ecore.cs21
-rw-r--r--mcs/mcs/expression.cs22
-rw-r--r--mcs/mcs/generic.cs15
-rw-r--r--mcs/tests/test-named-09.cs16
-rw-r--r--mcs/tests/test-pattern-06.cs12
-rw-r--r--mcs/tests/ver-il-net_4_5.xml14
20 files changed, 238 insertions, 40 deletions
diff --git a/mcs/errors/cs0103-16.cs b/mcs/errors/cs0103-16.cs
new file mode 100644
index 00000000000..da73c33c0a7
--- /dev/null
+++ b/mcs/errors/cs0103-16.cs
@@ -0,0 +1,10 @@
+// CS0103: The name `nameof' does not exist in the current context
+// Line: 8
+
+static class C
+{
+ static void Main ()
+ {
+ string s = nameof (nameof);
+ }
+} \ No newline at end of file
diff --git a/mcs/errors/cs7003-6.cs b/mcs/errors/cs7003-6.cs
new file mode 100644
index 00000000000..7c6fe68d46b
--- /dev/null
+++ b/mcs/errors/cs7003-6.cs
@@ -0,0 +1,10 @@
+// CS7003: Unbound generic name is not valid in this context
+// Line: 8
+
+class C
+{
+ static void Main ()
+ {
+ System.Action<>.Combine ();
+ }
+} \ No newline at end of file
diff --git a/mcs/errors/cs7003-7.cs b/mcs/errors/cs7003-7.cs
new file mode 100644
index 00000000000..e7bdd50145c
--- /dev/null
+++ b/mcs/errors/cs7003-7.cs
@@ -0,0 +1,14 @@
+// CS7003: Unbound generic name is not valid in this context
+// Line: 12
+
+static class C
+{
+ static void Foo<T> ()
+ {
+ }
+
+ static void Main ()
+ {
+ string s = nameof (Foo<>);
+ }
+} \ No newline at end of file
diff --git a/mcs/errors/cs7003-8.cs b/mcs/errors/cs7003-8.cs
new file mode 100644
index 00000000000..04d8b2c57d5
--- /dev/null
+++ b/mcs/errors/cs7003-8.cs
@@ -0,0 +1,14 @@
+// CS7003: Unbound generic name is not valid in this context
+// Line: 12
+
+static class C
+{
+ static void Foo<T> ()
+ {
+ }
+
+ static void Main ()
+ {
+ string s = nameof (C.Foo<>);
+ }
+} \ No newline at end of file
diff --git a/mcs/errors/cs8081-2.cs b/mcs/errors/cs8081-2.cs
new file mode 100644
index 00000000000..dcc1583db8a
--- /dev/null
+++ b/mcs/errors/cs8081-2.cs
@@ -0,0 +1,10 @@
+// CS8081: Expression does not have a name
+// Line: 8
+
+class C
+{
+ void Foo ()
+ {
+ string s = nameof (this);
+ }
+} \ No newline at end of file
diff --git a/mcs/errors/cs8081.cs b/mcs/errors/cs8081.cs
new file mode 100644
index 00000000000..366b9326a83
--- /dev/null
+++ b/mcs/errors/cs8081.cs
@@ -0,0 +1,10 @@
+// CS8081: Expression does not have a name
+// Line: 8
+
+class C
+{
+ static void Main ()
+ {
+ string s = nameof (Main ());
+ }
+} \ No newline at end of file
diff --git a/mcs/errors/cs8082.cs b/mcs/errors/cs8082.cs
new file mode 100644
index 00000000000..70afa6b7e79
--- /dev/null
+++ b/mcs/errors/cs8082.cs
@@ -0,0 +1,11 @@
+// CS8082: An argument to nameof operator cannot include sub-expression
+// Line: 9
+
+class C
+{
+ void Foo ()
+ {
+ object o = null;
+ var s = nameof (o.ToString ().Equals);
+ }
+} \ No newline at end of file
diff --git a/mcs/errors/cs8083.cs b/mcs/errors/cs8083.cs
new file mode 100644
index 00000000000..26b90c846a9
--- /dev/null
+++ b/mcs/errors/cs8083.cs
@@ -0,0 +1,10 @@
+// CS8083: An alias-qualified name is not an expression
+// Line: 8
+
+class C
+{
+ static void Main ()
+ {
+ string s = nameof (global::C);
+ }
+} \ No newline at end of file
diff --git a/mcs/errors/cs8084-2.cs b/mcs/errors/cs8084-2.cs
new file mode 100644
index 00000000000..8a5b00425dd
--- /dev/null
+++ b/mcs/errors/cs8084-2.cs
@@ -0,0 +1,14 @@
+// CS8084: An argument to nameof operator cannot be method group with type arguments
+// Line: 12
+
+static class C
+{
+ static void Foo<T> ()
+ {
+ }
+
+ static void Main ()
+ {
+ string s = nameof (C.Foo<int>);
+ }
+} \ No newline at end of file
diff --git a/mcs/errors/cs8084.cs b/mcs/errors/cs8084.cs
new file mode 100644
index 00000000000..c5861b515f6
--- /dev/null
+++ b/mcs/errors/cs8084.cs
@@ -0,0 +1,14 @@
+// CS8084: An argument to nameof operator cannot be method group with type arguments
+// Line: 12
+
+static class C
+{
+ static void Foo<T> ()
+ {
+ }
+
+ static void Main ()
+ {
+ string s = nameof (Foo<int>);
+ }
+} \ No newline at end of file
diff --git a/mcs/mcs/complete.cs b/mcs/mcs/complete.cs
index 3504302d589..749c4efcb8a 100644
--- a/mcs/mcs/complete.cs
+++ b/mcs/mcs/complete.cs
@@ -142,7 +142,7 @@ namespace Mono.CSharp {
}
if (targs != null) {
- if (!targs.Resolve (rc))
+ if (!targs.Resolve (rc, true))
return null;
}
diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs
index 18763aa8226..050dd83490f 100644
--- a/mcs/mcs/constant.cs
+++ b/mcs/mcs/constant.cs
@@ -2144,6 +2144,11 @@ namespace Mono.CSharp {
this.name = name;
}
+ static void Error_MethodGroupWithTypeArguments (ResolveContext rc, Location loc)
+ {
+ rc.Report.Error (8084, loc, "An argument to nameof operator cannot be method group with type arguments");
+ }
+
protected override Expression DoResolve (ResolveContext rc)
{
throw new NotSupportedException ();
@@ -2158,20 +2163,37 @@ namespace Mono.CSharp {
if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6)
rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator");
- sn.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity);
+ var res = sn.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity | MemberLookupRestrictions.NameOfExcluded);
+ if (sn.HasTypeArguments && res is MethodGroupExpr) {
+ Error_MethodGroupWithTypeArguments (rc, expr.Location);
+ }
+
return true;
}
var ma = expr as MemberAccess;
if (ma != null) {
+ var lexpr = ma.LeftExpression;
+
var res = ma.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity);
- if (res == null)
+ if (res == null) {
return false;
+ }
if (rc.Module.Compiler.Settings.Version < LanguageVersion.V_6)
rc.Report.FeatureIsNotAvailable (rc.Module.Compiler, Location, "nameof operator");
+ if (ma is QualifiedAliasMember) {
+ rc.Report.Error (8083, loc, "An alias-qualified name is not an expression");
+ return false;
+ }
+
+ if (!IsLeftExpressionValid (lexpr)) {
+ rc.Report.Error (8082, lexpr.Location, "An argument to nameof operator cannot include sub-expression");
+ return false;
+ }
+
var mg = res as MethodGroupExpr;
if (mg != null) {
var emg = res as ExtensionMethodGroupExpr;
@@ -2182,12 +2204,40 @@ namespace Mono.CSharp {
if (!mg.HasAccessibleCandidate (rc)) {
ErrorIsInaccesible (rc, ma.GetSignatureForError (), loc);
}
+
+ if (ma.HasTypeArguments) {
+ Error_MethodGroupWithTypeArguments (rc, ma.Location);
+ }
}
Value = ma.Name;
return true;
}
+ rc.Report.Error (8081, loc, "Expression does not have a name");
+ return false;
+ }
+
+ static bool IsLeftExpressionValid (Expression expr)
+ {
+ if (expr is SimpleName)
+ return true;
+
+ if (expr is This)
+ return true;
+
+ if (expr is NamespaceExpression)
+ return true;
+
+ if (expr is TypeExpr)
+ return true;
+
+ var ma = expr as MemberAccess;
+ if (ma != null) {
+ // TODO: Will conditional access be allowed?
+ return IsLeftExpressionValid (ma.LeftExpression);
+ }
+
return false;
}
@@ -2201,7 +2251,6 @@ namespace Mono.CSharp {
var arg = args [0];
var res = ResolveArgumentExpression (rc, arg.Expr);
if (!res) {
- name.Error_NameDoesNotExist (rc);
return null;
}
diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay
index ed173cc5e4b..16f79e22c3c 100644
--- a/mcs/mcs/cs-parser.jay
+++ b/mcs/mcs/cs-parser.jay
@@ -5929,6 +5929,7 @@ switch_label
Error_SyntaxError (yyToken);
$$ = new SwitchLabel ((Expression) $2, GetLocation ($1));
}
+/*
| CASE pattern_expr_invocation COLON
{
if (lang_version != LanguageVersion.Experimental)
@@ -5939,6 +5940,7 @@ switch_label
};
lbag.AddLocation ($$, GetLocation ($3));
}
+*/
| DEFAULT_COLON
{
$$ = new SwitchLabel (null, GetLocation ($1));
diff --git a/mcs/mcs/dynamic.cs b/mcs/mcs/dynamic.cs
index 8a9a0c87de2..33fb4555363 100644
--- a/mcs/mcs/dynamic.cs
+++ b/mcs/mcs/dynamic.cs
@@ -787,7 +787,7 @@ namespace Mono.CSharp
if (member != null && member.HasTypeArguments) {
TypeArguments ta = member.TypeArguments;
- if (ta.Resolve (ec)) {
+ if (ta.Resolve (ec, false)) {
var targs = new ArrayInitializer (ta.Count, loc);
foreach (TypeSpec t in ta.Arguments)
targs.Add (new TypeOf (t, loc));
diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs
index a02b28c9d84..80e13f33aae 100644
--- a/mcs/mcs/ecore.cs
+++ b/mcs/mcs/ecore.cs
@@ -819,7 +819,8 @@ namespace Mono.CSharp {
ReadAccess = 1 << 3,
EmptyArguments = 1 << 4,
IgnoreArity = 1 << 5,
- IgnoreAmbiguity = 1 << 6
+ IgnoreAmbiguity = 1 << 6,
+ NameOfExcluded = 1 << 7,
}
//
@@ -2521,7 +2522,7 @@ namespace Mono.CSharp {
}
protected ATypeNameExpression (string name, int arity, Location l)
- : this (name, new UnboundTypeArguments (arity), l)
+ : this (name, new UnboundTypeArguments (arity, l), l)
{
}
@@ -2563,11 +2564,6 @@ namespace Mono.CSharp {
(targs == null || targs.Equals (atne.targs));
}
- protected void Error_OpenGenericTypeIsNotAllowed (IMemberContext mc)
- {
- mc.Module.Compiler.Report.Error (7003, Location, "Unbound generic name is not valid in this context");
- }
-
public override int GetHashCode ()
{
return Name.GetHashCode ();
@@ -2703,8 +2699,7 @@ namespace Mono.CSharp {
return ct;
}
- if (!allowUnboundTypeArguments)
- Error_OpenGenericTypeIsNotAllowed (mc);
+ targs.Resolve (mc, allowUnboundTypeArguments);
return new GenericOpenTypeExpr (fne.Type, loc);
}
@@ -2839,7 +2834,7 @@ namespace Mono.CSharp {
me = me.ResolveMemberAccess (rc, null, null);
if (Arity > 0) {
- targs.Resolve (rc);
+ targs.Resolve (rc, false);
me.SetTypeArguments (rc, targs);
}
@@ -2863,13 +2858,13 @@ namespace Mono.CSharp {
var mg = NamespaceContainer.LookupStaticUsings (rc, Name, Arity, loc);
if (mg != null) {
if (Arity > 0) {
- targs.Resolve (rc);
+ targs.Resolve (rc, false);
mg.SetTypeArguments (rc, targs);
}
return mg;
}
- if (Name == "nameof")
+ if ((restrictions & MemberLookupRestrictions.NameOfExcluded) == 0 && Name == "nameof")
return new NameOf (this);
if (errorMode) {
@@ -3130,7 +3125,7 @@ namespace Mono.CSharp {
return this;
}
- public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity)
+ public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity, Location loc)
{
var retval = Namespace.LookupType (ctx, name, arity, LookupMode.IgnoreAccessibility, loc);
if (retval != null) {
diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs
index 017ef439f11..deb121c140d 100644
--- a/mcs/mcs/expression.cs
+++ b/mcs/mcs/expression.cs
@@ -9666,12 +9666,16 @@ namespace Mono.CSharp
var retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc);
if (retval == null) {
- ns.Error_NamespaceDoesNotExist (rc, Name, Arity);
+ ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc);
return null;
}
- if (HasTypeArguments)
- return new GenericTypeExpr (retval.Type, targs, loc);
+ if (Arity > 0) {
+ if (HasTypeArguments)
+ return new GenericTypeExpr (retval.Type, targs, loc);
+
+ targs.Resolve (rc, false);
+ }
return retval;
}
@@ -9720,7 +9724,7 @@ namespace Mono.CSharp
if (methods != null) {
var emg = new ExtensionMethodGroupExpr (methods, expr, loc);
if (HasTypeArguments) {
- if (!targs.Resolve (rc))
+ if (!targs.Resolve (rc, false))
return null;
emg.SetTypeArguments (rc, targs);
@@ -9799,7 +9803,7 @@ namespace Mono.CSharp
me = me.ResolveMemberAccess (rc, expr, sn);
if (Arity > 0) {
- if (!targs.Resolve (rc))
+ if (!targs.Resolve (rc, false))
return null;
me.SetTypeArguments (rc, targs);
@@ -9826,15 +9830,14 @@ namespace Mono.CSharp
FullNamedExpression retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc);
if (retval == null) {
- ns.Error_NamespaceDoesNotExist (rc, Name, Arity);
+ ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc);
} else if (Arity > 0) {
if (HasTypeArguments) {
retval = new GenericTypeExpr (retval.Type, targs, loc);
if (retval.ResolveAsType (rc) == null)
return null;
} else {
- if (!allowUnboundTypeArguments)
- Error_OpenGenericTypeIsNotAllowed (rc);
+ targs.Resolve (rc, allowUnboundTypeArguments);
retval = new GenericOpenTypeExpr (retval.Type, loc);
}
@@ -9895,8 +9898,7 @@ namespace Mono.CSharp
if (HasTypeArguments) {
texpr = new GenericTypeExpr (nested, targs, loc);
} else {
- if (!allowUnboundTypeArguments || expr_resolved is GenericTypeExpr) // && HasTypeArguments
- Error_OpenGenericTypeIsNotAllowed (rc);
+ targs.Resolve (rc, allowUnboundTypeArguments && !(expr_resolved is GenericTypeExpr));
texpr = new GenericOpenTypeExpr (nested, loc);
}
diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs
index f549432b29a..304f0e52b0a 100644
--- a/mcs/mcs/generic.cs
+++ b/mcs/mcs/generic.cs
@@ -2186,7 +2186,7 @@ namespace Mono.CSharp {
/// <summary>
/// Resolve the type arguments.
/// </summary>
- public virtual bool Resolve (IMemberContext ec)
+ public virtual bool Resolve (IMemberContext ec, bool allowUnbound)
{
if (atypes != null)
return true;
@@ -2239,9 +2239,12 @@ namespace Mono.CSharp {
public class UnboundTypeArguments : TypeArguments
{
- public UnboundTypeArguments (int arity)
+ Location loc;
+
+ public UnboundTypeArguments (int arity, Location loc)
: base (new FullNamedExpression[arity])
{
+ this.loc = loc;
}
public override bool IsEmpty {
@@ -2250,8 +2253,12 @@ namespace Mono.CSharp {
}
}
- public override bool Resolve (IMemberContext ec)
+ public override bool Resolve (IMemberContext mc, bool allowUnbound)
{
+ if (!allowUnbound) {
+ mc.Module.Compiler.Report.Error (7003, loc, "Unbound generic name is not valid in this context");
+ }
+
// Nothing to be resolved
return true;
}
@@ -2437,7 +2444,7 @@ namespace Mono.CSharp {
if (eclass != ExprClass.Unresolved)
return type;
- if (!args.Resolve (mc))
+ if (!args.Resolve (mc, allowUnboundTypeArguments))
return null;
TypeSpec[] atypes = args.Arguments;
diff --git a/mcs/tests/test-named-09.cs b/mcs/tests/test-named-09.cs
new file mode 100644
index 00000000000..a44dca3a154
--- /dev/null
+++ b/mcs/tests/test-named-09.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+
+class X
+{
+ public static int Main ()
+ {
+ switch (nameof (Dictionary<int,int>.Add)) {
+ case nameof (List<int>.Equals):
+ return 1;
+ case nameof(List<int>.Add):
+ return 0;
+ default:
+ return 2;
+ }
+ }
+} \ No newline at end of file
diff --git a/mcs/tests/test-pattern-06.cs b/mcs/tests/test-pattern-06.cs
index 3b54b840acf..335f075e997 100644
--- a/mcs/tests/test-pattern-06.cs
+++ b/mcs/tests/test-pattern-06.cs
@@ -15,8 +15,8 @@ class RecursiveNamedPattern
if (Switch_1 (1) != 1)
return 3;
- if (Switch_1 (new C1 ()) != 3)
- return 4;
+// if (Switch_1 (new C1 ()) != 3)
+// return 4;
if (Switch_1 ((byte?) 1) != 1)
return 5;
@@ -36,10 +36,10 @@ class RecursiveNamedPattern
switch (o) {
case 1:
return 1;
- case C1 (3):
- return 2;
- case C1 (2):
- return 3;
+// case C1 (3):
+// return 2;
+// case C1 (2):
+// return 3;
case null:
return 4;
default:
diff --git a/mcs/tests/ver-il-net_4_5.xml b/mcs/tests/ver-il-net_4_5.xml
index c102999bf27..fd4e9ad17ad 100644
--- a/mcs/tests/ver-il-net_4_5.xml
+++ b/mcs/tests/ver-il-net_4_5.xml
@@ -67820,6 +67820,16 @@
</method>
</type>
</test>
+ <test name="test-named-09.cs">
+ <type name="X">
+ <method name="Int32 Main()" attrs="150">
+ <size>11</size>
+ </method>
+ <method name="Void .ctor()" attrs="6278">
+ <size>7</size>
+ </method>
+ </type>
+ </test>
<test name="test-nameof-01.cs">
<type name="X">
<method name="Int32 Main()" attrs="150">
@@ -69101,10 +69111,10 @@
<test name="test-pattern-06.cs">
<type name="RecursiveNamedPattern">
<method name="Int32 Main()" attrs="150">
- <size>182</size>
+ <size>159</size>
</method>
<method name="Int32 Switch_1(System.Object)" attrs="145">
- <size>149</size>
+ <size>53</size>
</method>
<method name="Int32 Switch_2(C1)" attrs="145">
<size>28</size>