summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp1201
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;
OpenPOWER on IntegriCloud