Beispiel #1
0
            internal BinderWithContainingMemberOrLambda(Binder next, BinderFlags flags, Symbol containingMemberOrLambda)
                : base(next, flags)
            {
                Debug.Assert(containingMemberOrLambda != null);

                _containingMemberOrLambda = containingMemberOrLambda;
            }
        /// <summary>
        /// Construct context
        /// </summary>
        public RegionAnalysisContext(CSharpCompilation compilation, Symbol member, BoundNode boundNode, BoundNode firstInRegion, BoundNode lastInRegion)
        {
            this.Compilation = compilation;
            this.Member = member;
            this.BoundNode = boundNode;
            this.FirstInRegion = firstInRegion;
            this.LastInRegion = lastInRegion;
            this.Failed =
                boundNode == null ||
                firstInRegion == null ||
                lastInRegion == null ||
                firstInRegion.Syntax.SpanStart > lastInRegion.Syntax.Span.End;

            if (!this.Failed && ReferenceEquals(firstInRegion, lastInRegion))
            {
                switch (firstInRegion.Kind)
                {
                    case BoundKind.NamespaceExpression:
                    case BoundKind.TypeExpression:

                        // Some bound nodes are still considered to be invalid for flow analysis
                        this.Failed = true;
                        break;
                }
            }
        }
 internal SubsumptionDiagnosticBuilder(Symbol enclosingSymbol,
                                        Conversions conversions,
                                        BoundExpression expression)
     : base(enclosingSymbol, conversions)
 {
     _subsumptionTree = DecisionTree.Create(expression, expression.Type, enclosingSymbol);
 }
Beispiel #4
0
 internal ExecutableCodeBinder(CSharpSyntaxNode root, Symbol memberSymbol, Binder next, BinderFlags additionalFlags)
     : base(next, (next.Flags | additionalFlags) & ~BinderFlags.AllClearedAtExecutableCodeBoundary)
 {
     this.memberSymbol = memberSymbol;
     this.root = root;
     this.owner = memberSymbol as MethodSymbol;
 }
Beispiel #5
0
        public static DecisionTree Create(BoundExpression expression, TypeSymbol type, Symbol enclosingSymbol)
        {
            Debug.Assert(expression.Type == type);
            LocalSymbol temp = null;
            if (expression.ConstantValue == null)
            {
                // Unless it is a constant, the decision tree acts on a copy of the input expression.
                // We create a temp to represent that copy. Lowering will assign into this temp.
                temp = new SynthesizedLocal(enclosingSymbol as MethodSymbol, type, SynthesizedLocalKind.PatternMatchingTemp, expression.Syntax, false, RefKind.None);
                expression = new BoundLocal(expression.Syntax, temp, null, type);
            }

            if (expression.Type.CanBeAssignedNull())
            {
                // We need the ByType decision tree to separate null from non-null values.
                // Note that, for the purpose of the decision tree (and subsumption), we
                // ignore the fact that the input may be a constant, and therefore always
                // or never null.
                return new ByType(expression, type, temp);
            }
            else
            {
                // If it is a (e.g. builtin) value type, we can switch on its (constant) values.
                // If it isn't a builtin, in practice we will only use the Default part of the
                // ByValue.
                return new ByValue(expression, type, temp);
            }
        }
 private void CheckArguments(ImmutableArray<RefKind> argumentRefKindsOpt, ImmutableArray<BoundExpression> arguments, Symbol method)
 {
     if (!argumentRefKindsOpt.IsDefault)
     {
         Debug.Assert(arguments.Length == argumentRefKindsOpt.Length);
         for (int i = 0; i < arguments.Length; i++)
         {
             if (argumentRefKindsOpt[i] != RefKind.None)
             {
                 var argument = arguments[i];
                 switch (argument.Kind)
                 {
                     case BoundKind.FieldAccess:
                         CheckFieldAddress((BoundFieldAccess)argument, method);
                         break;
                     case BoundKind.Local:
                         var local = (BoundLocal)argument;
                         if (local.Syntax.Kind() == SyntaxKind.DeclarationExpression)
                         {
                             CheckOutDeclaration(local, method);
                         }
                         break;
                 }
             }
         }
     }
 }
