ParameterHelpers.cs 26.4 KB
Newer Older
1
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
P
Pilchie 已提交
2

3
using System;
P
Pilchie 已提交
4 5 6 7 8 9
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
T
Tomas Matousek 已提交
10
using Microsoft.CodeAnalysis.PooledObjects;
P
Pilchie 已提交
11 12 13 14 15 16 17 18 19 20 21
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
    internal static class ParameterHelpers
    {
        public static ImmutableArray<ParameterSymbol> MakeParameters(
            Binder binder,
            Symbol owner,
            BaseParameterListSyntax syntax,
            out SyntaxToken arglistToken,
E
Evan Hauck 已提交
22
            DiagnosticBag diagnostics,
23
            bool allowRefOrOut,
24
            bool allowThis,
25
            bool addRefReadOnlyModifier)
P
Pilchie 已提交
26 27 28 29 30 31 32
        {
            arglistToken = default(SyntaxToken);

            int parameterIndex = 0;
            int firstDefault = -1;

            var builder = ArrayBuilder<ParameterSymbol>.GetInstance();
33
            var mustBeLastParameter = (ParameterSyntax)null;
P
Pilchie 已提交
34 35 36

            foreach (var parameterSyntax in syntax.Parameters)
            {
37 38 39 40 41 42 43 44 45
                if (mustBeLastParameter == null)
                {
                    if (parameterSyntax.Modifiers.Any(SyntaxKind.ParamsKeyword) ||
                        parameterSyntax.Identifier.Kind() == SyntaxKind.ArgListKeyword)
                    {
                        mustBeLastParameter = parameterSyntax;
                    }
                }

46 47
                CheckParameterModifiers(parameterSyntax, diagnostics);

48
                var refKind = GetModifiers(parameterSyntax.Modifiers, out SyntaxToken refnessKeyword, out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword);
49 50 51 52
                if (thisKeyword.Kind() != SyntaxKind.None && !allowThis)
                {
                    diagnostics.Add(ErrorCode.ERR_ThisInBadContext, thisKeyword.GetLocation());
                }
P
Pilchie 已提交
53 54 55 56 57 58

                if (parameterSyntax.IsArgList)
                {
                    arglistToken = parameterSyntax.Identifier;
                    // The native compiler produces "Expected type" here, in the parser. Roslyn produces
                    // the somewhat more informative "arglist not valid" error.
O
Omar Tawfik 已提交
59
                    if (paramsKeyword.Kind() != SyntaxKind.None
60
                        || refnessKeyword.Kind() != SyntaxKind.None
O
Omar Tawfik 已提交
61
                        || thisKeyword.Kind() != SyntaxKind.None)
P
Pilchie 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
                    {
                        // CS1669: __arglist is not valid in this context
                        diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, arglistToken.GetLocation());
                    }
                    continue;
                }

                if (parameterSyntax.Default != null && firstDefault == -1)
                {
                    firstDefault = parameterIndex;
                }

                Debug.Assert(parameterSyntax.Type != null);
                var parameterType = binder.BindType(parameterSyntax.Type, diagnostics);

77
                if (!allowRefOrOut && (refKind == RefKind.Ref || refKind == RefKind.Out))
P
Pilchie 已提交
78
                {
79
                    Debug.Assert(refnessKeyword.Kind() != SyntaxKind.None);
P
Pilchie 已提交
80 81

                    // error CS0631: ref and out are not valid in this context
82
                    diagnostics.Add(ErrorCode.ERR_IllegalRefParam, refnessKeyword.GetLocation());
P
Pilchie 已提交
83 84 85 86 87 88 89 90 91 92
                }

                var parameter = SourceParameterSymbol.Create(
                    binder,
                    owner,
                    parameterType,
                    parameterSyntax,
                    refKind,
                    parameterSyntax.Identifier,
                    parameterIndex,
93 94
                    (paramsKeyword.Kind() != SyntaxKind.None),
                    parameterIndex == 0 && thisKeyword.Kind() != SyntaxKind.None,
95
                    addRefReadOnlyModifier,
96
                    diagnostics);
P
Pilchie 已提交
97

98
                ReportParameterErrors(owner, parameterSyntax, parameter, thisKeyword, paramsKeyword, firstDefault, diagnostics);
P
Pilchie 已提交
99 100 101 102 103

                builder.Add(parameter);
                ++parameterIndex;
            }

104 105 106 107 108 109 110 111 112 113
            if (mustBeLastParameter != null && mustBeLastParameter != syntax.Parameters.Last())
            {
                diagnostics.Add(
                    mustBeLastParameter.Identifier.Kind() == SyntaxKind.ArgListKeyword
                        ? ErrorCode.ERR_VarargsLast
                        : ErrorCode.ERR_ParamsLast,
                    mustBeLastParameter.GetLocation());
            }

            ImmutableArray<ParameterSymbol> parameters = builder.ToImmutableAndFree();
114 115 116 117 118 119 120 121

            var methodOwner = owner as MethodSymbol;
            var typeParameters = (object)methodOwner != null ?
                methodOwner.TypeParameters :
                default(ImmutableArray<TypeParameterSymbol>);

            binder.ValidateParameterNameConflicts(typeParameters, parameters, diagnostics);
            return parameters;
P
Pilchie 已提交
122 123
        }

