diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp | 1201 |
1 files changed, 784 insertions, 417 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index 060ee3e..b053c83 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Sema/Initialization.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" @@ -19,13 +18,13 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/Designator.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include <map> using namespace clang; @@ -470,9 +469,14 @@ ExprResult InitListChecker::PerformEmptyInit(Sema &SemaRef, SemaRef.Diag(Entity.getDecl()->getLocation(), diag::note_in_omitted_aggregate_initializer) << /*field*/1 << Entity.getDecl(); - else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) + else if (Entity.getKind() == InitializedEntity::EK_ArrayElement) { + bool IsTrailingArrayNewMember = + Entity.getParent() && + Entity.getParent()->isVariableLengthArrayNew(); SemaRef.Diag(Loc, diag::note_in_omitted_aggregate_initializer) - << /*array element*/0 << Entity.getElementIndex(); + << (IsTrailingArrayNewMember ? 2 : /*array element*/0) + << Entity.getElementIndex(); + } } return ExprError(); } @@ -686,8 +690,12 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, unsigned NumElements = NumInits; if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { ElementType = AType->getElementType(); - if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) + if (const auto *CAType = dyn_cast<ConstantArrayType>(AType)) NumElements = CAType->getSize().getZExtValue(); + // For an array new with an unknown bound, ask for one additional element + // in order to populate the array filler. + if (Entity.isVariableLengthArrayNew()) + ++NumElements; ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); } else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) { @@ -937,6 +945,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity, case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: case InitializedEntity::EK_BlockElement: + case InitializedEntity::EK_Binding: llvm_unreachable("unexpected braced scalar init"); } @@ -1229,8 +1238,9 @@ 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 (!SemaRef.getLangOpts().OpenCL && - (ElemType->isAggregateType() || ElemType->isVectorType())) { + // OpenCL vector initializer is handled elsewhere. + if ((!SemaRef.getLangOpts().OpenCL && ElemType->isVectorType()) || + ElemType->isAggregateType()) { CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); ++StructuredIndex; @@ -1674,7 +1684,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, // If this is an incomplete array type, the actual type needs to // be calculated here. llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned()); - if (maxElements == Zero) { + if (maxElements == Zero && !Entity.isVariableLengthArrayNew()) { // Sizing an array implicitly to zero is not allowed by ISO C, // but is supported by GNU. SemaRef.Diag(IList->getLocStart(), @@ -1685,10 +1695,13 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, ArrayType::Normal, 0); } if (!hadError && VerifyOnly) { - // Check if there are any members of the array that get value-initialized. - // If so, check if doing that is possible. + // If there are any members of the array that get value-initialized, check + // that is possible. That happens if we know the bound and don't have + // enough elements, or if we're performing an array new with an unknown + // bound. // FIXME: This needs to detect holes left by designated initializers too. - if (maxElementsKnown && elementIndex < maxElements) + if ((maxElementsKnown && elementIndex < maxElements) || + Entity.isVariableLengthArrayNew()) CheckEmptyInitializable(InitializedEntity::InitializeElement( SemaRef.Context, 0, Entity), IList->getLocEnd()); @@ -2896,7 +2909,8 @@ DeclarationName InitializedEntity::getName() const { case EK_Variable: case EK_Member: - return VariableOrMember->getDeclName(); + case EK_Binding: + return Variable.VariableOrMember->getDeclName(); case EK_LambdaCapture: return DeclarationName(Capture.VarID); @@ -2919,11 +2933,12 @@ DeclarationName InitializedEntity::getName() const { llvm_unreachable("Invalid EntityKind!"); } -DeclaratorDecl *InitializedEntity::getDecl() const { +ValueDecl *InitializedEntity::getDecl() const { switch (getKind()) { case EK_Variable: case EK_Member: - return VariableOrMember; + case EK_Binding: + return Variable.VariableOrMember; case EK_Parameter: case EK_Parameter_CF_Audited: @@ -2958,6 +2973,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_Parameter: case EK_Parameter_CF_Audited: case EK_Member: + case EK_Binding: case EK_New: case EK_Temporary: case EK_CompoundLiteralInit: @@ -2989,6 +3005,7 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { case EK_Result: OS << "Result"; break; case EK_Exception: OS << "Exception"; break; case EK_Member: OS << "Member"; break; + case EK_Binding: OS << "Binding"; break; case EK_New: OS << "New"; break; case EK_Temporary: OS << "Temporary"; break; case EK_CompoundLiteralInit: OS << "CompoundLiteral";break; @@ -3005,9 +3022,9 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { break; } - if (Decl *D = getDecl()) { + if (auto *D = getDecl()) { OS << " "; - cast<NamedDecl>(D)->printQualifiedName(OS); + D->printQualifiedName(OS); } OS << " '" << getType().getAsString() << "'\n"; @@ -3031,6 +3048,7 @@ void InitializationSequence::Step::Destroy() { case SK_CastDerivedToBaseLValue: case SK_BindReference: case SK_BindReferenceToTemporary: + case SK_FinalCopy: case SK_ExtraneousCopyToTemporary: case SK_UserConversion: case SK_QualificationConversionRValue: @@ -3047,7 +3065,10 @@ void InitializationSequence::Step::Destroy() { case SK_CAssignment: case SK_StringInit: case SK_ObjCObjectConversion: + case SK_ArrayLoopIndex: + case SK_ArrayLoopInit: case SK_ArrayInit: + case SK_GNUArrayInit: case SK_ParenthesizedArrayInit: case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: @@ -3056,6 +3077,7 @@ void InitializationSequence::Step::Destroy() { case SK_StdInitializerListConstructorCall: case SK_OCLSamplerInit: case SK_OCLZeroEvent: + case SK_OCLZeroQueue: break; case SK_ConversionSequence: @@ -3065,7 +3087,14 @@ void InitializationSequence::Step::Destroy() { } bool InitializationSequence::isDirectReferenceBinding() const { - return !Steps.empty() && Steps.back().Kind == SK_BindReference; + // There can be some lvalue adjustments after the SK_BindReference step. + for (auto I = Steps.rbegin(); I != Steps.rend(); ++I) { + if (I->Kind == SK_BindReference) + return true; + if (I->Kind == SK_BindReferenceToTemporary) + return false; + } + return false; } bool InitializationSequence::isAmbiguous() const { @@ -3082,6 +3111,8 @@ bool InitializationSequence::isAmbiguous() const { case FK_IncompatWideStringIntoWideChar: case FK_AddressOfOverloadFailed: // FIXME: Could do better case FK_NonConstLValueReferenceBindingToTemporary: + case FK_NonConstLValueReferenceBindingToBitfield: + case FK_NonConstLValueReferenceBindingToVectorElement: case FK_NonConstLValueReferenceBindingToUnrelated: case FK_RValueReferenceBindingToLValue: case FK_ReferenceInitDropsQualifiers: @@ -3150,6 +3181,13 @@ void InitializationSequence::AddReferenceBindingStep(QualType T, Steps.push_back(S); } +void InitializationSequence::AddFinalCopy(QualType T) { + Step S; + S.Kind = SK_FinalCopy; + S.Type = T; + Steps.push_back(S); +} + void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) { Step S; S.Kind = SK_ExtraneousCopyToTemporary; @@ -3266,9 +3304,20 @@ void InitializationSequence::AddObjCObjectConversionStep(QualType T) { Steps.push_back(S); } -void InitializationSequence::AddArrayInitStep(QualType T) { +void InitializationSequence::AddArrayInitStep(QualType T, bool IsGNUExtension) { Step S; - S.Kind = SK_ArrayInit; + S.Kind = IsGNUExtension ? SK_GNUArrayInit : SK_ArrayInit; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddArrayInitLoopStep(QualType T, QualType EltT) { + Step S; + S.Kind = SK_ArrayLoopIndex; + S.Type = EltT; + Steps.insert(Steps.begin(), S); + + S.Kind = SK_ArrayLoopInit; S.Type = T; Steps.push_back(S); } @@ -3317,6 +3366,13 @@ void InitializationSequence::AddOCLZeroEventStep(QualType T) { Steps.push_back(S); } +void InitializationSequence::AddOCLZeroQueueStep(QualType T) { + Step S; + S.Kind = SK_OCLZeroQueue; + S.Type = T; + Steps.push_back(S); +} + void InitializationSequence::RewrapReferenceInitList(QualType T, InitListExpr *Syntactic) { assert(Syntactic->getNumInits() == 1 && @@ -3434,6 +3490,23 @@ static bool TryInitializerListConstruction(Sema &S, return true; } +/// Determine if the constructor has the signature of a copy or move +/// constructor for the type T of the class in which it was found. That is, +/// determine if its first parameter is of type T or reference to (possibly +/// cv-qualified) T. +static bool hasCopyOrMoveCtorParam(ASTContext &Ctx, + const ConstructorInfo &Info) { + if (Info.Constructor->getNumParams() == 0) + return false; + + QualType ParmT = + Info.Constructor->getParamDecl(0)->getType().getNonReferenceType(); + QualType ClassT = + Ctx.getRecordType(cast<CXXRecordDecl>(Info.FoundDecl->getDeclContext())); + + return Ctx.hasSameUnqualifiedType(ParmT, ClassT); +} + static OverloadingResult ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, MultiExprArg Args, @@ -3441,59 +3514,56 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, DeclContext::lookup_result Ctors, OverloadCandidateSet::iterator &Best, bool CopyInitializing, bool AllowExplicit, - bool OnlyListConstructors, bool IsListInit) { + bool OnlyListConstructors, bool IsListInit, + bool SecondStepOfCopyInit = false) { CandidateSet.clear(); for (NamedDecl *D : Ctors) { auto Info = getConstructorInfo(D); - if (!Info.Constructor) + if (!Info.Constructor || Info.Constructor->isInvalidDecl()) continue; - bool SuppressUserConversions = false; - - if (!Info.ConstructorTmpl) { - // C++11 [over.best.ics]p4: - // ... and the constructor or user-defined conversion function is a - // candidate by - // - 13.3.1.3, when the argument is the temporary in the second step - // of a class copy-initialization, or - // - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases), - // user-defined conversion sequences are not considered. - // FIXME: This breaks backward compatibility, e.g. PR12117. As a - // temporary fix, let's re-instate the third bullet above until - // there is a resolution in the standard, i.e., - // - 13.3.1.7 when the initializer list has exactly one element that is - // itself an initializer list and a conversion to some class X or - // reference to (possibly cv-qualified) X is considered for the first - // parameter of a constructor of X. - if ((CopyInitializing || - (IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]))) && - Info.Constructor->isCopyOrMoveConstructor()) - SuppressUserConversions = true; - } - - if (!Info.Constructor->isInvalidDecl() && - (AllowExplicit || !Info.Constructor->isExplicit()) && - (!OnlyListConstructors || S.isInitListConstructor(Info.Constructor))) { - if (Info.ConstructorTmpl) - S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, - /*ExplicitArgs*/ nullptr, Args, - CandidateSet, SuppressUserConversions); - else { - // C++ [over.match.copy]p1: - // - When initializing a temporary to be bound to the first parameter - // of a constructor that takes a reference to possibly cv-qualified - // T as its first argument, called with a single argument in the - // context of direct-initialization, explicit conversion functions - // are also considered. - bool AllowExplicitConv = AllowExplicit && !CopyInitializing && - Args.size() == 1 && - Info.Constructor->isCopyOrMoveConstructor(); - S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args, - CandidateSet, SuppressUserConversions, - /*PartialOverloading=*/false, - /*AllowExplicit=*/AllowExplicitConv); - } + if (!AllowExplicit && Info.Constructor->isExplicit()) + continue; + + if (OnlyListConstructors && !S.isInitListConstructor(Info.Constructor)) + continue; + + // C++11 [over.best.ics]p4: + // ... and the constructor or user-defined conversion function is a + // candidate by + // - 13.3.1.3, when the argument is the temporary in the second step + // of a class copy-initialization, or + // - 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases), [not handled here] + // - the second phase of 13.3.1.7 when the initializer list has exactly + // one element that is itself an initializer list, and the target is + // the first parameter of a constructor of class X, and the conversion + // is to X or reference to (possibly cv-qualified X), + // user-defined conversion sequences are not considered. + bool SuppressUserConversions = + SecondStepOfCopyInit || + (IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]) && + hasCopyOrMoveCtorParam(S.Context, Info)); + + if (Info.ConstructorTmpl) + S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, + /*ExplicitArgs*/ nullptr, Args, + CandidateSet, SuppressUserConversions); + else { + // C++ [over.match.copy]p1: + // - When initializing a temporary to be bound to the first parameter + // of a constructor [for type T] that takes a reference to possibly + // cv-qualified T as its first argument, called with a single + // argument in the context of direct-initialization, explicit + // conversion functions are also considered. + // FIXME: What if a constructor template instantiates to such a signature? + bool AllowExplicitConv = AllowExplicit && !CopyInitializing && + Args.size() == 1 && + hasCopyOrMoveCtorParam(S.Context, Info); + S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args, + CandidateSet, SuppressUserConversions, + /*PartialOverloading=*/false, + /*AllowExplicit=*/AllowExplicitConv); } } @@ -3504,6 +3574,9 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, /// \brief Attempt initialization by constructor (C++ [dcl.init]), which /// enumerates the constructors of the initialized entity and performs overload /// resolution to select the best. +/// \param DestType The destination class type. +/// \param DestArrayType The destination type, which is either DestType or +/// a (possibly multidimensional) array of DestType. /// \param IsListInit Is this list-initialization? /// \param IsInitListCopy Is this non-list-initialization resulting from a /// list-initialization from {x} where x is the same @@ -3512,11 +3585,18 @@ static void TryConstructorInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType DestType, + QualType DestArrayType, InitializationSequence &Sequence, bool IsListInit = false, bool IsInitListCopy = false) { - assert((!IsListInit || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) && - "IsListInit must come with a single initializer list argument."); + assert(((!IsListInit && !IsInitListCopy) || + (Args.size() == 1 && isa<InitListExpr>(Args[0]))) && + "IsListInit/IsInitListCopy must come with a single initializer list " + "argument."); + InitListExpr *ILE = + (IsListInit || IsInitListCopy) ? cast<InitListExpr>(Args[0]) : nullptr; + MultiExprArg UnwrappedArgs = + ILE ? MultiExprArg(ILE->getInits(), ILE->getNumInits()) : Args; // The type we're constructing needs to be complete. if (!S.isCompleteType(Kind.getLocation(), DestType)) { @@ -3524,6 +3604,25 @@ static void TryConstructorInitialization(Sema &S, return; } + // C++1z [dcl.init]p17: + // - If the initializer expression is a prvalue and the cv-unqualified + // version of the source type is the same class as the class of the + // destination, the initializer expression is used to initialize the + // destination object. + // Per DR (no number yet), this does not apply when initializing a base + // class or delegating to another constructor from a mem-initializer. + if (S.getLangOpts().CPlusPlus1z && + Entity.getKind() != InitializedEntity::EK_Base && + Entity.getKind() != InitializedEntity::EK_Delegating && + UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isRValue() && + S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) { + // Convert qualifications if necessary. + Sequence.AddQualificationConversionStep(DestType, VK_RValue); + if (ILE) + Sequence.RewrapReferenceInitList(DestType, ILE); + return; + } + const RecordType *DestRecordType = DestType->getAs<RecordType>(); assert(DestRecordType && "Constructor initialization requires record type"); CXXRecordDecl *DestRecordDecl @@ -3557,20 +3656,16 @@ static void TryConstructorInitialization(Sema &S, // constructors of the class T and the argument list consists of the // initializer list as a single argument. if (IsListInit) { - InitListExpr *ILE = cast<InitListExpr>(Args[0]); AsInitializerList = true; // If the initializer list has no elements and T has a default constructor, // the first phase is omitted. - if (ILE->getNumInits() != 0 || !DestRecordDecl->hasDefaultConstructor()) + if (!(UnwrappedArgs.empty() && DestRecordDecl->hasDefaultConstructor())) Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, CandidateSet, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructor=*/true, IsListInit); - - // Time to unwrap the init list. - Args = MultiExprArg(ILE->getInits(), ILE->getNumInits()); } // C++11 [over.match.list]p1: @@ -3580,7 +3675,7 @@ static void TryConstructorInitialization(Sema &S, // elements of the initializer list. if (Result == OR_No_Viable_Function) { AsInitializerList = false; - Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, + Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs, CandidateSet, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructors=*/false, @@ -3624,7 +3719,7 @@ static void TryConstructorInitialization(Sema &S, // subsumed by the initialization. bool HadMultipleCandidates = (CandidateSet.size() > 1); Sequence.AddConstructorInitializationStep( - Best->FoundDecl, CtorDecl, DestType, HadMultipleCandidates, + Best->FoundDecl, CtorDecl, DestArrayType, HadMultipleCandidates, IsListInit | IsInitListCopy, AsInitializerList); } @@ -3790,10 +3885,11 @@ static void TryListInitialization(Sema &S, QualType InitType = InitList->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, DestType) || S.IsDerivedFrom(InitList->getLocStart(), InitType, DestType)) { - Expr *InitAsExpr = InitList->getInit(0); - TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType, - Sequence, /*InitListSyntax*/ false, - /*IsInitListCopy*/ true); + Expr *InitListAsExpr = InitList; + TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, + DestType, Sequence, + /*InitListSyntax*/false, + /*IsInitListCopy*/true); return; } } @@ -3848,7 +3944,7 @@ static void TryListInitialization(Sema &S, // - Otherwise, if T is a class type, constructors are considered. Expr *InitListAsExpr = InitList; TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, - Sequence, /*InitListSyntax*/ true); + DestType, Sequence, /*InitListSyntax*/true); } else Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType); return; @@ -3940,12 +4036,10 @@ static void TryListInitialization(Sema &S, /// \brief Try a reference initialization that involves calling a conversion /// function. -static OverloadingResult TryRefInitWithConversionFunction(Sema &S, - const InitializedEntity &Entity, - const InitializationKind &Kind, - Expr *Initializer, - bool AllowRValues, - InitializationSequence &Sequence) { +static OverloadingResult TryRefInitWithConversionFunction( + Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, + Expr *Initializer, bool AllowRValues, bool IsLValueRef, + InitializationSequence &Sequence) { QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); QualType T1 = cv1T1.getUnqualifiedType(); @@ -4061,58 +4155,68 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // use this initialization. Mark it as referenced. Function->setReferenced(); - // Compute the returned type of the conversion. + // Compute the returned type and value kind of the conversion. + QualType cv3T3; if (isa<CXXConversionDecl>(Function)) - T2 = Function->getReturnType(); + cv3T3 = Function->getReturnType(); else - T2 = cv1T1; - - // Add the user-defined conversion step. - bool HadMultipleCandidates = (CandidateSet.size() > 1); - Sequence.AddUserConversionStep(Function, Best->FoundDecl, - T2.getNonLValueExprType(S.Context), - HadMultipleCandidates); + cv3T3 = T1; - // Determine whether we need to perform derived-to-base or - // cv-qualification adjustments. ExprValueKind VK = VK_RValue; - if (T2->isLValueReferenceType()) + if (cv3T3->isLValueReferenceType()) VK = VK_LValue; - else if (const RValueReferenceType *RRef = T2->getAs<RValueReferenceType>()) + else if (const auto *RRef = cv3T3->getAs<RValueReferenceType>()) VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue; + cv3T3 = cv3T3.getNonLValueExprType(S.Context); + + // Add the user-defined conversion step. + bool HadMultipleCandidates = (CandidateSet.size() > 1); + Sequence.AddUserConversionStep(Function, Best->FoundDecl, cv3T3, + HadMultipleCandidates); + // Determine whether we'll need to perform derived-to-base adjustments or + // other conversions. bool NewDerivedToBase = false; bool NewObjCConversion = false; bool NewObjCLifetimeConversion = false; Sema::ReferenceCompareResult NewRefRelationship - = S.CompareReferenceRelationship(DeclLoc, T1, - T2.getNonLValueExprType(S.Context), + = S.CompareReferenceRelationship(DeclLoc, T1, cv3T3, NewDerivedToBase, NewObjCConversion, NewObjCLifetimeConversion); + + // Add the final conversion sequence, if necessary. 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 - // we need to perform to produce a temporary of the right type - // that we'll be binding to. + assert(!isa<CXXConstructorDecl>(Function) && + "should not have conversion after constructor"); + ImplicitConversionSequence ICS; ICS.setStandard(); ICS.Standard = Best->FinalConversion; - T2 = ICS.Standard.getToType(2); - Sequence.AddConversionSequenceStep(ICS, T2); - } else if (NewDerivedToBase) - Sequence.AddDerivedToBaseCastStep( - S.Context.getQualifiedType(T1, - T2.getNonReferenceType().getQualifiers()), - VK); - else if (NewObjCConversion) - Sequence.AddObjCObjectConversionStep( - S.Context.getQualifiedType(T1, - T2.getNonReferenceType().getQualifiers())); + Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2)); + + // Every implicit conversion results in a prvalue, except for a glvalue + // derived-to-base conversion, which we handle below. + cv3T3 = ICS.Standard.getToType(2); + VK = VK_RValue; + } - if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers()) - Sequence.AddQualificationConversionStep(cv1T1, VK); + // If the converted initializer is a prvalue, its type T4 is adjusted to + // type "cv1 T4" and the temporary materialization conversion is applied. + // + // We adjust the cv-qualifications to match the reference regardless of + // whether we have a prvalue so that the AST records the change. In this + // case, T4 is "cv3 T3". + QualType cv1T4 = S.Context.getQualifiedType(cv3T3, cv1T1.getQualifiers()); + if (cv1T4.getQualifiers() != cv3T3.getQualifiers()) + Sequence.AddQualificationConversionStep(cv1T4, VK); + Sequence.AddReferenceBindingStep(cv1T4, VK == VK_RValue); + VK = IsLValueRef ? VK_LValue : VK_XValue; + + if (NewDerivedToBase) + Sequence.AddDerivedToBaseCastStep(cv1T1, VK); + else if (NewObjCConversion) + Sequence.AddObjCObjectConversionStep(cv1T1); - Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType()); return OR_Success; } @@ -4146,54 +4250,11 @@ static void TryReferenceInitialization(Sema &S, T1Quals, cv2T2, T2, T2Quals, Sequence); } -/// Converts the target of reference initialization so that it has the -/// appropriate qualifiers and value kind. -/// -/// In this case, 'x' is an 'int' lvalue, but it needs to be 'const int'. -/// \code -/// int x; -/// const int &r = x; -/// \endcode -/// -/// In this case the reference is binding to a bitfield lvalue, which isn't -/// valid. Perform a load to create a lifetime-extended temporary instead. -/// \code -/// const int &r = someStruct.bitfield; -/// \endcode -static ExprValueKind -convertQualifiersAndValueKindIfNecessary(Sema &S, - InitializationSequence &Sequence, - Expr *Initializer, - QualType cv1T1, - Qualifiers T1Quals, - Qualifiers T2Quals, - bool IsLValueRef) { - bool IsNonAddressableType = Initializer->refersToBitField() || - Initializer->refersToVectorElement(); - - if (IsNonAddressableType) { - // C++11 [dcl.init.ref]p5: [...] Otherwise, the reference shall be an - // lvalue reference to a non-volatile const type, or the reference shall be - // an rvalue reference. - // - // If not, we can't make a temporary and bind to that. Give up and allow the - // error to be diagnosed later. - if (IsLValueRef && (!T1Quals.hasConst() || T1Quals.hasVolatile())) { - assert(Initializer->isGLValue()); - return Initializer->getValueKind(); - } - - // Force a load so we can materialize a temporary. - Sequence.AddLValueToRValueStep(cv1T1.getUnqualifiedType()); - return VK_RValue; - } - - if (T1Quals != T2Quals) { - Sequence.AddQualificationConversionStep(cv1T1, - Initializer->getValueKind()); - } - - return Initializer->getValueKind(); +/// Determine whether an expression is a non-referenceable glvalue (one to +/// which a reference can never bind). Attemting to bind a reference to +/// such a glvalue will always create a temporary. +static bool isNonReferenceableGLValue(Expr *E) { + return E->refersToBitField() || E->refersToVectorElement(); } /// \brief Reference initialization without resolving overloaded functions. @@ -4231,31 +4292,28 @@ static void TryReferenceInitializationCore(Sema &S, OverloadingResult ConvOvlResult = OR_Success; bool T1Function = T1->isFunctionType(); if (isLValueRef || T1Function) { - if (InitCategory.isLValue() && - (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification || + if (InitCategory.isLValue() && !isNonReferenceableGLValue(Initializer) && + (RefRelationship == Sema::Ref_Compatible || (Kind.isCStyleOrFunctionalCast() && RefRelationship == Sema::Ref_Related))) { // - is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or - // - // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a - // bit-field when we're determining whether the reference initialization - // can occur. However, we do pay attention to whether it is a bit-field - // to decide whether we're actually binding to a temporary created from - // the bit-field. + if (T1Quals != T2Quals) + // Convert to cv1 T2. This should only add qualifiers unless this is a + // c-style cast. The removal of qualifiers in that case notionally + // happens after the reference binding, but that doesn't matter. + Sequence.AddQualificationConversionStep( + S.Context.getQualifiedType(T2, T1Quals), + Initializer->getValueKind()); if (DerivedToBase) - Sequence.AddDerivedToBaseCastStep( - S.Context.getQualifiedType(T1, T2Quals), - VK_LValue); + Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue); else if (ObjCConversion) - Sequence.AddObjCObjectConversionStep( - S.Context.getQualifiedType(T1, T2Quals)); - - ExprValueKind ValueKind = - convertQualifiersAndValueKindIfNecessary(S, Sequence, Initializer, - cv1T1, T1Quals, T2Quals, - isLValueRef); - Sequence.AddReferenceBindingStep(cv1T1, ValueKind == VK_RValue); + Sequence.AddObjCObjectConversionStep(cv1T1); + + // We only create a temporary here when binding a reference to a + // bit-field or vector element. Those cases are't supposed to be + // handled by this bullet, but the outcome is the same either way. + Sequence.AddReferenceBindingStep(cv1T1, false); return; } @@ -4270,7 +4328,8 @@ static void TryReferenceInitializationCore(Sema &S, if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() && (isLValueRef || InitCategory.isRValue())) { ConvOvlResult = TryRefInitWithConversionFunction( - S, Entity, Kind, Initializer, /*AllowRValues*/isRValueRef, Sequence); + S, Entity, Kind, Initializer, /*AllowRValues*/ isRValueRef, + /*IsLValueRef*/ isLValueRef, Sequence); if (ConvOvlResult == OR_Success) return; if (ConvOvlResult != OR_No_Viable_Function) @@ -4290,28 +4349,51 @@ static void TryReferenceInitializationCore(Sema &S, Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); - else - Sequence.SetFailed(InitCategory.isLValue() - ? (RefRelationship == Sema::Ref_Related - ? InitializationSequence::FK_ReferenceInitDropsQualifiers - : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated) - : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); - + else if (!InitCategory.isLValue()) + Sequence.SetFailed( + InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); + else { + InitializationSequence::FailureKind FK; + switch (RefRelationship) { + case Sema::Ref_Compatible: + if (Initializer->refersToBitField()) + FK = InitializationSequence:: + FK_NonConstLValueReferenceBindingToBitfield; + else if (Initializer->refersToVectorElement()) + FK = InitializationSequence:: + FK_NonConstLValueReferenceBindingToVectorElement; + else + llvm_unreachable("unexpected kind of compatible initializer"); + break; + case Sema::Ref_Related: + FK = InitializationSequence::FK_ReferenceInitDropsQualifiers; + break; + case Sema::Ref_Incompatible: + FK = InitializationSequence:: + FK_NonConstLValueReferenceBindingToUnrelated; + break; + } + Sequence.SetFailed(FK); + } return; } // - If the initializer expression - // - is an xvalue, class prvalue, array prvalue, or function lvalue and - // "cv1 T1" is reference-compatible with "cv2 T2" - // Note: functions are handled below. + // - is an + // [<=14] xvalue (but not a bit-field), class prvalue, array prvalue, or + // [1z] rvalue (but not a bit-field) or + // function lvalue and "cv1 T1" is reference-compatible with "cv2 T2" + // + // Note: functions are handled above and below rather than here... if (!T1Function && - (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification || + (RefRelationship == Sema::Ref_Compatible || (Kind.isCStyleOrFunctionalCast() && RefRelationship == Sema::Ref_Related)) && - (InitCategory.isXValue() || - (InitCategory.isPRValue() && T2->isRecordType()) || - (InitCategory.isPRValue() && T2->isArrayType()))) { - ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue; + ((InitCategory.isXValue() && !isNonReferenceableGLValue(Initializer)) || + (InitCategory.isPRValue() && + (S.getLangOpts().CPlusPlus1z || T2->isRecordType() || + T2->isArrayType())))) { + ExprValueKind ValueKind = InitCategory.isXValue() ? VK_XValue : VK_RValue; if (InitCategory.isPRValue() && T2->isRecordType()) { // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the // compiler the freedom to perform a copy here or bind to the @@ -4328,19 +4410,22 @@ static void TryReferenceInitializationCore(Sema &S, CheckCXX98CompatAccessibleCopy(S, Entity, Initializer); } + // C++1z [dcl.init.ref]/5.2.1.2: + // If the converted initializer is a prvalue, its type T4 is adjusted + // to type "cv1 T4" and the temporary materialization conversion is + // applied. + QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1Quals); + if (T1Quals != T2Quals) + Sequence.AddQualificationConversionStep(cv1T4, ValueKind); + Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_RValue); + ValueKind = isLValueRef ? VK_LValue : VK_XValue; + + // In any case, the reference is bound to the resulting glvalue (or to + // an appropriate base class subobject). if (DerivedToBase) - Sequence.AddDerivedToBaseCastStep(S.Context.getQualifiedType(T1, T2Quals), - ValueKind); + Sequence.AddDerivedToBaseCastStep(cv1T1, ValueKind); else if (ObjCConversion) - Sequence.AddObjCObjectConversionStep( - S.Context.getQualifiedType(T1, T2Quals)); - - ValueKind = convertQualifiersAndValueKindIfNecessary(S, Sequence, - Initializer, cv1T1, - T1Quals, T2Quals, - isLValueRef); - - Sequence.AddReferenceBindingStep(cv1T1, ValueKind == VK_RValue); + Sequence.AddObjCObjectConversionStep(cv1T1); return; } @@ -4353,7 +4438,8 @@ static void TryReferenceInitializationCore(Sema &S, if (T2->isRecordType()) { if (RefRelationship == Sema::Ref_Incompatible) { ConvOvlResult = TryRefInitWithConversionFunction( - S, Entity, Kind, Initializer, /*AllowRValues*/true, Sequence); + S, Entity, Kind, Initializer, /*AllowRValues*/ true, + /*IsLValueRef*/ isLValueRef, Sequence); if (ConvOvlResult) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, @@ -4362,8 +4448,7 @@ static void TryReferenceInitializationCore(Sema &S, return; } - if ((RefRelationship == Sema::Ref_Compatible || - RefRelationship == Sema::Ref_Compatible_With_Added_Qualification) && + if (RefRelationship == Sema::Ref_Compatible && isRValueRef && InitCategory.isLValue()) { Sequence.SetFailed( InitializationSequence::FK_RValueReferenceBindingToLValue); @@ -4462,23 +4547,21 @@ static void TryValueInitialization(Sema &S, if (const RecordType *RT = T->getAs<RecordType>()) { if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { bool NeedZeroInitialization = true; - if (!S.getLangOpts().CPlusPlus11) { - // C++98: - // -- if T is a class type (clause 9) with a user-declared constructor - // (12.1), then the default constructor for T is called (and the - // initialization is ill-formed if T has no accessible default - // constructor); - if (ClassDecl->hasUserDeclaredConstructor()) - NeedZeroInitialization = false; - } else { - // C++11: - // -- if T is a class type (clause 9) with either no default constructor - // (12.1 [class.ctor]) or a default constructor that is user-provided - // or deleted, then the object is default-initialized; - CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl); - if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted()) - NeedZeroInitialization = false; - } + // C++98: + // -- if T is a class type (clause 9) with a user-declared constructor + // (12.1), then the default constructor for T is called (and the + // initialization is ill-formed if T has no accessible default + // constructor); + // C++11: + // -- if T is a class type (clause 9) with either no default constructor + // (12.1 [class.ctor]) or a default constructor that is user-provided + // or deleted, then the object is default-initialized; + // + // Note that the C++11 rule is the same as the C++98 rule if there are no + // defaulted or deleted constructors, so we just use it unconditionally. + CXXConstructorDecl *CD = S.LookupDefaultConstructor(ClassDecl); + if (!CD || !CD->getCanonicalDecl()->isDefaulted() || CD->isDeleted()) + NeedZeroInitialization = false; // -- if T is a (possibly cv-qualified) non-union class type without a // user-provided or deleted default constructor, then the object is @@ -4512,8 +4595,10 @@ static void TryValueInitialization(Sema &S, MultiExprArg Args(&InitListAsExpr, InitList ? 1 : 0); bool InitListSyntax = InitList; - return TryConstructorInitialization(S, Entity, Kind, Args, T, Sequence, - InitListSyntax); + // FIXME: Instead of creating a CXXConstructExpr of array type here, + // wrap a class-typed CXXConstructExpr in an ArrayInitLoopExpr. + return TryConstructorInitialization( + S, Entity, Kind, Args, T, Entity.getType(), Sequence, InitListSyntax); } } @@ -4536,7 +4621,8 @@ static void TryDefaultInitialization(Sema &S, // constructor for T is called (and the initialization is ill-formed if // T has no accessible default constructor); if (DestType->isRecordType() && S.getLangOpts().CPlusPlus) { - TryConstructorInitialization(S, Entity, Kind, None, DestType, Sequence); + TryConstructorInitialization(S, Entity, Kind, None, DestType, + Entity.getType(), Sequence); return; } @@ -4680,26 +4766,55 @@ static void TryUserDefinedConversion(Sema &S, Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType.getUnqualifiedType(), HadMultipleCandidates); + + // C++14 and before: + // - if the function is a constructor, the call initializes a temporary + // of the cv-unqualified version of the destination type. The [...] + // temporary [...] is then used to direct-initialize, according to the + // rules above, the object that is the destination of the + // copy-initialization. + // Note that this just performs a simple object copy from the temporary. + // + // C++1z: + // - if the function is a constructor, the call is a prvalue of the + // cv-unqualified version of the destination type whose return object + // is initialized by the constructor. The call is used to + // direct-initialize, according to the rules above, the object that + // is the destination of the copy-initialization. + // Therefore we need to do nothing further. + // + // FIXME: Mark this copy as extraneous. + if (!S.getLangOpts().CPlusPlus1z) + Sequence.AddFinalCopy(DestType); + else if (DestType.hasQualifiers()) + Sequence.AddQualificationConversionStep(DestType, VK_RValue); return; } // Add the user-defined conversion step that calls the conversion function. QualType ConvType = Function->getCallResultType(); + Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType, + HadMultipleCandidates); + if (ConvType->getAs<RecordType>()) { - // If we're converting to a class type, there may be an copy of - // the resulting temporary object (possible to create an object of - // a base class type). That copy is not a separate conversion, so - // we just make a note of the actual destination type (possibly a - // base class of the type returned by the conversion function) and - // let the user-defined conversion step handle the conversion. - Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType, - HadMultipleCandidates); + // The call is used to direct-initialize [...] the object that is the + // destination of the copy-initialization. + // + // In C++1z, this does not call a constructor if we enter /17.6.1: + // - If the initializer expression is a prvalue and the cv-unqualified + // version of the source type is the same as the class of the + // destination [... do not make an extra copy] + // + // FIXME: Mark this copy as extraneous. + if (!S.getLangOpts().CPlusPlus1z || + Function->getReturnType()->isReferenceType() || + !S.Context.hasSameUnqualifiedType(ConvType, DestType)) + Sequence.AddFinalCopy(DestType); + else if (!S.Context.hasSameType(ConvType, DestType)) + Sequence.AddQualificationConversionStep(DestType, VK_RValue); return; } - Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType, - HadMultipleCandidates); - // If the conversion following the call to the conversion function // is interesting, add it as a separate step. if (Best->FinalConversion.First || Best->FinalConversion.Second || @@ -4886,7 +5001,8 @@ static bool TryOCLSamplerInitialization(Sema &S, QualType DestType, Expr *Initializer) { if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() || - !Initializer->isIntegerConstantExpr(S.getASTContext())) + (!Initializer->isIntegerConstantExpr(S.Context) && + !Initializer->getType()->isSamplerT())) return false; Sequence.AddOCLSamplerInitStep(DestType); @@ -4914,6 +5030,20 @@ static bool TryOCLZeroEventInitialization(Sema &S, return true; } +static bool TryOCLZeroQueueInitialization(Sema &S, + InitializationSequence &Sequence, + QualType DestType, + Expr *Initializer) { + if (!S.getLangOpts().OpenCL || S.getLangOpts().OpenCLVersion < 200 || + !DestType->isQueueT() || + !Initializer->isIntegerConstantExpr(S.getASTContext()) || + (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0)) + return false; + + Sequence.AddOCLZeroQueueStep(DestType); + return true; +} + InitializationSequence::InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -4936,6 +5066,42 @@ static bool isExprAnUnaddressableFunction(Sema &S, const Expr *E) { cast<FunctionDecl>(DRE->getDecl())); } +/// Determine whether we can perform an elementwise array copy for this kind +/// of entity. +static bool canPerformArrayCopy(const InitializedEntity &Entity) { + switch (Entity.getKind()) { + case InitializedEntity::EK_LambdaCapture: + // C++ [expr.prim.lambda]p24: + // For array members, the array elements are direct-initialized in + // increasing subscript order. + return true; + + case InitializedEntity::EK_Variable: + // C++ [dcl.decomp]p1: + // [...] each element is copy-initialized or direct-initialized from the + // corresponding element of the assignment-expression [...] + return isa<DecompositionDecl>(Entity.getDecl()); + + case InitializedEntity::EK_Member: + // C++ [class.copy.ctor]p14: + // - if the member is an array, each element is direct-initialized with + // the corresponding subobject of x + return Entity.isImplicitMemberInitializer(); + + case InitializedEntity::EK_ArrayElement: + // All the above cases are intended to apply recursively, even though none + // of them actually say that. + if (auto *E = Entity.getParent()) + return canPerformArrayCopy(*E); + break; + + default: + break; + } + + return false; +} + void InitializationSequence::InitializeFrom(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -5058,6 +5224,34 @@ void InitializationSequence::InitializeFrom(Sema &S, } } + // Some kinds of initialization permit an array to be initialized from + // another array of the same type, and perform elementwise initialization. + if (Initializer && isa<ConstantArrayType>(DestAT) && + S.Context.hasSameUnqualifiedType(Initializer->getType(), + Entity.getType()) && + canPerformArrayCopy(Entity)) { + // If source is a prvalue, use it directly. + if (Initializer->getValueKind() == VK_RValue) { + AddArrayInitStep(DestType, /*IsGNUExtension*/false); + return; + } + + // Emit element-at-a-time copy loop. + InitializedEntity Element = + InitializedEntity::InitializeElement(S.Context, 0, Entity); + QualType InitEltT = + Context.getAsArrayType(Initializer->getType())->getElementType(); + OpaqueValueExpr OVE(Initializer->getExprLoc(), InitEltT, + Initializer->getValueKind(), + Initializer->getObjectKind()); + Expr *OVEAsExpr = &OVE; + InitializeFrom(S, Element, Kind, OVEAsExpr, TopLevelOfInitList, + TreatUnavailableAsInvalid); + if (!Failed()) + AddArrayInitLoopStep(Entity.getType(), InitEltT); + return; + } + // Note: as an GNU C extension, we allow initialization of an // array from a compound literal that creates an array of the same // type, so long as the initializer has no side effects. @@ -5071,7 +5265,7 @@ void InitializationSequence::InitializeFrom(Sema &S, else if (Initializer->HasSideEffects(S.Context)) SetFailed(FK_NonConstantArrayInit); else { - AddArrayInitStep(DestType); + AddArrayInitStep(DestType, /*IsGNUExtension*/true); } } // Note: as a GNU C++ extension, we allow list-initialization of a @@ -5112,6 +5306,9 @@ void InitializationSequence::InitializeFrom(Sema &S, if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer)) return; + if (TryOCLZeroQueueInitialization(S, *this, DestType, Initializer)) + return; + // Handle initialization in C AddCAssignmentStep(DestType); MaybeProduceObjCObject(S, *this, Entity); @@ -5131,7 +5328,7 @@ void InitializationSequence::InitializeFrom(Sema &S, (Context.hasSameUnqualifiedType(SourceType, DestType) || S.IsDerivedFrom(Initializer->getLocStart(), SourceType, DestType)))) TryConstructorInitialization(S, Entity, Kind, Args, - DestType, *this); + DestType, DestType, *this); // - Otherwise (i.e., for the remaining copy-initialization cases), // user-defined conversion sequences that can convert from the source // type to the destination type or (when a conversion function is @@ -5270,6 +5467,7 @@ getAssignmentAction(const InitializedEntity &Entity, bool Diagnose = false) { return Sema::AA_Casting; case InitializedEntity::EK_Member: + case InitializedEntity::EK_Binding: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: @@ -5305,6 +5503,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_Parameter_CF_Audited: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_RelatedResult: + case InitializedEntity::EK_Binding: return true; } @@ -5313,7 +5512,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { /// \brief Whether the given entity, when initialized with an object /// created for that initialization, requires destruction. -static bool shouldDestroyTemporary(const InitializedEntity &Entity) { +static bool shouldDestroyEntity(const InitializedEntity &Entity) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: case InitializedEntity::EK_New: @@ -5326,6 +5525,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { return false; case InitializedEntity::EK_Member: + case InitializedEntity::EK_Binding: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: @@ -5340,50 +5540,6 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { llvm_unreachable("missed an InitializedEntity kind?"); } -/// \brief Look for copy and move constructors and constructor templates, for -/// copying an object via direct-initialization (per C++11 [dcl.init]p16). -static void LookupCopyAndMoveConstructors(Sema &S, - OverloadCandidateSet &CandidateSet, - CXXRecordDecl *Class, - Expr *CurInitExpr) { - DeclContext::lookup_result R = S.LookupConstructors(Class); - // The container holding the constructors can under certain conditions - // be changed while iterating (e.g. because of deserialization). - // To be safe we copy the lookup results to a new container. - SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end()); - for (SmallVectorImpl<NamedDecl *>::iterator - CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) { - NamedDecl *D = *CI; - auto Info = getConstructorInfo(D); - if (!Info.Constructor) - continue; - - if (!Info.ConstructorTmpl) { - // Handle copy/move constructors, only. - if (Info.Constructor->isInvalidDecl() || - !Info.Constructor->isCopyOrMoveConstructor() || - !Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) - continue; - - S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, - CurInitExpr, CandidateSet); - continue; - } - - // Handle constructor templates. - if (Info.ConstructorTmpl->isInvalidDecl()) - continue; - - if (!Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) - continue; - - // FIXME: Do we need to limit this to copy-constructor-like - // candidates? - S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl, - nullptr, CurInitExpr, CandidateSet, true); - } -} - /// \brief Get the location at which initialization diagnostics should appear. static SourceLocation getInitializationLoc(const InitializedEntity &Entity, Expr *Initializer) { @@ -5395,6 +5551,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity, return Entity.getThrowLoc(); case InitializedEntity::EK_Variable: + case InitializedEntity::EK_Binding: return Entity.getDecl()->getLocation(); case InitializedEntity::EK_LambdaCapture: @@ -5453,39 +5610,24 @@ static ExprResult CopyObject(Sema &S, if (!Class) return CurInit; - // C++0x [class.copy]p32: - // When certain criteria are met, an implementation is allowed to - // omit the copy/move construction of a class object, even if the - // copy/move constructor and/or destructor for the object have - // side effects. [...] - // - when a temporary class object that has not been bound to a - // reference (12.2) would be copied/moved to a class object - // with the same cv-unqualified type, the copy/move operation - // can be omitted by constructing the temporary object - // directly into the target of the omitted copy/move - // - // Note that the other three bullets are handled elsewhere. Copy - // elision for return statements and throw expressions are handled as part - // of constructor initialization, while copy elision for exception handlers - // is handled by the run-time. - bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class); SourceLocation Loc = getInitializationLoc(Entity, CurInit.get()); // Make sure that the type we are copying is complete. if (S.RequireCompleteType(Loc, T, diag::err_temp_copy_incomplete)) return CurInit; - // Perform overload resolution using the class's copy/move constructors. - // Only consider constructors and constructor templates. Per - // C++0x [dcl.init]p16, second bullet to class types, this initialization + // Perform overload resolution using the class's constructors. Per + // C++11 [dcl.init]p16, second bullet for class types, this initialization // is direct-initialization. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - LookupCopyAndMoveConstructors(S, CandidateSet, Class, CurInitExpr); - - bool HadMultipleCandidates = (CandidateSet.size() > 1); + DeclContext::lookup_result Ctors = S.LookupConstructors(Class); OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(S, Loc, Best)) { + switch (ResolveConstructorOverload( + S, Loc, CurInitExpr, CandidateSet, Ctors, Best, + /*CopyInitializing=*/false, /*AllowExplicit=*/true, + /*OnlyListConstructors=*/false, /*IsListInit=*/false, + /*SecondStepOfCopyInit=*/true)) { case OR_Success: break; @@ -5515,6 +5657,8 @@ static ExprResult CopyObject(Sema &S, return ExprError(); } + bool HadMultipleCandidates = CandidateSet.size() > 1; + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); SmallVector<Expr*, 8> ConstructorArgs; CurInit.get(); // Ownership transferred into MultiExprArg, below. @@ -5554,6 +5698,31 @@ static ExprResult CopyObject(Sema &S, if (S.CompleteConstructorCall(Constructor, CurInitExpr, Loc, ConstructorArgs)) return ExprError(); + // C++0x [class.copy]p32: + // When certain criteria are met, an implementation is allowed to + // omit the copy/move construction of a class object, even if the + // copy/move constructor and/or destructor for the object have + // side effects. [...] + // - when a temporary class object that has not been bound to a + // reference (12.2) would be copied/moved to a class object + // with the same cv-unqualified type, the copy/move operation + // can be omitted by constructing the temporary object + // directly into the target of the omitted copy/move + // + // Note that the other three bullets are handled elsewhere. Copy + // elision for return statements and throw expressions are handled as part + // of constructor initialization, while copy elision for exception handlers + // is handled by the run-time. + // + // FIXME: If the function parameter is not the same type as the temporary, we + // should still be able to elide the copy, but we don't have a way to + // represent in the AST how much should be elided in this case. + bool Elidable = + CurInitExpr->isTemporaryObject(S.Context, Class) && + S.Context.hasSameUnqualifiedType( + Best->Function->getParamDecl(0)->getType().getNonReferenceType(), + CurInitExpr->getType()); + // Actually perform the constructor call. CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor, Elidable, @@ -5589,12 +5758,16 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, // Find constructors which would have been considered. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - LookupCopyAndMoveConstructors( - S, CandidateSet, cast<CXXRecordDecl>(Record->getDecl()), CurInitExpr); + DeclContext::lookup_result Ctors = + S.LookupConstructors(cast<CXXRecordDecl>(Record->getDecl())); // Perform overload resolution. OverloadCandidateSet::iterator Best; - OverloadingResult OR = CandidateSet.BestViableFunction(S, Loc, Best); + OverloadingResult OR = ResolveConstructorOverload( + S, Loc, CurInitExpr, CandidateSet, Ctors, Best, + /*CopyInitializing=*/false, /*AllowExplicit=*/true, + /*OnlyListConstructors=*/false, /*IsListInit=*/false, + /*SecondStepOfCopyInit=*/true); PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy) << OR << (int)Entity.getKind() << CurInitExpr->getType() @@ -5643,11 +5816,6 @@ void InitializationSequence::PrintInitLocationNote(Sema &S, << Entity.getMethodDecl()->getDeclName(); } -static bool isReferenceBinding(const InitializationSequence::Step &s) { - return s.Kind == InitializationSequence::SK_BindReference || - s.Kind == InitializationSequence::SK_BindReferenceToTemporary; -} - /// Returns true if the parameters describe a constructor initialization of /// an explicit temporary object, e.g. "Point(x, y)". static bool isExplicitTemporary(const InitializedEntity &Entity, @@ -5714,9 +5882,10 @@ PerformConstructorInitialization(Sema &S, // T as its first argument, called with a single argument in the // context of direct-initialization, explicit conversion functions // are also considered. - bool AllowExplicitConv = Kind.AllowExplicit() && !Kind.isCopyInit() && - Args.size() == 1 && - Constructor->isCopyOrMoveConstructor(); + bool AllowExplicitConv = + Kind.AllowExplicit() && !Kind.isCopyInit() && Args.size() == 1 && + hasCopyOrMoveCtorParam(S.Context, + getConstructorInfo(Step.Function.FoundDecl)); // Determine the arguments required to actually perform the constructor // call. @@ -5776,7 +5945,7 @@ PerformConstructorInitialization(Sema &S, // If the entity allows NRVO, mark the construction as elidable // unconditionally. if (Entity.allowsNRVO()) - CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + CurInit = S.BuildCXXConstructExpr(Loc, Step.Type, Step.Function.FoundDecl, Constructor, /*Elidable=*/true, ConstructorArgs, @@ -5787,7 +5956,7 @@ PerformConstructorInitialization(Sema &S, ConstructKind, ParenOrBraceRange); else - CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + CurInit = S.BuildCXXConstructExpr(Loc, Step.Type, Step.Function.FoundDecl, Constructor, ConstructorArgs, @@ -5826,6 +5995,7 @@ InitializedEntityOutlivesFullExpression(const InitializedEntity &Entity) { case InitializedEntity::EK_Result: case InitializedEntity::EK_Exception: case InitializedEntity::EK_Member: + case InitializedEntity::EK_Binding: case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_Delegating: @@ -5875,6 +6045,11 @@ static const InitializedEntity *getEntityForTemporaryLifetimeExtension( // ctor-initializer persists until the constructor exits. return Entity; + case InitializedEntity::EK_Binding: + // Per [dcl.decomp]p3, the binding is treated as a variable of reference + // type. + return Entity; + case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Parameter_CF_Audited: // -- A temporary bound to a reference parameter in a function call @@ -5949,10 +6124,7 @@ performReferenceExtension(Expr *Init, // Step over any subobject adjustments; we may have a materialized // temporary inside them. - SmallVector<const Expr *, 2> CommaLHSs; - SmallVector<SubobjectAdjustment, 2> Adjustments; - Init = const_cast<Expr *>( - Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments)); + Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments()); // Per current approach for DR1376, look through casts to reference type // when performing lifetime extension. @@ -5960,9 +6132,10 @@ performReferenceExtension(Expr *Init, if (CE->getSubExpr()->isGLValue()) Init = CE->getSubExpr(); - // FIXME: Per DR1213, subscripting on an array temporary produces an xvalue. - // It's unclear if binding a reference to that xvalue extends the array - // temporary. + // Per the current approach for DR1299, look through array element access + // when performing lifetime extension. + if (auto *ASE = dyn_cast<ArraySubscriptExpr>(Init)) + Init = ASE->getBase(); } while (Init != Old); if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) { @@ -5982,10 +6155,7 @@ performReferenceExtension(Expr *Init, static void performLifetimeExtension(Expr *Init, const InitializedEntity *ExtendingEntity) { // Dig out the expression which constructs the extended temporary. - SmallVector<const Expr *, 2> CommaLHSs; - SmallVector<SubobjectAdjustment, 2> Adjustments; - Init = const_cast<Expr *>( - Init->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments)); + Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments()); if (CXXBindTemporaryExpr *BTE = dyn_cast<CXXBindTemporaryExpr>(Init)) Init = BTE->getSubExpr(); @@ -6204,6 +6374,24 @@ Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, return MTE; } +ExprResult Sema::TemporaryMaterializationConversion(Expr *E) { + // In C++98, we don't want to implicitly create an xvalue. + // FIXME: This means that AST consumers need to deal with "prvalues" that + // denote materialized temporaries. Maybe we should add another ValueKind + // for "xvalue pretending to be a prvalue" for C++98 support. + if (!E->isRValue() || !getLangOpts().CPlusPlus11) + return E; + + // C++1z [conv.rval]/1: T shall be a complete type. + // FIXME: Does this ever matter (can we form a prvalue of incomplete type)? + // If so, we should check for a non-abstract class type here too. + QualType T = E->getType(); + if (RequireCompleteType(E->getExprLoc(), T, diag::err_incomplete_type)) + return ExprError(); + + return CreateMaterializeTemporaryExpr(E->getType(), E, false); +} + ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -6250,7 +6438,7 @@ InitializationSequence::Perform(Sema &S, SourceRange Brackets; // Scavange the location of the brackets from the entity, if we can. - if (DeclaratorDecl *DD = Entity.getDecl()) { + if (auto *DD = dyn_cast_or_null<DeclaratorDecl>(Entity.getDecl())) { if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { TypeLoc TL = TInfo->getTypeLoc(); if (IncompleteArrayTypeLoc ArrayLoc = @@ -6302,7 +6490,9 @@ InitializationSequence::Perform(Sema &S, if (Args.size() == 1 && Args[0]->getType()->isArrayType() && Entity.getType()->isPointerType() && InitializedEntityOutlivesFullExpression(Entity)) { - Expr *Init = Args[0]; + const Expr *Init = Args[0]->skipRValueSubobjectAdjustments(); + if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) + Init = MTE->GetTemporaryExpr(); Expr::LValueClassification Kind = Init->ClassifyLValue(S.Context); if (Kind == Expr::LV_ClassTemporary || Kind == Expr::LV_ArrayTemporary) S.Diag(Init->getLocStart(), diag::warn_temporary_array_to_pointer_decay) @@ -6318,6 +6508,7 @@ InitializationSequence::Perform(Sema &S, Entity.getType(); ExprResult CurInit((Expr *)nullptr); + SmallVector<Expr*, 4> ArrayLoopCommonExprs; // For initialization steps that start with a single initializer, // grab the only argument out the Args and place it into the "current" @@ -6329,6 +6520,7 @@ InitializationSequence::Perform(Sema &S, case SK_CastDerivedToBaseLValue: case SK_BindReference: case SK_BindReferenceToTemporary: + case SK_FinalCopy: case SK_ExtraneousCopyToTemporary: case SK_UserConversion: case SK_QualificationConversionLValue: @@ -6344,14 +6536,18 @@ InitializationSequence::Perform(Sema &S, case SK_CAssignment: case SK_StringInit: case SK_ObjCObjectConversion: + case SK_ArrayLoopIndex: + case SK_ArrayLoopInit: case SK_ArrayInit: + case SK_GNUArrayInit: case SK_ParenthesizedArrayInit: case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: case SK_ProduceObjCObject: case SK_StdInitializerList: case SK_OCLSamplerInit: - case SK_OCLZeroEvent: { + case SK_OCLZeroEvent: + case SK_OCLZeroQueue: { assert(Args.size() == 1); CurInit = Args[0]; if (!CurInit.get()) return ExprError(); @@ -6365,6 +6561,24 @@ InitializationSequence::Perform(Sema &S, break; } + // Promote from an unevaluated context to an unevaluated list context in + // C++11 list-initialization; we need to instantiate entities usable in + // constant expressions here in order to perform narrowing checks =( + EnterExpressionEvaluationContext Evaluated( + S, EnterExpressionEvaluationContext::InitList, + CurInit.get() && isa<InitListExpr>(CurInit.get())); + + // C++ [class.abstract]p2: + // no objects of an abstract class can be created except as subobjects + // of a class derived from it + auto checkAbstractType = [&](QualType T) -> bool { + if (Entity.getKind() == InitializedEntity::EK_Base || + Entity.getKind() == InitializedEntity::EK_Delegating) + return false; + return S.RequireNonAbstractType(Kind.getLocation(), T, + diag::err_allocation_of_abstract_type); + }; + // Walk through the computed steps for the initialization sequence, // performing the specified conversions along the way. bool ConstructorInitRequiresZeroInit = false; @@ -6416,30 +6630,6 @@ InitializationSequence::Perform(Sema &S, } case SK_BindReference: - // References cannot bind to bit-fields (C++ [dcl.init.ref]p5). - if (CurInit.get()->refersToBitField()) { - // We don't necessarily have an unambiguous source bit-field. - FieldDecl *BitField = CurInit.get()->getSourceBitField(); - S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield) - << Entity.getType().isVolatileQualified() - << (BitField ? BitField->getDeclName() : DeclarationName()) - << (BitField != nullptr) - << CurInit.get()->getSourceRange(); - if (BitField) - S.Diag(BitField->getLocation(), diag::note_bitfield_decl); - - return ExprError(); - } - - if (CurInit.get()->refersToVectorElement()) { - // References cannot bind to vector elements. - S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element) - << Entity.getType().isVolatileQualified() - << CurInit.get()->getSourceRange(); - PrintInitLocationNote(S, Entity); - return ExprError(); - } - // Reference binding does not have any corresponding ASTs. // Check exception specifications @@ -6469,15 +6659,15 @@ InitializationSequence::Perform(Sema &S, // Materialize the temporary into memory. MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( - Entity.getType().getNonReferenceType(), CurInit.get(), - Entity.getType()->isLValueReferenceType()); + Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType()); // Maybe lifetime-extend the temporary's subobjects to match the // entity's lifetime. if (const InitializedEntity *ExtendingEntity = getEntityForTemporaryLifetimeExtension(&Entity)) if (performReferenceExtension(MTE, ExtendingEntity)) - warnOnLifetimeExtension(S, Entity, CurInit.get(), /*IsInitializerList=*/false, + warnOnLifetimeExtension(S, Entity, CurInit.get(), + /*IsInitializerList=*/false, ExtendingEntity->getDecl()); // If we're binding to an Objective-C object that has lifetime, we @@ -6494,6 +6684,21 @@ InitializationSequence::Perform(Sema &S, break; } + case SK_FinalCopy: + if (checkAbstractType(Step->Type)) + return ExprError(); + + // If the overall initialization is initializing a temporary, we already + // bound our argument if it was necessary to do so. If not (if we're + // ultimately initializing a non-temporary), our argument needs to be + // bound since it's initializing a function parameter. + // FIXME: This is a mess. Rationalize temporary destruction. + if (!shouldBindAsTemporary(Entity)) + CurInit = S.MaybeBindToTemporary(CurInit.get()); + CurInit = CopyObject(S, Step->Type, Entity, CurInit, + /*IsExtraneousCopy=*/false); + break; + case SK_ExtraneousCopyToTemporary: CurInit = CopyObject(S, Step->Type, Entity, CurInit, /*IsExtraneousCopy=*/true); @@ -6503,7 +6708,6 @@ InitializationSequence::Perform(Sema &S, // We have a user-defined conversion that invokes either a constructor // or a conversion function. CastKind CastKind; - bool IsCopy = false; FunctionDecl *Fn = Step->Function.Function; DeclAccessPair FoundFn = Step->Function.FoundDecl; bool HadMultipleCandidates = Step->Function.HadMultipleCandidates; @@ -6512,7 +6716,6 @@ InitializationSequence::Perform(Sema &S, // Build a call to the selected constructor. SmallVector<Expr*, 8> ConstructorArgs; SourceLocation Loc = CurInit.get()->getLocStart(); - CurInit.get(); // Ownership transferred into MultiExprArg, below. // Determine the arguments required to actually perform the constructor // call. @@ -6541,11 +6744,6 @@ InitializationSequence::Perform(Sema &S, return ExprError(); CastKind = CK_ConstructorConversion; - QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); - if (S.Context.hasSameUnqualifiedType(SourceType, Class) || - S.IsDerivedFrom(Loc, SourceType, Class)) - IsCopy = true; - CreatedObject = true; } else { // Build a call to the conversion function. @@ -6558,29 +6756,38 @@ InitializationSequence::Perform(Sema &S, // FIXME: Should we move this initialization into a separate // derived-to-base conversion? I believe the answer is "no", because // we don't want to turn off access control here for c-style casts. - ExprResult CurInitExprRes = - S.PerformObjectArgumentInitialization(CurInit.get(), - /*Qualifier=*/nullptr, - FoundFn, Conversion); - if(CurInitExprRes.isInvalid()) + CurInit = S.PerformObjectArgumentInitialization(CurInit.get(), + /*Qualifier=*/nullptr, + FoundFn, Conversion); + if (CurInit.isInvalid()) return ExprError(); - CurInit = CurInitExprRes; // Build the actual call to the conversion function. CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion, HadMultipleCandidates); - if (CurInit.isInvalid() || !CurInit.get()) + if (CurInit.isInvalid()) return ExprError(); CastKind = CK_UserDefinedConversion; - CreatedObject = Conversion->getReturnType()->isRecordType(); } - bool RequiresCopy = !IsCopy && !isReferenceBinding(Steps.back()); - bool MaybeBindToTemp = RequiresCopy || shouldBindAsTemporary(Entity); + if (CreatedObject && checkAbstractType(CurInit.get()->getType())) + return ExprError(); + + CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(), + CastKind, CurInit.get(), nullptr, + CurInit.get()->getValueKind()); - if (!MaybeBindToTemp && CreatedObject && shouldDestroyTemporary(Entity)) { + if (shouldBindAsTemporary(Entity)) + // The overall entity is temporary, so this expression should be + // destroyed at the end of its full-expression. + CurInit = S.MaybeBindToTemporary(CurInit.getAs<Expr>()); + else if (CreatedObject && shouldDestroyEntity(Entity)) { + // The object outlasts the full-expression, but we need to prepare for + // a destructor being run on it. + // FIXME: It makes no sense to do this here. This should happen + // regardless of how we initialized the entity. QualType T = CurInit.get()->getType(); if (const RecordType *Record = T->getAs<RecordType>()) { CXXDestructorDecl *Destructor @@ -6592,15 +6799,6 @@ InitializationSequence::Perform(Sema &S, return ExprError(); } } - - CurInit = ImplicitCastExpr::Create(S.Context, CurInit.get()->getType(), - CastKind, CurInit.get(), nullptr, - CurInit.get()->getValueKind()); - if (MaybeBindToTemp) - CurInit = S.MaybeBindToTemporary(CurInit.getAs<Expr>()); - if (RequiresCopy) - CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity, - CurInit, /*IsExtraneousCopy=*/false); break; } @@ -6645,16 +6843,23 @@ InitializationSequence::Perform(Sema &S, getAssignmentAction(Entity), CCK); if (CurInitExprRes.isInvalid()) return ExprError(); + + S.DiscardMisalignedMemberAddress(Step->Type.getTypePtr(), CurInit.get()); + CurInit = CurInitExprRes; if (Step->Kind == SK_ConversionSequenceNoNarrowing && - S.getLangOpts().CPlusPlus && !CurInit.get()->isValueDependent()) + S.getLangOpts().CPlusPlus) DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(), CurInit.get()); + break; } case SK_ListInitialization: { + if (checkAbstractType(Step->Type)) + return ExprError(); + InitListExpr *InitList = cast<InitListExpr>(CurInit.get()); // If we're not initializing the top-level entity, we need to create an // InitializeTemporary entity for our target type. @@ -6691,6 +6896,9 @@ InitializationSequence::Perform(Sema &S, } case SK_ConstructorInitializationFromList: { + if (checkAbstractType(Step->Type)) + return ExprError(); + // When an initializer list is passed for a parameter of type "reference // to object", we don't get an EK_Temporary entity, but instead an // EK_Parameter entity with reference type. @@ -6734,6 +6942,9 @@ InitializationSequence::Perform(Sema &S, case SK_ConstructorInitialization: case SK_StdInitializerListConstructorCall: { + if (checkAbstractType(Step->Type)) + return ExprError(); + // When an initializer list is passed for a parameter of type "reference // to object", we don't get an EK_Temporary entity, but instead an // EK_Parameter entity with reference type. @@ -6745,13 +6956,15 @@ InitializationSequence::Perform(Sema &S, bool UseTemporary = Entity.getType()->isReferenceType(); bool IsStdInitListInit = Step->Kind == SK_StdInitializerListConstructorCall; + Expr *Source = CurInit.get(); CurInit = PerformConstructorInitialization( - S, UseTemporary ? TempEntity : Entity, Kind, Args, *Step, + S, UseTemporary ? TempEntity : Entity, Kind, + Source ? MultiExprArg(Source) : Args, *Step, ConstructorInitRequiresZeroInit, - /*IsListInitialization*/IsStdInitListInit, - /*IsStdInitListInitialization*/IsStdInitListInit, - /*LBraceLoc*/SourceLocation(), - /*RBraceLoc*/SourceLocation()); + /*IsListInitialization*/ IsStdInitListInit, + /*IsStdInitListInitialization*/ IsStdInitListInit, + /*LBraceLoc*/ SourceLocation(), + /*RBraceLoc*/ SourceLocation()); break; } @@ -6830,13 +7043,36 @@ InitializationSequence::Perform(Sema &S, CurInit.get()->getValueKind()); break; - case SK_ArrayInit: + case SK_ArrayLoopIndex: { + Expr *Cur = CurInit.get(); + Expr *BaseExpr = new (S.Context) + OpaqueValueExpr(Cur->getExprLoc(), Cur->getType(), + Cur->getValueKind(), Cur->getObjectKind(), Cur); + Expr *IndexExpr = + new (S.Context) ArrayInitIndexExpr(S.Context.getSizeType()); + CurInit = S.CreateBuiltinArraySubscriptExpr( + BaseExpr, Kind.getLocation(), IndexExpr, Kind.getLocation()); + ArrayLoopCommonExprs.push_back(BaseExpr); + break; + } + + case SK_ArrayLoopInit: { + assert(!ArrayLoopCommonExprs.empty() && + "mismatched SK_ArrayLoopIndex and SK_ArrayLoopInit"); + Expr *Common = ArrayLoopCommonExprs.pop_back_val(); + CurInit = new (S.Context) ArrayInitLoopExpr(Step->Type, Common, + CurInit.get()); + break; + } + + case SK_GNUArrayInit: // Okay: we checked everything before creating this step. Note that // this is a GNU extension. S.Diag(Kind.getLocation(), diag::ext_array_init_copy) << Step->Type << CurInit.get()->getType() << CurInit.get()->getSourceRange(); - + LLVM_FALLTHROUGH; + case SK_ArrayInit: // If the destination type is an incomplete array type, update the // type accordingly. if (ResultType) { @@ -6904,19 +7140,93 @@ InitializationSequence::Perform(Sema &S, } case SK_OCLSamplerInit: { - assert(Step->Type->isSamplerT() && + // Sampler initialzation have 5 cases: + // 1. function argument passing + // 1a. argument is a file-scope variable + // 1b. argument is a function-scope variable + // 1c. argument is one of caller function's parameters + // 2. variable initialization + // 2a. initializing a file-scope variable + // 2b. initializing a function-scope variable + // + // For file-scope variables, since they cannot be initialized by function + // call of __translate_sampler_initializer in LLVM IR, their references + // need to be replaced by a cast from their literal initializers to + // sampler type. Since sampler variables can only be used in function + // calls as arguments, we only need to replace them when handling the + // argument passing. + assert(Step->Type->isSamplerT() && "Sampler initialization on non-sampler type."); - - QualType SourceType = CurInit.get()->getType(); - + Expr *Init = CurInit.get(); + QualType SourceType = Init->getType(); + // Case 1 if (Entity.isParameterKind()) { - if (!SourceType->isSamplerT()) + if (!SourceType->isSamplerT()) { S.Diag(Kind.getLocation(), diag::err_sampler_argument_required) << SourceType; - } else if (Entity.getKind() != InitializedEntity::EK_Variable) { - llvm_unreachable("Invalid EntityKind!"); + break; + } else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init)) { + auto Var = cast<VarDecl>(DRE->getDecl()); + // Case 1b and 1c + // No cast from integer to sampler is needed. + if (!Var->hasGlobalStorage()) { + CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, + CK_LValueToRValue, Init, + /*BasePath=*/nullptr, VK_RValue); + break; + } + // Case 1a + // For function call with a file-scope sampler variable as argument, + // get the integer literal. + // Do not diagnose if the file-scope variable does not have initializer + // since this has already been diagnosed when parsing the variable + // declaration. + if (!Var->getInit() || !isa<ImplicitCastExpr>(Var->getInit())) + break; + Init = cast<ImplicitCastExpr>(const_cast<Expr*>( + Var->getInit()))->getSubExpr(); + SourceType = Init->getType(); + } + } else { + // Case 2 + // Check initializer is 32 bit integer constant. + // If the initializer is taken from global variable, do not diagnose since + // this has already been done when parsing the variable declaration. + if (!Init->isConstantInitializer(S.Context, false)) + break; + + if (!SourceType->isIntegerType() || + 32 != S.Context.getIntWidth(SourceType)) { + S.Diag(Kind.getLocation(), diag::err_sampler_initializer_not_integer) + << SourceType; + break; + } + + llvm::APSInt Result; + Init->EvaluateAsInt(Result, S.Context); + const uint64_t SamplerValue = Result.getLimitedValue(); + // 32-bit value of sampler's initializer is interpreted as + // bit-field with the following structure: + // |unspecified|Filter|Addressing Mode| Normalized Coords| + // |31 6|5 4|3 1| 0| + // This structure corresponds to enum values of sampler properties + // defined in SPIR spec v1.2 and also opencl-c.h + unsigned AddressingMode = (0x0E & SamplerValue) >> 1; + unsigned FilterMode = (0x30 & SamplerValue) >> 4; + if (FilterMode != 1 && FilterMode != 2) + S.Diag(Kind.getLocation(), + diag::warn_sampler_initializer_invalid_bits) + << "Filter Mode"; + if (AddressingMode > 4) + S.Diag(Kind.getLocation(), + diag::warn_sampler_initializer_invalid_bits) + << "Addressing Mode"; } + // Cases 1a, 2a and 2b + // Insert cast from integer to sampler. + CurInit = S.ImpCastExprToType(Init, S.Context.OCLSamplerTy, + CK_IntToOCLSampler); break; } case SK_OCLZeroEvent: { @@ -6928,6 +7238,15 @@ InitializationSequence::Perform(Sema &S, CurInit.get()->getValueKind()); break; } + case SK_OCLZeroQueue: { + assert(Step->Type->isQueueT() && + "Event initialization on non queue type."); + + CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type, + CK_ZeroToOCLQueue, + CurInit.get()->getValueKind()); + break; + } } } @@ -7190,6 +7509,25 @@ bool InitializationSequence::Diagnose(Sema &S, << Args[0]->getSourceRange(); break; + case FK_NonConstLValueReferenceBindingToBitfield: { + // We don't necessarily have an unambiguous source bit-field. + FieldDecl *BitField = Args[0]->getSourceBitField(); + S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield) + << DestType.isVolatileQualified() + << (BitField ? BitField->getDeclName() : DeclarationName()) + << (BitField != nullptr) + << Args[0]->getSourceRange(); + if (BitField) + S.Diag(BitField->getLocation(), diag::note_bitfield_decl); + break; + } + + case FK_NonConstLValueReferenceBindingToVectorElement: + S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element) + << DestType.isVolatileQualified() + << Args[0]->getSourceRange(); + break; + case FK_RValueReferenceBindingToLValue: S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref) << DestType.getNonReferenceType() << Args[0]->getType() @@ -7487,6 +7825,14 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "non-const lvalue reference bound to temporary"; break; + case FK_NonConstLValueReferenceBindingToBitfield: + OS << "non-const lvalue reference bound to bit-field"; + break; + + case FK_NonConstLValueReferenceBindingToVectorElement: + OS << "non-const lvalue reference bound to vector element"; + break; + case FK_NonConstLValueReferenceBindingToUnrelated: OS << "non-const lvalue reference bound to unrelated type"; break; @@ -7583,15 +7929,15 @@ void InitializationSequence::dump(raw_ostream &OS) const { break; case SK_CastDerivedToBaseRValue: - OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")"; + OS << "derived-to-base (rvalue)"; break; case SK_CastDerivedToBaseXValue: - OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")"; + OS << "derived-to-base (xvalue)"; break; case SK_CastDerivedToBaseLValue: - OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")"; + OS << "derived-to-base (lvalue)"; break; case SK_BindReference: @@ -7602,6 +7948,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "bind reference to a temporary"; break; + case SK_FinalCopy: + OS << "final copy in class direct-initialization"; + break; + case SK_ExtraneousCopyToTemporary: OS << "extraneous C++03 copy to temporary"; break; @@ -7678,10 +8028,22 @@ void InitializationSequence::dump(raw_ostream &OS) const { OS << "Objective-C object conversion"; break; + case SK_ArrayLoopIndex: + OS << "indexing for array initialization loop"; + break; + + case SK_ArrayLoopInit: + OS << "array initialization loop"; + break; + case SK_ArrayInit: OS << "array initialization"; break; + case SK_GNUArrayInit: + OS << "array initialization (GNU extension)"; + break; + case SK_ParenthesizedArrayInit: OS << "parenthesized array initialization"; break; @@ -7713,6 +8075,10 @@ void InitializationSequence::dump(raw_ostream &OS) const { case SK_OCLZeroEvent: OS << "OpenCL event_t from zero"; break; + + case SK_OCLZeroQueue: + OS << "OpenCL queue_t from zero"; + break; } OS << " [" << S->Type.getAsString() << ']'; @@ -7750,6 +8116,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, switch (SCS->getNarrowingKind(S.Context, PostInit, ConstantValue, ConstantType)) { case NK_Not_Narrowing: + case NK_Dependent_Narrowing: // No narrowing occurred. return; |