Beispiel #7
0
        public MethodGroupResolution(
            MethodGroup methodGroup,
            Symbol otherSymbol,
            OverloadResolutionResult<MethodSymbol> overloadResolutionResult,
            AnalyzedArguments analyzedArguments,
            LookupResultKind resultKind,
            ImmutableArray<Diagnostic> diagnostics,
            bool extensionMethodsOfSameViabilityAreAvailable)
        {
            Debug.Assert((methodGroup == null) || (methodGroup.Methods.Count > 0));
            Debug.Assert((methodGroup == null) || ((object)otherSymbol == null));
            // Methods should be represented in the method group.
            Debug.Assert(((object)otherSymbol == null) || (otherSymbol.Kind != SymbolKind.Method));
            Debug.Assert(resultKind != LookupResultKind.Ambiguous); // HasAnyApplicableMethod is expecting Viable methods.
            Debug.Assert(!diagnostics.IsDefault);
            Debug.Assert(!extensionMethodsOfSameViabilityAreAvailable || methodGroup == null || !methodGroup.IsExtensionMethodGroup);

            this.MethodGroup = methodGroup;
            this.OtherSymbol = otherSymbol;
            this.OverloadResolutionResult = overloadResolutionResult;
            this.AnalyzedArguments = analyzedArguments;
            this.ResultKind = resultKind;
            this.Diagnostics = diagnostics;
            this.ExtensionMethodsOfSameViabilityAreAvailable = extensionMethodsOfSameViabilityAreAvailable;
        }
Beispiel #8
0
 protected DecisionTreeBuilder(
     Symbol enclosingSymbol,
     Conversions conversions)
 {
     this._enclosingSymbol = enclosingSymbol;
     this._conversions = conversions;
 }
 private static void CheckSymbolKind(Symbol symbol)
 {
     switch (symbol.Kind)
     {
         case SymbolKind.ErrorType:
         case SymbolKind.NamedType:
         case SymbolKind.Event:
         case SymbolKind.Field:
         case SymbolKind.Method:
         case SymbolKind.Property:
         case SymbolKind.TypeParameter:
             break; // Can sensibly append location.
         case SymbolKind.ArrayType:
         case SymbolKind.PointerType:
         case SymbolKind.Parameter:
             break; // Can sensibly append location, after unwrapping.
         case SymbolKind.DynamicType:
             break; // Can't sensibly append location, but it should never be ambiguous.
         case SymbolKind.Namespace:
         case SymbolKind.Alias:
         case SymbolKind.Assembly:
         case SymbolKind.NetModule:
         case SymbolKind.Label:
         case SymbolKind.Local:
         case SymbolKind.RangeVariable:
         case SymbolKind.Preprocessing:
         default:
             throw ExceptionUtilities.UnexpectedValue(symbol.Kind);
     }
 }
