private void SetValueForComparisonOperator(IOperation target, IOperation assignedValue, bool equals, ref PredicateValueKind predicateValueKind, ValueContentAnalysisData targetAnalysisData)
            {
                ValueContentAbstractValue currentAssignedValue = GetCachedAbstractValue(assignedValue);

                if (currentAssignedValue.IsLiteralState &&
                    AnalysisEntityFactory.TryCreate(target, out AnalysisEntity targetEntity))
                {
                    if (CurrentAnalysisData.TryGetValue(targetEntity, out ValueContentAbstractValue existingTargetValue) &&
                        existingTargetValue.IsLiteralState)
                    {
                        var newValue = currentAssignedValue.IntersectLiteralValues(existingTargetValue);
                        if (newValue.NonLiteralState == ValueContainsNonLiteralState.Invalid)
                        {
                            predicateValueKind = equals ? PredicateValueKind.AlwaysFalse : PredicateValueKind.AlwaysTrue;
                        }
                        else if (predicateValueKind != PredicateValueKind.AlwaysFalse &&
                                 newValue.IsLiteralState &&
                                 newValue.LiteralValues.Count == 1 &&
                                 currentAssignedValue.LiteralValues.Count == 1 &&
                                 existingTargetValue.LiteralValues.Count == 1)
                        {
                            predicateValueKind = equals ? PredicateValueKind.AlwaysTrue : PredicateValueKind.AlwaysFalse;
                        }

                        currentAssignedValue = newValue;
                    }

                    if (equals)
                    {
                        CopyAbstractValue copyValue = GetCopyAbstractValue(target);
                        if (copyValue.Kind.IsKnown())
                        {
                            // https://github.com/dotnet/roslyn-analyzers/issues/2106 tracks enabling the below assert.
                            //Debug.Assert(copyValue.AnalysisEntities.Contains(targetEntity));
                            foreach (var analysisEntity in copyValue.AnalysisEntities)
                            {
                                SetAbstractValue(targetAnalysisData, analysisEntity, currentAssignedValue);
                            }
                        }
                        else
                        {
                            SetAbstractValue(targetAnalysisData, targetEntity, currentAssignedValue);
                        }
                    }
                }
            }
Exemplo n.º 2
0
            private bool SetValueForComparisonOperator(IOperation target, IOperation assignedValue, PointsToAnalysisData negatedCurrentAnalysisData, bool equals, ref PredicateValueKind predicateValueKind)
            {
                NullAbstractValue value = GetNullAbstractValue(assignedValue);

                if (IsValidValueForPredicateAnalysis(value) &&
                    AnalysisEntityFactory.TryCreate(target, out AnalysisEntity targetEntity))
                {
                    bool inferInCurrentAnalysisData        = true;
                    bool inferInNegatedCurrentAnalysisData = true;
                    if (value == NullAbstractValue.NotNull)
                    {
                        // Comparison with a non-null value guarantees that we can infer result in only one of the branches.
                        // For example, predicate "a == c", where we know 'c' is non-null, guarantees 'a' is non-null in CurrentAnalysisData,
                        // but we cannot infer anything about nullness of 'a' in NegatedCurrentAnalysisData.
                        if (equals)
                        {
                            inferInNegatedCurrentAnalysisData = false;
                        }
                        else
                        {
                            inferInCurrentAnalysisData = false;
                        }
                    }

                    CopyAbstractValue copyValue = GetCopyAbstractValue(target);
                    if (copyValue.Kind == CopyAbstractValueKind.Known)
                    {
                        Debug.Assert(copyValue.AnalysisEntities.Contains(targetEntity));
                        foreach (var analysisEntity in copyValue.AnalysisEntities)
                        {
                            SetValueFromPredicate(analysisEntity, value, negatedCurrentAnalysisData, equals,
                                                  inferInCurrentAnalysisData, inferInNegatedCurrentAnalysisData, target, ref predicateValueKind);
                        }
                    }
                    else
                    {
                        SetValueFromPredicate(targetEntity, value, negatedCurrentAnalysisData, equals,
                                              inferInCurrentAnalysisData, inferInNegatedCurrentAnalysisData, target, ref predicateValueKind);
                    }

                    return(true);
                }

                return(false);
            }