124 125 126 127
        internal static void EnsureIsReadOnlyAttributeExists(ImmutableArray<ParameterSymbol> parameters, DiagnosticBag diagnostics, bool modifyCompilationForRefReadOnly)
        {
            foreach (var parameter in parameters)
            {
128
                if (parameter.RefKind == RefKind.In)
129
                {
130 131 132
                    // These parameters might not come from a compilation (example: lambdas evaluated in EE).
                    // During rewriting, lowering will take care of flagging the appropriate PEModuleBuilder instead.
                    parameter.DeclaringCompilation?.EnsureIsReadOnlyAttributeExists(diagnostics, parameter.GetNonNullSyntaxNode().Location, modifyCompilationForRefReadOnly);
133 134 135 136
                }
            }
        }

137 138 139 140 141 142 143
        private static void CheckParameterModifiers(
            ParameterSyntax parameter, DiagnosticBag diagnostics)
        {
            var seenThis = false;
            var seenRef = false;
            var seenOut = false;
            var seenParams = false;
O
Omar Tawfik 已提交
144
            var seenRefReadOnly = false;
145 146 147 148 149 150 151 152 153 154 155 156

            foreach (var modifier in parameter.Modifiers)
            {
                switch (modifier.Kind())
                {
                    case SyntaxKind.ThisKeyword:
                        if (seenThis)
                        {
                            diagnostics.Add(ErrorCode.ERR_DupParamMod, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ThisKeyword));
                        }
                        else if (seenOut)
                        {
O
Omar Tawfik 已提交
157
                            diagnostics.Add(ErrorCode.ERR_BadParameterModifiers, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ThisKeyword), SyntaxFacts.GetText(SyntaxKind.OutKeyword));
158 159 160 161 162 163 164 165 166 167 168 169
                        }
                        else if (seenParams)
                        {
                            diagnostics.Add(ErrorCode.ERR_BadParamModThis, modifier.GetLocation());
                        }
                        else
                        {
                            seenThis = true;
                        }
                        break;

                    case SyntaxKind.RefKeyword:
O
Omar Tawfik 已提交
170
                        if (seenRef || seenRefReadOnly)
171 172 173 174 175
                        {
                            diagnostics.Add(ErrorCode.ERR_DupParamMod, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.RefKeyword));
                        }
                        else if (seenThis)
                        {
176
                            diagnostics.Add(ErrorCode.ERR_BadParameterModifiersOrder, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.RefKeyword), SyntaxFacts.GetText(SyntaxKind.ThisKeyword));
177 178 179
                        }
                        else if (seenParams)
                        {
O
Omar Tawfik 已提交
180
                            diagnostics.Add(ErrorCode.ERR_ParamsCantBeWithModifier, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.RefKeyword));
181 182 183
                        }
                        else if (seenOut)
                        {
O
Omar Tawfik 已提交
184 185
                            diagnostics.Add(ErrorCode.ERR_BadParameterModifiers, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.RefKeyword), SyntaxFacts.GetText(SyntaxKind.OutKeyword));
                        }