Beispiel #10
0
        internal static void Analyze(
            CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion, HashSet<PrefixUnaryExpressionSyntax> unassignedVariableAddressOfSyntaxes,
            out IEnumerable<Symbol> readInside,
            out IEnumerable<Symbol> writtenInside,
            out IEnumerable<Symbol> readOutside,
            out IEnumerable<Symbol> writtenOutside,
            out IEnumerable<Symbol> captured,
            out IEnumerable<Symbol> unsafeAddressTaken)
        {
            var walker = new ReadWriteWalker(compilation, member, node, firstInRegion, lastInRegion, unassignedVariableAddressOfSyntaxes);
            try
            {
                bool badRegion = false;
                walker.Analyze(ref badRegion);
                if (badRegion)
                {
                    readInside = writtenInside = readOutside = writtenOutside = captured = unsafeAddressTaken = Enumerable.Empty<Symbol>();
                }
                else
                {
                    readInside = walker._readInside;
                    writtenInside = walker._writtenInside;
                    readOutside = walker._readOutside;
                    writtenOutside = walker._writtenOutside;

                    captured = walker.GetCaptured();
                    unsafeAddressTaken = walker.GetUnsafeAddressTaken();
                }
            }
            finally
            {
                walker.Free();
            }
        }
 internal ImmutableArray<Symbol> BindCref(CrefSyntax syntax, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
 {
     ImmutableArray<Symbol> symbols = BindCrefInternal(syntax, out ambiguityWinner, diagnostics);
     Debug.Assert(!symbols.IsDefault, "Prefer empty to null.");
     Debug.Assert((symbols.Length > 1) == ((object)ambiguityWinner != null), "ambiguityWinner should be set iff more than one symbol is returned.");
     return symbols;
 }
 private ImmutableArray<Symbol> BindQualifiedCref(QualifiedCrefSyntax syntax, out Symbol ambiguityWinner, DiagnosticBag diagnostics)
 {
     // NOTE: we won't check whether container is an error type - we'll just let BindMemberCref fail
     // and report a blanket diagnostic.
     NamespaceOrTypeSymbol container = BindNamespaceOrTypeSymbolInCref(syntax.Container);
     return BindMemberCref(syntax.Member, container, out ambiguityWinner, diagnostics);
 }
 public virtual void Visit(Symbol symbol)
 {
     if ((object)symbol != null)
     {
         symbol.Accept(this);
     }
 }
        private static string GetCapturedVariableFieldName(Symbol variable, ref int uniqueId)
        {
            if (IsThis(variable))
            {
                return GeneratedNames.ThisProxyFieldName();
            }

            var local = variable as LocalSymbol;
            if ((object)local != null)
            {
                if (local.SynthesizedKind == SynthesizedLocalKind.LambdaDisplayClass)
                {
                    return GeneratedNames.MakeLambdaDisplayLocalName(uniqueId++);
                }

                if (local.SynthesizedKind == SynthesizedLocalKind.ExceptionFilterAwaitHoistedExceptionLocal)
                {
                    return GeneratedNames.MakeHoistedLocalFieldName(local.SynthesizedKind, uniqueId++);
                }

                if (local.SynthesizedKind == SynthesizedLocalKind.InstrumentationPayload)
                {
                    return GeneratedNames.MakeSynthesizedInstrumentationPayloadLocalFieldName(uniqueId++);
                }
            }

            Debug.Assert(variable.Name != null);
            return variable.Name;
        }
 protected override void ReportUnassigned(Symbol symbol, SyntaxNode node)
 {
     if (node.Parent.Kind() == SyntaxKind.AddressOfExpression)
     {
         _result.Add((PrefixUnaryExpressionSyntax)node.Parent);
     }
 }
 private MethodBodySemanticModel(CSharpCompilation compilation, Symbol owner, Binder rootBinder, CSharpSyntaxNode syntax, SyntaxTreeSemanticModel parentSemanticModelOpt = null, int speculatedPosition = 0)
     : base(compilation, syntax, owner, rootBinder, parentSemanticModelOpt, speculatedPosition)
 {
     Debug.Assert((object)owner != null);
     Debug.Assert(owner.Kind == SymbolKind.Method);
     Debug.Assert(syntax != null);
     Debug.Assert(owner.ContainingType.IsScriptClass || syntax.Kind != SyntaxKind.CompilationUnit);
 }
 internal LazyObsoleteDiagnosticInfo(Symbol symbol, Symbol containingSymbol, BinderFlags binderFlags)
     : base(CSharp.MessageProvider.Instance, (int)ErrorCode.Unknown)
 {
     this.symbol = symbol;
     this.containingSymbol = containingSymbol;
     this.binderFlags = binderFlags;
     this.lazyActualObsoleteDiagnostic = null;
 }
        public static LambdaCapturedVariable Create(LambdaFrame frame, Symbol captured, ref int uniqueId)
        {
            Debug.Assert(captured is LocalSymbol || captured is ParameterSymbol);

            string fieldName = GetCapturedVariableFieldName(captured, ref uniqueId);
            TypeSymbol type = GetCapturedVariableFieldType(frame, captured);
            return new LambdaCapturedVariable(frame, type, fieldName, IsThis(captured));
        }
 protected override void ReportUnassigned(Symbol symbol, SyntaxNode node)
 {
     // TODO: how to handle fields of structs?
     if (symbol.Kind != SymbolKind.Field)
     {
         _result.Add(symbol);
     }
 }
Beispiel #20
0
 /// <summary>
 /// Checks if 'symbol' is accessible from within assembly 'within'.  
 /// </summary>
 public static bool IsSymbolAccessible(
     Symbol symbol,
     AssemblySymbol within,
     ref HashSet<DiagnosticInfo> useSiteDiagnostics)
 {
     bool failedThroughTypeCheck;
     return IsSymbolAccessibleCore(symbol, within, null, out failedThroughTypeCheck, within.DeclaringCompilation, ref useSiteDiagnostics);
 }
 internal AbstractRegionControlFlowPass(
     CSharpCompilation compilation,
     Symbol member,
     BoundNode node,
     BoundNode firstInRegion,
     BoundNode lastInRegion)
     : base(compilation, member, node, firstInRegion, lastInRegion)
 {
 }
 // create a SemanticModel for:
 // (a) A true field initializer (field = value) of a named type (incl. Enums) OR
 // (b) A constructor initializer (": this(...)" or ": base(...)") OR
 // (c) A parameter default value
 private InitializerSemanticModel(CSharpCompilation compilation,
                              CSharpSyntaxNode syntax,
                              Symbol symbol,
                              Binder rootBinder,
                              SyntaxTreeSemanticModel parentSemanticModelOpt = null,
                              int speculatedPosition = 0) :
     base(compilation, syntax, symbol, rootBinder, parentSemanticModelOpt, speculatedPosition)
 {
 }
Beispiel #23
0
        internal ExecutableCodeBinder(CSharpSyntaxNode root, Symbol memberSymbol, Binder next, BinderFlags additionalFlags)
            : base(next, (next.Flags | additionalFlags) & ~BinderFlags.AllClearedAtExecutableCodeBoundary)
        {
            Debug.Assert((object)memberSymbol == null ||
                         (memberSymbol.Kind != SymbolKind.Local && memberSymbol.Kind != SymbolKind.RangeVariable && memberSymbol.Kind != SymbolKind.Parameter));

            _memberSymbol = memberSymbol;
            _root = root;
        }
Beispiel #24
0
 /// <summary>
 /// Checks if 'symbol' is accessible from within type 'within', with
 /// an optional qualifier of type "throughTypeOpt".
 /// </summary>
 public static bool IsSymbolAccessible(
     Symbol symbol,
     NamedTypeSymbol within,
     ref HashSet<DiagnosticInfo> useSiteDiagnostics,
     TypeSymbol throughTypeOpt = null)
 {
     bool failedThroughTypeCheck;
     return IsSymbolAccessibleCore(symbol, within, throughTypeOpt, out failedThroughTypeCheck, within.DeclaringCompilation, ref useSiteDiagnostics);
 }
        public SymbolDistinguisher(Compilation compilation, Symbol symbol0, Symbol symbol1)
        {
            Debug.Assert(symbol0 != symbol1);
            CheckSymbolKind(symbol0);
            CheckSymbolKind(symbol1);

            _compilation = compilation;
            _symbol0 = symbol0;
            _symbol1 = symbol1;
        }
Beispiel #26
0
 /// <summary>
 /// Checks if 'symbol' is accessible from within type 'within', with
 /// an qualifier of type "throughTypeOpt". Sets "failedThroughTypeCheck" to true
 /// if it failed the "through type" check.
 /// </summary>
 public static bool IsSymbolAccessible(
     Symbol symbol,
     NamedTypeSymbol within,
     TypeSymbol throughTypeOpt,
     out bool failedThroughTypeCheck,
     ref HashSet<DiagnosticInfo> useSiteDiagnostics,
     ConsList<Symbol> basesBeingResolved = null)
 {
     return IsSymbolAccessibleCore(symbol, within, throughTypeOpt, out failedThroughTypeCheck, within.DeclaringCompilation, ref useSiteDiagnostics, basesBeingResolved);
 }
        /// <summary>
        /// Creates a speculative SemanticModel for an initializer node (field initializer, constructor initializer, or parameter default value)
        /// that did not appear in the original source code.
        /// </summary>
        internal static InitializerSemanticModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, Symbol owner, CSharpSyntaxNode syntax, Binder rootBinder, int position)
        {
            Debug.Assert(parentSemanticModel != null);
            Debug.Assert(syntax != null);
            Debug.Assert(syntax.IsKind(SyntaxKind.EqualsValueClause) || syntax.IsKind(SyntaxKind.ThisConstructorInitializer) || syntax.IsKind(SyntaxKind.BaseConstructorInitializer));
            Debug.Assert(rootBinder != null);
            Debug.Assert(rootBinder.IsSemanticModelBinder);

            return new InitializerSemanticModel(parentSemanticModel.Compilation, syntax, owner, rootBinder, parentSemanticModel, position);
        }
