mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #5865 from tamasvajk/feature/remove-base-class-dependency-id
C#: Remove base class from type IDs in trap files
This commit is contained in:
@@ -170,7 +170,8 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
public static Expression? CreateGenerated(Context cx, IParameterSymbol parameter, IExpressionParentEntity parent,
|
||||
int childIndex, Extraction.Entities.Location location)
|
||||
{
|
||||
if (!parameter.HasExplicitDefaultValue)
|
||||
if (!parameter.HasExplicitDefaultValue ||
|
||||
parameter.Type is IErrorTypeSymbol)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
Symbol.BuildTypeId(Context, trapFile, Symbol);
|
||||
Symbol.BuildTypeId(Context, trapFile, Symbol, constructUnderlyingTupleType: false);
|
||||
trapFile.Write(";functionpointertype");
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
Symbol.BuildTypeId(Context, trapFile, Symbol);
|
||||
Symbol.BuildTypeId(Context, trapFile, Symbol, constructUnderlyingTupleType: false);
|
||||
trapFile.Write(";tuple");
|
||||
}
|
||||
|
||||
|
||||
@@ -81,22 +81,45 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
Symbol.BuildDisplayName(Context, trapFile, constructUnderlyingTupleType);
|
||||
trapFile.WriteLine("\")");
|
||||
|
||||
var baseTypes = GetBaseTypeDeclarations();
|
||||
|
||||
// Visit base types
|
||||
var baseTypes = new List<Type>();
|
||||
if (Symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
|
||||
{
|
||||
var baseKey = Create(Context, @base);
|
||||
trapFile.extend(this, baseKey.TypeRef);
|
||||
if (Symbol.TypeKind != TypeKind.Struct)
|
||||
baseTypes.Add(baseKey);
|
||||
var bts = GetBaseTypeDeclarations(baseTypes, @base);
|
||||
|
||||
Context.PopulateLater(() =>
|
||||
{
|
||||
var baseKey = Create(Context, @base);
|
||||
trapFile.extend(this, baseKey.TypeRef);
|
||||
|
||||
if (Symbol.TypeKind != TypeKind.Struct)
|
||||
{
|
||||
foreach (var bt in bts)
|
||||
{
|
||||
TypeMention.Create(Context, bt.Type, this, baseKey);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Visit implemented interfaces
|
||||
if (!(base.Symbol is IArrayTypeSymbol))
|
||||
{
|
||||
foreach (var t in base.Symbol.Interfaces.Select(i => Create(Context, i)))
|
||||
foreach (var i in base.Symbol.Interfaces)
|
||||
{
|
||||
trapFile.implement(this, t.TypeRef);
|
||||
baseTypes.Add(t);
|
||||
var bts = GetBaseTypeDeclarations(baseTypes, i);
|
||||
|
||||
Context.PopulateLater(() =>
|
||||
{
|
||||
var interfaceKey = Create(Context, i);
|
||||
trapFile.implement(this, interfaceKey.TypeRef);
|
||||
|
||||
foreach (var bt in bts)
|
||||
{
|
||||
TypeMention.Create(Context, bt.Type, this, interfaceKey);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,23 +168,30 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
Modifier.ExtractModifiers(Context, trapFile, this, Symbol);
|
||||
}
|
||||
|
||||
if (IsSourceDeclaration && Symbol.FromSource())
|
||||
private IEnumerable<BaseTypeSyntax> GetBaseTypeDeclarations()
|
||||
{
|
||||
if (!IsSourceDeclaration || !Symbol.FromSource())
|
||||
{
|
||||
var declSyntaxReferences = Symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()).ToArray();
|
||||
|
||||
var baseLists = declSyntaxReferences.OfType<ClassDeclarationSyntax>().Select(c => c.BaseList);
|
||||
baseLists = baseLists.Concat(declSyntaxReferences.OfType<InterfaceDeclarationSyntax>().Select(c => c.BaseList));
|
||||
baseLists = baseLists.Concat(declSyntaxReferences.OfType<StructDeclarationSyntax>().Select(c => c.BaseList));
|
||||
|
||||
baseLists
|
||||
.Where(bl => bl is not null)
|
||||
.SelectMany(bl => bl!.Types)
|
||||
.Zip(
|
||||
baseTypes.Where(bt => bt.Symbol.SpecialType != SpecialType.System_Object),
|
||||
(s, t) => TypeMention.Create(Context, s.Type, this, t))
|
||||
.Enumerate();
|
||||
return Enumerable.Empty<BaseTypeSyntax>();
|
||||
}
|
||||
|
||||
var declSyntaxReferences = Symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()).ToArray();
|
||||
|
||||
var baseLists = declSyntaxReferences.OfType<ClassDeclarationSyntax>().Select(c => c.BaseList);
|
||||
baseLists = baseLists.Concat(declSyntaxReferences.OfType<InterfaceDeclarationSyntax>().Select(c => c.BaseList));
|
||||
baseLists = baseLists.Concat(declSyntaxReferences.OfType<StructDeclarationSyntax>().Select(c => c.BaseList));
|
||||
|
||||
return baseLists
|
||||
.Where(bl => bl is not null)
|
||||
.SelectMany(bl => bl!.Types)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private IEnumerable<BaseTypeSyntax> GetBaseTypeDeclarations(IEnumerable<BaseTypeSyntax> baseTypes, INamedTypeSymbol type)
|
||||
{
|
||||
return baseTypes.Where(bt => SymbolEqualityComparer.Default.Equals(Context.GetModel(bt).GetTypeInfo(bt.Type).Type, type));
|
||||
}
|
||||
|
||||
private void ExtractParametersForDelegateLikeType(TextWriter trapFile, IMethodSymbol invokeMethod, Action<Type> storeReturnType)
|
||||
|
||||
@@ -121,8 +121,6 @@ namespace Semmle.Extraction.CSharp
|
||||
named = named.TupleUnderlyingType;
|
||||
if (IdDependsOnImpl(named.ContainingType))
|
||||
return true;
|
||||
if (IdDependsOnImpl(named.GetNonObjectBaseType(cx)))
|
||||
return true;
|
||||
if (IdDependsOnImpl(named.ConstructedFrom))
|
||||
return true;
|
||||
return named.TypeArguments.Any(IdDependsOnImpl);
|
||||
@@ -160,10 +158,7 @@ namespace Semmle.Extraction.CSharp
|
||||
/// <param name="trapFile">The trap builder used to store the result.</param>
|
||||
/// <param name="symbolBeingDefined">The outer symbol being defined (to avoid recursive ids).</param>
|
||||
/// <param name="constructUnderlyingTupleType">Whether to build a type ID for the underlying `System.ValueTuple` struct in the case of tuple types.</param>
|
||||
public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType = false) =>
|
||||
type.BuildTypeId(cx, trapFile, symbolBeingDefined, true, constructUnderlyingTupleType);
|
||||
|
||||
private static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
|
||||
public static void BuildTypeId(this ITypeSymbol type, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
|
||||
{
|
||||
using (cx.StackGuard)
|
||||
{
|
||||
@@ -171,7 +166,7 @@ namespace Semmle.Extraction.CSharp
|
||||
{
|
||||
case TypeKind.Array:
|
||||
var array = (IArrayTypeSymbol)type;
|
||||
array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
array.BuildArraySuffix(trapFile);
|
||||
return;
|
||||
case TypeKind.Class:
|
||||
@@ -181,16 +176,16 @@ namespace Semmle.Extraction.CSharp
|
||||
case TypeKind.Delegate:
|
||||
case TypeKind.Error:
|
||||
var named = (INamedTypeSymbol)type;
|
||||
named.BuildNamedTypeId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
|
||||
named.BuildNamedTypeId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
|
||||
return;
|
||||
case TypeKind.Pointer:
|
||||
var ptr = (IPointerTypeSymbol)type;
|
||||
ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
trapFile.Write('*');
|
||||
return;
|
||||
case TypeKind.TypeParameter:
|
||||
var tp = (ITypeParameterSymbol)type;
|
||||
tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
trapFile.Write('_');
|
||||
trapFile.Write(tp.Name);
|
||||
return;
|
||||
@@ -207,7 +202,7 @@ namespace Semmle.Extraction.CSharp
|
||||
}
|
||||
}
|
||||
|
||||
private static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType = false)
|
||||
private static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
|
||||
{
|
||||
if (symbol is null)
|
||||
{
|
||||
@@ -232,7 +227,7 @@ namespace Semmle.Extraction.CSharp
|
||||
if (SymbolEqualityComparer.Default.Equals(symbol, symbolBeingDefined))
|
||||
trapFile.Write("__self__");
|
||||
else if (symbol is ITypeSymbol type && type.IdDependsOn(cx, symbolBeingDefined))
|
||||
type.BuildTypeId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
|
||||
type.BuildTypeId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
|
||||
else if (symbol is INamedTypeSymbol namedType && namedType.IsTupleType && constructUnderlyingTupleType)
|
||||
trapFile.WriteSubId(NamedType.CreateNamedTypeFromTupleType(cx, namedType));
|
||||
else
|
||||
@@ -250,7 +245,7 @@ namespace Semmle.Extraction.CSharp
|
||||
/// <paramref name="symbol" />.
|
||||
/// </summary>
|
||||
public static void BuildOrWriteId(this ISymbol? symbol, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined) =>
|
||||
symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, true);
|
||||
symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an array suffix string for this array type symbol.
|
||||
@@ -287,7 +282,7 @@ namespace Semmle.Extraction.CSharp
|
||||
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildOrWriteId(cx, trapFile, symbolBeingDefined));
|
||||
}
|
||||
|
||||
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass, bool constructUnderlyingTupleType)
|
||||
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
|
||||
{
|
||||
if (!constructUnderlyingTupleType && named.IsTupleType)
|
||||
{
|
||||
@@ -297,7 +292,7 @@ namespace Semmle.Extraction.CSharp
|
||||
{
|
||||
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
|
||||
trapFile.Write(":");
|
||||
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
}
|
||||
);
|
||||
trapFile.Write(")");
|
||||
@@ -308,7 +303,7 @@ namespace Semmle.Extraction.CSharp
|
||||
{
|
||||
if (named.ContainingType is not null)
|
||||
{
|
||||
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
trapFile.Write('.');
|
||||
}
|
||||
else if (named.ContainingNamespace is not null)
|
||||
@@ -333,35 +328,17 @@ namespace Semmle.Extraction.CSharp
|
||||
}
|
||||
else
|
||||
{
|
||||
named.ConstructedFrom.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass, constructUnderlyingTupleType);
|
||||
named.ConstructedFrom.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType);
|
||||
trapFile.Write('<');
|
||||
// Encode the nullability of the type arguments in the label.
|
||||
// Type arguments with different nullability can result in
|
||||
// a constructed type with different nullability of its members and methods,
|
||||
// so we need to create a distinct database entity for it.
|
||||
trapFile.BuildList(",", named.GetAnnotatedTypeArguments(),
|
||||
ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass)
|
||||
ta => ta.Symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false)
|
||||
);
|
||||
trapFile.Write('>');
|
||||
}
|
||||
|
||||
if (addBaseClass && named.GetNonObjectBaseType(cx) is INamedTypeSymbol @base)
|
||||
{
|
||||
// We need to limit unfolding of base classes. For example, in
|
||||
//
|
||||
// ```csharp
|
||||
// class C1<T> { }
|
||||
// class C2<T> : C1<C3<T>> { }
|
||||
// class C3<T> : C1<C2<T>> { }
|
||||
// class C4 : C3<C4> { }
|
||||
// ```
|
||||
//
|
||||
// when we generate the label for `C4`, the base class `C3<C4>` has itself `C1<C2<C4>>` as
|
||||
// a base class, which in turn has `C1<C3<C4>>` as a base class. The latter has the original
|
||||
// base class `C3<C4>` as a type argument, which would lead to infinite unfolding.
|
||||
trapFile.Write(" : ");
|
||||
@base.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass: false);
|
||||
}
|
||||
}
|
||||
|
||||
private static void BuildNamespace(this INamespaceSymbol ns, Context cx, EscapingTextWriter trapFile)
|
||||
|
||||
@@ -529,7 +529,7 @@ function_pointer_return_type(
|
||||
int return_type_id: @type_or_ref ref);
|
||||
|
||||
extend(
|
||||
unique int sub: @type ref,
|
||||
int sub: @type ref,
|
||||
int super: @type_or_ref ref);
|
||||
|
||||
anonymous_types(
|
||||
|
||||
@@ -613,13 +613,13 @@ foreach.cs:
|
||||
# 5| r5_28(glval<Int32>) = PointerAdd[4] : r5_1, r5_27
|
||||
# 5| r5_29(Int32) = Constant[7] :
|
||||
# 5| mu5_30(Int32) = Store[?] : &:r5_28, r5_29
|
||||
# 7| r7_1(glval<IEnumerator>) = VariableAddress[#temp7:9] :
|
||||
# 7| r7_1(glval<Boolean>) = VariableAddress[#temp7:9] :
|
||||
# 7| r7_2(glval<Int32[]>) = VariableAddress[a_array] :
|
||||
# 7| r7_3(Int32[]) = Load[a_array] : &:r7_2, ~m?
|
||||
# 7| r7_4(<funcaddr>) = FunctionAddress[GetEnumerator] :
|
||||
# 7| r7_5(IEnumerator) = Call[GetEnumerator] : func:r7_4, this:r7_3
|
||||
# 7| mu7_6(<unknown>) = ^CallSideEffect : ~m?
|
||||
# 7| mu7_7(IEnumerator) = Store[#temp7:9] : &:r7_1, r7_5
|
||||
# 7| mu7_7(Boolean) = Store[#temp7:9] : &:r7_1, r7_5
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 7| Block 1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Removed unique base class constraint
|
||||
compatibility: backwards
|
||||
Reference in New Issue
Block a user