aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r--lib/Sema/SemaInit.cpp410
1 files changed, 350 insertions, 60 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index a33f5d0b2f3e..9fbcbab0b7d0 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -769,7 +769,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
// subaggregate, brace elision is assumed and the initializer is
// considered for the initialization of the first member of
// the subaggregate.
- if (ElemType->isAggregateType() || ElemType->isVectorType()) {
+ if (!SemaRef.getLangOptions().OpenCL &&
+ (ElemType->isAggregateType() || ElemType->isVectorType())) {
CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList,
StructuredIndex);
++StructuredIndex;
@@ -1184,6 +1185,15 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
continue;
}
+ // Make sure we can use this declaration.
+ if (SemaRef.DiagnoseUseOfDecl(*Field,
+ IList->getInit(Index)->getLocStart())) {
+ ++Index;
+ ++Field;
+ hadError = true;
+ continue;
+ }
+
InitializedEntity MemberEntity =
InitializedEntity::InitializeMember(*Field, &Entity);
CheckSubElementType(MemberEntity, IList, Field->getType(), Index,
@@ -1443,19 +1453,23 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// was a typo for another field name.
LookupResult R(SemaRef, FieldName, D->getFieldLoc(),
Sema::LookupMemberName);
- if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false,
- Sema::CTC_NoKeywords) &&
- (ReplacementField = R.getAsSingle<FieldDecl>()) &&
+ TypoCorrection Corrected = SemaRef.CorrectTypo(
+ DeclarationNameInfo(FieldName, D->getFieldLoc()),
+ Sema::LookupMemberName, /*Scope=*/NULL, /*SS=*/NULL,
+ RT->getDecl(), false, Sema::CTC_NoKeywords);
+ if ((ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>()) &&
ReplacementField->getDeclContext()->getRedeclContext()
->Equals(RT->getDecl())) {
+ std::string CorrectedStr(
+ Corrected.getAsString(SemaRef.getLangOptions()));
+ std::string CorrectedQuotedStr(
+ Corrected.getQuoted(SemaRef.getLangOptions()));
SemaRef.Diag(D->getFieldLoc(),
diag::err_field_designator_unknown_suggest)
- << FieldName << CurrentObjectType << R.getLookupName()
- << FixItHint::CreateReplacement(D->getFieldLoc(),
- R.getLookupName().getAsString());
+ << FieldName << CurrentObjectType << CorrectedQuotedStr
+ << FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr);
SemaRef.Diag(ReplacementField->getLocation(),
- diag::note_previous_decl)
- << ReplacementField->getDeclName();
+ diag::note_previous_decl) << CorrectedQuotedStr;
} else {
SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)
<< FieldName << CurrentObjectType;
@@ -1499,6 +1513,12 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
StructuredList->setInitializedFieldInUnion(*Field);
}
+ // Make sure we can use this declaration.
+ if (SemaRef.DiagnoseUseOfDecl(*Field, D->getFieldLoc())) {
+ ++Index;
+ return true;
+ }
+
// Update the designator with the field declaration.
D->setField(*Field);
@@ -2029,10 +2049,10 @@ InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
DeclarationName InitializedEntity::getName() const {
switch (getKind()) {
- case EK_Parameter:
- if (!VariableOrMember)
- return DeclarationName();
- // Fall through
+ case EK_Parameter: {
+ ParmVarDecl *D = reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
+ return (D ? D->getDeclName() : DeclarationName());
+ }
case EK_Variable:
case EK_Member:
@@ -2057,10 +2077,12 @@ DeclarationName InitializedEntity::getName() const {
DeclaratorDecl *InitializedEntity::getDecl() const {
switch (getKind()) {
case EK_Variable:
- case EK_Parameter:
case EK_Member:
return VariableOrMember;
+ case EK_Parameter:
+ return reinterpret_cast<ParmVarDecl*>(Parameter & ~0x1);
+
case EK_Result:
case EK_Exception:
case EK_New:
@@ -2123,6 +2145,9 @@ void InitializationSequence::Step::Destroy() {
case SK_StringInit:
case SK_ObjCObjectConversion:
case SK_ArrayInit:
+ case SK_PassByIndirectCopyRestore:
+ case SK_PassByIndirectRestore:
+ case SK_ProduceObjCObject:
break;
case SK_ConversionSequence:
@@ -2131,7 +2156,7 @@ void InitializationSequence::Step::Destroy() {
}
bool InitializationSequence::isDirectReferenceBinding() const {
- return getKind() == ReferenceBinding && Steps.back().Kind == SK_BindReference;
+ return !Steps.empty() && Steps.back().Kind == SK_BindReference;
}
bool InitializationSequence::isAmbiguous() const {
@@ -2306,6 +2331,22 @@ void InitializationSequence::AddArrayInitStep(QualType T) {
Steps.push_back(S);
}
+void InitializationSequence::AddPassByIndirectCopyRestoreStep(QualType type,
+ bool shouldCopy) {
+ Step s;
+ s.Kind = (shouldCopy ? SK_PassByIndirectCopyRestore
+ : SK_PassByIndirectRestore);
+ s.Type = type;
+ Steps.push_back(s);
+}
+
+void InitializationSequence::AddProduceObjCObjectStep(QualType T) {
+ Step S;
+ S.Kind = SK_ProduceObjCObject;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::SetOverloadFailure(FailureKind Failure,
OverloadingResult Result) {
setSequenceKind(FailedSequence);
@@ -2317,6 +2358,33 @@ void InitializationSequence::SetOverloadFailure(FailureKind Failure,
// Attempt initialization
//===----------------------------------------------------------------------===//
+static void MaybeProduceObjCObject(Sema &S,
+ InitializationSequence &Sequence,
+ const InitializedEntity &Entity) {
+ if (!S.getLangOptions().ObjCAutoRefCount) return;
+
+ /// When initializing a parameter, produce the value if it's marked
+ /// __attribute__((ns_consumed)).
+ if (Entity.getKind() == InitializedEntity::EK_Parameter) {
+ if (!Entity.isParameterConsumed())
+ return;
+
+ assert(Entity.getType()->isObjCRetainableType() &&
+ "consuming an object of unretainable type?");
+ Sequence.AddProduceObjCObjectStep(Entity.getType());
+
+ /// When initializing a return value, if the return type is a
+ /// retainable type, then returns need to immediately retain the
+ /// object. If an autorelease is required, it will be done at the
+ /// last instant.
+ } else if (Entity.getKind() == InitializedEntity::EK_Result) {
+ if (!Entity.getType()->isObjCRetainableType())
+ return;
+
+ Sequence.AddProduceObjCObjectStep(Entity.getType());
+ }
+}
+
/// \brief Attempt list initialization (C++0x [dcl.init.list])
static void TryListInitialization(Sema &S,
const InitializedEntity &Entity,
@@ -2380,13 +2448,16 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
bool DerivedToBase;
bool ObjCConversion;
+ bool ObjCLifetimeConversion;
assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
T1, T2, DerivedToBase,
- ObjCConversion) &&
+ ObjCConversion,
+ ObjCLifetimeConversion) &&
"Must have incompatible references when binding via conversion");
(void)DerivedToBase;
(void)ObjCConversion;
-
+ (void)ObjCLifetimeConversion;
+
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
@@ -2513,10 +2584,12 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
bool NewDerivedToBase = false;
bool NewObjCConversion = false;
+ bool NewObjCLifetimeConversion = false;
Sema::ReferenceCompareResult NewRefRelationship
= S.CompareReferenceRelationship(DeclLoc, T1,
T2.getNonLValueExprType(S.Context),
- NewDerivedToBase, NewObjCConversion);
+ NewDerivedToBase, NewObjCConversion,
+ NewObjCLifetimeConversion);
if (NewRefRelationship == Sema::Ref_Incompatible) {
// If the type we've converted to is not reference-related to the
// type we're looking for, then there is another conversion step
@@ -2550,8 +2623,6 @@ static void TryReferenceInitialization(Sema &S,
const InitializationKind &Kind,
Expr *Initializer,
InitializationSequence &Sequence) {
- Sequence.setSequenceKind(InitializationSequence::ReferenceBinding);
-
QualType DestType = Entity.getType();
QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
Qualifiers T1Quals;
@@ -2584,10 +2655,11 @@ static void TryReferenceInitialization(Sema &S,
bool isRValueRef = !isLValueRef;
bool DerivedToBase = false;
bool ObjCConversion = false;
+ bool ObjCLifetimeConversion = false;
Expr::Classification InitCategory = Initializer->Classify(S.Context);
Sema::ReferenceCompareResult RefRelationship
= S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase,
- ObjCConversion);
+ ObjCConversion, ObjCLifetimeConversion);
// C++0x [dcl.init.ref]p5:
// A reference to type "cv1 T1" is initialized by an expression of type
@@ -2746,11 +2818,15 @@ static void TryReferenceInitialization(Sema &S,
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
- if (S.TryImplicitConversion(Sequence, TempEntity, Initializer,
+ ImplicitConversionSequence ICS
+ = S.TryImplicitConversion(Initializer, TempEntity.getType(),
/*SuppressUserConversions*/ false,
AllowExplicit,
/*FIXME:InOverloadResolution=*/false,
- /*CStyle=*/Kind.isCStyleOrFunctionalCast())) {
+ /*CStyle=*/Kind.isCStyleOrFunctionalCast(),
+ /*AllowObjCWritebackConversion=*/false);
+
+ if (ICS.isBad()) {
// FIXME: Use the conversion function set stored in ICS to turn
// this into an overloading ambiguity diagnostic. However, we need
// to keep that set as an OverloadCandidateSet rather than as some
@@ -2764,6 +2840,8 @@ static void TryReferenceInitialization(Sema &S,
else
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
return;
+ } else {
+ Sequence.AddConversionSequenceStep(ICS, TempEntity.getType());
}
// [...] If T1 is reference-related to T2, cv1 must be the
@@ -2953,10 +3031,8 @@ static void TryDefaultInitialization(Sema &S,
// C++ [dcl.init]p6:
// To default-initialize an object of type T means:
// - if T is an array type, each element is default-initialized;
- QualType DestType = Entity.getType();
- while (const ArrayType *Array = S.Context.getAsArrayType(DestType))
- DestType = Array->getElementType();
-
+ QualType DestType = S.Context.getBaseElementType(Entity.getType());
+
// - if T is a (possibly cv-qualified) class type (Clause 9), the default
// constructor for T is called (and the initialization is ill-formed if
// T has no accessible default constructor);
@@ -2970,8 +3046,16 @@ static void TryDefaultInitialization(Sema &S,
// If a program calls for the default initialization of an object of
// a const-qualified type T, T shall be a class type with a user-provided
// default constructor.
- if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus)
+ if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus) {
Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ return;
+ }
+
+ // If the destination type has a lifetime property, zero-initialize it.
+ if (DestType.getQualifiers().hasObjCLifetime()) {
+ Sequence.AddZeroInitializationStep(Entity.getType());
+ return;
+ }
}
/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
@@ -3125,6 +3209,86 @@ static void TryUserDefinedConversion(Sema &S,
}
}
+/// The non-zero enum values here are indexes into diagnostic alternatives.
+enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar };
+
+/// Determines whether this expression is an acceptable ICR source.
+static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
+ bool isAddressOf) {
+ // Skip parens.
+ e = e->IgnoreParens();
+
+ // Skip address-of nodes.
+ if (UnaryOperator *op = dyn_cast<UnaryOperator>(e)) {
+ if (op->getOpcode() == UO_AddrOf)
+ return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true);
+
+ // Skip certain casts.
+ } else if (CastExpr *ce = dyn_cast<CastExpr>(e)) {
+ switch (ce->getCastKind()) {
+ case CK_Dependent:
+ case CK_BitCast:
+ case CK_LValueBitCast:
+ case CK_NoOp:
+ return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf);
+
+ case CK_ArrayToPointerDecay:
+ return IIK_nonscalar;
+
+ case CK_NullToPointer:
+ return IIK_okay;
+
+ default:
+ break;
+ }
+
+ // If we have a declaration reference, it had better be a local variable.
+ } else if (isa<DeclRefExpr>(e) || isa<BlockDeclRefExpr>(e)) {
+ if (!isAddressOf) return IIK_nonlocal;
+
+ VarDecl *var;
+ if (isa<DeclRefExpr>(e)) {
+ var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl());
+ if (!var) return IIK_nonlocal;
+ } else {
+ var = cast<BlockDeclRefExpr>(e)->getDecl();
+ }
+
+ return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal);
+
+ // If we have a conditional operator, check both sides.
+ } else if (ConditionalOperator *cond = dyn_cast<ConditionalOperator>(e)) {
+ if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf))
+ return iik;
+
+ return isInvalidICRSource(C, cond->getRHS(), isAddressOf);
+
+ // These are never scalar.
+ } else if (isa<ArraySubscriptExpr>(e)) {
+ return IIK_nonscalar;
+
+ // Otherwise, it needs to be a null pointer constant.
+ } else {
+ return (e->isNullPointerConstant(C, Expr::NPC_ValueDependentIsNull)
+ ? IIK_okay : IIK_nonlocal);
+ }
+
+ return IIK_nonlocal;
+}
+
+/// Check whether the given expression is a valid operand for an
+/// indirect copy/restore.
+static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
+ assert(src->isRValue());
+
+ InvalidICRKind iik = isInvalidICRSource(S.Context, src, false);
+ if (iik == IIK_okay) return;
+
+ S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback)
+ << ((unsigned) iik - 1) // shift index into diagnostic explanations
+ << src->getSourceRange();
+}
+
/// \brief Determine whether we have compatible array types for the
/// purposes of GNU by-copy array initialization.
static bool hasCompatibleArrayTypes(ASTContext &Context,
@@ -3144,6 +3308,53 @@ static bool hasCompatibleArrayTypes(ASTContext &Context,
return Source->isConstantArrayType() && Dest->isIncompleteArrayType();
}
+static bool tryObjCWritebackConversion(Sema &S,
+ InitializationSequence &Sequence,
+ const InitializedEntity &Entity,
+ Expr *Initializer) {
+ bool ArrayDecay = false;
+ QualType ArgType = Initializer->getType();
+ QualType ArgPointee;
+ if (const ArrayType *ArgArrayType = S.Context.getAsArrayType(ArgType)) {
+ ArrayDecay = true;
+ ArgPointee = ArgArrayType->getElementType();
+ ArgType = S.Context.getPointerType(ArgPointee);
+ }
+
+ // Handle write-back conversion.
+ QualType ConvertedArgType;
+ if (!S.isObjCWritebackConversion(ArgType, Entity.getType(),
+ ConvertedArgType))
+ return false;
+
+ // We should copy unless we're passing to an argument explicitly
+ // marked 'out'.
+ bool ShouldCopy = true;
+ if (ParmVarDecl *param = cast_or_null<ParmVarDecl>(Entity.getDecl()))
+ ShouldCopy = (param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out);
+
+ // Do we need an lvalue conversion?
+ if (ArrayDecay || Initializer->isGLValue()) {
+ ImplicitConversionSequence ICS;
+ ICS.setStandard();
+ ICS.Standard.setAsIdentityConversion();
+
+ QualType ResultType;
+ if (ArrayDecay) {
+ ICS.Standard.First = ICK_Array_To_Pointer;
+ ResultType = S.Context.getPointerType(ArgPointee);
+ } else {
+ ICS.Standard.First = ICK_Lvalue_To_Rvalue;
+ ResultType = Initializer->getType().getNonLValueExprType(S.Context);
+ }
+
+ Sequence.AddConversionSequenceStep(ICS, ResultType);
+ }
+
+ Sequence.AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
+ return true;
+}
+
InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -3255,12 +3466,28 @@ InitializationSequence::InitializationSequence(Sema &S,
return;
}
- // Handle initialization in C
+ // Determine whether we should consider writeback conversions for
+ // Objective-C ARC.
+ bool allowObjCWritebackConversion = S.getLangOptions().ObjCAutoRefCount &&
+ Entity.getKind() == InitializedEntity::EK_Parameter;
+
+ // We're at the end of the line for C: it's either a write-back conversion
+ // or it's a C assignment. There's no need to check anything else.
if (!S.getLangOptions().CPlusPlus) {
+ // If allowed, check whether this is an Objective-C writeback conversion.
+ if (allowObjCWritebackConversion &&
+ tryObjCWritebackConversion(S, *this, Entity, Initializer)) {
+ return;
+ }
+
+ // Handle initialization in C
AddCAssignmentStep(DestType);
+ MaybeProduceObjCObject(S, *this, Entity);
return;
}
+ assert(S.getLangOptions().CPlusPlus);
+
// - If the destination type is a (possibly cv-qualified) class type:
if (DestType->isRecordType()) {
// - If the initialization is direct-initialization, or if it is
@@ -3294,6 +3521,7 @@ InitializationSequence::InitializationSequence(Sema &S,
// type, conversion functions are considered.
if (!SourceType.isNull() && SourceType->isRecordType()) {
TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+ MaybeProduceObjCObject(S, *this, Entity);
return;
}
@@ -3302,12 +3530,38 @@ InitializationSequence::InitializationSequence(Sema &S,
// conversions (Clause 4) will be used, if necessary, to convert the
// initializer expression to the cv-unqualified version of the
// destination type; no user-defined conversions are considered.
- if (S.TryImplicitConversion(*this, Entity, Initializer,
- /*SuppressUserConversions*/ true,
+
+ ImplicitConversionSequence ICS
+ = S.TryImplicitConversion(Initializer, Entity.getType(),
+ /*SuppressUserConversions*/true,
/*AllowExplicitConversions*/ false,
/*InOverloadResolution*/ false,
- /*CStyle=*/Kind.isCStyleOrFunctionalCast()))
- {
+ /*CStyle=*/Kind.isCStyleOrFunctionalCast(),
+ allowObjCWritebackConversion);
+
+ if (ICS.isStandard() &&
+ ICS.Standard.Second == ICK_Writeback_Conversion) {
+ // Objective-C ARC writeback conversion.
+
+ // We should copy unless we're passing to an argument explicitly
+ // marked 'out'.
+ bool ShouldCopy = true;
+ if (ParmVarDecl *Param = cast_or_null<ParmVarDecl>(Entity.getDecl()))
+ ShouldCopy = (Param->getObjCDeclQualifier() != ParmVarDecl::OBJC_TQ_Out);
+
+ // If there was an lvalue adjustment, add it as a separate conversion.
+ if (ICS.Standard.First == ICK_Array_To_Pointer ||
+ ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
+ ImplicitConversionSequence LvalueICS;
+ LvalueICS.setStandard();
+ LvalueICS.Standard.setAsIdentityConversion();
+ LvalueICS.Standard.setAllToTypes(ICS.Standard.getToType(0));
+ LvalueICS.Standard.First = ICS.Standard.First;
+ AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));
+ }
+
+ AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
+ } else if (ICS.isBad()) {
DeclAccessPair dap;
if (Initializer->getType() == Context.OverloadTy &&
!S.ResolveAddressOfOverloadedFunction(Initializer
@@ -3315,6 +3569,10 @@ InitializationSequence::InitializationSequence(Sema &S,
SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
else
SetFailed(InitializationSequence::FK_ConversionFailed);
+ } else {
+ AddConversionSequenceStep(ICS, Entity.getType());
+
+ MaybeProduceObjCObject(S, *this, Entity);
}
}
@@ -3560,7 +3818,7 @@ static ExprResult CopyObject(Sema &S,
<< (int)Entity.getKind() << CurInitExpr->getType()
<< CurInitExpr->getSourceRange();
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
- << Best->Function->isDeleted();
+ << 1 << Best->Function->isDeleted();
return ExprError();
}
@@ -3633,6 +3891,11 @@ void InitializationSequence::PrintInitLocationNote(Sema &S,
}
}
+static bool isReferenceBinding(const InitializationSequence::Step &s) {
+ return s.Kind == InitializationSequence::SK_BindReference ||
+ s.Kind == InitializationSequence::SK_BindReferenceToTemporary;
+}
+
ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
@@ -3684,19 +3947,9 @@ InitializationSequence::Perform(Sema &S,
}
}
-
- if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast())
- return ExprResult(Args.release()[0]);
-
- if (Args.size() == 0)
- return S.Owned((Expr *)0);
-
- unsigned NumArgs = Args.size();
- return S.Owned(new (S.Context) ParenListExpr(S.Context,
- SourceLocation(),
- (Expr **)Args.release(),
- NumArgs,
- SourceLocation()));
+ assert(Kind.getKind() == InitializationKind::IK_Copy ||
+ Kind.isExplicitCast());
+ return ExprResult(Args.release()[0]);
}
// No steps means no initialization.
@@ -3733,7 +3986,10 @@ InitializationSequence::Perform(Sema &S,
case SK_CAssignment:
case SK_StringInit:
case SK_ObjCObjectConversion:
- case SK_ArrayInit: {
+ case SK_ArrayInit:
+ case SK_PassByIndirectCopyRestore:
+ case SK_PassByIndirectRestore:
+ case SK_ProduceObjCObject: {
assert(Args.size() == 1);
CurInit = Args.get()[0];
if (!CurInit.get()) return ExprError();
@@ -3841,12 +4097,22 @@ InitializationSequence::Perform(Sema &S,
break;
case SK_BindReferenceToTemporary:
- // Reference binding does not have any corresponding ASTs.
-
// Check exception specifications
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
+ // Materialize the temporary into memory.
+ CurInit = new (S.Context) MaterializeTemporaryExpr(
+ Entity.getType().getNonReferenceType(),
+ CurInit.get(),
+ Entity.getType()->isLValueReferenceType());
+
+ // If we're binding to an Objective-C object that has lifetime, we
+ // need cleanups.
+ if (S.getLangOptions().ObjCAutoRefCount &&
+ CurInit.get()->getType()->isObjCLifetimeType())
+ S.ExprNeedsCleanups = true;
+
break;
case SK_ExtraneousCopyToTemporary:
@@ -3925,8 +4191,7 @@ InitializationSequence::Perform(Sema &S,
CreatedObject = Conversion->getResultType()->isRecordType();
}
- bool RequiresCopy = !IsCopy &&
- getKind() != InitializationSequence::ReferenceBinding;
+ bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back());
if (RequiresCopy || shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
else if (CreatedObject && shouldDestroyTemporary(Entity)) {
@@ -3969,10 +4234,14 @@ InitializationSequence::Perform(Sema &S,
}
case SK_ConversionSequence: {
+ Sema::CheckedConversionKind CCK
+ = Kind.isCStyleCast()? Sema::CCK_CStyleCast
+ : Kind.isFunctionalCast()? Sema::CCK_FunctionalCast
+ : Kind.isExplicitCast()? Sema::CCK_OtherCast
+ : Sema::CCK_ImplicitConversion;
ExprResult CurInitExprRes =
S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS,
- getAssignmentAction(Entity),
- Kind.isCStyleOrFunctionalCast());
+ getAssignmentAction(Entity), CCK);
if (CurInitExprRes.isInvalid())
return ExprError();
CurInit = move(CurInitExprRes);
@@ -4182,7 +4451,20 @@ InitializationSequence::Perform(Sema &S,
}
}
}
+ break;
+ case SK_PassByIndirectCopyRestore:
+ case SK_PassByIndirectRestore:
+ checkIndirectCopyRestoreSource(S, CurInit.get());
+ CurInit = S.Owned(new (S.Context)
+ ObjCIndirectCopyRestoreExpr(CurInit.take(), Step->Type,
+ Step->Kind == SK_PassByIndirectCopyRestore));
+ break;
+
+ case SK_ProduceObjCObject:
+ CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, Step->Type,
+ CK_ObjCProduceObject,
+ CurInit.take(), 0, VK_RValue));
break;
}
}
@@ -4278,7 +4560,7 @@ bool InitializationSequence::Diagnose(Sema &S,
true);
if (Ovl == OR_Deleted) {
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
- << Best->Function->isDeleted();
+ << 1 << Best->Function->isDeleted();
} else {
llvm_unreachable("Inconsistent overload resolution?");
}
@@ -4443,7 +4725,7 @@ bool InitializationSequence::Diagnose(Sema &S,
= FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
if (Ovl == OR_Deleted) {
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
- << Best->Function->isDeleted();
+ << 1 << Best->Function->isDeleted();
} else {
llvm_unreachable("Inconsistent overload resolution?");
}
@@ -4587,10 +4869,6 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case NormalSequence:
OS << "Normal sequence: ";
break;
-
- case ReferenceBinding:
- OS << "Reference binding: ";
- break;
}
for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) {
@@ -4674,6 +4952,18 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case SK_ArrayInit:
OS << "array initialization";
break;
+
+ case SK_PassByIndirectCopyRestore:
+ OS << "pass by indirect copy and restore";
+ break;
+
+ case SK_PassByIndirectRestore:
+ OS << "pass by indirect restore";
+ break;
+
+ case SK_ProduceObjCObject:
+ OS << "Objective-C object retension";
+ break;
}
}
}