Beispiel #28
0
        // methodsWithYields will contain all function-declaration-like CSharpSyntaxNodes with yield statements contained within them.
        // Currently the types of these are restricted to only be whatever the syntax parameter is, plus any LocalFunctionStatementSyntax contained within it.
        // This may change if the language is extended to allow iterator lambdas, in which case the lambda would also be returned.
        // (lambdas currently throw a diagnostic in WithLambdaParametersBinder.GetIteratorElementType when a yield is used within them)
        public static SmallDictionary<SyntaxNode, Binder> BuildMap(
            Symbol containingMemberOrLambda, 
            SyntaxNode syntax, 
            Binder enclosing, 
            ArrayBuilder<SyntaxNode> methodsWithYields,
            Func<Binder, SyntaxNode, Binder> rootBinderAdjusterOpt = null)
        {
            var builder = new LocalBinderFactory(containingMemberOrLambda, syntax, enclosing, methodsWithYields);

            StatementSyntax statement;
            var expressionSyntax = syntax as ExpressionSyntax;
            if (expressionSyntax != null)
            {
                enclosing = new ExpressionVariableBinder(syntax, enclosing);

                if ((object)rootBinderAdjusterOpt != null)
                {
                    enclosing = rootBinderAdjusterOpt(enclosing, syntax);
                }

                builder.AddToMap(syntax, enclosing);
                builder.Visit(expressionSyntax, enclosing);
            }
            else if (syntax.Kind() != SyntaxKind.Block && (statement = syntax as StatementSyntax) != null)
            {
                CSharpSyntaxNode embeddedScopeDesignator;
                enclosing = builder.GetBinderForPossibleEmbeddedStatement(statement, enclosing, out embeddedScopeDesignator);

                if ((object)rootBinderAdjusterOpt != null)
                {
                    enclosing = rootBinderAdjusterOpt(enclosing, embeddedScopeDesignator);
                }

                if (embeddedScopeDesignator != null)
                {
                    builder.AddToMap(embeddedScopeDesignator, enclosing);
                }

                builder.Visit(statement, enclosing);
            }
            else
            {
                if ((object)rootBinderAdjusterOpt != null)
                {
                    enclosing = rootBinderAdjusterOpt(enclosing, null);
                }

                builder.Visit((CSharpSyntaxNode)syntax, enclosing);
            }

            // the other place this is possible is in a local function
            if (builder._sawYield)
                methodsWithYields.Add(syntax);
            return builder._map;
        }
        internal override bool EnsureSingleDefinition(Symbol symbol, string name, Location location, DiagnosticBag diagnostics)
        {
            ParameterSymbol existingDeclaration;
            var map = this.definitionMap;
            if (map != null && map.TryGetValue(name, out existingDeclaration))
            {
                return InMethodBinder.ReportConflictWithParameter(existingDeclaration, symbol, name, location, diagnostics);
            }

            return false;
        }
