diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprMember.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 77 | ||||
-rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaPseudoObject.cpp | 36 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 14 |
7 files changed, 111 insertions, 73 deletions
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index ac1e3923afa..f28abf4c070 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -600,7 +600,8 @@ ActOnSuperClassOfClassInterface(Scope *S, } } -DeclResult Sema::actOnObjCTypeParam(Scope *S, IdentifierInfo *paramName, +DeclResult Sema::actOnObjCTypeParam(Scope *S, unsigned index, + IdentifierInfo *paramName, SourceLocation paramLoc, SourceLocation colonLoc, ParsedType parsedTypeBound) { @@ -643,6 +644,23 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S, IdentifierInfo *paramName, // Forget the bound; we'll default to id later. typeBoundInfo = nullptr; } + + // Type bounds cannot have explicit nullability. + if (typeBoundInfo) { + // Type arguments cannot explicitly specify nullability. + if (auto nullability = AttributedType::stripOuterNullability(typeBound)) { + // Look at the type location information to find the nullability + // specifier so we can zap it. + SourceLocation nullabilityLoc + = typeBoundInfo->getTypeLoc().findNullabilityLoc(); + SourceLocation diagLoc + = nullabilityLoc.isValid()? nullabilityLoc + : typeBoundInfo->getTypeLoc().getLocStart(); + Diag(diagLoc, diag::err_type_param_bound_explicit_nullability) + << paramName << typeBoundInfo->getType() + << FixItHint::CreateRemoval(nullabilityLoc); + } + } } // If there was no explicit type bound (or we removed it due to an error), @@ -653,8 +671,8 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S, IdentifierInfo *paramName, } // Create the type parameter. - return ObjCTypeParamDecl::Create(Context, CurContext, paramLoc, paramName, - colonLoc, typeBoundInfo); + return ObjCTypeParamDecl::Create(Context, CurContext, index, paramLoc, + paramName, colonLoc, typeBoundInfo); } ObjCTypeParamList *Sema::actOnObjCTypeParamList(Scope *S, @@ -868,6 +886,7 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, ObjCTypeParamDecl::Create( Context, CurContext, + typeParam->getIndex(), SourceLocation(), typeParam->getIdentifier(), SourceLocation(), diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c6b53d03890..afc9279cba1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2466,8 +2466,8 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName(); ObjCIvarRefExpr *Result = new (Context) - ObjCIvarRefExpr(IV, IV->getType(), Loc, IV->getLocation(), - SelfExpr.get(), true, true); + ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc, + IV->getLocation(), SelfExpr.get(), true, true); if (getLangOpts().ObjCAutoRefCount) { if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { @@ -5185,17 +5185,17 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, } /// Do an explicit extend of the given block pointer if we're in ARC. -static void maybeExtendBlockObject(Sema &S, ExprResult &E) { +void Sema::maybeExtendBlockObject(ExprResult &E) { assert(E.get()->getType()->isBlockPointerType()); assert(E.get()->isRValue()); // Only do this in an r-value context. - if (!S.getLangOpts().ObjCAutoRefCount) return; + if (!getLangOpts().ObjCAutoRefCount) return; - E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), + E = ImplicitCastExpr::Create(Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(), /*base path*/ nullptr, VK_RValue); - S.ExprNeedsCleanups = true; + ExprNeedsCleanups = true; } /// Prepare a conversion of the given expression to an ObjC object @@ -5205,7 +5205,7 @@ CastKind Sema::PrepareCastToObjCObjectPointer(ExprResult &E) { if (type->isObjCObjectPointerType()) { return CK_BitCast; } else if (type->isBlockPointerType()) { - maybeExtendBlockObject(*this, E); + maybeExtendBlockObject(E); return CK_BlockPointerToObjCPointerCast; } else { assert(type->isPointerType()); @@ -5247,7 +5247,7 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { return CK_BitCast; if (SrcKind == Type::STK_CPointer) return CK_CPointerToObjCPointerCast; - maybeExtendBlockObject(*this, Src); + maybeExtendBlockObject(Src); return CK_BlockPointerToObjCPointerCast; case Type::STK_Bool: return CK_PointerToBoolean; @@ -6980,7 +6980,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // Only under strict condition T^ is compatible with an Objective-C pointer. if (RHSType->isBlockPointerType() && LHSType->isBlockCompatibleObjCPointerType(Context)) { - maybeExtendBlockObject(*this, RHS); + maybeExtendBlockObject(RHS); Kind = CK_BlockPointerToObjCPointerCast; return Compatible; } @@ -8189,9 +8189,6 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { // Get the LHS object's interface type. QualType InterfaceType = Type->getPointeeType(); - if (const ObjCObjectType *iQFaceTy = - InterfaceType->getAsObjCQualifiedInterfaceType()) - InterfaceType = iQFaceTy->getBaseType(); // If the RHS isn't an Objective-C object, bail out. if (!RHS->getType()->isObjCObjectPointerType()) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index e421349338b..a9f1919e18a 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1378,7 +1378,8 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, } ObjCIvarRefExpr *Result = new (S.Context) ObjCIvarRefExpr( - IV, IV->getType(), MemberLoc, OpLoc, BaseExpr.get(), IsArrow); + IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(), + IsArrow); if (S.getLangOpts().ObjCAutoRefCount) { if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 7280f588c8b..51ab68a8ab1 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -1281,7 +1281,7 @@ static QualType getBaseMessageSendResultType(Sema &S, bool isSuperMessage) { assert(Method && "Must have a method"); if (!Method->hasRelatedResultType()) - return Method->getSendResultType(); + return Method->getSendResultType(ReceiverType); ASTContext &Context = S.Context; @@ -1289,7 +1289,8 @@ static QualType getBaseMessageSendResultType(Sema &S, // result type to the returned result. auto transferNullability = [&](QualType type) -> QualType { // If the method's result type has nullability, extract it. - if (auto nullability = Method->getSendResultType()->getNullability(Context)){ + if (auto nullability = Method->getSendResultType(ReceiverType) + ->getNullability(Context)){ // Strip off any outer nullability sugar from the provided type. (void)AttributedType::stripOuterNullability(type); @@ -1308,7 +1309,8 @@ static QualType getBaseMessageSendResultType(Sema &S, // was a class message send, T is the declared return type of the method // found if (Method->isInstanceMethod() && isClassMessage) - return stripObjCInstanceType(Context, Method->getSendResultType()); + return stripObjCInstanceType(Context, + Method->getSendResultType(ReceiverType)); // - if the receiver is super, T is a pointer to the class of the // enclosing method definition @@ -1322,14 +1324,14 @@ static QualType getBaseMessageSendResultType(Sema &S, } // - if the receiver is the name of a class U, T is a pointer to U - if (ReceiverType->getAs<ObjCInterfaceType>() || - ReceiverType->isObjCQualifiedInterfaceType()) + if (ReceiverType->getAsObjCInterfaceType()) return transferNullability(Context.getObjCObjectPointerType(ReceiverType)); // - if the receiver is of type Class or qualified Class type, // T is the declared return type of the method. if (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()) - return stripObjCInstanceType(Context, Method->getSendResultType()); + return stripObjCInstanceType(Context, + Method->getSendResultType(ReceiverType)); // - if the receiver is id, qualified id, Class, or qualified Class, T // is the receiver type, otherwise @@ -1592,6 +1594,10 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, return false; } + // Compute the set of type arguments to be substituted into each parameter + // type. + Optional<ArrayRef<QualType>> typeArgs + = ReceiverType->getObjCSubstitutions(Method->getDeclContext()); bool IsError = false; for (unsigned i = 0; i < NumNamedArgs; i++) { // We can't do any type-checking on a type-dependent argument. @@ -1625,18 +1631,37 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, continue; } + QualType origParamType = param->getType(); + QualType paramType = param->getType(); + if (typeArgs) + paramType = paramType.substObjCTypeArgs( + Context, + *typeArgs, + ObjCSubstitutionContext::Parameter); + if (RequireCompleteType(argExpr->getSourceRange().getBegin(), - param->getType(), + paramType, diag::err_call_incomplete_argument, argExpr)) return true; - InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, - param); + InitializedEntity Entity + = InitializedEntity::InitializeParameter(Context, param, paramType); ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), argExpr); if (ArgE.isInvalid()) IsError = true; - else + else { Args[i] = ArgE.getAs<Expr>(); + + // If we are type-erasing a block to a block-compatible + // Objective-C pointer type, we may need to extend the lifetime + // of the block object. + if (typeArgs && Args[i]->isRValue() && paramType->isBlockPointerType() && + origParamType->isBlockCompatibleObjCPointerType(Context)) { + ExprResult arg = Args[i]; + maybeExtendBlockObject(arg); + Args[i] = arg.get(); + } + } } // Promote additional arguments to variadic methods. @@ -1904,27 +1929,24 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr, receiverNameLoc); - bool IsSuper = false; + QualType SuperType; if (!IFace) { // If the "receiver" is 'super' in a method, handle it as an expression-like // property reference. if (receiverNamePtr->isStr("super")) { - IsSuper = true; - if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) { - if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) { + if (auto classDecl = CurMethod->getClassInterface()) { + SuperType = QualType(classDecl->getSuperClassType(), 0); if (CurMethod->isInstanceMethod()) { - ObjCInterfaceDecl *Super = Class->getSuperClass(); - if (!Super) { + if (SuperType.isNull()) { // The current class does not have a superclass. Diag(receiverNameLoc, diag::error_root_class_cannot_use_super) - << Class->getIdentifier(); + << CurMethod->getClassInterface()->getIdentifier(); return ExprError(); } - QualType T = Context.getObjCInterfaceType(Super); - T = Context.getObjCObjectPointerType(T); + QualType T = Context.getObjCObjectPointerType(SuperType); - return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), + return HandleExprPropertyRefExpr(T->castAs<ObjCObjectPointerType>(), /*BaseExpr*/nullptr, SourceLocation()/*OpLoc*/, &propertyName, @@ -1934,7 +1956,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, // Otherwise, if this is a class method, try dispatching to our // superclass. - IFace = Class->getSuperClass(); + IFace = CurMethod->getClassInterface()->getSuperClass(); } } } @@ -1964,7 +1986,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, // Look for the matching setter, in case it is needed. Selector SetterSel = SelectorTable::constructSetterSelector(PP.getIdentifierTable(), - PP.getSelectorTable(), + PP.getSelectorTable(), &propertyName); ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); @@ -1981,11 +2003,11 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, return ExprError(); if (Getter || Setter) { - if (IsSuper) + if (!SuperType.isNull()) return new (Context) ObjCPropertyRefExpr(Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, propertyNameLoc, receiverNameLoc, - Context.getObjCInterfaceType(IFace)); + SuperType); return new (Context) ObjCPropertyRefExpr( Getter, Setter, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, @@ -2132,8 +2154,8 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, return ExprError(); } - ObjCInterfaceDecl *Super = Class->getSuperClass(); - if (!Super) { + QualType SuperTy(Class->getSuperClassType(), 0); + if (SuperTy.isNull()) { // The current class does not have a superclass. Diag(SuperLoc, diag::error_root_class_cannot_use_super) << Class->getIdentifier(); @@ -2148,7 +2170,6 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, if (Method->isInstanceMethod()) { // Since we are in an instance method, this is an instance // message to the superclass instance. - QualType SuperTy = Context.getObjCInterfaceType(Super); SuperTy = Context.getObjCObjectPointerType(SuperTy); return BuildInstanceMessage(nullptr, SuperTy, SuperLoc, Sel, /*Method=*/nullptr, @@ -2158,7 +2179,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, // Since we are in a class method, this is a class message to // the superclass. return BuildClassMessage(/*ReceiverTypeInfo=*/nullptr, - Context.getObjCInterfaceType(Super), + SuperTy, SuperLoc, Sel, /*Method=*/nullptr, LBracLoc, SelectorLocs, RBracLoc, Args); } diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 0f88abcdf9e..f139c83c734 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1157,7 +1157,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, CK_LValueToRValue, SelfExpr, nullptr, VK_RValue); Expr *IvarRefExpr = - new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, + new (Context) ObjCIvarRefExpr(Ivar, + Ivar->getUsageType(SelfDecl->getType()), + PropertyDiagLoc, Ivar->getLocation(), LoadSelfExpr, true, true); ExprResult Res = PerformCopyInitialization( @@ -1207,7 +1209,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, CK_LValueToRValue, SelfExpr, nullptr, VK_RValue); Expr *lhs = - new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, + new (Context) ObjCIvarRefExpr(Ivar, + Ivar->getUsageType(SelfDecl->getType()), + PropertyDiagLoc, Ivar->getLocation(), LoadSelfExpr, true, true); ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index 3e465af9632..fec97488f53 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -689,15 +689,7 @@ ExprResult ObjCPropertyOpBuilder::buildGet() { if (SyntacticRefExpr) SyntacticRefExpr->setIsMessagingGetter(); - QualType receiverType; - if (RefExpr->isClassReceiver()) { - receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); - } else if (RefExpr->isSuperReceiver()) { - receiverType = RefExpr->getSuperReceiverType(); - } else { - assert(InstanceReceiver); - receiverType = InstanceReceiver->getType(); - } + QualType receiverType = RefExpr->getReceiverType(S.Context); if (!Getter->isImplicit()) S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true); // Build a message-send. @@ -730,21 +722,17 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, if (SyntacticRefExpr) SyntacticRefExpr->setIsMessagingSetter(); - QualType receiverType; - if (RefExpr->isClassReceiver()) { - receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); - } else if (RefExpr->isSuperReceiver()) { - receiverType = RefExpr->getSuperReceiverType(); - } else { - assert(InstanceReceiver); - receiverType = InstanceReceiver->getType(); - } + QualType receiverType = RefExpr->getReceiverType(S.Context); // Use assignment constraints when possible; they give us better // diagnostics. "When possible" basically means anything except a // C++ class type. if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) { - QualType paramType = (*Setter->param_begin())->getType(); + QualType paramType = (*Setter->param_begin())->getType() + .substObjCMemberType( + receiverType, + Setter->getDeclContext(), + ObjCSubstitutionContext::Parameter); if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) { ExprResult opResult = op; Sema::AssignConvertType assignResult @@ -819,7 +807,9 @@ ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { // As a special case, if the method returns 'id', try to get // a better type from the property. if (RefExpr->isExplicitProperty() && result.get()->isRValue()) { - QualType propType = RefExpr->getExplicitProperty()->getType(); + QualType receiverType = RefExpr->getReceiverType(S.Context); + QualType propType = RefExpr->getExplicitProperty() + ->getUsageType(receiverType); if (result.get()->getType()->isObjCIdType()) { if (const ObjCObjectPointerType *ptr = propType->getAs<ObjCObjectPointerType>()) { @@ -1119,9 +1109,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { if (const ObjCObjectPointerType *PTy = BaseT->getAs<ObjCObjectPointerType>()) { ResultType = PTy->getPointeeType(); - if (const ObjCObjectType *iQFaceTy = - ResultType->getAsObjCQualifiedInterfaceType()) - ResultType = iQFaceTy->getBaseType(); } Sema::ObjCSubscriptKind Res = S.CheckSubscriptingKind(RefExpr->getKeyExpr()); @@ -1228,9 +1215,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { if (const ObjCObjectPointerType *PTy = BaseT->getAs<ObjCObjectPointerType>()) { ResultType = PTy->getPointeeType(); - if (const ObjCObjectType *iQFaceTy = - ResultType->getAsObjCQualifiedInterfaceType()) - ResultType = iQFaceTy->getBaseType(); } Sema::ObjCSubscriptKind Res = diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 9170ac760d4..1257ae361f0 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -786,6 +786,19 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) { TypeSourceInfo *typeArgInfo = nullptr; QualType typeArg = S.GetTypeFromParser(typeArgs[i], &typeArgInfo); + + // Type arguments cannot explicitly specify nullability. + if (auto nullability = AttributedType::stripOuterNullability(typeArg)) { + SourceLocation nullabilityLoc + = typeArgInfo->getTypeLoc().findNullabilityLoc(); + SourceLocation diagLoc = nullabilityLoc.isValid()? nullabilityLoc + : typeArgInfo->getTypeLoc().getLocStart(); + S.Diag(diagLoc, + diag::err_type_arg_explicit_nullability) + << typeArg + << FixItHint::CreateRemoval(nullabilityLoc); + } + finalTypeArgs.push_back(typeArg); // Objective-C object pointer types must be substitutable for the bounds. @@ -3257,7 +3270,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case CAMN_Yes: checkNullabilityConsistency(state, pointerKind, pointerLoc); } - return nullptr; }; |