186 187 188 189 190 191 192 193 194 195 196 197 198
                        else
                        {
                            seenRef = true;
                        }
                        break;

                    case SyntaxKind.OutKeyword:
                        if (seenOut)
                        {
                            diagnostics.Add(ErrorCode.ERR_DupParamMod, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.OutKeyword));
                        }
                        else if (seenThis)
                        {
O
Omar Tawfik 已提交
199
                            diagnostics.Add(ErrorCode.ERR_BadParameterModifiers, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.OutKeyword), SyntaxFacts.GetText(SyntaxKind.ThisKeyword));
200 201 202
                        }
                        else if (seenParams)
                        {
O
Omar Tawfik 已提交
203
                            diagnostics.Add(ErrorCode.ERR_ParamsCantBeWithModifier, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.OutKeyword));
204
                        }
O
Omar Tawfik 已提交
205
                        else if (seenRef || seenRefReadOnly)
206
                        {
O
Omar Tawfik 已提交
207 208
                            diagnostics.Add(ErrorCode.ERR_BadParameterModifiers, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.OutKeyword), SyntaxFacts.GetText(SyntaxKind.RefKeyword));
                        }
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
                        else
                        {
                            seenOut = true;
                        }
                        break;

                    case SyntaxKind.ParamsKeyword:
                        if (seenParams)
                        {
                            diagnostics.Add(ErrorCode.ERR_DupParamMod, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ParamsKeyword));
                        }
                        else if (seenThis)
                        {
                            diagnostics.Add(ErrorCode.ERR_BadParamModThis, modifier.GetLocation());
                        }
O
Omar Tawfik 已提交
224
                        else if (seenRef || seenRefReadOnly)
225
                        {
O
Omar Tawfik 已提交
226 227 228 229 230 231
                            diagnostics.Add(ErrorCode.ERR_BadParameterModifiers, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ParamsKeyword), SyntaxFacts.GetText(SyntaxKind.RefKeyword));
                        }
                        else if (seenOut)
                        {
                            diagnostics.Add(ErrorCode.ERR_BadParameterModifiers, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ParamsKeyword), SyntaxFacts.GetText(SyntaxKind.OutKeyword));
                        }
232 233 234 235 236 237
                        else
                        {
                            seenParams = true;
                        }
                        break;

O
Omar Tawfik 已提交
238 239 240 241 242 243 244 245 246 247 248
                    case SyntaxKind.ReadOnlyKeyword:
                        if(seenRefReadOnly)
                        {
                            diagnostics.Add(ErrorCode.ERR_DupParamMod, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword));
                        }
                        else if (seenOut)
                        {
                            diagnostics.Add(ErrorCode.ERR_BadParameterModifiers, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword), SyntaxFacts.GetText(SyntaxKind.OutKeyword));
                        }
                        else if (seenThis)
                        {
249
                            diagnostics.Add(ErrorCode.ERR_BadParameterModifiersOrder, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword), SyntaxFacts.GetText(SyntaxKind.ThisKeyword));
O
Omar Tawfik 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
                        }
                        else if(seenRef)
                        {
                            seenRef = false;
                            seenRefReadOnly = true;
                        }
                        else if (seenParams)
                        {
                            diagnostics.Add(ErrorCode.ERR_ParamsCantBeWithModifier, modifier.GetLocation(), SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword));
                        }
                        else
                        {
                            diagnostics.Add(ErrorCode.ERR_UnexpectedToken, modifier.GetLocation(), modifier.Text);
                        }
                        break;

266
                    default:
O
Omar Tawfik 已提交
267
                        throw new InvalidOperationException($"Unexpected SyntaxKind {modifier.Kind()}");
268 269 270 271
                }
            }
        }