Beispiel #30
0
        private LocalBinderFactory(Symbol containingMemberOrLambda, CSharpSyntaxNode root, Binder enclosing, ArrayBuilder<CSharpSyntaxNode> methodsWithYields)
        {
            Debug.Assert((object)containingMemberOrLambda != null);
            Debug.Assert(containingMemberOrLambda.Kind != SymbolKind.Local && containingMemberOrLambda.Kind != SymbolKind.RangeVariable && containingMemberOrLambda.Kind != SymbolKind.Parameter);

            _map = new SmallDictionary<CSharpSyntaxNode, Binder>(ReferenceEqualityComparer.Instance);
            _containingMemberOrLambda = containingMemberOrLambda;
            _enclosing = enclosing;
            _methodsWithYields = methodsWithYields;
            _root = root;
        }
        /// <summary>
        /// Creates a speculative SemanticModel for an initializer node (field initializer, constructor initializer, or parameter default value)
        /// that did not appear in the original source code.
        /// </summary>
        internal static InitializerSemanticModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, Symbol owner, CSharpSyntaxNode syntax, Binder rootBinder, int position)
        {
            Debug.Assert(parentSemanticModel != null);
            Debug.Assert(syntax != null);
            Debug.Assert(syntax.IsKind(SyntaxKind.EqualsValueClause));
            Debug.Assert(rootBinder != null);
            Debug.Assert(rootBinder.IsSemanticModelBinder);

            return(new InitializerSemanticModel(parentSemanticModel.Compilation, syntax, owner, rootBinder, parentSemanticModel, position));
        }
Beispiel #32
0
        internal static bool ReportConflictWithParameter(Symbol parameter, Symbol newSymbol, string name, Location newLocation, DiagnosticBag diagnostics)
        {
            var oldLocation = parameter.Locations[0];

#if PATTERNS_FIXED
            Debug.Assert(oldLocation != newLocation || oldLocation == Location.None || newLocation.SourceTree?.GetRoot().ContainsDiagnostics == true,
                         "same nonempty location refers to different symbols?");
#else
            if (oldLocation == newLocation)
            {
                return(false);
            }
#endif
            SymbolKind parameterKind = parameter.Kind;

            // Quirk of the way we represent lambda parameters.
            SymbolKind newSymbolKind = (object)newSymbol == null ? SymbolKind.Parameter : newSymbol.Kind;

            if (newSymbolKind == SymbolKind.ErrorType)
            {
                return(true);
            }

            if (parameterKind == SymbolKind.Parameter)
            {
                if (newSymbolKind == SymbolKind.Parameter || newSymbolKind == SymbolKind.Local ||
                    (newSymbolKind == SymbolKind.Method &&
                     ((MethodSymbol)newSymbol).MethodKind == MethodKind.LocalFunction))
                {
                    // A local or parameter named '{0}' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
                    diagnostics.Add(ErrorCode.ERR_LocalIllegallyOverrides, newLocation, name);
                    return(true);
                }

                if (newSymbolKind == SymbolKind.RangeVariable)
                {
                    // The range variable '{0}' conflicts with a previous declaration of '{0}'
                    diagnostics.Add(ErrorCode.ERR_QueryRangeVariableOverrides, newLocation, name);
                    return(true);
                }
            }

            if (parameterKind == SymbolKind.TypeParameter)
            {
                if (newSymbolKind == SymbolKind.Parameter || newSymbolKind == SymbolKind.Local ||
                    (newSymbolKind == SymbolKind.Method &&
                     ((MethodSymbol)newSymbol).MethodKind == MethodKind.LocalFunction))
                {
                    // CS0412: '{0}': a parameter, local variable, or local function cannot have the same name as a method type parameter
                    diagnostics.Add(ErrorCode.ERR_LocalSameNameAsTypeParam, newLocation, name);
                    return(true);
                }

                if (newSymbolKind == SymbolKind.TypeParameter)
                {
                    // Type parameter declaration name conflicts are detected elsewhere
                    return(false);
                }

                if (newSymbolKind == SymbolKind.RangeVariable)
                {
                    // The range variable '{0}' cannot have the same name as a method type parameter
                    diagnostics.Add(ErrorCode.ERR_QueryRangeVariableSameAsTypeParam, newLocation, name);
                    return(true);
                }
            }

            Debug.Assert(false, "what else could be defined in a method?");
            return(true);
        }
 private RegionReachableWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
     : base(compilation, member, node, firstInRegion, lastInRegion)
 {
 }
