diff options
Diffstat (limited to 'lib')
87 files changed, 7735 insertions, 967 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 4c66ed8d7e..fac2eacc4f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -221,9 +221,9 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, DependentTemplateSpecializationTypes(this_()), GlobalNestedNameSpecifier(0), IsInt128Installed(false), CFConstantStringTypeDecl(0), NSConstantStringTypeDecl(0), - ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), - sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0), - cudaConfigureCallDecl(0), + ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), + jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0), + BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0), NullTypeSourceInfo(QualType()), SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)), AddrSpaceMap(getAddressSpaceMap(t, LOpts)), Target(t), @@ -2040,10 +2040,13 @@ ASTContext::getFunctionType(QualType ResultTy, assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } - // FunctionProtoType objects are allocated with extra bytes after them - // for two variable size arrays (for parameter and exception types) at the - // end of them. Instead of the exception types, there could be a noexcept - // expression and a context pointer. + // FunctionProtoType objects are allocated with extra bytes after + // them for three variable size arrays at the end: + // - parameter types + // - exception types + // - consumed-arguments flags + // Instead of the exception types, there could be a noexcept + // expression. size_t Size = sizeof(FunctionProtoType) + NumArgs * sizeof(QualType); if (EPI.ExceptionSpecType == EST_Dynamic) @@ -2051,6 +2054,9 @@ ASTContext::getFunctionType(QualType ResultTy, else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { Size += sizeof(Expr*); } + if (EPI.ConsumedArguments) + Size += NumArgs * sizeof(bool); + FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv); @@ -2925,7 +2931,6 @@ CanQualType ASTContext::getCanonicalParamType(QualType T) const { return CanQualType::CreateUnsafe(Result); } - QualType ASTContext::getUnqualifiedArrayType(QualType type, Qualifiers &quals) { SplitQualType splitType = type.getSplitUnqualifiedType(); @@ -3725,11 +3730,7 @@ void ASTContext::setBlockDescriptorExtendedType(QualType T) { } bool ASTContext::BlockRequiresCopying(QualType Ty) const { - if (Ty->isBlockPointerType()) - return true; - if (isObjCNSObjectType(Ty)) - return true; - if (Ty->isObjCObjectPointerType()) + if (Ty->isObjCRetainableType()) return true; if (getLangOptions().CPlusPlus) { if (const RecordType *RT = Ty->getAs<RecordType>()) { @@ -4826,20 +4827,6 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const { // Type Predicates. //===----------------------------------------------------------------------===// -/// isObjCNSObjectType - Return true if this is an NSObject object using -/// NSObject attribute on a c-style pointer type. -/// FIXME - Make it work directly on types. -/// FIXME: Move to Type. -/// -bool ASTContext::isObjCNSObjectType(QualType Ty) const { - if (const TypedefType *TDT = dyn_cast<TypedefType>(Ty)) { - if (TypedefNameDecl *TD = TDT->getDecl()) - if (TD->getAttr<ObjCNSObjectAttr>()) - return true; - } - return false; -} - /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's /// garbage collection attribute. /// @@ -5452,6 +5439,9 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lbaseInfo.getRegParm() != rbaseInfo.getRegParm()) return QualType(); + if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult()) + return QualType(); + // It's noreturn if either type is. // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'. bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn(); @@ -5460,10 +5450,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (NoReturn != rbaseInfo.getNoReturn()) allRTypes = false; - FunctionType::ExtInfo einfo(NoReturn, - lbaseInfo.getHasRegParm(), - lbaseInfo.getRegParm(), - lbaseInfo.getCC()); + FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn); if (lproto && rproto) { // two C99 style function prototypes assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() && @@ -5584,7 +5571,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, // If any of these qualifiers are different, we have a type // mismatch. if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() || - LQuals.getAddressSpace() != RQuals.getAddressSpace()) + LQuals.getAddressSpace() != RQuals.getAddressSpace() || + LQuals.getObjCLifetime() != RQuals.getObjCLifetime()) return QualType(); // Exactly one GC qualifier difference is allowed: __strong is diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 08ac2a5be4..c10e6c40d3 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -228,6 +228,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (!BaseClassDecl->hasTrivialDestructor()) data().HasTrivialDestructor = false; + // A class has an Objective-C object member if... or any of its bases + // has an Objective-C object member. + if (BaseClassDecl->hasObjectMember()) + setHasObjectMember(true); + // Keep track of the presence of mutable fields. if (BaseClassDecl->hasMutableFields()) data().HasMutableFields = true; @@ -698,10 +703,23 @@ NotASpecialMember:; // A POD struct is a class that is both a trivial class and a // standard-layout class, and has no non-static data members of type // non-POD struct, non-POD union (or array of such types). + // + // Automatic Reference Counting: the presence of a member of Objective-C pointer type + // that does not explicitly have no lifetime makes the class a non-POD. + // However, we delay setting PlainOldData to false in this case so that + // Sema has a chance to diagnostic causes where the same class will be + // non-POD with Automatic Reference Counting but a POD without Instant Objects. + // In this case, the class will become a non-POD class when we complete + // the definition. ASTContext &Context = getASTContext(); QualType T = Context.getBaseElementType(Field->getType()); - if (!T->isPODType()) + if (T->isObjCRetainableType() || T.isObjCGCStrong()) { + if (!Context.getLangOptions().ObjCAutoRefCount || + T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) + setHasObjectMember(true); + } else if (!T.isPODType(Context)) data().PlainOldData = false; + if (T->isReferenceType()) { data().HasTrivialDefaultConstructor = false; @@ -768,6 +786,8 @@ NotASpecialMember:; if (!FieldRec->hasTrivialDestructor()) data().HasTrivialDestructor = false; + if (FieldRec->hasObjectMember()) + setHasObjectMember(true); // C++0x [class]p7: // A standard-layout class is a class that: @@ -1078,6 +1098,20 @@ void CXXRecordDecl::completeDefinition() { void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { RecordDecl::completeDefinition(); + if (hasObjectMember() && getASTContext().getLangOptions().ObjCAutoRefCount) { + // Objective-C Automatic Reference Counting: + // If a class has a non-static data member of Objective-C pointer + // type (or array thereof), it is a non-POD type and its + // default constructor (if any), copy constructor, copy assignment + // operator, and destructor are non-trivial. + struct DefinitionData &Data = data(); + Data.PlainOldData = false; + Data.HasTrivialDefaultConstructor = false; + Data.HasTrivialCopyConstructor = false; + Data.HasTrivialCopyAssignment = false; + Data.HasTrivialDestructor = false; + } + // If the class may be abstract (but hasn't been marked as such), check for // any pure final overriders. if (mayBeAbstract()) { diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index e2c4f38ff9..99eb0d386b 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -474,8 +474,28 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context, } else // we have a factory method. selfTy = Context.getObjCClassType(); - setSelfDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(), - &Context.Idents.get("self"), selfTy)); + bool selfIsConsumed = false; + if (isInstanceMethod() && Context.getLangOptions().ObjCAutoRefCount) { + selfIsConsumed = hasAttr<NSConsumesSelfAttr>(); + + // 'self' is always __strong, although as a special case we don't + // actually retain it except in init methods. + Qualifiers qs; + qs.setObjCLifetime(Qualifiers::OCL_Strong); + selfTy = Context.getQualifiedType(selfTy, qs); + + // In addition, 'self' is const unless this is an init method. + if (getMethodFamily() != OMF_init) + selfTy = selfTy.withConst(); + } + + ImplicitParamDecl *self + = ImplicitParamDecl::Create(Context, this, SourceLocation(), + &Context.Idents.get("self"), selfTy); + setSelfDecl(self); + + if (selfIsConsumed) + self->addAttr(new (Context) NSConsumedAttr(SourceLocation(), Context)); setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(), &Context.Idents.get("_cmd"), diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 421770ea70..19554a3baa 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -933,6 +933,11 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) { first = false; } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) { + Out << (first ? ' ' : ',') << "strong"; + first = false; + } + if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) { Out << (first ? ' ' : ',') << "copy"; first = false; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 987213907e..97f4ea6cba 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1045,6 +1045,10 @@ const char *CastExpr::getCastKindName() const { return "IntegralComplexCast"; case CK_IntegralComplexToFloatingComplex: return "IntegralComplexToFloatingComplex"; + case CK_ObjCConsumeObject: + return "ObjCConsumeObject"; + case CK_ObjCProduceObject: + return "ObjCProduceObject"; } llvm_unreachable("Unhandled cast kind!"); @@ -1490,6 +1494,17 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, case ObjCMessageExprClass: { const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this); + if (Ctx.getLangOptions().ObjCAutoRefCount && + ME->isInstanceMessage() && + !ME->getType()->isVoidType() && + ME->getSelector().getIdentifierInfoForSlot(0) && + ME->getSelector().getIdentifierInfoForSlot(0) + ->getName().startswith("init")) { + Loc = getExprLoc(); + R1 = ME->getSourceRange(); + return true; + } + const ObjCMethodDecl *MD = ME->getMethodDecl(); if (MD && MD->getAttr<WarnUnusedResultAttr>()) { Loc = getExprLoc(); @@ -2519,7 +2534,7 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, /*TypeDependent=*/false, /*ValueDependent=*/false, /*ContainsUnexpandedParameterPack=*/false), NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass), - HasMethod(Method != 0), SuperLoc(SuperLoc), + HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) @@ -2540,7 +2555,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, SourceLocation RBracLoc) : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(), T->isDependentType(), T->containsUnexpandedParameterPack()), - NumArgs(NumArgs), Kind(Class), HasMethod(Method != 0), + NumArgs(NumArgs), Kind(Class), + HasMethod(Method != 0), IsDelegateInitCall(false), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) @@ -2571,7 +2587,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(), Receiver->isTypeDependent(), Receiver->containsUnexpandedParameterPack()), - NumArgs(NumArgs), Kind(Instance), HasMethod(Method != 0), + NumArgs(NumArgs), Kind(Instance), + HasMethod(Method != 0), IsDelegateInitCall(false), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) @@ -2702,6 +2719,19 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { return 0; } +llvm::StringRef ObjCBridgedCastExpr::getBridgeKindName() const { + switch (getBridgeKind()) { + case OBC_Bridge: + return "__bridge"; + case OBC_BridgeTransfer: + return "__bridge_transfer"; + case OBC_BridgeRetained: + return "__bridge_retained"; + } + + return "__bridge"; +} + bool ChooseExpr::isConditionTrue(const ASTContext &C) const { return getCond()->EvaluateAsInt(C) != 0; } diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index d177cb5cbc..1a1fa91a40 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -162,6 +162,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::SizeOfPackExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: case Expr::AsTypeExprClass: + case Expr::ObjCIndirectCopyRestoreExprClass: return Cl::CL_PRValue; // Next come the complicated cases. @@ -289,6 +290,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CXXDynamicCastExprClass: case Expr::CXXReinterpretCastExprClass: case Expr |