P
Pilchie 已提交
272 273 274 275
        private static void ReportParameterErrors(
            Symbol owner,
            ParameterSyntax parameterSyntax,
            SourceParameterSymbol parameter,
276 277
            SyntaxToken thisKeyword,
            SyntaxToken paramsKeyword,
P
Pilchie 已提交
278 279 280 281 282 283 284
            int firstDefault,
            DiagnosticBag diagnostics)
        {
            TypeSymbol parameterType = parameter.Type;
            int parameterIndex = parameter.Ordinal;
            bool isDefault = parameterSyntax.Default != null;

285
            if (thisKeyword.Kind() == SyntaxKind.ThisKeyword && parameterIndex != 0)
P
Pilchie 已提交
286 287 288 289 290 291 292 293 294 295
            {
                // Report CS1100 on "this". Note that is a change from Dev10
                // which reports the error on the type following "this".

                // error CS1100: Method '{0}' has a parameter modifier 'this' which is not on the first parameter
                diagnostics.Add(ErrorCode.ERR_BadThisParam, thisKeyword.GetLocation(), owner.Name);
            }
            else if (parameter.IsParams && owner.IsOperator())
            {
                // error CS1670: params is not valid in this context
296
                diagnostics.Add(ErrorCode.ERR_IllegalParams, paramsKeyword.GetLocation());
P
Pilchie 已提交
297
            }
298
            else if (parameter.IsParams && !parameterType.IsSZArray())
P
Pilchie 已提交
299 300
            {
                // error CS0225: The params parameter must be a single dimensional array
301
                diagnostics.Add(ErrorCode.ERR_ParamsMustBeArray, paramsKeyword.GetLocation());
P
Pilchie 已提交
302 303 304 305 306 307 308 309 310 311 312 313
            }
            else if (parameter.Type.IsStatic && !parameter.ContainingSymbol.ContainingType.IsInterfaceType())
            {
                // error CS0721: '{0}': static types cannot be used as parameters
                diagnostics.Add(ErrorCode.ERR_ParameterIsStaticClass, owner.Locations[0], parameter.Type);
            }
            else if (firstDefault != -1 && parameterIndex > firstDefault && !isDefault && !parameter.IsParams)
            {
                // error CS1737: Optional parameters must appear after all required parameters
                Location loc = parameterSyntax.Identifier.GetNextToken(includeZeroWidth: true).GetLocation(); //could be missing
                diagnostics.Add(ErrorCode.ERR_DefaultValueBeforeRequiredValue, loc);
            }
314
            else if (parameter.RefKind != RefKind.None && 
V
vsadov 已提交
315
                parameter.Type.IsRestrictedType(ignoreSpanLikeTypes: true))
P
Pilchie 已提交
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
            {
                // CS1601: Cannot make reference to variable of type 'System.TypedReference'
                diagnostics.Add(ErrorCode.ERR_MethodArgCantBeRefAny, parameterSyntax.Location, parameter.Type);
            }
        }

        internal static bool ReportDefaultParameterErrors(
            Binder binder,
            Symbol owner,
            ParameterSyntax parameterSyntax,
            SourceParameterSymbol parameter,
            BoundExpression defaultExpression,
            DiagnosticBag diagnostics)
        {
            bool hasErrors = false;

            // SPEC VIOLATION: The spec says that the conversion from the initializer to the 
            // parameter type is required to be either an identity or a nullable conversion, but
            // that is not right:
            //
            // void M(short myShort = 10) {}
            // * not an identity or nullable conversion but should be legal
            //
            // void M(object obj = (dynamic)null) {}
            // * an identity conversion, but should be illegal
            //
            // void M(MyStruct? myStruct = default(MyStruct)) {}
            // * a nullable conversion, but must be illegal because we cannot generate metadata for it
            // 
            // Even if the expression is thoroughly illegal, we still want to bind it and 
            // stick it in the parameter because we want to be able to analyze it for
            // IntelliSense purposes.

            TypeSymbol parameterType = parameter.Type;
            HashSet<DiagnosticInfo> useSiteDiagnostics = null;
            Conversion conversion = binder.Conversions.ClassifyImplicitConversionFromExpression(defaultExpression, parameterType, ref useSiteDiagnostics);
            diagnostics.Add(defaultExpression.Syntax, useSiteDiagnostics);

354
            var refKind = GetModifiers(parameterSyntax.Modifiers, out SyntaxToken refnessKeyword, out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword);
P
Pilchie 已提交
355 356 357 358 359

            // CONSIDER: We are inconsistent here regarding where the error is reported; is it
            // CONSIDER: reported on the parameter name, or on the value of the initializer?
            // CONSIDER: Consider making this consistent.

V
vsadov 已提交
360
            if (refKind == RefKind.Ref || refKind == RefKind.Out)
P
Pilchie 已提交
361 362
            {
                // error CS1741: A ref or out parameter cannot have a default value
363
                diagnostics.Add(ErrorCode.ERR_RefOutDefaultValue, refnessKeyword.GetLocation());
P
Pilchie 已提交
364 365
                hasErrors = true;
            }
366
            else if (paramsKeyword.Kind() == SyntaxKind.ParamsKeyword)
P
Pilchie 已提交
367 368 369 370 371
            {
                // error CS1751: Cannot specify a default value for a parameter array
                diagnostics.Add(ErrorCode.ERR_DefaultValueForParamsParameter, paramsKeyword.GetLocation());
                hasErrors = true;
            }
372
            else if (thisKeyword.Kind() == SyntaxKind.ThisKeyword)
P
Pilchie 已提交
373 374 375 376 377 378 379 380 381 382
            {
                // Only need to report CS1743 for the first parameter. The caller will
                // have reported CS1100 if 'this' appeared on another parameter.
                if (parameter.Ordinal == 0)
                {
                    // error CS1743: Cannot specify a default value for the 'this' parameter
                    diagnostics.Add(ErrorCode.ERR_DefaultValueForExtensionParameter, thisKeyword.GetLocation());
                    hasErrors = true;
                }
            }
G
gafter 已提交
383
            else if (!defaultExpression.HasAnyErrors && !IsValidDefaultValue(defaultExpression))
P
Pilchie 已提交
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
            {
                // error CS1736: Default parameter value for '{0}' must be a compile-time constant
                diagnostics.Add(ErrorCode.ERR_DefaultValueMustBeConstant, parameterSyntax.Default.Value.Location, parameterSyntax.Identifier.ValueText);
                hasErrors = true;
            }
            else if (!conversion.Exists ||
                conversion.IsUserDefined ||
                conversion.IsIdentity && parameterType.SpecialType == SpecialType.System_Object && defaultExpression.Type.IsDynamic())
            {
                // If we had no implicit conversion, or a user-defined conversion, report an error.
                //
                // Even though "object x = (dynamic)null" is a legal identity conversion, we do not allow it. 
                // CONSIDER: We could. Doesn't hurt anything.

                // error CS1750: A value of type '{0}' cannot be used as a default parameter because there are no standard conversions to type '{1}'
                diagnostics.Add(ErrorCode.ERR_NoConversionForDefaultParam, parameterSyntax.Identifier.GetLocation(),
400
                    defaultExpression.Display, parameterType);
P
Pilchie 已提交
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416

                hasErrors = true;
            }
            else if (conversion.IsReference &&
                (parameterType.SpecialType == SpecialType.System_Object || parameterType.Kind == SymbolKind.DynamicType) &&
                (object)defaultExpression.Type != null &&
                defaultExpression.Type.SpecialType == SpecialType.System_String ||
                conversion.IsBoxing)
            {
                // We don't allow object x = "hello", object x = 123, dynamic x = "hello", etc.
                // error CS1763: '{0}' is of type '{1}'. A default parameter value of a reference type other than string can only be initialized with null
                diagnostics.Add(ErrorCode.ERR_NotNullRefDefaultParameter, parameterSyntax.Identifier.GetLocation(),
                    parameterSyntax.Identifier.ValueText, parameterType);

                hasErrors = true;
            }
417
            else if (conversion.IsNullable && !defaultExpression.Type.IsNullableType() &&
P
Pilchie 已提交
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
                !(parameterType.GetNullableUnderlyingType().IsEnumType() || parameterType.GetNullableUnderlyingType().IsIntrinsicType()))
            {
                // We can do:
                // M(int? x = default(int)) 
                // M(int? x = default(int?)) 
                // M(MyEnum? e = default(enum))
                // M(MyEnum? e = default(enum?))
                // M(MyStruct? s = default(MyStruct?))
                //
                // but we cannot do:
                //
                // M(MyStruct? s = default(MyStruct))

                // error CS1770: 
                // A value of type '{0}' cannot be used as default parameter for nullable parameter '{1}' because '{0}' is not a simple type
                diagnostics.Add(ErrorCode.ERR_NoConversionForNubDefaultParam, parameterSyntax.Identifier.GetLocation(),
                    defaultExpression.Type, parameterSyntax.Identifier.ValueText);

                hasErrors = true;
            }

            // Certain contexts allow default parameter values syntactically but they are ignored during
            // semantic analysis. They are:

            // 1. Explicitly implemented interface methods; since the method will always be called
            //    via the interface, the defaults declared on the implementation will not 
            //    be seen at the call site.
            //
            // UNDONE: 2. The "actual" side of a partial method; the default values are taken from the
            // UNDONE:    "declaring" side of the method.
            //
            // UNDONE: 3. An indexer with only one formal parameter; it is illegal to omit every argument
            // UNDONE:    to an indexer.
            //
            // 4. A user-defined operator; it is syntactically impossible to omit the argument.

            if (owner.IsExplicitInterfaceImplementation() ||
                owner.IsPartialImplementation() ||
                owner.IsOperator())
            {
                // CS1066: The default value specified for parameter '{0}' will have no effect because it applies to a 
                //         member that is used in contexts that do not allow optional arguments
                diagnostics.Add(ErrorCode.WRN_DefaultValueForUnconsumedLocation,
                    parameterSyntax.Identifier.GetLocation(),
                    parameterSyntax.Identifier.ValueText);
            }

            return hasErrors;
        }