Beispiel #34
0
        /// <summary>
        /// Checks if 'symbol' is accessible from within 'within', which must be a NamedTypeSymbol
        /// or an AssemblySymbol.
        ///
        /// Note that NamedTypeSymbol, if available, is the type that is associated with the binder
        /// that found the 'symbol', not the inner-most type that contains the access to the
        /// 'symbol'.
        ///
        /// If 'symbol' is accessed off of an expression then 'throughTypeOpt' is the type of that
        /// expression. This is needed to properly do protected access checks. Sets
        /// "failedThroughTypeCheck" to true if this protected check failed.
        ///
        /// NOTE(cyrusn): I expect this function to be called a lot.  As such, i do not do any memory
        /// allocations in the function itself (including not making any iterators).  This does mean
        /// that certain helper functions that we'd like to call are inlined in this method to
        /// prevent the overhead of returning collections or enumerators.
        /// </summary>
        private static bool IsSymbolAccessibleCore(
            Symbol symbol,
            Symbol within,  // must be assembly or named type symbol
            TypeSymbol throughTypeOpt,
            out bool failedThroughTypeCheck,
            CSharpCompilation compilation,
            ref HashSet <DiagnosticInfo> useSiteDiagnostics,
            ConsList <Symbol> basesBeingResolved = null)
        {
            Debug.Assert((object)symbol != null);
            Debug.Assert((object)within != null);
            Debug.Assert(within.IsDefinition);
            Debug.Assert(within is NamedTypeSymbol || within is AssemblySymbol);

            failedThroughTypeCheck = false;

            switch (symbol.Kind)
            {
            case SymbolKind.ArrayType:
                return(IsSymbolAccessibleCore(((ArrayTypeSymbol)symbol).ElementType, within, null, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved));

            case SymbolKind.PointerType:
                return(IsSymbolAccessibleCore(((PointerTypeSymbol)symbol).PointedAtType, within, null, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved));

            case SymbolKind.NamedType:
                return(IsNamedTypeAccessible((NamedTypeSymbol)symbol, within, ref useSiteDiagnostics, basesBeingResolved));

            case SymbolKind.ErrorType:
                // Always assume that error types are accessible.
                return(true);

            case SymbolKind.TypeParameter:
            case SymbolKind.Parameter:
            case SymbolKind.Local:
            case SymbolKind.Label:
            case SymbolKind.Namespace:
            case SymbolKind.DynamicType:
            case SymbolKind.Assembly:
            case SymbolKind.NetModule:
            case SymbolKind.RangeVariable:
                // These types of symbols are always accessible (if visible).
                return(true);

            case SymbolKind.Method:
            case SymbolKind.Property:
            case SymbolKind.Event:
            case SymbolKind.Field:
                if (symbol.IsStatic)
                {
                    // static members aren't accessed "through" an "instance" of any type.  So we
                    // null out the "through" instance here.  This ensures that we'll understand
                    // accessing protected statics properly.
                    throughTypeOpt = null;
                }

                return(IsMemberAccessible(symbol.ContainingType, symbol.DeclaredAccessibility, within, throughTypeOpt, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics));

            default:
                throw ExceptionUtilities.UnexpectedValue(symbol.Kind);
            }
        }
