mirror of
https://github.com/github/codeql.git
synced 2025-12-19 18:33:16 +01:00
166 lines
3.3 KiB
C#
166 lines
3.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using static StaticMethods;
|
|
|
|
interface I1 { int Foo(); }
|
|
interface I2 { float Foo(); }
|
|
interface I3 : I2 { }
|
|
interface I4 : I3 { }
|
|
|
|
class A : I1, I2
|
|
{
|
|
public int Foo() { return 0; }
|
|
float I2.Foo() { return 0; }
|
|
public void M(A a) { }
|
|
}
|
|
|
|
class B : A
|
|
{
|
|
public static bool operator==(B b1, B b2) { return false; }
|
|
public static bool operator!=(B b1, B b2) { return true; }
|
|
public void M(B b) { }
|
|
}
|
|
|
|
class C : B { }
|
|
|
|
class D : C { }
|
|
|
|
static class AExtensions1
|
|
{
|
|
public static void M1(this A a, A x) { }
|
|
public static void M2(this A a, A x) { }
|
|
}
|
|
|
|
static class AExtensions2
|
|
{
|
|
public static void M2(this A a, B b) { }
|
|
}
|
|
|
|
class Tests
|
|
{
|
|
void Fn(A a) { }
|
|
void Fn(B a) { }
|
|
void Fn2(A a) { }
|
|
|
|
void Test1(string[] args)
|
|
{
|
|
A a = new A();
|
|
B b = new B();
|
|
object o;
|
|
|
|
o = (A)b; // BAD
|
|
|
|
o = (B)b; // GOOD: Not an upcast
|
|
|
|
b.M((A)b); // GOOD: Disambiguating method call
|
|
|
|
a.M1((A)b); // BAD
|
|
a.M2((A)b); // GOOD: Disambiguating method call
|
|
|
|
o = true ? (A)a : b; // GOOD: Needed for ternary
|
|
|
|
o = a ?? (A)b; // GOOD: Null coalescing expression
|
|
|
|
Fn((A)b); // GOOD: Disambiguating method call
|
|
|
|
Fn2((A)b); // BAD
|
|
|
|
((I2)a).Foo(); // GOOD: Cast to an interface
|
|
|
|
o = a==(A)b; // GOOD: EQExpr
|
|
|
|
o = b==(B)b; // GOOD: Operator call
|
|
|
|
var act = (Action) (() => { }); // GOOD
|
|
|
|
var objects = args.Select(arg => (object)arg); // GOOD
|
|
|
|
M1((A)b); // GOOD: disambiguate targets from `StaticMethods`
|
|
StaticMethods.M1((A)b); // GOOD: disambiguate targets from `StaticMethods`
|
|
|
|
void M2(A _) { }
|
|
M2((A)b); // BAD: local functions cannot be overloaded
|
|
}
|
|
|
|
static void M2(A _) { }
|
|
|
|
void Test2(B b)
|
|
{
|
|
// BAD: even though `StaticMethods` has an `M2`, only overloads in
|
|
// `Tests` are taken into account
|
|
M2((A)b);
|
|
}
|
|
|
|
class Nested
|
|
{
|
|
static void M2(B _) { }
|
|
|
|
static void Test(C c)
|
|
{
|
|
// BAD: even though `StaticMethods` and `Tests` have `M2`s, only
|
|
// overloads in `Nested` are taken into account
|
|
M2((B)c);
|
|
}
|
|
}
|
|
}
|
|
|
|
static class IExtensions
|
|
{
|
|
public static void M1(this I2 i) { }
|
|
|
|
public static void M1(this I3 i) =>
|
|
M1((I2)i); // GOOD
|
|
|
|
public static void M1(I4 i)
|
|
{
|
|
M1((I3)i); // GOOD
|
|
((I3)i).M1(); // GOOD
|
|
}
|
|
|
|
public static void M2(I2 i) { }
|
|
|
|
public static void M2(this I3 i) =>
|
|
M2((I2)i); // GOOD
|
|
}
|
|
|
|
static class StaticMethods
|
|
{
|
|
public static void M1(A _) { }
|
|
public static void M1(B _) { }
|
|
public static void M2(B _) { }
|
|
}
|
|
|
|
class Constructors : I2
|
|
{
|
|
Constructors(I1 i) { }
|
|
Constructors(I2 i) { }
|
|
Constructors(Constructors c) : this((I1)c) { } // GOOD
|
|
Constructors(Sub s) : this((I2)s) { } // GOOD
|
|
|
|
void M(Constructors c)
|
|
{
|
|
new Constructors((I1)c); // GOOD
|
|
new Constructors((I2)c); // GOOD
|
|
}
|
|
|
|
public int Foo() => 0;
|
|
|
|
float I2.Foo() => 0;
|
|
|
|
class Sub : Constructors
|
|
{
|
|
public Sub(Sub s) : base((I1)s) { } // GOOD
|
|
}
|
|
|
|
class SubSub : Sub
|
|
{
|
|
SubSub(SubSub ss) : base((Sub)ss) { } // BAD
|
|
|
|
void M(SubSub ss)
|
|
{
|
|
new Sub((Sub)ss); // BAD
|
|
}
|
|
}
|
|
}
|