#1087. Added tests for static invocations and type object member ambiguity
diff --git a/LanguageFeatures/Constructor-tear-offs/ambiguities_A34_t01.dart b/LanguageFeatures/Constructor-tear-offs/ambiguities_A34_t01.dart
index b906ce9..7f0d24f 100644
--- a/LanguageFeatures/Constructor-tear-offs/ambiguities_A34_t01.dart
+++ b/LanguageFeatures/Constructor-tear-offs/ambiguities_A34_t01.dart
@@ -47,7 +47,7 @@
   int a = 1;
   int b = 2;
   int c = 3;
-  int d = 4;
+
   f(a<b,
       c>@A);
 //      ^
diff --git a/LanguageFeatures/Constructor-tear-offs/static_invocations_A01_t01.dart b/LanguageFeatures/Constructor-tear-offs/static_invocations_A01_t01.dart
new file mode 100644
index 0000000..7877d00
--- /dev/null
+++ b/LanguageFeatures/Constructor-tear-offs/static_invocations_A01_t01.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// @assertion A static member invocation still only works on an uninstantiated
+/// type literal. You can write List.copyRange, but not List<int>.copyRange.
+///
+/// Allowing List<int>.copyRange is confusing. The invocation will not have
+/// access to the type parameter anyway, so allowing it is not going to help
+/// anyone. The occurrence of List in List.copyRange refers to the class
+/// declaration, treated as a namespace, not the class itself.
+///
+/// This goes for type aliases too. We can declare typedef MyList<T> = List<T>;
+/// and typedef IntList = List<int>; and do MyList.copyRange or
+/// IntList.copyRange to access the static member of the declaration of the type
+/// being aliased. This is specially introduced semantics for aliases of class
+/// or mixin types, not something that falls out of first resolving the type
+/// alias to the class or mixin type. We do not allow MyList<int>.copyRange
+/// either, even though we allow IntList.copyRange. They are not the same when
+/// doing static member accesses.
+///
+/// @description Checks that List<int>.copyRange is a compile time error
+/// @author sgrekhov@unipro.ru
+
+// SharedOptions=--enable-experiment=constructor-tearoffs
+
+main() {
+  var f1 = List.copyRange;
+  var f2 = List<int>.copyRange;
+//             ^^^^^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
diff --git a/LanguageFeatures/Constructor-tear-offs/static_invocations_A02_t01.dart b/LanguageFeatures/Constructor-tear-offs/static_invocations_A02_t01.dart
new file mode 100644
index 0000000..4a15c27
--- /dev/null
+++ b/LanguageFeatures/Constructor-tear-offs/static_invocations_A02_t01.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// @assertion A static member invocation still only works on an uninstantiated
+/// type literal. You can write List.copyRange, but not List<int>.copyRange.
+///
+/// Allowing List<int>.copyRange is confusing. The invocation will not have
+/// access to the type parameter anyway, so allowing it is not going to help
+/// anyone. The occurrence of List in List.copyRange refers to the class
+/// declaration, treated as a namespace, not the class itself.
+///
+/// This goes for type aliases too. We can declare typedef MyList<T> = List<T>;
+/// and typedef IntList = List<int>; and do MyList.copyRange or
+/// IntList.copyRange to access the static member of the declaration of the type
+/// being aliased. This is specially introduced semantics for aliases of class
+/// or mixin types, not something that falls out of first resolving the type
+/// alias to the class or mixin type. We do not allow MyList<int>.copyRange
+/// either, even though we allow IntList.copyRange. They are not the same when
+/// doing static member accesses.
+///
+/// @description Checks that it is allowed to tear off MyList.copyRange and
+/// IntList.copyRange, where
+/// typedef MyList<T> = List<T>;
+/// typedef IntList = List<int>;
+/// @author sgrekhov@unipro.ru
+
+// SharedOptions=--enable-experiment=constructor-tearoffs
+
+import "../../Utils/expect.dart";
+
+typedef MyList<T> = List<T>;
+typedef IntList = List<int>;
+
+main() {
+  var list1 = [1, 2, 3, 4];
+  var list2 = [3, 1, 4];
+  var f1 = MyList.copyRange;
+  var f2 = IntList.copyRange;
+  f1(list1, 1, list2);
+  Expect.listEquals([1, 3, 1, 4], list1);
+  f2(list1, 0, list2);
+  Expect.listEquals([3, 1, 4, 4], list1);
+}
diff --git a/LanguageFeatures/Constructor-tear-offs/static_invocations_A02_t02.dart b/LanguageFeatures/Constructor-tear-offs/static_invocations_A02_t02.dart
new file mode 100644
index 0000000..666a439
--- /dev/null
+++ b/LanguageFeatures/Constructor-tear-offs/static_invocations_A02_t02.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// @assertion A static member invocation still only works on an uninstantiated
+/// type literal. You can write List.copyRange, but not List<int>.copyRange.
+///
+/// Allowing List<int>.copyRange is confusing. The invocation will not have
+/// access to the type parameter anyway, so allowing it is not going to help
+/// anyone. The occurrence of List in List.copyRange refers to the class
+/// declaration, treated as a namespace, not the class itself.
+///
+/// This goes for type aliases too. We can declare typedef MyList<T> = List<T>;
+/// and typedef IntList = List<int>; and do MyList.copyRange or
+/// IntList.copyRange to access the static member of the declaration of the type
+/// being aliased. This is specially introduced semantics for aliases of class
+/// or mixin types, not something that falls out of first resolving the type
+/// alias to the class or mixin type. We do not allow MyList<int>.copyRange
+/// either, even though we allow IntList.copyRange. They are not the same when
+/// doing static member accesses.
+///
+/// @description Checks that it MyList<int>.copyRange; where
+/// typedef MyList<T> = List<T>;
+/// produces a compile time error
+/// @author sgrekhov@unipro.ru
+
+// SharedOptions=--enable-experiment=constructor-tearoffs
+
+typedef MyList<T> = List<T>;
+
+main() {
+  var f1 = MyList<int>.copyRange;
+//               ^^^^^
+// [analyzer] unspecified
+// [cfe] unspecified
+}
diff --git a/LanguageFeatures/Constructor-tear-offs/type_object_member_ambiguity_A01_t01.dart b/LanguageFeatures/Constructor-tear-offs/type_object_member_ambiguity_A01_t01.dart
new file mode 100644
index 0000000..1125c74
--- /dev/null
+++ b/LanguageFeatures/Constructor-tear-offs/type_object_member_ambiguity_A01_t01.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// @assertion Constructor/type object member ambiguity
+/// Until now, writing C.foo means that foo must be a static member of C. If you
+/// write C.toString(), then it's interpreted as trying to call a static
+/// toString method on the class C, not the instance toString method of the Type
+/// object for the class C. You have to write (C).toString() if that is what you
+/// want.
+///
+/// Similarly, we always treat C<T>.toString() as an attempted constructor
+/// invocation, not an invocation of the instance toString method of the Type
+/// object corresponding to C<T> (which is now otherwise a valid expression).
+///
+/// That is, disambiguation of the otherwise grammatically ambiguous
+/// "(instantiated class-reference or type-literal).name" always chooses the
+/// "constructor tear-off" interpretation over the "type-literal instance
+/// member" interpretation. If followed by an argument list, it's always treated
+/// as a constructor invocation, not the (now otherwise allowed) Type object
+/// instance method invocation. This is a generalization of what we already do
+/// for static members and for constructor invocations.
+///
+/// @description Checks that C<T>.toString() is treated as a constructor
+/// invocation, not as a call ot Type.toString()
+/// @author sgrekhov@unipro.ru
+
+// SharedOptions=--enable-experiment=constructor-tearoffs
+
+import "../../Utils/expect.dart";
+
+class C {
+  C.toString() {}
+}
+
+main() {
+  Expect.isTrue(C.toString() is C);
+  Expect.isTrue((C).toString() is String);
+}
diff --git a/LanguageFeatures/Constructor-tear-offs/type_object_member_ambiguity_A01_t02.dart b/LanguageFeatures/Constructor-tear-offs/type_object_member_ambiguity_A01_t02.dart
new file mode 100644
index 0000000..b388e10
--- /dev/null
+++ b/LanguageFeatures/Constructor-tear-offs/type_object_member_ambiguity_A01_t02.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// @assertion Constructor/type object member ambiguity
+/// Until now, writing C.foo means that foo must be a static member of C. If you
+/// write C.toString(), then it's interpreted as trying to call a static
+/// toString method on the class C, not the instance toString method of the Type
+/// object for the class C. You have to write (C).toString() if that is what you
+/// want.
+///
+/// Similarly, we always treat C<T>.toString() as an attempted constructor
+/// invocation, not an invocation of the instance toString method of the Type
+/// object corresponding to C<T> (which is now otherwise a valid expression).
+///
+/// That is, disambiguation of the otherwise grammatically ambiguous
+/// "(instantiated class-reference or type-literal).name" always chooses the
+/// "constructor tear-off" interpretation over the "type-literal instance
+/// member" interpretation. If followed by an argument list, it's always treated
+/// as a constructor invocation, not the (now otherwise allowed) Type object
+/// instance method invocation. This is a generalization of what we already do
+/// for static members and for constructor invocations.
+///
+/// @description Checks that C<T>.toString() is treated as a constructor
+/// invocation, not as a call ot Type.toString()
+/// @author sgrekhov@unipro.ru
+
+// SharedOptions=--enable-experiment=constructor-tearoffs
+
+import "../../Utils/expect.dart";
+
+class C<T> {
+  C.toString() {}
+}
+
+main() {
+  Expect.isTrue(C<int>.toString() is C);
+  Expect.isTrue((C<int>).toString() is String);
+}