Beispiel #35
0
 public virtual TResult DefaultVisit(Symbol symbol)
 {
     return(default(TResult));
 }
        /// <summary>
        /// Learn from any constant null patterns appearing in the pattern.
        /// </summary>
        /// <param name="inputType">Type type of the input expression (before nullable analysis).
        /// Used to determine which types can contain null.</param>
        private void LearnFromAnyNullPatterns(
            int inputSlot,
            TypeSymbol inputType,
            BoundPattern pattern)
        {
            if (inputSlot <= 0)
                return;

            // https://github.com/dotnet/roslyn/issues/35041 We only need to do this when we're rewriting, so we
            // can get information for any nodes in the pattern.
            VisitPatternForRewriting(pattern);

            switch (pattern)
            {
                case BoundConstantPattern cp:
                    bool isExplicitNullCheck = cp.Value.ConstantValue == ConstantValue.Null;
                    if (isExplicitNullCheck)
                    {
                        // Since we're not branching on this null test here, we just infer the top level
                        // nullability.  We'll branch on it later.
                        LearnFromNullTest(inputSlot, inputType, ref this.State, markDependentSlotsNotNull: false);
                    }
                    break;
                case BoundDeclarationPattern _:
                case BoundDiscardPattern _:
                case BoundITuplePattern _:
                    break; // nothing to learn
                case BoundRecursivePattern rp:
                    {
                        if (rp.IsExplicitNotNullTest)
                        {
                            LearnFromNullTest(inputSlot, inputType, ref this.State, markDependentSlotsNotNull: false);
                        }

                        // for positional part: we only learn from tuples (not Deconstruct)
                        if (rp.DeconstructMethod is null && !rp.Deconstruction.IsDefault)
                        {
                            var elements = inputType.TupleElements;
                            for (int i = 0, n = Math.Min(rp.Deconstruction.Length, elements.IsDefault ? 0 : elements.Length); i < n; i++)
                            {
                                BoundSubpattern item = rp.Deconstruction[i];
                                FieldSymbol element = elements[i];
                                LearnFromAnyNullPatterns(GetOrCreateSlot(element, inputSlot), element.Type, item.Pattern);
                            }
                        }

                        // for property part
                        if (!rp.Properties.IsDefault)
                        {
                            for (int i = 0, n = rp.Properties.Length; i < n; i++)
                            {
                                BoundSubpattern item = rp.Properties[i];
                                Symbol symbol = item.Symbol;
                                if (symbol?.ContainingType.Equals(inputType, TypeCompareKind.AllIgnoreOptions) == true)
                                {
                                    LearnFromAnyNullPatterns(GetOrCreateSlot(symbol, inputSlot), symbol.GetTypeOrReturnType().Type, item.Pattern);
                                }
                            }
                        }
                    }
                    break;
                default:
                    throw ExceptionUtilities.UnexpectedValue(pattern);
            }
        }
Beispiel #37
0
        private ImmutableArray <Symbol> ProcessParameterlessCrefMemberLookupResults(
            ImmutableArray <Symbol> symbols,
            int arity,
            MemberCrefSyntax memberSyntax,
            TypeArgumentListSyntax?typeArgumentListSyntax,
            out Symbol?ambiguityWinner,
            DiagnosticBag diagnostics)
        {
            // If the syntax indicates arity zero, then we match methods of any arity.
            // However, if there are both generic and non-generic methods, then the
            // generic methods should be ignored.
            if (symbols.Length > 1 && arity == 0)
            {
                bool hasNonGenericMethod = false;
                bool hasGenericMethod    = false;
                foreach (Symbol s in symbols)
                {
                    if (s.Kind != SymbolKind.Method)
                    {
                        continue;
                    }

                    if (((MethodSymbol)s).Arity == 0)
                    {
                        hasNonGenericMethod = true;
                    }
                    else
                    {
                        hasGenericMethod = true;
                    }

                    if (hasGenericMethod && hasNonGenericMethod)
                    {
                        break; //Nothing else to be learned.
                    }
                }

                if (hasNonGenericMethod && hasGenericMethod)
                {
                    symbols = symbols.WhereAsArray(s =>
                                                   s.Kind != SymbolKind.Method || ((MethodSymbol)s).Arity == 0);
                }
            }

            Debug.Assert(!symbols.IsEmpty);

            Symbol symbol = symbols[0];

            // If there's ambiguity, prefer source symbols.
            // Logic is similar to ResultSymbol, but separate because the error handling is totally different.
            if (symbols.Length > 1)
            {
                // Size is known, but IndexOfSymbolFromCurrentCompilation expects a builder.
                ArrayBuilder <Symbol> unwrappedSymbols = ArrayBuilder <Symbol> .GetInstance(symbols.Length);

                foreach (Symbol wrapped in symbols)
                {
                    unwrappedSymbols.Add(UnwrapAliasNoDiagnostics(wrapped));
                }

                BestSymbolInfo secondBest;
                BestSymbolInfo best = GetBestSymbolInfo(unwrappedSymbols, out secondBest);

                Debug.Assert(!best.IsNone);
                Debug.Assert(!secondBest.IsNone);

                unwrappedSymbols.Free();

                int symbolIndex = 0;

                if (best.IsFromCompilation)
                {
                    symbolIndex = best.Index;
                    symbol      = symbols[symbolIndex]; // NOTE: symbols, not unwrappedSymbols.
                }

                if (symbol.Kind == SymbolKind.TypeParameter)
                {
                    CrefSyntax crefSyntax = GetRootCrefSyntax(memberSyntax);
                    diagnostics.Add(ErrorCode.WRN_BadXMLRefTypeVar, crefSyntax.Location, crefSyntax.ToString());
                }
                else if (secondBest.IsFromCompilation == best.IsFromCompilation)
                {
                    CrefSyntax crefSyntax = GetRootCrefSyntax(memberSyntax);
                    int        otherIndex = symbolIndex == 0 ? 1 : 0;
                    diagnostics.Add(ErrorCode.WRN_AmbiguousXMLReference, crefSyntax.Location, crefSyntax.ToString(), symbol, symbols[otherIndex]);

                    ambiguityWinner = ConstructWithCrefTypeParameters(arity, typeArgumentListSyntax, symbol);
                    return(symbols.SelectAsArray(sym => ConstructWithCrefTypeParameters(arity, typeArgumentListSyntax, sym)));
                }
            }
            else if (symbol.Kind == SymbolKind.TypeParameter)
            {
                CrefSyntax crefSyntax = GetRootCrefSyntax(memberSyntax);
                diagnostics.Add(ErrorCode.WRN_BadXMLRefTypeVar, crefSyntax.Location, crefSyntax.ToString());
            }

            ambiguityWinner = null;
            return(ImmutableArray.Create <Symbol>(ConstructWithCrefTypeParameters(arity, typeArgumentListSyntax, symbol)));
        }
 internal VariablesDeclaredWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
     : base(compilation, member, node, firstInRegion, lastInRegion)
 {
 }
