public ParameterModifierType GetParameterModifier(CType paramType, bool isOut) { Name name = NameManager.GetPredefinedName(isOut ? PredefinedName.PN_OUTPARAM : PredefinedName.PN_REFPARAM); ParameterModifierType pParamModifier = _typeTable.LookupParameterModifier(name, paramType); if (pParamModifier == null) { // No existing parammod symbol. Create a new one. pParamModifier = _typeFactory.CreateParameterModifier(name, paramType); pParamModifier.isOut = isOut; pParamModifier.InitFromParent(); _typeTable.InsertParameterModifier(name, paramType, pParamModifier); } else { Debug.Assert(pParamModifier.HasErrors() == paramType.HasErrors()); } Debug.Assert(pParamModifier.GetParameterType() == paramType); return(pParamModifier); }
public PointerType GetPointer(CType baseType) { PointerType pPointer = _typeTable.LookupPointer(baseType); if (pPointer == null) { // No existing type. Create a new one. Name namePtr = NameManager.GetPredefinedName(PredefinedName.PN_PTR); pPointer = _typeFactory.CreatePointer(namePtr, baseType); pPointer.InitFromParent(); _typeTable.InsertPointer(baseType, pPointer); } else { Debug.Assert(pPointer.HasErrors() == baseType.HasErrors()); } Debug.Assert(pPointer.GetReferentType() == baseType); return(pPointer); }
private bool IsDisplayableName(Name name) { return(name != NameManager.GetPredefinedName(PredefinedName.PN_MISSING)); }
// Returns true if the argument could be converted to a string. public bool ErrArgToString(out string psz, ErrArg parg, out bool fUserStrings) { fUserStrings = false; psz = null; bool result = true; switch (parg.eak) { case ErrArgKind.Ids: ErrId(out psz, parg.ids); break; case ErrArgKind.SymKind: ErrSK(out psz, parg.sk); break; case ErrArgKind.Type: BeginString(); ErrAppendType(parg.pType, null); EndString(out psz); fUserStrings = true; break; case ErrArgKind.Sym: BeginString(); ErrAppendSym(parg.sym, null); EndString(out psz); fUserStrings = true; break; case ErrArgKind.Name: if (parg.name == NameManager.GetPredefinedName(PredefinedName.PN_INDEXERINTERNAL)) { psz = "this"; } else { psz = parg.name.Text; } break; case ErrArgKind.Str: psz = parg.psz; break; case ErrArgKind.SymWithType: { SubstContext ctx = new SubstContext(parg.swtMemo.ats, null); BeginString(); ErrAppendSym(parg.swtMemo.sym, ctx, true); EndString(out psz); fUserStrings = true; break; } case ErrArgKind.MethWithInst: { SubstContext ctx = new SubstContext(parg.mpwiMemo.ats, parg.mpwiMemo.typeArgs); BeginString(); ErrAppendSym(parg.mpwiMemo.sym, ctx, true); EndString(out psz); fUserStrings = true; break; } default: result = false; break; } return(result); }
private void ErrAppendMethod(MethodSymbol meth, SubstContext pctx, bool fArgs) { if (meth.IsExpImpl() && meth.swtSlot) { ErrAppendParentSym(meth, pctx); // Get the type args from the explicit impl type and substitute using pctx (if there is one). SubstContext ctx = new SubstContext(GetTypeManager().SubstType(meth.swtSlot.GetType(), pctx).AsAggregateType()); ErrAppendSym(meth.swtSlot.Sym, ctx, fArgs); // args already added return; } if (meth.isPropertyAccessor()) { PropertySymbol prop = meth.getProperty(); // this includes the parent class ErrAppendSym(prop, pctx); // add accessor name if (prop.methGet == meth) { ErrAppendString(".get"); } else { Debug.Assert(meth == prop.methSet); ErrAppendString(".set"); } // args already added return; } if (meth.isEventAccessor()) { EventSymbol @event = meth.getEvent(); // this includes the parent class ErrAppendSym(@event, pctx); // add accessor name if (@event.methAdd == meth) { ErrAppendString(".add"); } else { Debug.Assert(meth == @event.methRemove); ErrAppendString(".remove"); } // args already added return; } TypeArray replacementTypeArray = null; ErrAppendMethodParentSym(meth, pctx, out replacementTypeArray); if (meth.IsConstructor()) { // Use the name of the parent class instead of the name "<ctor>". ErrAppendName(meth.getClass().name); } else if (meth.IsDestructor()) { // Use the name of the parent class instead of the name "Finalize". ErrAppendChar('~'); ErrAppendName(meth.getClass().name); } else if (meth.isConversionOperator()) { // implicit/explicit ErrAppendString(meth.isImplicit() ? "implicit" : "explicit"); ErrAppendString(" operator "); // destination type name ErrAppendType(meth.RetType, pctx); } else if (meth.isOperator) { // handle user defined operators // map from CLS predefined names to "operator <X>" ErrAppendString("operator "); // // This is kinda slow, but the alternative is to add bits to methsym. // string operatorName; OperatorKind op = Operators.OperatorOfMethodName(meth.name); if (Operators.HasDisplayName(op)) { operatorName = Operators.GetDisplayName(op); } else { // // either equals or compare // if (meth.name == NameManager.GetPredefinedName(PredefinedName.PN_OPEQUALS)) { operatorName = "equals"; } else { Debug.Assert(meth.name == NameManager.GetPredefinedName(PredefinedName.PN_OPCOMPARE)); operatorName = "compare"; } } ErrAppendString(operatorName); } else if (meth.IsExpImpl()) { if (meth.errExpImpl != null) { ErrAppendType(meth.errExpImpl, pctx, fArgs); } } else { // regular method ErrAppendName(meth.name); } if (null == replacementTypeArray) { ErrAppendTypeParameters(meth.typeVars, pctx, false); } if (fArgs) { // append argument types ErrAppendChar('('); if (!meth.computeCurrentBogusState()) { ErrAppendParamList(GetTypeManager().SubstTypeArray(meth.Params, pctx), meth.isVarargs, meth.isParamArray); } ErrAppendChar(')'); } }
private Name GetPredefName(PredefinedName pn) { return(NameManager.GetPredefinedName(pn)); }
private static PropertySymbol LoadProperty(PREDEFPROP property) { PredefinedPropertyInfo info = GetPropInfo(property); return(LoadProperty(property, NameManager.GetPredefinedName(info.name), info.getter)); }
private static bool CheckSingleConstraint(CSemanticChecker checker, ErrorHandling errHandling, Symbol symErr, TypeParameterType var, CType arg, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags) { bool fReportErrors = 0 == (flags & CheckConstraintsFlags.NoErrors); if (arg.IsOpenTypePlaceholderType()) { return(true); } if (arg.IsErrorType()) { // Error should have been reported previously. return(false); } if (checker.CheckBogus(arg)) { if (fReportErrors) { errHandling.ErrorRef(ErrorCode.ERR_BogusType, arg); } return(false); } if (arg.IsPointerType() || arg.isSpecialByRefType()) { if (fReportErrors) { errHandling.Error(ErrorCode.ERR_BadTypeArgument, arg); } return(false); } if (arg.isStaticClass()) { if (fReportErrors) { checker.ReportStaticClassError(null, arg, ErrorCode.ERR_GenericArgIsStaticClass); } return(false); } bool fError = false; if (var.HasRefConstraint() && !arg.IsRefType()) { if (fReportErrors) { errHandling.ErrorRef(ErrorCode.ERR_RefConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg); } fError = true; } TypeArray bnds = checker.GetSymbolLoader().GetTypeManager().SubstTypeArray(var.GetBounds(), typeArgsCls, typeArgsMeth); int itypeMin = 0; if (var.HasValConstraint()) { // If we have a type variable that is constrained to a value type, then we // want to check if its a nullable type, so that we can report the // constraint error below. In order to do this however, we need to check // that either the type arg is not a value type, or it is a nullable type. // // To check whether or not its a nullable type, we need to get the resolved // bound from the type argument and check against that. bool bIsValueType = arg.IsValType(); bool bIsNullable = arg.IsNullableType(); if (bIsValueType && arg.IsTypeParameterType()) { TypeArray pArgBnds = arg.AsTypeParameterType().GetBounds(); if (pArgBnds.Count > 0) { bIsNullable = pArgBnds[0].IsNullableType(); } } if (!bIsValueType || bIsNullable) { if (fReportErrors) { errHandling.ErrorRef(ErrorCode.ERR_ValConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg); } fError = true; } // Since FValCon() is set it is redundant to check System.ValueType as well. if (bnds.Count != 0 && bnds[0].isPredefType(PredefinedType.PT_VALUE)) { itypeMin = 1; } } for (int j = itypeMin; j < bnds.Count; j++) { CType typeBnd = bnds[j]; if (!SatisfiesBound(checker, arg, typeBnd)) { if (fReportErrors) { // The bound isn't satisfied because of a constraint type. Explain to the user why not. // There are 4 main cases, based on the type of the supplied type argument: // - reference type, or type parameter known to be a reference type // - nullable type, from which there is a boxing conversion to the constraint type(see below for details) // - type variable // - value type // These cases are broken out because: a) The sets of conversions which can be used // for constraint satisfaction is different based on the type argument supplied, // and b) Nullable is one funky type, and user's can use all the help they can get // when using it. ErrorCode error; if (arg.IsRefType()) { // A reference type can only satisfy bounds to types // to which they have an implicit reference conversion error = ErrorCode.ERR_GenericConstraintNotSatisfiedRefType; } else if (arg.IsNullableType() && checker.GetSymbolLoader().HasBaseConversion(arg.AsNullableType().GetUnderlyingType(), typeBnd)) // This is inlining FBoxingConv { // nullable types do not satisfy bounds to every type that they are boxable to // They only satisfy bounds of object and ValueType if (typeBnd.isPredefType(PredefinedType.PT_ENUM) || arg.AsNullableType().GetUnderlyingType() == typeBnd) { // Nullable types don't satisfy bounds of EnumType, or the underlying type of the enum // even though the conversion from Nullable to these types is a boxing conversion // This is a rare case, because these bounds can never be directly stated ... // These bounds can only occur when one type paramter is constrained to a second type parameter // and the second type parameter is instantiated with Enum or the underlying type of the first type // parameter error = ErrorCode.ERR_GenericConstraintNotSatisfiedNullableEnum; } else { // Nullable types don't satisfy the bounds of any interface type // even when there is a boxing conversion from the Nullable type to // the interface type. This will be a relatively common scenario // so we cal it out separately from the previous case. Debug.Assert(typeBnd.isInterfaceType()); error = ErrorCode.ERR_GenericConstraintNotSatisfiedNullableInterface; } } else if (arg.IsTypeParameterType()) { // Type variables can satisfy bounds through boxing and type variable conversions Debug.Assert(!arg.IsRefType()); error = ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar; } else { // Value types can only satisfy bounds through boxing conversions. // Note that the exceptional case of Nullable types and boxing is handled above. error = ErrorCode.ERR_GenericConstraintNotSatisfiedValType; } errHandling.Error(error, new ErrArgRef(symErr), new ErrArg(typeBnd, ErrArgFlags.Unique), var, new ErrArgRef(arg, ErrArgFlags.Unique)); } fError = true; } } // Check the newable constraint. if (!var.HasNewConstraint() || arg.IsValType()) { return(!fError); } if (arg.isClassType()) { AggregateSymbol agg = arg.AsAggregateType().getAggregate(); // Due to late binding nature of IDE created symbols, the AggregateSymbol might not // have all the information necessary yet, if it is not fully bound. // by calling LookupAggMember, it will ensure that we will update all the // information necessary at least for the given method. checker.GetSymbolLoader().LookupAggMember(NameManager.GetPredefinedName(PredefinedName.PN_CTOR), agg, symbmask_t.MASK_ALL); if (agg.HasPubNoArgCtor() && !agg.IsAbstract()) { return(!fError); } } else if (arg.IsTypeParameterType() && arg.AsTypeParameterType().HasNewConstraint()) { return(!fError); } if (fReportErrors) { errHandling.ErrorRef(ErrorCode.ERR_NewConstraintNotSatisfied, symErr, new ErrArgNoRef(var), arg); } return(false); }