Index: cfe/trunk/include/clang/Sema/Initialization.h =================================================================== --- cfe/trunk/include/clang/Sema/Initialization.h +++ cfe/trunk/include/clang/Sema/Initialization.h @@ -886,14 +886,17 @@ /// \param TopLevelOfInitList true if we are initializing from an expression /// at the top level inside an initializer list. This disallows /// narrowing conversions in C++11 onwards. + /// \param TreatUnavailableAsInvalid true if we want to treat unavailable + /// as invalid. InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - bool TopLevelOfInitList = false); + bool TopLevelOfInitList = false, + bool TreatUnavailableAsInvalid = true); void InitializeFrom(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - bool TopLevelOfInitList); + bool TopLevelOfInitList, bool TreatUnavailableAsInvalid); ~InitializationSequence(); Index: cfe/trunk/include/clang/Sema/Sema.h =================================================================== --- cfe/trunk/include/clang/Sema/Sema.h +++ cfe/trunk/include/clang/Sema/Sema.h @@ -3555,7 +3555,7 @@ //===--------------------------------------------------------------------===// // Expression Parsing Callbacks: SemaExpr.cpp. - bool CanUseDecl(NamedDecl *D); + bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid); bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass=nullptr, bool ObjCPropertyAccess=false); Index: cfe/trunk/lib/Sema/SemaDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -9524,7 +9524,9 @@ if (VDecl->isInvalidDecl()) return; - InitializationSequence InitSeq(*this, Entity, Kind, Args); + InitializationSequence InitSeq(*this, Entity, Kind, Args, + /*TopLevelOfInitList=*/false, + /*TreatUnavailableAsInvalid=*/false); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT); if (Result.isInvalid()) { VDecl->setInvalidDecl(); Index: cfe/trunk/lib/Sema/SemaExpr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp +++ cfe/trunk/lib/Sema/SemaExpr.cpp @@ -49,7 +49,7 @@ /// \brief Determine whether the use of this declaration is valid, without /// emitting diagnostics. -bool Sema::CanUseDecl(NamedDecl *D) { +bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) { // See if this is an auto-typed variable whose initializer we are parsing. if (ParsingInitForAutoVars.count(D)) return false; @@ -67,7 +67,7 @@ } // See if this function is unavailable. - if (D->getAvailability() == AR_Unavailable && + if (TreatUnavailableAsInvalid && D->getAvailability() == AR_Unavailable && cast(CurContext)->getAvailability() != AR_Unavailable) return false; Index: cfe/trunk/lib/Sema/SemaInit.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp +++ cfe/trunk/lib/Sema/SemaInit.cpp @@ -238,6 +238,7 @@ Sema &SemaRef; bool hadError; bool VerifyOnly; // no diagnostics, no structure building + bool TreatUnavailableAsInvalid; // Used only in VerifyOnly mode. llvm::DenseMap SyntacticToSemantic; InitListExpr *FullyStructuredList; @@ -320,7 +321,8 @@ static ExprResult PerformEmptyInit(Sema &SemaRef, SourceLocation Loc, const InitializedEntity &Entity, - bool VerifyOnly); + bool VerifyOnly, + bool TreatUnavailableAsInvalid); // Explanation on the "FillWithNoInit" mode: // @@ -360,7 +362,8 @@ public: InitListChecker(Sema &S, const InitializedEntity &Entity, - InitListExpr *IL, QualType &T, bool VerifyOnly); + InitListExpr *IL, QualType &T, bool VerifyOnly, + bool TreatUnavailableAsInvalid); bool HadError() { return hadError; } // @brief Retrieves the fully-structured initializer list used for @@ -373,7 +376,8 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef, SourceLocation Loc, const InitializedEntity &Entity, - bool VerifyOnly) { + bool VerifyOnly, + bool TreatUnavailableAsInvalid) { InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, true); MultiExprArg SubInit; @@ -443,7 +447,8 @@ InitSeq.InitializeFrom( SemaRef, Entity, InitializationKind::CreateValue(Loc, Loc, Loc, true), - MultiExprArg(), /*TopLevelOfInitList=*/false); + MultiExprArg(), /*TopLevelOfInitList=*/false, + TreatUnavailableAsInvalid); // Emit a warning for this. System header warnings aren't shown // by default, but people working on system headers should see it. if (!VerifyOnly) { @@ -480,7 +485,8 @@ SourceLocation Loc) { assert(VerifyOnly && "CheckEmptyInitializable is only inteded for verification mode."); - if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true).isInvalid()) + if (PerformEmptyInit(SemaRef, Loc, Entity, /*VerifyOnly*/true, + TreatUnavailableAsInvalid).isInvalid()) hadError = true; } @@ -497,7 +503,8 @@ ExprResult BaseInit = FillWithNoInit ? new (SemaRef.Context) NoInitExpr(Base.getType()) : PerformEmptyInit(SemaRef, ILE->getLocEnd(), BaseEntity, - /*VerifyOnly*/ false); + /*VerifyOnly*/ false, + TreatUnavailableAsInvalid); if (BaseInit.isInvalid()) { hadError = true; return; @@ -572,7 +579,8 @@ } ExprResult MemberInit = PerformEmptyInit(SemaRef, Loc, MemberEntity, - /*VerifyOnly*/false); + /*VerifyOnly*/false, + TreatUnavailableAsInvalid); if (MemberInit.isInvalid()) { hadError = true; return; @@ -709,7 +717,8 @@ else { ExprResult ElementInit = PerformEmptyInit(SemaRef, ILE->getLocEnd(), ElementEntity, - /*VerifyOnly*/false); + /*VerifyOnly*/false, + TreatUnavailableAsInvalid); if (ElementInit.isInvalid()) { hadError = true; return; @@ -757,8 +766,10 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, InitListExpr *IL, QualType &T, - bool VerifyOnly) - : SemaRef(S), VerifyOnly(VerifyOnly) { + bool VerifyOnly, + bool TreatUnavailableAsInvalid) + : SemaRef(S), VerifyOnly(VerifyOnly), + TreatUnavailableAsInvalid(TreatUnavailableAsInvalid) { // FIXME: Check that IL isn't already the semantic form of some other // InitListExpr. If it is, we'd create a broken AST. @@ -1852,7 +1863,7 @@ // Make sure we can use this declaration. bool InvalidUse; if (VerifyOnly) - InvalidUse = !SemaRef.CanUseDecl(*Field); + InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid); else InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, IList->getInit(Index)->getLocStart()); @@ -2256,7 +2267,7 @@ // Make sure we can use this declaration. bool InvalidUse; if (VerifyOnly) - InvalidUse = !SemaRef.CanUseDecl(*Field); + InvalidUse = !SemaRef.CanUseDecl(*Field, TreatUnavailableAsInvalid); else InvalidUse = SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc()); if (InvalidUse) { @@ -3387,7 +3398,8 @@ const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, - InitializationSequence &Sequence); + InitializationSequence &Sequence, + bool TreatUnavailableAsInvalid); /// \brief When initializing from init list via constructor, handle /// initialization of an object of type std::initializer_list. @@ -3397,7 +3409,8 @@ static bool TryInitializerListConstruction(Sema &S, InitListExpr *List, QualType DestType, - InitializationSequence &Sequence) { + InitializationSequence &Sequence, + bool TreatUnavailableAsInvalid) { QualType E; if (!S.isStdInitializerList(DestType, &E)) return false; @@ -3416,7 +3429,8 @@ InitializedEntity::InitializeTemporary(ArrayType); InitializationKind Kind = InitializationKind::CreateDirectList(List->getExprLoc()); - TryListInitialization(S, HiddenArray, Kind, List, Sequence); + TryListInitialization(S, HiddenArray, Kind, List, Sequence, + TreatUnavailableAsInvalid); if (Sequence) Sequence.AddStdInitializerListConstructionStep(DestType); return true; @@ -3670,7 +3684,8 @@ const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, - InitializationSequence &Sequence) { + InitializationSequence &Sequence, + bool TreatUnavailableAsInvalid) { // First, catch C++03 where this isn't possible. if (!S.getLangOpts().CPlusPlus11) { Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); @@ -3726,7 +3741,8 @@ // Not reference-related. Create a temporary and bind to that. InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); - TryListInitialization(S, TempEntity, Kind, InitList, Sequence); + TryListInitialization(S, TempEntity, Kind, InitList, Sequence, + TreatUnavailableAsInvalid); if (Sequence) { if (DestType->isRValueReferenceType() || (T1Quals.hasConst() && !T1Quals.hasVolatile())) @@ -3742,7 +3758,8 @@ const InitializedEntity &Entity, const InitializationKind &Kind, InitListExpr *InitList, - InitializationSequence &Sequence) { + InitializationSequence &Sequence, + bool TreatUnavailableAsInvalid) { QualType DestType = Entity.getType(); // C++ doesn't allow scalar initialization with more than one argument. @@ -3753,7 +3770,8 @@ return; } if (DestType->isReferenceType()) { - TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence); + TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence, + TreatUnavailableAsInvalid); return; } @@ -3797,7 +3815,8 @@ InitList->getRBraceLoc()) : Kind; Sequence.InitializeFrom(S, Entity, SubKind, SubInit, - /*TopLevelOfInitList*/ true); + /*TopLevelOfInitList*/ true, + TreatUnavailableAsInvalid); // TryStringLiteralInitialization() (in InitializeFrom()) will fail if // the element is not an appropriately-typed string literal, in which @@ -3829,7 +3848,8 @@ // - Otherwise, if T is a specialization of std::initializer_list, // an initializer_list object constructed [...] - if (TryInitializerListConstruction(S, InitList, DestType, Sequence)) + if (TryInitializerListConstruction(S, InitList, DestType, Sequence, + TreatUnavailableAsInvalid)) return; // - Otherwise, if T is a class type, constructors are considered. @@ -3865,14 +3885,15 @@ : Kind; Expr *SubInit[1] = { InitList->getInit(0) }; Sequence.InitializeFrom(S, Entity, SubKind, SubInit, - /*TopLevelOfInitList*/true); + /*TopLevelOfInitList*/true, + TreatUnavailableAsInvalid); if (Sequence) Sequence.RewrapReferenceInitList(Entity.getType(), InitList); return; } InitListChecker CheckInitList(S, Entity, InitList, - DestType, /*VerifyOnly=*/true); + DestType, /*VerifyOnly=*/true, TreatUnavailableAsInvalid); if (CheckInitList.HadError()) { Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed); return; @@ -4877,9 +4898,11 @@ const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - bool TopLevelOfInitList) + bool TopLevelOfInitList, + bool TreatUnavailableAsInvalid) : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) { - InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList); + InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList, + TreatUnavailableAsInvalid); } /// Tries to get a FunctionDecl out of `E`. If it succeeds and we can take the @@ -4897,7 +4920,8 @@ const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - bool TopLevelOfInitList) { + bool TopLevelOfInitList, + bool TreatUnavailableAsInvalid) { ASTContext &Context = S.Context; // Eliminate non-overload placeholder types in the arguments. We @@ -4951,7 +4975,8 @@ // object is list-initialized (8.5.4). if (Kind.getKind() != InitializationKind::IK_Direct) { if (InitListExpr *InitList = dyn_cast_or_null(Initializer)) { - TryListInitialization(S, Entity, Kind, InitList, *this); + TryListInitialization(S, Entity, Kind, InitList, *this, + TreatUnavailableAsInvalid); return; } } @@ -5035,7 +5060,7 @@ Entity.getKind() == InitializedEntity::EK_Member && Initializer && isa(Initializer)) { TryListInitialization(S, Entity, Kind, cast(Initializer), - *this); + *this, TreatUnavailableAsInvalid); AddParenthesizedArrayInitStep(DestType); } else if (DestAT->getElementType()->isCharType()) SetFailed(FK_ArrayNeedsInitListOrStringLiteral); @@ -6581,7 +6606,8 @@ InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty); InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity; InitListChecker PerformInitList(S, InitEntity, - InitList, Ty, /*VerifyOnly=*/false); + InitList, Ty, /*VerifyOnly=*/false, + /*TreatUnavailableAsInvalid=*/false); if (PerformInitList.HadError()) return ExprError(); @@ -6952,7 +6978,8 @@ } InitListChecker DiagnoseInitList(S, Entity, InitList, DestType, - /*VerifyOnly=*/false); + /*VerifyOnly=*/false, + /*TreatUnavailableAsInvalid=*/false); assert(DiagnoseInitList.HadError() && "Inconsistent init list check result."); } Index: cfe/trunk/test/SemaObjC/Inputs/arc-system-header.h =================================================================== --- cfe/trunk/test/SemaObjC/Inputs/arc-system-header.h +++ cfe/trunk/test/SemaObjC/Inputs/arc-system-header.h @@ -50,3 +50,8 @@ static inline void *test8(id ptr) { return (__bridge_retain void*) ptr; } + +typedef struct { + const char *name; + id field; +} Test9; Index: cfe/trunk/test/SemaObjC/arc-system-header.m =================================================================== --- cfe/trunk/test/SemaObjC/arc-system-header.m +++ cfe/trunk/test/SemaObjC/arc-system-header.m @@ -46,6 +46,13 @@ // expected-note@arc-system-header.h:41 4 {{declaration uses type that is ill-formed in ARC}} // expected-note@arc-system-header.h:41 2 {{property 'prop' is declared unavailable here}} } + +extern void doSomething(Test9 arg); +void test9() { + Test9 foo2 = {0, 0}; // expected-error {{'field' is unavailable in ARC}} + // expected-note@arc-system-header.h:56 {{field has non-trivial ownership qualification}} + doSomething(foo2); +} #endif // test8 in header