Beispiel #39
0
        private static bool IsNonPublicMemberAccessible(
            NamedTypeSymbol containingType,              // the symbol's containing type
            Accessibility declaredAccessibility,
            Symbol within,
            TypeSymbol throughTypeOpt,
            out bool failedThroughTypeCheck,
            CSharpCompilation compilation,
            ref HashSet <DiagnosticInfo> useSiteDiagnostics,
            ConsList <Symbol> basesBeingResolved = null)
        {
            failedThroughTypeCheck = false;

            var originalContainingType = containingType.OriginalDefinition;
            var withinType             = within as NamedTypeSymbol;
            var withinAssembly         = (object)withinType != null ? withinType.ContainingAssembly : (AssemblySymbol)within;

            switch (declaredAccessibility)
            {
            case Accessibility.NotApplicable:
                // TODO(cyrusn): Is this the right thing to do here?  Should the caller ever be
                // asking about the accessibility of a symbol that has "NotApplicable" as its
                // value?  For now, I'm preserving the behavior of the existing code.  But perhaps
                // we should fail here and require the caller to not do this?
                return(true);

            case Accessibility.Private:
                // All expressions in the current submission (top-level or nested in a method or
                // type) can access previous submission's private top-level members. Previous
                // submissions are treated like outer classes for the current submission - the
                // inner class can access private members of the outer class.
                if (containingType.TypeKind == TypeKind.Submission)
                {
                    return(true);
                }

                // private members never accessible from outside a type.
                return((object)withinType != null && IsPrivateSymbolAccessible(withinType, originalContainingType));

            case Accessibility.Internal:
                // An internal type is accessible if we're in the same assembly or we have
                // friend access to the assembly it was defined in.
                return(withinAssembly.HasInternalAccessTo(containingType.ContainingAssembly));

            case Accessibility.ProtectedAndInternal:
                if (!withinAssembly.HasInternalAccessTo(containingType.ContainingAssembly))
                {
                    // We require internal access.  If we don't have it, then this symbol is
                    // definitely not accessible to us.
                    return(false);
                }

                // We had internal access.  Also have to make sure we have protected access.
                return(IsProtectedSymbolAccessible(withinType, throughTypeOpt, originalContainingType, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved));

            case Accessibility.ProtectedOrInternal:
                if (withinAssembly.HasInternalAccessTo(containingType.ContainingAssembly))
                {
                    // If we have internal access to this symbol, then that's sufficient.  no
                    // need to do the complicated protected case.
                    return(true);
                }

                // We don't have internal access.  But if we have protected access then that's
                // sufficient.
                return(IsProtectedSymbolAccessible(withinType, throughTypeOpt, originalContainingType, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved));

            case Accessibility.Protected:
                return(IsProtectedSymbolAccessible(withinType, throughTypeOpt, originalContainingType, out failedThroughTypeCheck, compilation, ref useSiteDiagnostics, basesBeingResolved));

            default:
                throw ExceptionUtilities.UnexpectedValue(declaredAccessibility);
            }
        }
Beispiel #40
0
 internal override bool IsAccessible(Symbol symbol, TypeSymbol accessThroughType, out bool failedThroughTypeCheck, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <Symbol> basesBeingResolved = null)
 {
     failedThroughTypeCheck = false;
     return(this.IsSymbolAccessibleConditional(symbol, Compilation.Assembly, ref useSiteDiagnostics));
 }
Beispiel #41
0
 public virtual TResult Visit(Symbol symbol)
 {
     return((object)symbol == null
         ? default(TResult)
         : symbol.Accept(this));
 }
Beispiel #42
0
 private ReadWriteWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion,
                         HashSet <PrefixUnaryExpressionSyntax> unassignedVariableAddressOfSyntaxes)
     : base(compilation, member, node, firstInRegion, lastInRegion, unassignedVariableAddressOfSyntaxes: unassignedVariableAddressOfSyntaxes)
 {
 }