using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Extraction.CSharp.Populators; using Semmle.Extraction.Kinds; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis; using Semmle.Extraction.Entities; namespace Semmle.Extraction.CSharp.Entities.Expressions { abstract class ElementAccess : Expression { protected ElementAccess(ExpressionNodeInfo info, ExpressionSyntax qualifier, BracketedArgumentListSyntax argumentList) : base(info.SetKind(GetKind(info.Context, qualifier))) { Qualifier = qualifier; ArgumentList = argumentList; } readonly ExpressionSyntax Qualifier; readonly BracketedArgumentListSyntax ArgumentList; protected override void Populate() { if (Kind == ExprKind.POINTER_INDIRECTION) { var qualifierInfo = new ExpressionNodeInfo(cx, Qualifier, this, 0); var add = new Expression(new ExpressionInfo(cx, qualifierInfo.Type, Location, ExprKind.ADD, this, 0, false, null)); qualifierInfo.SetParent(add, 0); CreateFromNode(qualifierInfo); PopulateArguments(ArgumentList, 1); } else { var child = -1; Create(cx, Qualifier, this, child++); foreach (var a in ArgumentList.Arguments) { cx.Extract(a, this, child++); } var symbolInfo = cx.GetSymbolInfo(base.Syntax); var indexer = symbolInfo.Symbol as IPropertySymbol; if (indexer != null) { cx.Emit(Tuples.expr_access(this, Indexer.Create(cx, indexer))); } } } public sealed override Microsoft.CodeAnalysis.Location ReportingLocation => base.ReportingLocation; static ExprKind GetKind(Context cx, ExpressionSyntax qualifier) { var qualifierType = cx.GetType(qualifier); // This is a compilation error, so make a guess and continue. if (qualifierType == null) return ExprKind.ARRAY_ACCESS; if (qualifierType.TypeKind == Microsoft.CodeAnalysis.TypeKind.Pointer) { // Convert expressions of the form a[b] into *(a+b) return ExprKind.POINTER_INDIRECTION; } return IsDynamic(cx, qualifier) ? ExprKind.DYNAMIC_ELEMENT_ACCESS : qualifierType.TypeKind == Microsoft.CodeAnalysis.TypeKind.Array ? ExprKind.ARRAY_ACCESS : ExprKind.INDEXER_ACCESS; } } class NormalElementAccess : ElementAccess { NormalElementAccess(ExpressionNodeInfo info) : base(info, ((ElementAccessExpressionSyntax)info.Node).Expression, ((ElementAccessExpressionSyntax)info.Node).ArgumentList) { } public static Expression Create(ExpressionNodeInfo info) => new NormalElementAccess(info).TryPopulate(); } class BindingElementAccess : ElementAccess { BindingElementAccess(ExpressionNodeInfo info) : base(info, FindConditionalQualifier(info.Node), ((ElementBindingExpressionSyntax)info.Node).ArgumentList) { } public static Expression Create(ExpressionNodeInfo info) => new BindingElementAccess(info).TryPopulate(); protected override void Populate() { base.Populate(); MakeConditional(); } } }