G
gafter 已提交
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
        private static bool IsValidDefaultValue(BoundExpression expression)
        {
            // SPEC VIOLATION: 
            // By the spec an optional parameter initializer is required to be either:
            // * a constant,
            // * new S() where S is a value type
            // * default(S) where S is a value type.
            // 
            // The native compiler considers default(T) to be a valid
            // initializer regardless of whether T is a value type
            // reference type, type parameter type, and so on.
            // We should consider simply allowing this in the spec.
            //
            // Also when valuetype S has a parameterless constructor, 
            // new S() is clearly not a constant expression and should produce an error
            return (expression.ConstantValue != null) ||
484
                   (expression.Kind == BoundKind.DefaultExpression) ||
G
gafter 已提交
485 486 487 488 489 490 491 492 493
                   (expression.Kind == BoundKind.ObjectCreationExpression &&
                       IsValidDefaultValue((BoundObjectCreationExpression)expression));
        }

        private static bool IsValidDefaultValue(BoundObjectCreationExpression expression)
        {
            return expression.Constructor.IsDefaultValueTypeConstructor() && expression.InitializerExpressionOpt == null;
        }

P
Pilchie 已提交
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
        internal static MethodSymbol FindContainingGenericMethod(Symbol symbol)
        {
            for (Symbol current = symbol; (object)current != null; current = current.ContainingSymbol)
            {
                if (current.Kind == SymbolKind.Method)
                {
                    MethodSymbol method = (MethodSymbol)current;
                    if (method.MethodKind != MethodKind.AnonymousFunction)
                    {
                        return method.IsGenericMethod ? method : null;
                    }
                }
            }
            return null;
        }

