/****************************************************************************** * Search just the given type (not any bases). Returns true iff it finds * something (which will have been recorded by RecordType). * * pfHideByName is set to true iff something was found that hides all * members of base types (eg, a hidebyname method). ******************************************************************************/ private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName) { bool fFoundSome = false; MethPropWithType mwpInsert; pfHideByName = false; // Make sure this type is accessible. It may not be due to private inheritance // or friend assemblies. bool fInaccess = !GetSemanticChecker().CheckTypeAccess(typeCur, _symWhere); if (fInaccess && (_csym != 0 || _swtInaccess != null)) { return(false); } // Loop through symbols. Symbol symCur = null; for (symCur = GetSymbolLoader().LookupAggMember(_name, typeCur.getAggregate(), symbmask_t.MASK_ALL); symCur != null; symCur = GetSymbolLoader().LookupNextSym(symCur, typeCur.getAggregate(), symbmask_t.MASK_ALL)) { // Check for arity. switch (symCur.getKind()) { case SYMKIND.SK_MethodSymbol: // For non-zero arity, only methods of the correct arity are considered. // For zero arity, don't filter out any methods since we do type argument // inferencing. if (_arity > 0 && symCur.AsMethodSymbol().typeVars.size != _arity) { if (!_swtBadArity) { _swtBadArity.Set(symCur, typeCur); } continue; } break; case SYMKIND.SK_AggregateSymbol: // For types, always filter on arity. if (symCur.AsAggregateSymbol().GetTypeVars().size != _arity) { if (!_swtBadArity) { _swtBadArity.Set(symCur, typeCur); } continue; } break; case SYMKIND.SK_TypeParameterSymbol: if ((_flags & MemLookFlags.TypeVarsAllowed) == 0) { continue; } if (_arity > 0) { if (!_swtBadArity) { _swtBadArity.Set(symCur, typeCur); } continue; } break; default: // All others are only considered when arity is zero. if (_arity > 0) { if (!_swtBadArity) { _swtBadArity.Set(symCur, typeCur); } continue; } break; } // Check for user callability. if (symCur.IsOverride() && !symCur.IsHideByName()) { if (!_swtOverride) { _swtOverride.Set(symCur, typeCur); } continue; } if ((_flags & MemLookFlags.UserCallable) != 0 && symCur.IsMethodOrPropertySymbol() && !symCur.AsMethodOrPropertySymbol().isUserCallable()) { bool bIsIndexedProperty = false; // If its an indexed property method symbol, let it through. if (symCur.IsMethodSymbol() && symCur.AsMethodSymbol().isPropertyAccessor() && ((symCur.name.Text.StartsWith("set_", StringComparison.Ordinal) && symCur.AsMethodSymbol().Params.size > 1) || (symCur.name.Text.StartsWith("get_", StringComparison.Ordinal) && symCur.AsMethodSymbol().Params.size > 0))) { bIsIndexedProperty = true; } if (!bIsIndexedProperty) { if (!_swtInaccess) { _swtInaccess.Set(symCur, typeCur); } continue; } } if (fInaccess || !GetSemanticChecker().CheckAccess(symCur, typeCur, _symWhere, _typeQual)) { // Not accessible so get the next sym. if (!_swtInaccess) { _swtInaccess.Set(symCur, typeCur); } if (fInaccess) { return(false); } continue; } // Make sure that whether we're seeing a ctor, operator, or indexer is consistent with the flags. if (((_flags & MemLookFlags.Ctor) == 0) != (!symCur.IsMethodSymbol() || !symCur.AsMethodSymbol().IsConstructor()) || ((_flags & MemLookFlags.Operator) == 0) != (!symCur.IsMethodSymbol() || !symCur.AsMethodSymbol().isOperator) || ((_flags & MemLookFlags.Indexer) == 0) != (!symCur.IsPropertySymbol() || !symCur.AsPropertySymbol().isIndexer())) { if (!_swtBad) { _swtBad.Set(symCur, typeCur); } continue; } // 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.IsMethodSymbol() && (_flags & MemLookFlags.Indexer) == 0 && GetSemanticChecker().CheckBogus(symCur)) { // A bogus member - we can't use these, so only record them for error reporting. if (!_swtBogus) { _swtBogus.Set(symCur, typeCur); } continue; } // if we are in a calling context then we should only find a property if it is delegate valued if ((_flags & MemLookFlags.MustBeInvocable) != 0) { if ((symCur.IsFieldSymbol() && !IsDelegateType(symCur.AsFieldSymbol().GetType(), typeCur) && !IsDynamicMember(symCur)) || (symCur.IsPropertySymbol() && !IsDelegateType(symCur.AsPropertySymbol().RetType, typeCur) && !IsDynamicMember(symCur))) { if (!_swtBad) { _swtBad.Set(symCur, typeCur); } continue; } } if (symCur.IsMethodOrPropertySymbol()) { mwpInsert = new MethPropWithType(symCur.AsMethodOrPropertySymbol(), typeCur); _methPropWithTypeList.Add(mwpInsert); } // We have a visible symbol. fFoundSome = true; if (_swtFirst) { if (!typeCur.isInterfaceType()) { // Non-interface case. Debug.Assert(_fMulti || typeCur == _prgtype[0]); if (!_fMulti) { if (_swtFirst.Sym.IsFieldSymbol() && symCur.IsEventSymbol() #if !CSEE // The isEvent bit is only set on symbols which come from source... // This is not a problem for the compiler because the field is only // accessible in the scope in which it is declared, // but in the EE we ignore accessibility... && _swtFirst.Field().isEvent #endif ) { // m_swtFirst is just the field behind the event symCur so ignore symCur. continue; } else if (_swtFirst.Sym.IsFieldSymbol() && symCur.IsEventSymbol()) { // symCur is the matching event. continue; } goto LAmbig; } if (_swtFirst.Sym.getKind() != symCur.getKind()) { if (typeCur == _prgtype[0]) { goto LAmbig; } // This one is hidden by the first one. This one also hides any more in base types. pfHideByName = true; continue; } } // Interface case. // m_fMulti : n n n y y y y y // same-kind : * * * y n n n n // fDiffHidden: * * * * y n n n // meth : * * * * * y n * can n happen? just in case, we better handle it.... // hack : n * y * * y * n // meth-2 : * n y * * * * * // res : A A S R H H A A else if (!_fMulti) { // Give method groups priority. if (/* !GetSymbolLoader().options.fLookupHack ||*/ !symCur.IsMethodSymbol()) { goto LAmbig; } _swtAmbigWarn = _swtFirst; // Erase previous results so we'll record this method as the first. _prgtype = new List <AggregateType>(); _csym = 0; _swtFirst.Clear(); _swtAmbig.Clear(); } else if (_swtFirst.Sym.getKind() != symCur.getKind()) { if (!typeCur.fDiffHidden) { // Give method groups priority. if (/*!GetSymbolLoader().options.fLookupHack ||*/ !_swtFirst.Sym.IsMethodSymbol()) { goto LAmbig; } if (!_swtAmbigWarn) { _swtAmbigWarn.Set(symCur, typeCur); } } // This one is hidden by another. This one also hides any more in base types. pfHideByName = true; continue; } } RecordType(typeCur, symCur); if (symCur.IsMethodOrPropertySymbol() && symCur.AsMethodOrPropertySymbol().isHideByName) { pfHideByName = true; } // We've found a symbol in this type but need to make sure there aren't any conflicting // syms here, so keep searching the type. } Debug.Assert(!fInaccess || !fFoundSome); return(fFoundSome); LAmbig: // Ambiguous! if (!_swtAmbig) { _swtAmbig.Set(symCur, typeCur); } pfHideByName = true; return(true); }
/****************************************************************************** Search just the given type (not any bases). Returns true iff it finds something (which will have been recorded by RecordType). pfHideByName is set to true iff something was found that hides all members of base types (eg, a hidebyname method). ******************************************************************************/ private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName) { bool fFoundSome = false; pfHideByName = false; // Make sure this type is accessible. It may not be due to private inheritance // or friend assemblies. bool fInaccess = !GetSemanticChecker().CheckTypeAccess(typeCur, _symWhere); if (fInaccess && (_csym != 0 || _swtInaccess != null)) return false; // Loop through symbols. Symbol symCur = null; for (symCur = GetSymbolLoader().LookupAggMember(_name, typeCur.getAggregate(), symbmask_t.MASK_ALL); symCur != null; symCur = GetSymbolLoader().LookupNextSym(symCur, typeCur.getAggregate(), symbmask_t.MASK_ALL)) { // Check for arity. switch (symCur.getKind()) { case SYMKIND.SK_MethodSymbol: // For non-zero arity, only methods of the correct arity are considered. // For zero arity, don't filter out any methods since we do type argument // inferencing. if (_arity > 0 && symCur.AsMethodSymbol().typeVars.size != _arity) { if (!_swtBadArity) _swtBadArity.Set(symCur, typeCur); continue; } break; case SYMKIND.SK_AggregateSymbol: // For types, always filter on arity. if (symCur.AsAggregateSymbol().GetTypeVars().size != _arity) { if (!_swtBadArity) _swtBadArity.Set(symCur, typeCur); continue; } break; case SYMKIND.SK_TypeParameterSymbol: if ((_flags & MemLookFlags.TypeVarsAllowed) == 0) continue; if (_arity > 0) { if (!_swtBadArity) _swtBadArity.Set(symCur, typeCur); continue; } break; default: // All others are only considered when arity is zero. if (_arity > 0) { if (!_swtBadArity) _swtBadArity.Set(symCur, typeCur); continue; } break; } // Check for user callability. if (symCur.IsOverride() && !symCur.IsHideByName()) { if (!_swtOverride) { _swtOverride.Set(symCur, typeCur); } continue; } if ((_flags & MemLookFlags.UserCallable) != 0 && symCur.IsMethodOrPropertySymbol() && !symCur.AsMethodOrPropertySymbol().isUserCallable()) { bool bIsIndexedProperty = false; // If its an indexed property method symbol, let it through. if (symCur.IsMethodSymbol() && symCur.AsMethodSymbol().isPropertyAccessor() && ((symCur.name.Text.StartsWith("set_", StringComparison.Ordinal) && symCur.AsMethodSymbol().Params.size > 1) || (symCur.name.Text.StartsWith("get_", StringComparison.Ordinal) && symCur.AsMethodSymbol().Params.size > 0))) { bIsIndexedProperty = true; } if (!bIsIndexedProperty) { if (!_swtInaccess) { _swtInaccess.Set(symCur, typeCur); } continue; } } if (fInaccess || !GetSemanticChecker().CheckAccess(symCur, typeCur, _symWhere, _typeQual)) { // Not accessible so get the next sym. if (!_swtInaccess) { _swtInaccess.Set(symCur, typeCur); } if (fInaccess) { return false; } continue; } // Make sure that whether we're seeing a ctor, operator, or indexer is consistent with the flags. if (((_flags & MemLookFlags.Ctor) == 0) != (!symCur.IsMethodSymbol() || !symCur.AsMethodSymbol().IsConstructor()) || ((_flags & MemLookFlags.Operator) == 0) != (!symCur.IsMethodSymbol() || !symCur.AsMethodSymbol().isOperator) || ((_flags & MemLookFlags.Indexer) == 0) != (!symCur.IsPropertySymbol() || !symCur.AsPropertySymbol().isIndexer())) { if (!_swtBad) { _swtBad.Set(symCur, typeCur); } continue; } // 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.IsMethodSymbol() && (_flags & MemLookFlags.Indexer) == 0 && GetSemanticChecker().CheckBogus(symCur)) { // A bogus member - we can't use these, so only record them for error reporting. if (!_swtBogus) { _swtBogus.Set(symCur, typeCur); } continue; } // if we are in a calling context then we should only find a property if it is delegate valued if ((_flags & MemLookFlags.MustBeInvocable) != 0) { if ((symCur.IsFieldSymbol() && !IsDelegateType(symCur.AsFieldSymbol().GetType(), typeCur) && !IsDynamicMember(symCur)) || (symCur.IsPropertySymbol() && !IsDelegateType(symCur.AsPropertySymbol().RetType, typeCur) && !IsDynamicMember(symCur))) { if (!_swtBad) { _swtBad.Set(symCur, typeCur); } continue; } } if (symCur.IsMethodOrPropertySymbol()) { MethPropWithType mwpInsert = new MethPropWithType(symCur.AsMethodOrPropertySymbol(), typeCur); _methPropWithTypeList.Add(mwpInsert); } // We have a visible symbol. fFoundSome = true; if (_swtFirst) { if (!typeCur.isInterfaceType()) { // Non-interface case. Debug.Assert(_fMulti || typeCur == _prgtype[0]); if (!_fMulti) { if (_swtFirst.Sym.IsFieldSymbol() && symCur.IsEventSymbol() #if !CSEE // The isEvent bit is only set on symbols which come from source... // This is not a problem for the compiler because the field is only // accessible in the scope in which it is declared, // but in the EE we ignore accessibility... && _swtFirst.Field().isEvent #endif ) { // m_swtFirst is just the field behind the event symCur so ignore symCur. continue; } else if (_swtFirst.Sym.IsFieldSymbol() && symCur.IsEventSymbol()) { // symCur is the matching event. continue; } goto LAmbig; } if (_swtFirst.Sym.getKind() != symCur.getKind()) { if (typeCur == _prgtype[0]) goto LAmbig; // This one is hidden by the first one. This one also hides any more in base types. pfHideByName = true; continue; } } // Interface case. // m_fMulti : n n n y y y y y // same-kind : * * * y n n n n // fDiffHidden: * * * * y n n n // meth : * * * * * y n * can n happen? just in case, we better handle it.... // hack : n * y * * y * n // meth-2 : * n y * * * * * // res : A A S R H H A A else if (!_fMulti) { // Give method groups priority. if ( /* !GetSymbolLoader().options.fLookupHack ||*/ !symCur.IsMethodSymbol()) goto LAmbig; _swtAmbigWarn = _swtFirst; // Erase previous results so we'll record this method as the first. _prgtype = new List<AggregateType>(); _csym = 0; _swtFirst.Clear(); _swtAmbig.Clear(); } else if (_swtFirst.Sym.getKind() != symCur.getKind()) { if (!typeCur.fDiffHidden) { // Give method groups priority. if ( /*!GetSymbolLoader().options.fLookupHack ||*/ !_swtFirst.Sym.IsMethodSymbol()) goto LAmbig; if (!_swtAmbigWarn) _swtAmbigWarn.Set(symCur, typeCur); } // This one is hidden by another. This one also hides any more in base types. pfHideByName = true; continue; } } RecordType(typeCur, symCur); if (symCur.IsMethodOrPropertySymbol() && symCur.AsMethodOrPropertySymbol().isHideByName) pfHideByName = true; // We've found a symbol in this type but need to make sure there aren't any conflicting // syms here, so keep searching the type. } Debug.Assert(!fInaccess || !fFoundSome); return fFoundSome; LAmbig: // Ambiguous! if (!_swtAmbig) _swtAmbig.Set(symCur, typeCur); pfHideByName = true; return true; }