From d681a41a67d171fbad6b9309c4a7c1e4e5baa3e2 Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Sun, 23 Jul 2017 15:12:00 +0100 Subject: [PATCH 01/10] Remove concept of bogus from types and most symbols. Since bogus types can't get as far as the dynamic binder, the only case where bogus can be true is when a non-indexer parametrized property, defined in a language where that is allowed, is encountered. In other cases computing bogosity involves recursive checks that always hit false. Give PropertySymbol a separate Bogus property to use where it could be set, and remove all other uses of GetBogus and similar. Entails removal of ERR_BogusType, contributes to #22470 --- .../CSharp/RuntimeBinder/Errors/ErrorCode.cs | 1 - .../CSharp/RuntimeBinder/Errors/ErrorFacts.cs | 3 - .../RuntimeBinder/Errors/UserStringBuilder.cs | 6 +- .../RuntimeBinder/Semantics/Conversion.cs | 2 - .../Semantics/ExpressionBinder.cs | 10 -- .../Semantics/GroupToArgsBinder.cs | 7 +- .../RuntimeBinder/Semantics/MemberLookup.cs | 47 ++----- .../RuntimeBinder/Semantics/Operators.cs | 10 -- .../Semantics/PredefinedMembers.cs | 5 +- .../Semantics/SemanticChecker.cs | 41 +----- .../Semantics/Symbols/PropertySymbol.cs | 2 + .../Semantics/Symbols/SymFactory.cs | 1 - .../RuntimeBinder/Semantics/Symbols/Symbol.cs | 128 ------------------ .../RuntimeBinder/Semantics/TypeBind.cs | 10 -- .../RuntimeBinder/Semantics/Types/Type.cs | 68 ---------- .../CSharp/RuntimeBinder/SymbolTable.cs | 4 +- .../Microsoft.CSharp.de.xlf | 4 - .../Microsoft.CSharp.es.xlf | 4 - .../Microsoft.CSharp.fr.xlf | 4 - .../Microsoft.CSharp.it.xlf | 4 - .../Microsoft.CSharp.ja.xlf | 4 - .../Microsoft.CSharp.ko.xlf | 4 - .../Microsoft.CSharp.ru.xlf | 4 - .../Microsoft.CSharp.zh-Hans.xlf | 4 - .../Microsoft.CSharp.zh-Hant.xlf | 4 - .../src/Resources/Strings.de.resx | 3 - .../src/Resources/Strings.es.resx | 3 - .../src/Resources/Strings.fr.resx | 3 - .../src/Resources/Strings.it.resx | 3 - .../src/Resources/Strings.ja.resx | 3 - .../src/Resources/Strings.ko.resx | 3 - .../src/Resources/Strings.resx | 3 - .../src/Resources/Strings.ru.resx | 3 - .../src/Resources/Strings.zh-Hans.resx | 3 - .../src/Resources/Strings.zh-Hant.resx | 3 - 35 files changed, 23 insertions(+), 388 deletions(-) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorCode.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorCode.cs index 919231a4eb16..2b06fdd89030 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorCode.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorCode.cs @@ -64,7 +64,6 @@ internal enum ErrorCode ERR_PredefinedTypeNotFound = 518, ERR_BindToBogus = 570, ERR_CantCallSpecialMethod = 571, - ERR_BogusType = 648, ERR_MissingPredefinedMember = 656, ERR_LiteralDoubleCast = 664, ERR_ConvertToStaticClass = 716, diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorFacts.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorFacts.cs index 7cf2531b8019..373cce64a41f 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorFacts.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/ErrorFacts.cs @@ -188,9 +188,6 @@ public static string GetMessage(ErrorCode code) case ErrorCode.ERR_CantCallSpecialMethod: codeStr = SR.CantCallSpecialMethod; break; - case ErrorCode.ERR_BogusType: - codeStr = SR.BogusType; - break; case ErrorCode.ERR_MissingPredefinedMember: codeStr = SR.MissingPredefinedMember; break; diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs index 1a1aecd5061b..4bc567b64efd 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs @@ -347,14 +347,12 @@ private void ErrAppendMethod(MethodSymbol meth, SubstContext pctx, bool fArgs) // append argument types ErrAppendChar('('); - if (!meth.computeCurrentBogusState()) - { - ErrAppendParamList(GetTypeManager().SubstTypeArray(meth.Params, pctx), meth.isVarargs, meth.isParamArray); - } + ErrAppendParamList(GetTypeManager().SubstTypeArray(meth.Params, pctx), meth.isVarargs, meth.isParamArray); ErrAppendChar(')'); } } + private void ErrAppendIndexer(IndexerSymbol indexer, SubstContext pctx) { ErrAppendString("this["); diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs index 832a0870d753..b6b52e6ac915 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs @@ -1032,8 +1032,6 @@ private bool bindUserDefinedConversion(Expr exprSrc, CType typeSrc, CType typeDs if (fImplicitOnly && !convCur.isImplicit()) continue; - if (GetSemanticChecker().CheckBogus(convCur)) - continue; // Get the substituted src and dst types. typeFrom = GetTypes().SubstType(convCur.Params[0], atsCur); diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs index baa4ef0ff1b7..764f7ec188cc 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs @@ -1036,16 +1036,6 @@ internal Expr bindUDUnop(ExpressionKind ek, Expr arg) return rval; } - if (SemanticChecker.CheckBogus(pmethBest.mpwi.Meth())) - { - ErrorContext.ErrorRef(ErrorCode.ERR_BindToBogus, pmethBest.mpwi); - - ExprMemberGroup pMemGroup = GetExprFactory().CreateMemGroup(null, pmethBest.mpwi); - ExprCall rval = GetExprFactory().CreateCall(0, null, arg, pMemGroup, null); - rval.SetError(); - return rval; - } - ExprCall call; if (pmethBest.ctypeLift != 0) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs index 530acbad76e2..652bbab3d259 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs @@ -236,7 +236,7 @@ private void LookForCandidates() if (!bFoundExpanded) { lookedAtCandidates = true; - allCandidatesUnsupported &= _pCurrentSym.getBogus(); + allCandidatesUnsupported &= (_pCurrentSym is PropertySymbol prop && prop.Bogus); // If we have the wrong number of arguments and still have room in our cache of 20, // then store it in our cache and go to the next sym. @@ -1512,10 +1512,7 @@ private void ReportErrorsForBestMatching(bool bUseDelegateErrors, Name nameErr) if (ivar == 0 && sym is MethodSymbol meth && meth.IsExtension() && _pGroup.OptionalObject != null && !_pExprBinder.canConvertInstanceParamForExtension(_pGroup.OptionalObject, meth.Params[0])) { - if (!_pGroup.OptionalObject.Type.getBogus()) - { - GetErrorContext().Error(ErrorCode.ERR_BadInstanceArgType, _pGroup.OptionalObject.Type, var); - } + GetErrorContext().Error(ErrorCode.ERR_BadInstanceArgType, _pGroup.OptionalObject.Type, var); } else { diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs index 5c38aa812a01..e91d3d65664f 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs @@ -535,45 +535,22 @@ private bool LookupInInterfaces(AggregateType typeStart, TypeArray types) private void ReportBogus(SymWithType swt) { - Debug.Assert(swt.Sym.hasBogus() && swt.Sym.checkBogus()); - - switch (swt.Sym.getKind()) + Debug.Assert(swt.Sym is PropertySymbol propAssert && propAssert.Bogus); + MethodSymbol meth1 = swt.Prop().methGet; + MethodSymbol meth2 = swt.Prop().methSet; + Debug.Assert((meth1 ?? meth2) != null); + if (meth1 == null | meth2 == null) { - case SYMKIND.SK_PropertySymbol: - if (swt.Prop().useMethInstead) - { - MethodSymbol meth1 = swt.Prop().methGet; - MethodSymbol meth2 = swt.Prop().methSet; - ReportBogusForEventsAndProperties(swt, meth1, meth2); - return; - } - break; - - case SYMKIND.SK_MethodSymbol: - if (swt.Meth().name == NameManager.GetPredefinedName(PredefinedName.PN_INVOKE) && swt.Meth().getClass().IsDelegate()) - { - swt.Set(swt.Meth().getClass(), swt.GetType()); - } - break; + GetErrorContext().Error( + ErrorCode.ERR_BindToBogusProp1, swt.Sym.name, new SymWithType(meth1 ?? meth2, swt.GetType()), + new ErrArgRefOnly(swt.Sym)); } - - // Generic bogus error. - GetErrorContext().ErrorRef(ErrorCode.ERR_BindToBogus, swt); - } - - private void ReportBogusForEventsAndProperties(SymWithType swt, MethodSymbol meth1, MethodSymbol meth2) - { - if (meth1 != null && meth2 != null) - { - GetErrorContext().Error(ErrorCode.ERR_BindToBogusProp2, swt.Sym.name, new SymWithType(meth1, swt.GetType()), new SymWithType(meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym)); - return; - } - if (meth1 != null || meth2 != null) + else { - GetErrorContext().Error(ErrorCode.ERR_BindToBogusProp1, swt.Sym.name, new SymWithType(meth1 != null ? meth1 : meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym)); - return; + GetErrorContext().Error( + ErrorCode.ERR_BindToBogusProp2, swt.Sym.name, new SymWithType(meth1, swt.GetType()), + new SymWithType(meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym)); } - throw Error.InternalCompilerError(); } private bool IsDelegateType(CType pSrcType, AggregateType pAggType) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Operators.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Operators.cs index dba78eee1d50..db35fa235e6d 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Operators.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Operators.cs @@ -2758,16 +2758,6 @@ private ExprCall BindUDBinop(ExpressionKind ek, Expr arg1, Expr arg2, bool fDont return rval; } - if (GetSemanticChecker().CheckBogus(pmethBest.mpwi.Meth())) - { - GetErrorContext().ErrorRef(ErrorCode.ERR_BindToBogus, pmethBest.mpwi); - - ExprMemberGroup pMemGroup = GetExprFactory().CreateMemGroup(null, pmethBest.mpwi); - ExprCall rval = GetExprFactory().CreateCall(0, null, GetExprFactory().CreateList(arg1, arg2), pMemGroup, null); - rval.SetError(); - return rval; - } - ppmpwi = pmethBest.mpwi; if (pmethBest.ctypeLift != 0) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs index 5aaa65dff52d..86b7ce8fb4b6 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs @@ -358,7 +358,7 @@ private PropertySymbol LoadProperty( (setter == null || !setter.isPropertyAccessor() || setter.getProperty() != property)) || - property.getBogus()) + property.Bogus) { property = null; } @@ -610,8 +610,7 @@ private MethodSymbol LookupMethodWhileLoading(AggregateSymbol type, int cMethodT methsym.typeVars.Count == cMethodTyVars && GetTypeManager().SubstEqualTypes(methsym.RetType, returnType, null, methsym.typeVars, SubstTypeFlags.DenormMeth) && GetTypeManager().SubstEqualTypeArrays(methsym.Params, argumentTypes, (TypeArray)null, - methsym.typeVars, SubstTypeFlags.DenormMeth) && - !methsym.getBogus()) + methsym.typeVars, SubstTypeFlags.DenormMeth)) { return methsym; } diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs index b4b436bfb787..fa58311917c1 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs @@ -288,46 +288,7 @@ typeThru is NullableType || public bool CheckBogus(Symbol sym) { - if (sym == null) - { - return false; - } - - if (!sym.hasBogus()) - { - bool fBogus = sym.computeCurrentBogusState(); - - if (fBogus) - { - // Only set this if everything is declared or - // at least 1 declared thing is bogus - sym.setBogus(fBogus); - } - } - - return sym.hasBogus() && sym.checkBogus(); - } - - public bool CheckBogus(CType pType) - { - if (pType == null) - { - return false; - } - - if (!pType.hasBogus()) - { - bool fBogus = pType.computeCurrentBogusState(); - - if (fBogus) - { - // Only set this if everything is declared or - // at least 1 declared thing is bogus - pType.setBogus(fBogus); - } - } - - return pType.hasBogus() && pType.checkBogus(); + return sym is PropertySymbol prop && prop.Bogus; } public void ReportAccessError(SymWithType swtBad, Symbol symWhere, CType typeQual) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs index f55899152668..9b54b322fe53 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs @@ -31,5 +31,7 @@ public IndexerSymbol AsIndexerSymbol() Debug.Assert(isIndexer()); return (IndexerSymbol)this; } + + public bool Bogus { get; set; } } } diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymFactory.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymFactory.cs index fa36f67a9b2a..358a55d95bec 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymFactory.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymFactory.cs @@ -46,7 +46,6 @@ public AggregateSymbol CreateAggregate(Name name, NamespaceOrAggregateSymbol par sym.SetTypeManager(typeManager); sym.SetSealed(false); sym.SetAccess(ACCESS.ACC_UNKNOWN); - sym.initBogus(); sym.SetIfaces(null); sym.SetIfacesAll(null); sym.SetTypeVars(null); diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/Symbol.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/Symbol.cs index 2f0167126b26..7bae029cb2d1 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/Symbol.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/Symbol.cs @@ -56,8 +56,6 @@ internal enum SpecCons internal abstract class Symbol { private SYMKIND _kind; // the symbol kind - private bool _isBogus; // can't be used in our language -- unsupported type(s) - private bool _checkedBogus; // Have we checked a method args/return for bogus types private ACCESS _access; // access level // If this is true, then we had an error the first time so do not give an error the second time. @@ -94,132 +92,6 @@ public symbmask_t mask() return (symbmask_t)(1 << (int)_kind); } - public bool checkBogus() - { - Debug.Assert(_checkedBogus); - return _isBogus; - } // if this Debug.Assert fires then call COMPILER_BASE::CheckBogus() instead - - public bool getBogus() - { - return _isBogus; - } - - public bool hasBogus() - { - return _checkedBogus; - } - - public void setBogus(bool isBogus) - { - _isBogus = isBogus; - _checkedBogus = true; - } - - public void initBogus() - { - _isBogus = false; - _checkedBogus = false; - } - - public bool computeCurrentBogusState() - { - if (hasBogus()) - { - return checkBogus(); - } - - bool fBogus = false; - - switch (getKind()) - { - case SYMKIND.SK_PropertySymbol: - case SYMKIND.SK_MethodSymbol: - { - MethodOrPropertySymbol meth = (MethodOrPropertySymbol)this; - - if (meth.RetType != null) - { - fBogus = meth.RetType.computeCurrentBogusState(); - } - if (meth.Params != null) - { - for (int i = 0; !fBogus && i < meth.Params.Count; i++) - { - fBogus |= meth.Params[i].computeCurrentBogusState(); - } - } - } - break; - - /* - case SYMKIND.SK_ParameterModifierType: - case SYMKIND.SK_OptionalModifierType: - case SYMKIND.SK_PointerType: - case SYMKIND.SK_ArrayType: - case SYMKIND.SK_NullableType: - case SYMKIND.SK_PinnedType: - if (this.AsType().GetBaseOrParameterOrElementType() != null) - { - fBogus = this.AsType().GetBaseOrParameterOrElementType().computeCurrentBogusState(); - } - break; - */ - - case SYMKIND.SK_EventSymbol: - CType evType = ((EventSymbol)this).type; - if (evType != null) - { - fBogus = evType.computeCurrentBogusState(); - } - break; - - case SYMKIND.SK_FieldSymbol: - var fiType = ((FieldSymbol)this).GetType(); - if (fiType != null) - { - fBogus = fiType.computeCurrentBogusState(); - } - break; - - /* - case SYMKIND.SK_ErrorType: - this.setBogus(false); - break; - - case SYMKIND.SK_AggregateType: - fBogus = this.AsAggregateType().getAggregate().computeCurrentBogusState(); - for (int i = 0; !fBogus && i < this.AsAggregateType().GetTypeArgsAll().size; i++) - { - fBogus |= this.AsAggregateType().GetTypeArgsAll()[i].computeCurrentBogusState(); - } - break; - */ - - case SYMKIND.SK_TypeParameterSymbol: - case SYMKIND.SK_LocalVariableSymbol: - setBogus(false); - break; - - case SYMKIND.SK_AggregateSymbol: - fBogus = hasBogus() && checkBogus(); - break; - - default: - Debug.Assert(false, "CheckBogus with invalid Symbol kind"); - setBogus(false); - break; - } - - if (fBogus) - { - // Only set this if at least 1 declared thing is bogus - setBogus(fBogus); - } - - return hasBogus() && checkBogus(); - } - public CType getType() { if (this is MethodOrPropertySymbol methProp) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/TypeBind.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/TypeBind.cs index dc9b52aa9808..0f7910a55869 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/TypeBind.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/TypeBind.cs @@ -157,16 +157,6 @@ private static bool CheckSingleConstraint(CSemanticChecker checker, ErrorHandlin return false; } - if (checker.CheckBogus(arg)) - { - if (fReportErrors) - { - errHandling.ErrorRef(ErrorCode.ERR_BogusType, arg); - } - - return false; - } - if (arg is PointerType) { if (fReportErrors) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/Type.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/Type.cs index f0403e3c1da6..c651d28e762e 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/Type.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/Type.cs @@ -16,8 +16,6 @@ internal abstract class CType private Name _pName; private bool _fHasErrors; // Whether anyituents have errors. This is immutable. - private bool _isBogus; // can't be used in our language -- unsupported type(s) - private bool _checkedBogus; // Have we checked a method args/return for bogus types public bool IsWindowsRuntimeType() { @@ -167,72 +165,6 @@ private static Type CalculateAssociatedSystemTypeForAggregate(AggregateType aggt public Name GetName() { return _pName; } public void SetName(Name pName) { _pName = pName; } - public bool checkBogus() { return _isBogus; } - public bool getBogus() { return _isBogus; } - public bool hasBogus() { return _checkedBogus; } - public void setBogus(bool isBogus) - { - _isBogus = isBogus; - _checkedBogus = true; - } - public bool computeCurrentBogusState() - { - if (hasBogus()) - { - return checkBogus(); - } - - bool fBogus = false; - - switch (GetTypeKind()) - { - case TypeKind.TK_ParameterModifierType: - case TypeKind.TK_PointerType: - case TypeKind.TK_ArrayType: - case TypeKind.TK_NullableType: - if (GetBaseOrParameterOrElementType() != null) - { - fBogus = GetBaseOrParameterOrElementType().computeCurrentBogusState(); - } - break; - - case TypeKind.TK_ErrorType: - setBogus(false); - break; - - case TypeKind.TK_AggregateType: - AggregateType aggThis = (AggregateType)this; - fBogus = aggThis.getAggregate().computeCurrentBogusState(); - for (int i = 0; !fBogus && i < aggThis.GetTypeArgsAll().Count; i++) - { - fBogus |= aggThis.GetTypeArgsAll()[i].computeCurrentBogusState(); - } - break; - - case TypeKind.TK_TypeParameterType: - case TypeKind.TK_VoidType: - case TypeKind.TK_NullType: - case TypeKind.TK_OpenTypePlaceholderType: - case TypeKind.TK_ArgumentListType: - case TypeKind.TK_NaturalIntegerType: - setBogus(false); - break; - - default: - throw Error.InternalCompilerError(); - //setBogus(false); - //break; - } - - if (fBogus) - { - // Only set this if at least 1 declared thing is bogus - setBogus(fBogus); - } - - return hasBogus() && checkBogus(); - } - // This call switches on the kind and dispatches accordingly. This should really only be // used when dereferencing TypeArrays. We should consider refactoring our code to not // need this type of thing - strongly typed handling of TypeArrays would be much better. diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs index 5e6055f474ce..5c49f503798d 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs @@ -1458,7 +1458,7 @@ private void AddPropertyToSymbolTable(PropertyInfo property, AggregateSymbol agg } else { - prop.setBogus(true); + prop.Bogus = true; prop.methGet.SetMethKind(MethodKindEnum.Actual); } @@ -1479,7 +1479,7 @@ private void AddPropertyToSymbolTable(PropertyInfo property, AggregateSymbol agg } else { - prop.setBogus(true); + prop.Bogus = true; prop.methSet.SetMethKind(MethodKindEnum.Actual); } diff --git a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.de.xlf b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.de.xlf index 33ab2643cd45..935897a69b08 100644 --- a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.de.xlf +++ b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.de.xlf @@ -290,10 +290,6 @@ '{0}': cannot explicitly call operator or accessor {0}: Der Operator oder Accessor kann nicht explizit aufgerufen werden. - - '{0}' is a type not supported by the language - {0} ist ein Typ, der von der Sprache nicht unterstützt wird. - Missing compiler required member '{0}.{1}' Der vom Compiler angeforderte Member "{0}.{1}" fehlt. diff --git a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.es.xlf b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.es.xlf index b171e6e095a9..ffe0ef338ce0 100644 --- a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.es.xlf +++ b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.es.xlf @@ -290,10 +290,6 @@ '{0}': cannot explicitly call operator or accessor '{0}': no se puede llamar explícitamente al operador o al descriptor de acceso - - '{0}' is a type not supported by the language - No se admite el tipo '{0}' para este lenguaje - Missing compiler required member '{0}.{1}' Falta el miembro '{0}.{1}' que requiere el compilador. diff --git a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.fr.xlf b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.fr.xlf index fd951062fe0b..097a5eca3e7a 100644 --- a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.fr.xlf +++ b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.fr.xlf @@ -290,10 +290,6 @@ '{0}': cannot explicitly call operator or accessor '{0}' : impossible d'appeler explicitement un opérateur ou un accesseur - - '{0}' is a type not supported by the language - '{0}' est un type qui n'est pas pris en charge par le langage - Missing compiler required member '{0}.{1}' Membre requis par le compilateur '{0}.{1}' manquant diff --git a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.it.xlf b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.it.xlf index 745e03daad12..ccc71142ca9d 100644 --- a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.it.xlf +++ b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.it.xlf @@ -290,10 +290,6 @@ '{0}': cannot explicitly call operator or accessor '{0}': impossibile chiamare in modo esplicito l'operatore o la funzione di accesso - - '{0}' is a type not supported by the language - '{0}' è un tipo non supportato dal linguaggio - Missing compiler required member '{0}.{1}' Manca il membro '{0}.{1}', necessario per il compilatore. diff --git a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ja.xlf b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ja.xlf index f9e5e5032063..af79f19f2d7a 100644 --- a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ja.xlf +++ b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ja.xlf @@ -290,10 +290,6 @@ '{0}': cannot explicitly call operator or accessor '{0}': 演算子またはアクセサーを明示的に呼び出すことはできません - - '{0}' is a type not supported by the language - '{0}' はこの言語でサポートされていない型です - Missing compiler required member '{0}.{1}' コンパイラが必要とするメンバー '{0}.{1}' がありません diff --git a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ko.xlf b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ko.xlf index 08110b2b8410..35b97d5a878f 100644 --- a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ko.xlf +++ b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ko.xlf @@ -290,10 +290,6 @@ '{0}': cannot explicitly call operator or accessor '{0}': 연산자나 접근자를 명시적으로 호출할 수 없습니다. - - '{0}' is a type not supported by the language - '{0}'은(는) 언어에서 지원하는 형식이 아닙니다. - Missing compiler required member '{0}.{1}' '{0}.{1}' 멤버를 필요로 하는 컴파일러가 없습니다. diff --git a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ru.xlf b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ru.xlf index 890e2db2dc2b..d58e8e0a5521 100644 --- a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ru.xlf +++ b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.ru.xlf @@ -290,10 +290,6 @@ '{0}': cannot explicitly call operator or accessor "{0}": явный вызов оператора или метода доступа невозможен - - '{0}' is a type not supported by the language - "{0}" является типом, который не поддерживается в данном языке - Missing compiler required member '{0}.{1}' Отсутствует обязательный для компилятора член "{0}.{1}" diff --git a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.zh-Hans.xlf b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.zh-Hans.xlf index d2ee5a9ccfee..18efd6578168 100644 --- a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.zh-Hans.xlf +++ b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.zh-Hans.xlf @@ -290,10 +290,6 @@ '{0}': cannot explicitly call operator or accessor “{0}”: 无法显式调用运算符或访问器 - - '{0}' is a type not supported by the language - “{0}”不是现用语言支持的类型 - Missing compiler required member '{0}.{1}' 缺少编译器要求的成员“{0}.{1}” diff --git a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.zh-Hant.xlf b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.zh-Hant.xlf index d48dd517903d..a8535b2bdec9 100644 --- a/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.zh-Hant.xlf +++ b/src/Microsoft.CSharp/src/MultilingualResources/Microsoft.CSharp.zh-Hant.xlf @@ -290,10 +290,6 @@ '{0}': cannot explicitly call operator or accessor '{0}': 無法明確呼叫運算子或存取子 - - '{0}' is a type not supported by the language - 此語言不支援型別 '{0}' - Missing compiler required member '{0}.{1}' 遺漏編譯器所需的成員 '{0}.{1}' diff --git a/src/Microsoft.CSharp/src/Resources/Strings.de.resx b/src/Microsoft.CSharp/src/Resources/Strings.de.resx index 1261865aa063..42df6c405c15 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.de.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.de.resx @@ -225,9 +225,6 @@ {0}: Der Operator oder Accessor kann nicht explizit aufgerufen werden. - - {0} ist ein Typ, der von der Sprache nicht unterstützt wird. - Der vom Compiler angeforderte Member "{0}.{1}" fehlt. diff --git a/src/Microsoft.CSharp/src/Resources/Strings.es.resx b/src/Microsoft.CSharp/src/Resources/Strings.es.resx index c609da3e6edb..7dce91fb4766 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.es.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.es.resx @@ -225,9 +225,6 @@ '{0}': no se puede llamar explícitamente al operador o al descriptor de acceso - - No se admite el tipo '{0}' para este lenguaje - Falta el miembro '{0}.{1}' que requiere el compilador. diff --git a/src/Microsoft.CSharp/src/Resources/Strings.fr.resx b/src/Microsoft.CSharp/src/Resources/Strings.fr.resx index 35e06bed46b9..d48864e0bc30 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.fr.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.fr.resx @@ -225,9 +225,6 @@ '{0}' : impossible d'appeler explicitement un opérateur ou un accesseur - - '{0}' est un type qui n'est pas pris en charge par le langage - Membre requis par le compilateur '{0}.{1}' manquant diff --git a/src/Microsoft.CSharp/src/Resources/Strings.it.resx b/src/Microsoft.CSharp/src/Resources/Strings.it.resx index 6cea069b015d..607cfd677240 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.it.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.it.resx @@ -225,9 +225,6 @@ '{0}': impossibile chiamare in modo esplicito l'operatore o la funzione di accesso - - '{0}' è un tipo non supportato dal linguaggio - Manca il membro '{0}.{1}', necessario per il compilatore. diff --git a/src/Microsoft.CSharp/src/Resources/Strings.ja.resx b/src/Microsoft.CSharp/src/Resources/Strings.ja.resx index 5464930517aa..2a9c3121faf1 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.ja.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.ja.resx @@ -225,9 +225,6 @@ '{0}': 演算子またはアクセサーを明示的に呼び出すことはできません - - '{0}' はこの言語でサポートされていない型です - コンパイラが必要とするメンバー '{0}.{1}' がありません diff --git a/src/Microsoft.CSharp/src/Resources/Strings.ko.resx b/src/Microsoft.CSharp/src/Resources/Strings.ko.resx index a42a379b42d3..2c23d8c2fb5b 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.ko.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.ko.resx @@ -225,9 +225,6 @@ '{0}': 연산자나 접근자를 명시적으로 호출할 수 없습니다. - - '{0}'은(는) 언어에서 지원하는 형식이 아닙니다. - '{0}.{1}' 멤버를 필요로 하는 컴파일러가 없습니다. diff --git a/src/Microsoft.CSharp/src/Resources/Strings.resx b/src/Microsoft.CSharp/src/Resources/Strings.resx index 19269c0a9eea..14d22cacc885 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.resx @@ -271,9 +271,6 @@ '{0}': cannot explicitly call operator or accessor - - '{0}' is a type not supported by the language - Missing compiler required member '{0}.{1}' diff --git a/src/Microsoft.CSharp/src/Resources/Strings.ru.resx b/src/Microsoft.CSharp/src/Resources/Strings.ru.resx index 8530157c039f..9e5bcf2b31f2 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.ru.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.ru.resx @@ -225,9 +225,6 @@ "{0}": явный вызов оператора или метода доступа невозможен - - "{0}" является типом, который не поддерживается в данном языке - Отсутствует обязательный для компилятора член "{0}.{1}" diff --git a/src/Microsoft.CSharp/src/Resources/Strings.zh-Hans.resx b/src/Microsoft.CSharp/src/Resources/Strings.zh-Hans.resx index e97c4b3d20aa..9d843fc5eeca 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.zh-Hans.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.zh-Hans.resx @@ -225,9 +225,6 @@ “{0}”: 无法显式调用运算符或访问器 - - “{0}”不是现用语言支持的类型 - 缺少编译器要求的成员“{0}.{1}” diff --git a/src/Microsoft.CSharp/src/Resources/Strings.zh-Hant.resx b/src/Microsoft.CSharp/src/Resources/Strings.zh-Hant.resx index 9f80d7f592fc..e7a190d85c1e 100644 --- a/src/Microsoft.CSharp/src/Resources/Strings.zh-Hant.resx +++ b/src/Microsoft.CSharp/src/Resources/Strings.zh-Hant.resx @@ -225,9 +225,6 @@ '{0}': 無法明確呼叫運算子或存取子 - - 此語言不支援型別 '{0}' - 遺漏編譯器所需的成員 '{0}.{1}' From a25d7d4f9e91f63129c8128a0f0d204d4476e333 Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Sun, 23 Jul 2017 17:50:09 +0100 Subject: [PATCH 02/10] Identify indexer properties correctly in AddPropertyToSymbolTable AddPropertyToSymbolTable assumes any property with parameters is an indexer, which makes the subsequent check that only indexers can have parameters tautologous. Check DefaultMemberAttribute instead. --- .../src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs index 5c49f503798d..451cb7e93c4d 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs @@ -1354,7 +1354,9 @@ internal void AddPredefinedPropertyToSymbolTable(AggregateSymbol type, Name prop private void AddPropertyToSymbolTable(PropertyInfo property, AggregateSymbol aggregate) { Name name; - bool isIndexer = property.GetIndexParameters() != null && property.GetIndexParameters().Length != 0; + bool isIndexer = property.GetIndexParameters().Length != 0 + && (property.DeclaringType?.GetCustomAttribute(typeof(DefaultMemberAttribute)) as DefaultMemberAttribute) + ?.MemberName == property.Name; if (isIndexer) { From fdecb9fce90cd982d6cf43d6676a4e8f5b377b9d Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Sun, 23 Jul 2017 18:25:43 +0100 Subject: [PATCH 03/10] Remove useMethInstead from property symbols and consider always true. useMethInstead should be set in AddPropertyToSymbolTable when bogus is set, but is not. However, the only time it is looked for the only possible value is true as that is the only condition under which a symbol can be bogus, so remove it, and the path for it being false. This now means that ErrorCode.ERR_BindToBogusProp1 or ErrorCode.ERR_BindToBogusProp2 will be used when appropriate. Fixes #22534 --- .../RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs | 1 - .../src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs index 87595137fb28..6cd690140fb8 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs @@ -29,7 +29,6 @@ internal abstract class MethodOrPropertySymbol : ParentSymbol public new bool isStatic; // Static member? public bool isOverride; // Overrides an inherited member. Only valid if isVirtual is set. // false implies that a new vtable slot is required for this method. - public bool useMethInstead; // Only valid iff isBogus == TRUE && IsPropertySymbol(). // If this is true then tell the user to call the accessors directly. public bool isOperator; // a user defined operator (or default indexed property) public bool isParamArray; // new style varargs diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs index 451cb7e93c4d..2d6c0db5f2bc 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs @@ -1655,7 +1655,6 @@ private MethodSymbol AddMethodToSymbolTable(MemberInfo member, AggregateSymbol c } methodSymbol.modOptCount = GetCountOfModOpts(parameters); - methodSymbol.useMethInstead = false; methodSymbol.isParamArray = DoesMethodHaveParameterArray(parameters); methodSymbol.isHideByName = false; From 47d10ea1d59eb1702ddcdb650fc0214d9213404d Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Sun, 23 Jul 2017 20:56:01 +0100 Subject: [PATCH 04/10] Tests for accessing non-indexer parameter properties --- .../tests/Dynamic/InvokeMemberBindingTests.cs | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/src/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs b/src/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs index a5eb3b3fa568..a27639c46866 100644 --- a/src/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs +++ b/src/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; using Microsoft.CSharp.RuntimeBinder; using Xunit; @@ -182,5 +184,94 @@ public void CallInfoStored() CallInfo info = new CallInfo(0); Assert.Same(info, new MinimumOverrideInvokeMemberBinding("name", false, info).CallInfo); } + +#if FEATURE_COMPILE // We're not testing compilation, but we do need Reflection.Emit for the test + + private static dynamic GetObjectWithNonIndexerParameterProperty(bool hasGetter, bool hasSetter) + { + TypeBuilder typeBuild = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run) + .DefineDynamicModule("TestModule") + .DefineType("TestType", TypeAttributes.Public); + FieldBuilder field = typeBuild.DefineField("_value", typeof(int), FieldAttributes.Private); + + PropertyBuilder property = typeBuild.DefineProperty( + "ItemProp", PropertyAttributes.None, typeof(int), new[] { typeof(int) }); + + if (hasGetter) + { + MethodBuilder getter = typeBuild.DefineMethod( + "get_ItemProp", + MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig + | MethodAttributes.PrivateScope, typeof(int), new[] { typeof(int) }); + + ILGenerator ilGen = getter.GetILGenerator(); + ilGen.Emit(OpCodes.Ldarg_0); + ilGen.Emit(OpCodes.Ldfld, field); + ilGen.Emit(OpCodes.Ret); + + property.SetGetMethod(getter); + } + + if (hasSetter) + { + + MethodBuilder setter = typeBuild.DefineMethod( + "set_ItemProp", + MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig + | MethodAttributes.PrivateScope, typeof(void), new[] { typeof(int), typeof(int) }); + + ILGenerator ilGen = setter.GetILGenerator(); + ilGen.Emit(OpCodes.Ldarg_0); + ilGen.Emit(OpCodes.Ldarg_2); + ilGen.Emit(OpCodes.Stfld, field); + ilGen.Emit(OpCodes.Ret); + + property.SetSetMethod(setter); + } + + return Activator.CreateInstance(typeBuild.CreateType()); + } + + [Fact] + public void NonIndexerParameterizedDirectAccess() + { + // If a paramterized property isn't the type's indexer, we should be allowed to use the + // getter or setter directly. + dynamic d = GetObjectWithNonIndexerParameterProperty(true, true); + d.set_ItemProp(2, 19); + int value = d.get_ItemProp(2); + Assert.Equal(19, value); + } + + [Fact] + public void NonIndexerParamterizedGetterAndSetterIndexAccess() + { + dynamic d = GetObjectWithNonIndexerParameterProperty(true, true); + RuntimeBinderException ex = Assert.Throws(() => d.ItemProp[2] = 3); + // Similar message to CS1545 advises about getter and setter methods. + Assert.Contains("get_ItemProp", ex.Message); + Assert.Contains("set_ItemProp", ex.Message); + } + + [Fact] + public void NonIndexerParamterizedGetterOnlyIndexAccess() + { + dynamic d = GetObjectWithNonIndexerParameterProperty(true, false); + int dump; + RuntimeBinderException ex = Assert.Throws(() => dump = d.ItemProp[2]); + // Similar message to CS1546 advises about getter method. + Assert.Contains("get_ItemProp", ex.Message); + } + + [Fact] + public void NonIndexerParamterizedSetterOnlyIndexAccess() + { + dynamic d = GetObjectWithNonIndexerParameterProperty(false, true); + RuntimeBinderException ex = Assert.Throws(() => d.ItemProp[2] = 9); + // Similar message to CS1546 advises about setter method. + Assert.Contains("set_ItemProp", ex.Message); + } + +#endif } } From 5cdcc285ad4676f9f9df2a46d3f019a0d770ddba Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Sun, 23 Jul 2017 21:08:49 +0100 Subject: [PATCH 05/10] Remove bogus check within PredefinedMembers Predefined properties cannot be bogus. --- .../CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs index 86b7ce8fb4b6..345687ffc52a 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs @@ -353,13 +353,10 @@ private PropertySymbol LoadProperty( property = getter.getProperty(); Debug.Assert(property != null); - if (property.name != propertyName || - (propertySetter != PREDEFMETH.PM_COUNT && - (setter == null || - !setter.isPropertyAccessor() || - setter.getProperty() != property)) || - property.Bogus) + if (property.name != propertyName || propertySetter != PREDEFMETH.PM_COUNT + && (setter == null || !setter.isPropertyAccessor() || setter.getProperty() != property)) { + Debug.Assert(!property.Bogus); property = null; } } From a0f2d2cc40dd6da2ea3bb128aaa015bf602ee34e Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Wed, 26 Jul 2017 02:56:08 +0100 Subject: [PATCH 06/10] Refactor CheckBogus to static and use consistently. --- .../CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs | 2 +- .../Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs | 4 ++-- .../CSharp/RuntimeBinder/Semantics/MethodIterator.cs | 2 +- .../CSharp/RuntimeBinder/Semantics/SemanticChecker.cs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs index 652bbab3d259..6ac90a793b6e 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs @@ -236,7 +236,7 @@ private void LookForCandidates() if (!bFoundExpanded) { lookedAtCandidates = true; - allCandidatesUnsupported &= (_pCurrentSym is PropertySymbol prop && prop.Bogus); + allCandidatesUnsupported &= CSemanticChecker.CheckBogus(_pCurrentSym); // If we have the wrong number of arguments and still have room in our cache of 20, // then store it in our cache and go to the next sym. diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs index e91d3d65664f..6b9017c13e36 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs @@ -244,7 +244,7 @@ private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName) // We can't call CheckBogus on methods or indexers because if the method has the wrong // number of parameters people don't think they should have to /r the assemblies containing // the parameter types and they complain about the resulting CS0012 errors. - if (!(symCur is MethodSymbol) && (_flags & MemLookFlags.Indexer) == 0 && GetSemanticChecker().CheckBogus(symCur)) + if (!(symCur is MethodSymbol) && (_flags & MemLookFlags.Indexer) == 0 && CSemanticChecker.CheckBogus(symCur)) { // A bogus member - we can't use these, so only record them for error reporting. if (!_swtBogus) @@ -535,7 +535,7 @@ private bool LookupInInterfaces(AggregateType typeStart, TypeArray types) private void ReportBogus(SymWithType swt) { - Debug.Assert(swt.Sym is PropertySymbol propAssert && propAssert.Bogus); + Debug.Assert(CSemanticChecker.CheckBogus(swt.Sym)); MethodSymbol meth1 = swt.Prop().methGet; MethodSymbol meth2 = swt.Prop().methSet; Debug.Assert((meth1 ?? meth2) != null); diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs index d019a213169d..3f4245c3548a 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs @@ -181,7 +181,7 @@ public bool CanUseCurrentSymbol() } // Check bogus. - if (GetSemanticChecker().CheckBogus(_pCurrentSym)) + if (CSemanticChecker.CheckBogus(_pCurrentSym)) { // Sym is bogus, but if we're allow it, then let it through and mark it. if (_bAllowBogusAndInaccessible) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs index fa58311917c1..7823dbed8d44 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs @@ -286,9 +286,9 @@ typeThru is NullableType || return (atsThru == null) ? ACCESSERROR.ACCESSERROR_NOACCESS : ACCESSERROR.ACCESSERROR_NOACCESSTHRU; } - public bool CheckBogus(Symbol sym) + public static bool CheckBogus(Symbol sym) { - return sym is PropertySymbol prop && prop.Bogus; + return (sym as PropertySymbol)?.Bogus ?? false; } public void ReportAccessError(SymWithType swtBad, Symbol symWhere, CType typeQual) From 202dba59adbcc9f75518f148c95c742e184a637d Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Wed, 26 Jul 2017 13:05:39 +0100 Subject: [PATCH 07/10] Replace IsIndexer and AsIndexer with direct operations --- .../CSharp/RuntimeBinder/Errors/UserStringBuilder.cs | 8 ++++---- .../RuntimeBinder/Semantics/ExpressionBinder.cs | 6 +++--- .../RuntimeBinder/Semantics/GroupToArgsBinder.cs | 2 +- .../CSharp/RuntimeBinder/Semantics/MemberLookup.cs | 4 ++-- .../CSharp/RuntimeBinder/Semantics/MethodIterator.cs | 2 +- .../RuntimeBinder/Semantics/Symbols/PropertySymbol.cs | 11 ----------- 6 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs index 4bc567b64efd..f53e83f0f804 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs @@ -371,15 +371,15 @@ private void ErrAppendProperty(PropertySymbol prop, SubstContext pctx) { if (prop.errExpImpl != null) ErrAppendType(prop.errExpImpl, pctx, false); - if (prop.isIndexer()) + if (prop is IndexerSymbol indexer) { ErrAppendChar('.'); - ErrAppendIndexer(prop.AsIndexerSymbol(), pctx); + ErrAppendIndexer(indexer, pctx); } } - else if (prop.isIndexer()) + else if (prop is IndexerSymbol indexer) { - ErrAppendIndexer(prop.AsIndexerSymbol(), pctx); + ErrAppendIndexer(indexer, pctx); } else { diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs index 764f7ec188cc..b233b5dd6324 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs @@ -546,7 +546,7 @@ private Expr bindIndexer(Expr pObject, Expr args, BindingFlag bindFlags) return rval; } - Debug.Assert(mem.SymFirst() is PropertySymbol prop && prop.isIndexer()); + Debug.Assert(mem.SymFirst() is IndexerSymbol); ExprMemberGroup grp = GetExprFactory().CreateMemGroup((EXPRFLAG)mem.GetFlags(), pName, BSYMMGR.EmptyTypeArray(), mem.SymFirst().getKind(), mem.GetSourceType(), null/*pMPS*/, mem.GetObject(), mem.GetResults()); @@ -796,9 +796,9 @@ internal Expr BindToProperty(Expr pObject, PropWithType pwt, BindingFlag bindFla pwt.Sym is PropertySymbol && pwt.GetType() != null && pwt.Prop().getClass() == pwt.GetType().getAggregate()); - Debug.Assert(pwt.Prop().Params.Count == 0 || pwt.Prop().isIndexer()); + Debug.Assert(pwt.Prop().Params.Count == 0 || pwt.Prop() is IndexerSymbol); Debug.Assert(pOtherType == null || - !pwt.Prop().isIndexer() && + !(pwt.Prop() is IndexerSymbol) && pOtherType.getAggregate() == pwt.Prop().RetType.getAggregate()); bool fConstrained; diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs index 6ac90a793b6e..e772814ef654 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs @@ -700,7 +700,7 @@ public static MethodOrPropertySymbol FindMostDerivedMethod( return null; } - bIsIndexer = prop.isIndexer(); + bIsIndexer = prop is IndexerSymbol; } if (!method.isVirtual || pType == null) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs index 6b9017c13e36..a04ca2da8fd2 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs @@ -109,7 +109,7 @@ private void RecordType(AggregateType type, Symbol sym) _swtFirst.Set(sym, type); Debug.Assert(_csym == 1); Debug.Assert(_prgtype[0] == type); - _fMulti = sym is MethodSymbol || sym is PropertySymbol prop && prop.isIndexer(); + _fMulti = sym is MethodSymbol || sym is IndexerSymbol; } } @@ -232,7 +232,7 @@ private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName) // Make sure that whether we're seeing a ctor, operator, or indexer is consistent with the flags. if (((_flags & MemLookFlags.Ctor) == 0) != (meth == null || !meth.IsConstructor()) || ((_flags & MemLookFlags.Operator) == 0) != (meth == null || !meth.isOperator) || - ((_flags & MemLookFlags.Indexer) == 0) != (prop == null || !prop.isIndexer())) + ((_flags & MemLookFlags.Indexer) == 0) != !(prop is IndexerSymbol)) { if (!_swtBad) { diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs index 3f4245c3548a..5cff17de4a6d 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs @@ -145,7 +145,7 @@ public bool CanUseCurrentSymbol() if (_mask == symbmask_t.MASK_MethodSymbol && ( 0 == (_flags & EXPRFLAG.EXF_CTOR) != !((MethodSymbol)_pCurrentSym).IsConstructor() || 0 == (_flags & EXPRFLAG.EXF_OPERATOR) != !((MethodSymbol)_pCurrentSym).isOperator) || - _mask == symbmask_t.MASK_PropertySymbol && !((PropertySymbol)_pCurrentSym).isIndexer()) + _mask == symbmask_t.MASK_PropertySymbol && !(_pCurrentSym is IndexerSymbol)) { // Get the next symbol. return false; diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs index 9b54b322fe53..06c36deec742 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs @@ -21,17 +21,6 @@ internal class PropertySymbol : MethodOrPropertySymbol public MethodSymbol methSet; // Setter method (always has same parent) public PropertyInfo AssociatedPropertyInfo; - public bool isIndexer() - { - return isOperator; - } - - public IndexerSymbol AsIndexerSymbol() - { - Debug.Assert(isIndexer()); - return (IndexerSymbol)this; - } - public bool Bogus { get; set; } } } From 680e0ff764aabeea7f54f44a435dafb9e69f5b6d Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Wed, 26 Jul 2017 13:11:29 +0100 Subject: [PATCH 08/10] Make all fields in PropertySymbol auto properties. --- .../RuntimeBinder/Errors/UserStringBuilder.cs | 4 ++-- .../Semantics/ExpressionBinder.cs | 8 +++---- .../Semantics/GroupToArgsBinder.cs | 2 +- .../RuntimeBinder/Semantics/MemberLookup.cs | 4 ++-- .../Semantics/Symbols/MethodSymbol.cs | 2 +- .../Semantics/Symbols/PropertySymbol.cs | 9 +++---- .../RuntimeBinder/Semantics/Symbols/Symbol.cs | 2 +- .../CSharp/RuntimeBinder/SymbolTable.cs | 24 +++++++++---------- 8 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs index f53e83f0f804..8d07dfdb5a5b 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Errors/UserStringBuilder.cs @@ -236,13 +236,13 @@ private void ErrAppendMethod(MethodSymbol meth, SubstContext pctx, bool fArgs) ErrAppendSym(prop, pctx); // add accessor name - if (prop.methGet == meth) + if (prop.GetterMethod == meth) { ErrAppendString(".get"); } else { - Debug.Assert(meth == prop.methSet); + Debug.Assert(meth == prop.SetterMethod); ErrAppendString(".set"); } diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs index b233b5dd6324..83c020669a16 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs @@ -1447,18 +1447,18 @@ private void PostBindProperty(bool fBaseCall, PropWithType pwt, Expr pObject, ou pmwtGet = new MethWithType(); pmwtSet = new MethWithType(); // Get the accessors. - if (pwt.Prop().methGet != null) + if (pwt.Prop().GetterMethod != null) { - pmwtGet.Set(pwt.Prop().methGet, pwt.GetType()); + pmwtGet.Set(pwt.Prop().GetterMethod, pwt.GetType()); } else { pmwtGet.Clear(); } - if (pwt.Prop().methSet != null) + if (pwt.Prop().SetterMethod != null) { - pmwtSet.Set(pwt.Prop().methSet, pwt.GetType()); + pmwtSet.Set(pwt.Prop().SetterMethod, pwt.GetType()); } else { diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs index e772814ef654..01e190bd3982 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs @@ -694,7 +694,7 @@ public static MethodOrPropertySymbol FindMostDerivedMethod( if (!(pMethProp is MethodSymbol method)) { PropertySymbol prop = (PropertySymbol)pMethProp; - method = prop.methGet ?? prop.methSet; + method = prop.GetterMethod ?? prop.SetterMethod; if (method == null) { return null; diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs index a04ca2da8fd2..5faf2151fb0e 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs @@ -536,8 +536,8 @@ private bool LookupInInterfaces(AggregateType typeStart, TypeArray types) private void ReportBogus(SymWithType swt) { Debug.Assert(CSemanticChecker.CheckBogus(swt.Sym)); - MethodSymbol meth1 = swt.Prop().methGet; - MethodSymbol meth2 = swt.Prop().methSet; + MethodSymbol meth1 = swt.Prop().GetterMethod; + MethodSymbol meth2 = swt.Prop().SetterMethod; Debug.Assert((meth1 ?? meth2) != null); if (meth1 == null | meth2 == null) { diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodSymbol.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodSymbol.cs index a2636e1be67d..4b9386ec10bb 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodSymbol.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodSymbol.cs @@ -194,7 +194,7 @@ public bool isSetAccessor() return false; } - return (this == property.methSet); + return (this == property.SetterMethod); } } } diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs index 06c36deec742..b0c9089b0acb 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/PropertySymbol.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; using System.Reflection; namespace Microsoft.CSharp.RuntimeBinder.Semantics @@ -17,9 +16,11 @@ namespace Microsoft.CSharp.RuntimeBinder.Semantics internal class PropertySymbol : MethodOrPropertySymbol { - public MethodSymbol methGet; // Getter method (always has same parent) - public MethodSymbol methSet; // Setter method (always has same parent) - public PropertyInfo AssociatedPropertyInfo; + public MethodSymbol GetterMethod { get; set; } // (always has same parent) + + public MethodSymbol SetterMethod { get; set; } // (always has same parent) + + public PropertyInfo AssociatedPropertyInfo { get; set; } public bool Bogus { get; set; } } diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/Symbol.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/Symbol.cs index 7bae029cb2d1..0f6d9466b7b8 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/Symbol.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/Symbol.cs @@ -202,7 +202,7 @@ public bool IsVirtual() case SYMKIND.SK_PropertySymbol: PropertySymbol prop = ((PropertySymbol)this); - MethodSymbol meth = prop.methGet ?? prop.methSet; + MethodSymbol meth = prop.GetterMethod ?? prop.SetterMethod; return meth != null && meth.isVirtual; default: diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs index 2d6c0db5f2bc..01178e7a63c4 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs @@ -1450,44 +1450,44 @@ private void AddPropertyToSymbolTable(PropertyInfo property, AggregateSymbol agg ACCESS access = ACCESS.ACC_PRIVATE; if (methGet != null) { - prop.methGet = AddMethodToSymbolTable(methGet, aggregate, MethodKindEnum.PropAccessor); + prop.GetterMethod = AddMethodToSymbolTable(methGet, aggregate, MethodKindEnum.PropAccessor); // If we have an indexed property, leave the method as a method we can call, // and mark the property as bogus. - if (isIndexer || prop.methGet.Params.Count == 0) + if (isIndexer || prop.GetterMethod.Params.Count == 0) { - prop.methGet.SetProperty(prop); + prop.GetterMethod.SetProperty(prop); } else { prop.Bogus = true; - prop.methGet.SetMethKind(MethodKindEnum.Actual); + prop.GetterMethod.SetMethKind(MethodKindEnum.Actual); } - if (prop.methGet.GetAccess() > access) + if (prop.GetterMethod.GetAccess() > access) { - access = prop.methGet.GetAccess(); + access = prop.GetterMethod.GetAccess(); } } if (methSet != null) { - prop.methSet = AddMethodToSymbolTable(methSet, aggregate, MethodKindEnum.PropAccessor); + prop.SetterMethod = AddMethodToSymbolTable(methSet, aggregate, MethodKindEnum.PropAccessor); // If we have an indexed property, leave the method as a method we can call, // and mark the property as bogus. - if (isIndexer || prop.methSet.Params.Count == 1) + if (isIndexer || prop.SetterMethod.Params.Count == 1) { - prop.methSet.SetProperty(prop); + prop.SetterMethod.SetProperty(prop); } else { prop.Bogus = true; - prop.methSet.SetMethKind(MethodKindEnum.Actual); + prop.SetterMethod.SetMethKind(MethodKindEnum.Actual); } - if (prop.methSet.GetAccess() > access) + if (prop.SetterMethod.GetAccess() > access) { - access = prop.methSet.GetAccess(); + access = prop.SetterMethod.GetAccess(); } } From c3221ec3d063c65d2f36e2c62a741c1c18b86431 Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Wed, 26 Jul 2017 13:35:54 +0100 Subject: [PATCH 09/10] Use generic form of GetCustomAttribute in looking up default member. --- .../Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs | 2 +- .../src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs index 0a58613d776a..53aaf42d9845 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs @@ -331,7 +331,7 @@ public static string GetIndexerName(this Type type) private static string GetTypeIndexerName(Type type) { Debug.Assert(type != null); - string name = (type.GetCustomAttribute(typeof(DefaultMemberAttribute)) as DefaultMemberAttribute)?.MemberName; + string name = type.GetCustomAttribute()?.MemberName; if (name != null) { if (type.GetProperties( diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs index 01178e7a63c4..5123d14b7cf6 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs @@ -1355,7 +1355,7 @@ private void AddPropertyToSymbolTable(PropertyInfo property, AggregateSymbol agg { Name name; bool isIndexer = property.GetIndexParameters().Length != 0 - && (property.DeclaringType?.GetCustomAttribute(typeof(DefaultMemberAttribute)) as DefaultMemberAttribute) + && property.DeclaringType?.GetCustomAttribute() ?.MemberName == property.Name; if (isIndexer) From ca232cb49b956586fee6e08019be2a43f631b3a9 Mon Sep 17 00:00:00 2001 From: Jon Hanna Date: Thu, 27 Jul 2017 21:12:57 +0100 Subject: [PATCH 10/10] Remove confusing leftover remnant of comment. --- .../RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs index 6cd690140fb8..9b7bdd4283b0 100644 --- a/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs +++ b/src/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/MethodOrPropertySymbol.cs @@ -28,8 +28,7 @@ internal abstract class MethodOrPropertySymbol : ParentSymbol public new bool isStatic; // Static member? public bool isOverride; // Overrides an inherited member. Only valid if isVirtual is set. - // false implies that a new vtable slot is required for this method. - // If this is true then tell the user to call the accessors directly. + // false implies that a new vtable slot is required for this method. public bool isOperator; // a user defined operator (or default indexed property) public bool isParamArray; // new style varargs public bool isHideByName; // this property hides all below it regardless of signature