510
        private static RefKind GetModifiers(SyntaxTokenList modifiers, out SyntaxToken refnessKeyword, out SyntaxToken paramsKeyword, out SyntaxToken thisKeyword)
P
Pilchie 已提交
511 512 513
        {
            var refKind = RefKind.None;

514
            refnessKeyword = default(SyntaxToken);
P
Pilchie 已提交
515 516 517 518 519
            paramsKeyword = default(SyntaxToken);
            thisKeyword = default(SyntaxToken);

            foreach (var modifier in modifiers)
            {
520
                switch (modifier.Kind())
P
Pilchie 已提交
521 522 523 524
                {
                    case SyntaxKind.OutKeyword:
                        if (refKind == RefKind.None)
                        {
525
                            refnessKeyword = modifier;
P
Pilchie 已提交
526 527 528 529 530 531
                            refKind = RefKind.Out;
                        }
                        break;
                    case SyntaxKind.RefKeyword:
                        if (refKind == RefKind.None)
                        {
532
                            refnessKeyword = modifier;
P
Pilchie 已提交
533 534 535
                            refKind = RefKind.Ref;
                        }
                        break;
536 537
                    case SyntaxKind.InKeyword:
                        if (refKind == RefKind.None)
538
                        {
539
                            refnessKeyword = modifier;
540
                            refKind = RefKind.In;
541 542
                        }
                        break;
P
Pilchie 已提交
543 544 545 546 547 548 549 550 551 552 553 554 555
                    case SyntaxKind.ParamsKeyword:
                        paramsKeyword = modifier;
                        break;
                    case SyntaxKind.ThisKeyword:
                        thisKeyword = modifier;
                        break;
                }
            }

            return refKind;
        }
    }
}