Exemplo n.º 3
0
            private void SetValueForComparisonOperator(IOperation target, IOperation assignedValue, StringContentAnalysisData negatedCurrentAnalysisData, bool equals, ref PredicateValueKind predicateValueKind)
            {
                var analysisData = equals ? CurrentAnalysisData : negatedCurrentAnalysisData;
                StringContentAbstractValue stringContentValue = GetCachedAbstractValue(assignedValue);

                if (stringContentValue.IsLiteralState &&
                    AnalysisEntityFactory.TryCreate(target, out AnalysisEntity targetEntity))
                {
                    if (analysisData.TryGetValue(targetEntity, out StringContentAbstractValue existingValue) &&
                        existingValue.IsLiteralState)
                    {
                        var newStringContentValue = stringContentValue.IntersectLiteralValues(existingValue);
                        if (newStringContentValue.NonLiteralState == StringContainsNonLiteralState.Invalid)
                        {
                            predicateValueKind = equals ? PredicateValueKind.AlwaysFalse : PredicateValueKind.AlwaysTrue;
                        }
                        else if (predicateValueKind != PredicateValueKind.AlwaysFalse &&
                                 newStringContentValue.IsLiteralState &&
                                 newStringContentValue.LiteralValues.Count == 1 &&
                                 stringContentValue.LiteralValues.Count == 1 &&
                                 existingValue.LiteralValues.Count == 1)
                        {
                            predicateValueKind = equals ? PredicateValueKind.AlwaysTrue : PredicateValueKind.AlwaysFalse;
                        }

                        stringContentValue = newStringContentValue;
                    }

                    CopyAbstractValue copyValue = GetCopyAbstractValue(target);
                    if (copyValue.Kind == CopyAbstractValueKind.Known)
                    {
                        Debug.Assert(copyValue.AnalysisEntities.Contains(targetEntity));
                        foreach (var analysisEntity in copyValue.AnalysisEntities)
                        {
                            SetAbstractValue(analysisData, analysisEntity, stringContentValue);
                        }
                    }
                    else
                    {
                        SetAbstractValue(analysisData, targetEntity, stringContentValue);
                    }
                }
            }
        public bool TryCreate(IOperation operation, [NotNullWhen(returnValue: true)] out AnalysisEntity?analysisEntity)
        {
            if (_analysisEntityMap.TryGetValue(operation, out analysisEntity))
            {
                return(analysisEntity != null);
            }

            analysisEntity = null;
            ISymbol?symbol = null;
            ImmutableArray <AbstractIndex> indices = ImmutableArray <AbstractIndex> .Empty;
            IOperation? instance = null;
            ITypeSymbol?type     = operation.Type;

            switch (operation)
            {
            case ILocalReferenceOperation localReference:
                symbol = localReference.Local;
                break;

            case IParameterReferenceOperation parameterReference:
                symbol = parameterReference.Parameter;
                break;

            case IMemberReferenceOperation memberReference:
                instance = memberReference.Instance;
                GetSymbolAndIndicesForMemberReference(memberReference, ref symbol, ref indices);

                // Workaround for https://github.com/dotnet/roslyn/issues/22736 (IPropertyReferenceExpressions in IAnonymousObjectCreationExpression are missing a receiver).
                if (instance == null &&
                    symbol != null &&
                    memberReference is IPropertyReferenceOperation propertyReference)
                {
                    instance = propertyReference.GetAnonymousObjectCreation();
                }

                break;

            case IArrayElementReferenceOperation arrayElementReference:
                instance = arrayElementReference.ArrayReference;
                indices  = CreateAbstractIndices(arrayElementReference.Indices);
                break;

            case IDynamicIndexerAccessOperation dynamicIndexerAccess:
                instance = dynamicIndexerAccess.Operation;
                indices  = CreateAbstractIndices(dynamicIndexerAccess.Arguments);
                break;

            case IConditionalAccessInstanceOperation conditionalAccessInstance:
                IConditionalAccessOperation?conditionalAccess = conditionalAccessInstance.GetConditionalAccess();
                instance = conditionalAccess?.Operation;
                if (conditionalAccessInstance.Parent is IMemberReferenceOperation memberReferenceParent)
                {
                    GetSymbolAndIndicesForMemberReference(memberReferenceParent, ref symbol, ref indices);
                }
                break;

            case IInstanceReferenceOperation instanceReference:
                if (_getPointsToAbstractValue != null)
                {
                    instance = instanceReference.GetInstance(_getIsInsideAnonymousObjectInitializer());
                    if (instance == null)
                    {
                        // Reference to this or base instance.
                        analysisEntity = _interproceduralCallStack != null && _interproceduralCallStack.Peek().DescendantsAndSelf().Contains(instanceReference) ?
                                         _interproceduralThisOrMeInstanceForCaller :
                                         ThisOrMeInstance;
                    }
                    else
                    {
                        var instanceLocation = _getPointsToAbstractValue(instanceReference);
                        analysisEntity = AnalysisEntity.Create(instanceReference, instanceLocation);
                    }
                }
                break;

            case IConversionOperation conversion:
                return(TryCreate(conversion.Operand, out analysisEntity));

            case IParenthesizedOperation parenthesized:
                return(TryCreate(parenthesized.Operand, out analysisEntity));

            case IArgumentOperation argument:
                return(TryCreate(argument.Value, out analysisEntity));

            case IFlowCaptureOperation flowCapture:
                var isLvalueFlowCapture = _getIsLValueFlowCapture(flowCapture);
                analysisEntity = GetOrCreateForFlowCapture(flowCapture.Id, flowCapture.Value.Type, flowCapture, isLvalueFlowCapture);

                // Store flow capture copy values for simple flow captures of non-flow captured entity.
                // This enables pseudo copy-analysis of values of these two entities in absence of true copy analysis, which is expensive.
                if (!isLvalueFlowCapture &&
                    TryCreate(flowCapture.Value, out var capturedEntity) &&
                    capturedEntity.CaptureId == null &&
                    !_captureIdCopyValueMap.ContainsKey(flowCapture.Id) &&
                    analysisEntity.Type.IsValueType == capturedEntity.Type.IsValueType)
                {
                    // Skip flow capture for conversions unless we know the points to value
                    // for conversion and operand is identical.
                    if (flowCapture.Value is IConversionOperation conversion)
                    {
                        if (_getPointsToAbstractValue == null ||
                            _getPointsToAbstractValue(conversion) != _getPointsToAbstractValue(conversion.Operand))
                        {
                            break;
                        }
                    }

                    var kind      = capturedEntity.Type.IsValueType ? CopyAbstractValueKind.KnownValueCopy : CopyAbstractValueKind.KnownReferenceCopy;
                    var copyValue = new CopyAbstractValue(ImmutableHashSet.Create(analysisEntity, capturedEntity), kind);
                    _captureIdCopyValueMap.Add(flowCapture.Id, copyValue);
                }

                break;

            case IFlowCaptureReferenceOperation flowCaptureReference:
                analysisEntity = GetOrCreateForFlowCapture(flowCaptureReference.Id, flowCaptureReference.Type, flowCaptureReference, flowCaptureReference.IsLValueFlowCaptureReference());
                break;

            case IDeclarationExpressionOperation declarationExpression:
                switch (declarationExpression.Expression)
                {
                case ILocalReferenceOperation localReference:
                    return(TryCreateForSymbolDeclaration(localReference.Local, out analysisEntity));

                case ITupleOperation tupleOperation:
                    return(TryCreate(tupleOperation, out analysisEntity));
                }

                break;

            case IVariableDeclaratorOperation variableDeclarator:
                symbol = variableDeclarator.Symbol;
                type   = variableDeclarator.Symbol.Type;
                break;

            case IDeclarationPatternOperation declarationPattern:
                var declaredLocal = declarationPattern.DeclaredSymbol as ILocalSymbol;
                symbol = declaredLocal;
                type   = declaredLocal?.Type;
                break;

            default:
                break;
            }

            if (symbol != null || !indices.IsEmpty)
            {
                TryCreate(symbol, indices, type !, instance, out analysisEntity);
            }

            _analysisEntityMap[operation] = analysisEntity;
            return(analysisEntity != null);
        }