summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
commit2298981669bf3bd63335a4be179bc0f96823a8f4 (patch)
tree1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/Sema/SemaInit.cpp
parent9a83721404652cea39e9f02ae3e3b5c964602a5c (diff)
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r--lib/Sema/SemaInit.cpp480
1 files changed, 302 insertions, 178 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 10c0c6bf33b3..bc1069609336 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -1,9 +1,8 @@
//===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -145,16 +144,43 @@ static StringInitFailureKind IsStringInit(Expr *init, QualType declType,
static void updateStringLiteralType(Expr *E, QualType Ty) {
while (true) {
E->setType(Ty);
- if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E))
+ E->setValueKind(VK_RValue);
+ if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E)) {
break;
- else if (ParenExpr *PE = dyn_cast<ParenExpr>(E))
+ } else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
E = PE->getSubExpr();
- else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E))
+ } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ assert(UO->getOpcode() == UO_Extension);
E = UO->getSubExpr();
- else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E))
+ } else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
E = GSE->getResultExpr();
- else
+ } else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
+ E = CE->getChosenSubExpr();
+ } else {
llvm_unreachable("unexpected expr in string literal init");
+ }
+ }
+}
+
+/// Fix a compound literal initializing an array so it's correctly marked
+/// as an rvalue.
+static void updateGNUCompoundLiteralRValue(Expr *E) {
+ while (true) {
+ E->setValueKind(VK_RValue);
+ if (isa<CompoundLiteralExpr>(E)) {
+ break;
+ } else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+ E = PE->getSubExpr();
+ } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+ assert(UO->getOpcode() == UO_Extension);
+ E = UO->getSubExpr();
+ } else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
+ E = GSE->getResultExpr();
+ } else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
+ E = CE->getChosenSubExpr();
+ } else {
+ llvm_unreachable("unexpected expr in array compound literal init");
+ }
}
}
@@ -1681,6 +1707,30 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity,
}
}
+/// Check if the type of a class element has an accessible destructor, and marks
+/// it referenced. Returns true if we shouldn't form a reference to the
+/// destructor.
+///
+/// Aggregate initialization requires a class element's destructor be
+/// accessible per 11.6.1 [dcl.init.aggr]:
+///
+/// The destructor for each element of class type is potentially invoked
+/// (15.4 [class.dtor]) from the context where the aggregate initialization
+/// occurs.
+static bool checkDestructorReference(QualType ElementType, SourceLocation Loc,
+ Sema &SemaRef) {
+ auto *CXXRD = ElementType->getAsCXXRecordDecl();
+ if (!CXXRD)
+ return false;
+
+ CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(CXXRD);
+ SemaRef.CheckDestructorAccess(Loc, Destructor,
+ SemaRef.PDiag(diag::err_access_dtor_temp)
+ << ElementType);
+ SemaRef.MarkFunctionReferenced(Loc, Destructor);
+ return SemaRef.DiagnoseUseOfDecl(Destructor, Loc);
+}
+
void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
InitListExpr *IList, QualType &DeclType,
llvm::APSInt elementIndex,
@@ -1690,6 +1740,14 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
unsigned &StructuredIndex) {
const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType);
+ if (!VerifyOnly) {
+ if (checkDestructorReference(arrayType->getElementType(),
+ IList->getEndLoc(), SemaRef)) {
+ hadError = true;
+ return;
+ }
+ }
+
// Check for the special-case of initializing an array with a string.
if (Index < IList->getNumInits()) {
if (IsStringInit(IList->getInit(Index), arrayType, SemaRef.Context) ==
@@ -1851,30 +1909,6 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
return FlexArrayDiag != diag::ext_flexible_array_init;
}
-/// Check if the type of a class element has an accessible destructor.
-///
-/// Aggregate initialization requires a class element's destructor be
-/// accessible per 11.6.1 [dcl.init.aggr]:
-///
-/// The destructor for each element of class type is potentially invoked
-/// (15.4 [class.dtor]) from the context where the aggregate initialization
-/// occurs.
-static bool hasAccessibleDestructor(QualType ElementType, SourceLocation Loc,
- Sema &SemaRef) {
- auto *CXXRD = ElementType->getAsCXXRecordDecl();
- if (!CXXRD)
- return false;
-
- CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(CXXRD);
- SemaRef.CheckDestructorAccess(Loc, Destructor,
- SemaRef.PDiag(diag::err_access_dtor_temp)
- << ElementType);
- SemaRef.MarkFunctionReferenced(Loc, Destructor);
- if (SemaRef.DiagnoseUseOfDecl(Destructor, Loc))
- return true;
- return false;
-}
-
void InitListChecker::CheckStructUnionTypes(
const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType,
CXXRecordDecl::base_class_range Bases, RecordDecl::field_iterator Field,
@@ -1898,7 +1932,7 @@ void InitListChecker::CheckStructUnionTypes(
if (!VerifyOnly)
for (FieldDecl *FD : RD->fields()) {
QualType ET = SemaRef.Context.getBaseElementType(FD->getType());
- if (hasAccessibleDestructor(ET, IList->getEndLoc(), SemaRef)) {
+ if (checkDestructorReference(ET, IList->getEndLoc(), SemaRef)) {
hadError = true;
return;
}
@@ -1958,7 +1992,7 @@ void InitListChecker::CheckStructUnionTypes(
}
if (!VerifyOnly)
- if (hasAccessibleDestructor(Base.getType(), InitLoc, SemaRef)) {
+ if (checkDestructorReference(Base.getType(), InitLoc, SemaRef)) {
hadError = true;
return;
}
@@ -2000,7 +2034,7 @@ void InitListChecker::CheckStructUnionTypes(
while (std::next(F) != Field)
++F;
QualType ET = SemaRef.Context.getBaseElementType(F->getType());
- if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) {
+ if (checkDestructorReference(ET, InitLoc, SemaRef)) {
hadError = true;
return;
}
@@ -2049,7 +2083,7 @@ void InitListChecker::CheckStructUnionTypes(
if (!VerifyOnly) {
QualType ET = SemaRef.Context.getBaseElementType(Field->getType());
- if (hasAccessibleDestructor(ET, InitLoc, SemaRef)) {
+ if (checkDestructorReference(ET, InitLoc, SemaRef)) {
hadError = true;
return;
}
@@ -2105,7 +2139,7 @@ void InitListChecker::CheckStructUnionTypes(
: Field;
for (RecordDecl::field_iterator E = RD->field_end(); I != E; ++I) {
QualType ET = SemaRef.Context.getBaseElementType(I->getType());
- if (hasAccessibleDestructor(ET, IList->getEndLoc(), SemaRef)) {
+ if (checkDestructorReference(ET, IList->getEndLoc(), SemaRef)) {
hadError = true;
return;
}
@@ -2182,7 +2216,7 @@ namespace {
// Callback to only accept typo corrections that are for field members of
// the given struct or union.
-class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
+class FieldInitializerValidatorCCC final : public CorrectionCandidateCallback {
public:
explicit FieldInitializerValidatorCCC(RecordDecl *RD)
: Record(RD) {}
@@ -2192,6 +2226,10 @@ class FieldInitializerValidatorCCC : public CorrectionCandidateCallback {
return FD && FD->getDeclContext()->getRedeclContext()->Equals(Record);
}
+ std::unique_ptr<CorrectionCandidateCallback> clone() override {
+ return llvm::make_unique<FieldInitializerValidatorCCC>(*this);
+ }
+
private:
RecordDecl *Record;
};
@@ -2394,10 +2432,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
// Name lookup didn't find anything.
// Determine whether this was a typo for another field name.
+ FieldInitializerValidatorCCC CCC(RT->getDecl());
if (TypoCorrection Corrected = SemaRef.CorrectTypo(
DeclarationNameInfo(FieldName, D->getFieldLoc()),
- Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr,
- llvm::make_unique<FieldInitializerValidatorCCC>(RT->getDecl()),
+ Sema::LookupMemberName, /*Scope=*/nullptr, /*SS=*/nullptr, CCC,
Sema::CTK_ErrorRecovery, RT->getDecl())) {
SemaRef.diagnoseTypo(
Corrected,
@@ -3244,7 +3282,6 @@ void InitializationSequence::Step::Destroy() {
case SK_QualificationConversionXValue:
case SK_QualificationConversionLValue:
case SK_AtomicConversion:
- case SK_LValueToRValue:
case SK_ListInitialization:
case SK_UnwrapInitList:
case SK_RewrapInitList:
@@ -3306,6 +3343,7 @@ bool InitializationSequence::isAmbiguous() const {
case FK_NonConstLValueReferenceBindingToVectorElement:
case FK_NonConstLValueReferenceBindingToUnrelated:
case FK_RValueReferenceBindingToLValue:
+ case FK_ReferenceAddrspaceMismatchTemporary:
case FK_ReferenceInitDropsQualifiers:
case FK_ReferenceInitFailed:
case FK_ConversionFailed:
@@ -3427,15 +3465,6 @@ void InitializationSequence::AddAtomicConversionStep(QualType Ty) {
Steps.push_back(S);
}
-void InitializationSequence::AddLValueToRValueStep(QualType Ty) {
- assert(!Ty.hasQualifiers() && "rvalues may not have qualifiers");
-
- Step S;
- S.Kind = SK_LValueToRValue;
- S.Type = Ty;
- Steps.push_back(S);
-}
-
void InitializationSequence::AddConversionSequenceStep(
const ImplicitConversionSequence &ICS, QualType T,
bool TopLevelOfInitList) {
@@ -3704,6 +3733,7 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
bool OnlyListConstructors, bool IsListInit,
bool SecondStepOfCopyInit = false) {
CandidateSet.clear(OverloadCandidateSet::CSK_InitByConstructor);
+ CandidateSet.setDestAS(DestType.getQualifiers().getAddressSpace());
for (NamedDecl *D : Ctors) {
auto Info = getConstructorInfo(D);
@@ -3733,9 +3763,10 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
hasCopyOrMoveCtorParam(S.Context, Info));
if (Info.ConstructorTmpl)
- S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
- /*ExplicitArgs*/ nullptr, Args,
- CandidateSet, SuppressUserConversions);
+ S.AddTemplateOverloadCandidate(
+ Info.ConstructorTmpl, Info.FoundDecl,
+ /*ExplicitArgs*/ nullptr, Args, CandidateSet, SuppressUserConversions,
+ /*PartialOverloading=*/false, AllowExplicit);
else {
// C++ [over.match.copy]p1:
// - When initializing a temporary to be bound to the first parameter
@@ -3749,8 +3780,8 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
hasCopyOrMoveCtorParam(S.Context, Info);
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
CandidateSet, SuppressUserConversions,
- /*PartialOverloading=*/false,
- /*AllowExplicit=*/AllowExplicitConv);
+ /*PartialOverloading=*/false, AllowExplicit,
+ AllowExplicitConv);
}
}
@@ -3783,16 +3814,17 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
else
Conv = cast<CXXConversionDecl>(D);
- if ((AllowExplicit && !CopyInitializing) || !Conv->isExplicit()) {
+ if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
- S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
- ActingDC, Initializer, DestType,
- CandidateSet, AllowExplicit,
- /*AllowResultConversion*/false);
+ S.AddTemplateConversionCandidate(
+ ConvTemplate, I.getPair(), ActingDC, Initializer, DestType,
+ CandidateSet, AllowExplicit, AllowExplicit,
+ /*AllowResultConversion*/ false);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer,
DestType, CandidateSet, AllowExplicit,
- /*AllowResultConversion*/false);
+ AllowExplicit,
+ /*AllowResultConversion*/ false);
}
}
}
@@ -3899,7 +3931,7 @@ static void TryConstructorInitialization(Sema &S,
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args,
CandidateSet, DestType, Ctors, Best,
CopyInitialization, AllowExplicit,
- /*OnlyListConstructor=*/true,
+ /*OnlyListConstructors=*/true,
IsListInit);
}
@@ -4086,7 +4118,7 @@ static void TryReferenceListInitialization(Sema &S,
if (Sequence) {
if (DestType->isRValueReferenceType() ||
(T1Quals.hasConst() && !T1Quals.hasVolatile()))
- Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+ Sequence.AddReferenceBindingStep(cv1T1, /*BindingTemporary=*/true);
else
Sequence.SetFailed(
InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
@@ -4338,14 +4370,16 @@ static OverloadingResult TryRefInitWithConversionFunction(
if (!Info.Constructor->isInvalidDecl() &&
Info.Constructor->isConvertingConstructor(AllowExplicitCtors)) {
if (Info.ConstructorTmpl)
- S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
- /*ExplicitArgs*/ nullptr,
- Initializer, CandidateSet,
- /*SuppressUserConversions=*/true);
+ S.AddTemplateOverloadCandidate(
+ Info.ConstructorTmpl, Info.FoundDecl,
+ /*ExplicitArgs*/ nullptr, Initializer, CandidateSet,
+ /*SuppressUserConversions=*/true,
+ /*PartialOverloading*/ false, AllowExplicitCtors);
else
- S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
- Initializer, CandidateSet,
- /*SuppressUserConversions=*/true);
+ S.AddOverloadCandidate(
+ Info.Constructor, Info.FoundDecl, Initializer, CandidateSet,
+ /*SuppressUserConversions=*/true,
+ /*PartialOverloading*/ false, AllowExplicitCtors);
}
}
}
@@ -4380,17 +4414,17 @@ static OverloadingResult TryRefInitWithConversionFunction(
// candidates with reference-compatible results? That might be needed to
// break recursion.
if ((AllowExplicitConvs || !Conv->isExplicit()) &&
- (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
+ (AllowRValues ||
+ Conv->getConversionType()->isLValueReferenceType())) {
if (ConvTemplate)
- S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
- ActingDC, Initializer,
- DestType, CandidateSet,
- /*AllowObjCConversionOnExplicit=*/
- false);
+ S.AddTemplateConversionCandidate(
+ ConvTemplate, I.getPair(), ActingDC, Initializer, DestType,
+ CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs);
else
- S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
- Initializer, DestType, CandidateSet,
- /*AllowObjCConversionOnExplicit=*/false);
+ S.AddConversionCandidate(
+ Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet,
+ /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs);
}
}
}
@@ -4597,7 +4631,10 @@ static void TryReferenceInitializationCore(Sema &S,
// - Otherwise, the reference shall be an lvalue reference to a
// non-volatile const type (i.e., cv1 shall be const), or the reference
// shall be an rvalue reference.
- if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) {
+ // For address spaces, we interpret this to mean that an addr space
+ // of a reference "cv1 T1" is a superset of addr space of "cv2 T2".
+ if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile() &&
+ T1Quals.isAddressSpaceSupersetOf(T2Quals))) {
if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy)
Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
@@ -4606,7 +4643,10 @@ static void TryReferenceInitializationCore(Sema &S,
ConvOvlResult);
else if (!InitCategory.isLValue())
Sequence.SetFailed(
- InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
+ T1Quals.isAddressSpaceSupersetOf(T2Quals)
+ ? InitializationSequence::
+ FK_NonConstLValueReferenceBindingToTemporary
+ : InitializationSequence::FK_ReferenceInitDropsQualifiers);
else {
InitializationSequence::FailureKind FK;
switch (RefRelationship) {
@@ -4671,19 +4711,23 @@ static void TryReferenceInitializationCore(Sema &S,
// applied.
// Postpone address space conversions to after the temporary materialization
// conversion to allow creating temporaries in the alloca address space.
- auto AS1 = T1Quals.getAddressSpace();
- auto AS2 = T2Quals.getAddressSpace();
- T1Quals.removeAddressSpace();
- T2Quals.removeAddressSpace();
- QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1Quals);
- if (T1Quals != T2Quals)
+ auto T1QualsIgnoreAS = T1Quals;
+ auto T2QualsIgnoreAS = T2Quals;
+ if (T1Quals.getAddressSpace() != T2Quals.getAddressSpace()) {
+ T1QualsIgnoreAS.removeAddressSpace();
+ T2QualsIgnoreAS.removeAddressSpace();
+ }
+ QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1QualsIgnoreAS);
+ if (T1QualsIgnoreAS != T2QualsIgnoreAS)
Sequence.AddQualificationConversionStep(cv1T4, ValueKind);
Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_RValue);
ValueKind = isLValueRef ? VK_LValue : VK_XValue;
- if (AS1 != AS2) {
- T1Quals.addAddressSpace(AS1);
- QualType cv1AST4 = S.Context.getQualifiedType(cv2T2, T1Quals);
- Sequence.AddQualificationConversionStep(cv1AST4, ValueKind);
+ // Add addr space conversion if required.
+ if (T1Quals.getAddressSpace() != T2Quals.getAddressSpace()) {
+ auto T4Quals = cv1T4.getQualifiers();
+ T4Quals.addAddressSpace(T1Quals.getAddressSpace());
+ QualType cv1T4WithAS = S.Context.getQualifiedType(T2, T4Quals);
+ Sequence.AddQualificationConversionStep(cv1T4WithAS, ValueKind);
}
// In any case, the reference is bound to the resulting glvalue (or to
@@ -4730,7 +4774,15 @@ static void TryReferenceInitializationCore(Sema &S,
// copy-initialization (8.5). The reference is then bound to the
// temporary. [...]
- InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
+ // Ignore address space of reference type at this point and perform address
+ // space conversion after the reference binding step.
+ QualType cv1T1IgnoreAS =
+ T1Quals.hasAddressSpace()
+ ? S.Context.getQualifiedType(T1, T1Quals.withoutAddressSpace())
+ : cv1T1;
+
+ InitializedEntity TempEntity =
+ InitializedEntity::InitializeTemporary(cv1T1IgnoreAS);
// FIXME: Why do we use an implicit conversion here rather than trying
// copy-initialization?
@@ -4765,8 +4817,9 @@ static void TryReferenceInitializationCore(Sema &S,
// than, cv2; otherwise, the program is ill-formed.
unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
- if (RefRelationship == Sema::Ref_Related &&
- (T1CVRQuals | T2CVRQuals) != T1CVRQuals) {
+ if ((RefRelationship == Sema::Ref_Related &&
+ (T1CVRQuals | T2CVRQuals) != T1CVRQuals) ||
+ !T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
return;
}
@@ -4780,7 +4833,18 @@ static void TryReferenceInitializationCore(Sema &S,
return;
}
- Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+ Sequence.AddReferenceBindingStep(cv1T1IgnoreAS, /*BindingTemporary=*/true);
+
+ if (T1Quals.hasAddressSpace()) {
+ if (!Qualifiers::isAddressSpaceSupersetOf(T1Quals.getAddressSpace(),
+ LangAS::Default)) {
+ Sequence.SetFailed(
+ InitializationSequence::FK_ReferenceAddrspaceMismatchTemporary);
+ return;
+ }
+ Sequence.AddQualificationConversionStep(cv1T1, isLValueRef ? VK_LValue
+ : VK_XValue);
+ }
}
/// Attempt character array initialization from a string literal
@@ -4928,6 +4992,7 @@ static void TryUserDefinedConversion(Sema &S,
// structure, so that it will persist if we fail.
OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
+ CandidateSet.setDestAS(DestType.getQualifiers().getAddressSpace());
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
@@ -4949,14 +5014,16 @@ static void TryUserDefinedConversion(Sema &S,
if (!Info.Constructor->isInvalidDecl() &&
Info.Constructor->isConvertingConstructor(AllowExplicit)) {
if (Info.ConstructorTmpl)
- S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
- /*ExplicitArgs*/ nullptr,
- Initializer, CandidateSet,
- /*SuppressUserConversions=*/true);
+ S.AddTemplateOverloadCandidate(
+ Info.ConstructorTmpl, Info.FoundDecl,
+ /*ExplicitArgs*/ nullptr, Initializer, CandidateSet,
+ /*SuppressUserConversions=*/true,
+ /*PartialOverloading*/ false, AllowExplicit);
else
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
Initializer, CandidateSet,
- /*SuppressUserConversions=*/true);
+ /*SuppressUserConversions=*/true,
+ /*PartialOverloading*/ false, AllowExplicit);
}
}
}
@@ -4991,12 +5058,12 @@ static void TryUserDefinedConversion(Sema &S,
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
- S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
- ActingDC, Initializer, DestType,
- CandidateSet, AllowExplicit);
+ S.AddTemplateConversionCandidate(
+ ConvTemplate, I.getPair(), ActingDC, Initializer, DestType,
+ CandidateSet, AllowExplicit, AllowExplicit);
else
- S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
- Initializer, DestType, CandidateSet,
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Initializer,
+ DestType, CandidateSet, AllowExplicit,
AllowExplicit);
}
}
@@ -5538,8 +5605,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
// array from a compound literal that creates an array of the same
// type, so long as the initializer has no side effects.
if (!S.getLangOpts().CPlusPlus && Initializer &&
- (isa<ConstantExpr>(Initializer->IgnoreParens()) ||
- isa<CompoundLiteralExpr>(Initializer->IgnoreParens())) &&
+ isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) &&
Initializer->getType()->isArrayType()) {
const ArrayType *SourceAT
= Context.getAsArrayType(Initializer->getType());
@@ -5574,6 +5640,9 @@ void InitializationSequence::InitializeFrom(Sema &S,
bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount &&
Entity.isParameterKind();
+ if (TryOCLSamplerInitialization(S, *this, DestType, Initializer))
+ return;
+
// We're at the end of the line for C: it's either a write-back conversion
// or it's a C assignment. There's no need to check anything else.
if (!S.getLangOpts().CPlusPlus) {
@@ -5583,9 +5652,6 @@ void InitializationSequence::InitializeFrom(Sema &S,
return;
}
- if (TryOCLSamplerInitialization(S, *this, DestType, Initializer))
- return;
-
if (TryOCLZeroOpaqueTypeInitialization(S, *this, DestType, Initializer))
return;
@@ -5925,21 +5991,25 @@ static ExprResult CopyObject(Sema &S,
break;
case OR_No_Viable_Function:
- S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext()
- ? diag::ext_rvalue_to_reference_temp_copy_no_viable
- : diag::err_temp_copy_no_viable)
- << (int)Entity.getKind() << CurInitExpr->getType()
- << CurInitExpr->getSourceRange();
- CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr);
+ CandidateSet.NoteCandidates(
+ PartialDiagnosticAt(
+ Loc, S.PDiag(IsExtraneousCopy && !S.isSFINAEContext()
+ ? diag::ext_rvalue_to_reference_temp_copy_no_viable
+ : diag::err_temp_copy_no_viable)
+ << (int)Entity.getKind() << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange()),
+ S, OCD_AllCandidates, CurInitExpr);
if (!IsExtraneousCopy || S.isSFINAEContext())
return ExprError();
return CurInit;
case OR_Ambiguous:
- S.Diag(Loc, diag::err_temp_copy_ambiguous)
- << (int)Entity.getKind() << CurInitExpr->getType()
- << CurInitExpr->getSourceRange();
- CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr);
+ CandidateSet.NoteCandidates(
+ PartialDiagnosticAt(Loc, S.PDiag(diag::err_temp_copy_ambiguous)
+ << (int)Entity.getKind()
+ << CurInitExpr->getType()
+ << CurInitExpr->getSourceRange()),
+ S, OCD_ViableCandidates, CurInitExpr);
return ExprError();
case OR_Deleted:
@@ -6074,13 +6144,13 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S,
break;
case OR_No_Viable_Function:
- S.Diag(Loc, Diag);
- CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr);
+ CandidateSet.NoteCandidates(PartialDiagnosticAt(Loc, Diag), S,
+ OCD_AllCandidates, CurInitExpr);
break;
case OR_Ambiguous:
- S.Diag(Loc, Diag);
- CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr);
+ CandidateSet.NoteCandidates(PartialDiagnosticAt(Loc, Diag), S,
+ OCD_ViableCandidates, CurInitExpr);
break;
case OR_Deleted:
@@ -6269,6 +6339,10 @@ PerformConstructorInitialization(Sema &S,
if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc))
return ExprError();
+ if (const ArrayType *AT = S.Context.getAsArrayType(Entity.getType()))
+ if (checkDestructorReference(S.Context.getBaseElementType(AT), Loc, S))
+ return ExprError();
+
if (shouldBindAsTemporary(Entity))
CurInit = S.MaybeBindToTemporary(CurInit.get());
@@ -6784,6 +6858,9 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
RK_ReferenceBinding, Visit);
else {
unsigned Index = 0;
+ for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
+ visitLocalsRetainedByInitializer(Path, ILE->getInit(Index), Visit,
+ RevisitSubinits);
for (const auto *I : RD->fields()) {
if (Index >= ILE->getNumInits())
break;
@@ -7275,9 +7352,19 @@ ExprResult Sema::TemporaryMaterializationConversion(Expr *E) {
ExprResult Sema::PerformQualificationConversion(Expr *E, QualType Ty,
ExprValueKind VK,
CheckedConversionKind CCK) {
- CastKind CK = (Ty.getAddressSpace() != E->getType().getAddressSpace())
- ? CK_AddressSpaceConversion
- : CK_NoOp;
+
+ CastKind CK = CK_NoOp;
+
+ if (VK == VK_RValue) {
+ auto PointeeTy = Ty->getPointeeType();
+ auto ExprPointeeTy = E->getType()->getPointeeType();
+ if (!PointeeTy.isNull() &&
+ PointeeTy.getAddressSpace() != ExprPointeeTy.getAddressSpace())
+ CK = CK_AddressSpaceConversion;
+ } else if (Ty.getAddressSpace() != E->getType().getAddressSpace()) {
+ CK = CK_AddressSpaceConversion;
+ }
+
return ImpCastExprToType(E, Ty, CK, VK, /*BasePath=*/nullptr, CCK);
}
@@ -7416,7 +7503,6 @@ ExprResult InitializationSequence::Perform(Sema &S,
case SK_QualificationConversionXValue:
case SK_QualificationConversionRValue:
case SK_AtomicConversion:
- case SK_LValueToRValue:
case SK_ConversionSequence:
case SK_ConversionSequenceNoNarrowing:
case SK_ListInitialization:
@@ -7688,14 +7774,6 @@ ExprResult InitializationSequence::Perform(Sema &S,
break;
}
- case SK_LValueToRValue: {
- assert(CurInit.get()->isGLValue() && "cannot load from a prvalue");
- CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,
- CK_LValueToRValue, CurInit.get(),
- /*BasePath=*/nullptr, VK_RValue);
- break;
- }
-
case SK_ConversionSequence:
case SK_ConversionSequenceNoNarrowing: {
if (const auto *FromPtrType =
@@ -7952,6 +8030,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
<< Step->Type << CurInit.get()->getType()
<< CurInit.get()->getSourceRange();
+ updateGNUCompoundLiteralRValue(CurInit.get());
LLVM_FALLTHROUGH;
case SK_ArrayInit:
// If the destination type is an incomplete array type, update the
@@ -8342,19 +8421,22 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_UserConversionOverloadFailed:
switch (FailedOverloadResult) {
case OR_Ambiguous:
- if (Failure == FK_UserConversionOverloadFailed)
- S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
- << OnlyArg->getType() << DestType
- << Args[0]->getSourceRange();
- else
- S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
- << DestType << OnlyArg->getType()
- << Args[0]->getSourceRange();
- FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args);
+ FailedCandidateSet.NoteCandidates(
+ PartialDiagnosticAt(
+ Kind.getLocation(),
+ Failure == FK_UserConversionOverloadFailed
+ ? (S.PDiag(diag::err_typecheck_ambiguous_condition)
+ << OnlyArg->getType() << DestType
+ << Args[0]->getSourceRange())
+ : (S.PDiag(diag::err_ref_init_ambiguous)
+ << DestType << OnlyArg->getType()
+ << Args[0]->getSourceRange())),
+ S, OCD_ViableCandidates, Args);
break;
- case OR_No_Viable_Function:
+ case OR_No_Viable_Function: {
+ auto Cands = FailedCandidateSet.CompleteCandidates(S, OCD_AllCandidates, Args);
if (!S.RequireCompleteType(Kind.getLocation(),
DestType.getNonReferenceType(),
diag::err_typecheck_nonviable_condition_incomplete,
@@ -8364,9 +8446,9 @@ bool InitializationSequence::Diagnose(Sema &S,
<< OnlyArg->getType() << Args[0]->getSourceRange()
<< DestType.getNonReferenceType();
- FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
+ FailedCandidateSet.NoteCandidates(S, Args, Cands);
break;
-
+ }
case OR_Deleted: {
S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
<< OnlyArg->getType() << DestType.getNonReferenceType()
@@ -8434,23 +8516,34 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getSourceRange();
break;
+ case FK_ReferenceAddrspaceMismatchTemporary:
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_temporary_addrspace)
+ << DestType << Args[0]->getSourceRange();
+ break;
+
case FK_ReferenceInitDropsQualifiers: {
QualType SourceType = OnlyArg->getType();
QualType NonRefType = DestType.getNonReferenceType();
Qualifiers DroppedQualifiers =
SourceType.getQualifiers() - NonRefType.getQualifiers();
- S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
- << SourceType
- << NonRefType
- << DroppedQualifiers.getCVRQualifiers()
- << Args[0]->getSourceRange();
+ if (!NonRefType.getQualifiers().isAddressSpaceSupersetOf(
+ SourceType.getQualifiers()))
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+ << NonRefType << SourceType << 1 /*addr space*/
+ << Args[0]->getSourceRange();
+ else
+ S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+ << NonRefType << SourceType << 0 /*cv quals*/
+ << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers())
+ << DroppedQualifiers.getCVRQualifiers() << Args[0]->getSourceRange();
break;
}
case FK_ReferenceInitFailed:
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
<< DestType.getNonReferenceType()
+ << DestType.getNonReferenceType()->isIncompleteType()
<< OnlyArg->isLValue()
<< OnlyArg->getType()
<< Args[0]->getSourceRange();
@@ -8529,9 +8622,11 @@ bool InitializationSequence::Diagnose(Sema &S,
// bad.
switch (FailedOverloadResult) {
case OR_Ambiguous:
- S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init)
- << DestType << ArgsRange;
- FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args);
+ FailedCandidateSet.NoteCandidates(
+ PartialDiagnosticAt(Kind.getLocation(),
+ S.PDiag(diag::err_ovl_ambiguous_init)
+ << DestType << ArgsRange),
+ S, OCD_ViableCandidates, Args);
break;
case OR_No_Viable_Function:
@@ -8580,9 +8675,12 @@ bool InitializationSequence::Diagnose(Sema &S,
break;
}
- S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
- << DestType << ArgsRange;
- FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
+ FailedCandidateSet.NoteCandidates(
+ PartialDiagnosticAt(
+ Kind.getLocation(),
+ S.PDiag(diag::err_ovl_no_viable_function_in_init)
+ << DestType << ArgsRange),
+ S, OCD_AllCandidates, Args);
break;
case OR_Deleted: {
@@ -8591,7 +8689,7 @@ bool InitializationSequence::Diagnose(Sema &S,
= FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
if (Ovl != OR_Deleted) {
S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
- << true << DestType << ArgsRange;
+ << DestType << ArgsRange;
llvm_unreachable("Inconsistent overload resolution?");
break;
}
@@ -8605,7 +8703,7 @@ bool InitializationSequence::Diagnose(Sema &S,
<< DestType << ArgsRange;
else
S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
- << true << DestType << ArgsRange;
+ << DestType << ArgsRange;
S.NoteDeletedFunction(Best->Function);
break;
@@ -8763,6 +8861,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "reference initialization drops qualifiers";
break;
+ case FK_ReferenceAddrspaceMismatchTemporary:
+ OS << "reference with mismatching address space bound to temporary";
+ break;
+
case FK_ReferenceInitFailed:
OS << "reference initialization failed";
break;
@@ -8898,10 +9000,6 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "non-atomic-to-atomic conversion";
break;
- case SK_LValueToRValue:
- OS << "load (lvalue to rvalue)";
- break;
-
case SK_ConversionSequence:
OS << "implicit conversion sequence (";
S->ICS->dump(); // FIXME: use OS
@@ -9264,9 +9362,15 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
OverloadCandidateSet Candidates(Kind.getLocation(),
OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
+
+ bool HasAnyDeductionGuide = false;
+ bool AllowExplicit = !Kind.isCopyInit() || ListInit;
+
auto tryToResolveOverload =
[&](bool OnlyListConstructors) -> OverloadingResult {
Candidates.clear(OverloadCandidateSet::CSK_Normal);
+ HasAnyDeductionGuide = false;
+
for (auto I = Guides.begin(), E = Guides.end(); I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
if (D->isInvalidDecl())
@@ -9278,12 +9382,15 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
if (!GD)
continue;
+ if (!GD->isImplicit())
+ HasAnyDeductionGuide = true;
+
// C++ [over.match.ctor]p1: (non-list copy-initialization from non-class)
// For copy-initialization, the candidate functions are all the
// converting constructors (12.3.1) of that class.
// C++ [over.match.copy]p1: (non-list copy-initialization from class)
// The converting constructors of T are candidate functions.
- if (Kind.isCopyInit() && !ListInit) {
+ if (!AllowExplicit) {
// Only consider converting constructors.
if (GD->isExplicit())
continue;
@@ -9318,11 +9425,13 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
if (TD)
AddTemplateOverloadCandidate(TD, I.getPair(), /*ExplicitArgs*/ nullptr,
- Inits, Candidates,
- SuppressUserConversions);
+ Inits, Candidates, SuppressUserConversions,
+ /*PartialOverloading*/ false,
+ AllowExplicit);
else
AddOverloadCandidate(GD, I.getPair(), Inits, Candidates,
- SuppressUserConversions);
+ SuppressUserConversions,
+ /*PartialOverloading*/ false, AllowExplicit);
}
return Candidates.BestViableFunction(*this, Kind.getLocation(), Best);
};
@@ -9372,12 +9481,15 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
switch (Result) {
case OR_Ambiguous:
- Diag(Kind.getLocation(), diag::err_deduced_class_template_ctor_ambiguous)
- << TemplateName;
// FIXME: For list-initialization candidates, it'd usually be better to
// list why they were not viable when given the initializer list itself as
// an argument.
- Candidates.NoteCandidates(*this, OCD_ViableCandidates, Inits);
+ Candidates.NoteCandidates(
+ PartialDiagnosticAt(
+ Kind.getLocation(),
+ PDiag(diag::err_deduced_class_template_ctor_ambiguous)
+ << TemplateName),
+ *this, OCD_ViableCandidates, Inits);
return QualType();
case OR_No_Viable_Function: {
@@ -9385,11 +9497,13 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
cast<ClassTemplateDecl>(Template)->getTemplatedDecl();
bool Complete =
isCompleteType(Kind.getLocation(), Context.getTypeDeclType(Primary));
- Diag(Kind.getLocation(),
- Complete ? diag::err_deduced_class_template_ctor_no_viable
- : diag::err_deduced_class_template_incomplete)
- << TemplateName << !Guides.empty();
- Candidates.NoteCandidates(*this, OCD_AllCandidates, Inits);
+ Candidates.NoteCandidates(
+ PartialDiagnosticAt(
+ Kind.getLocation(),
+ PDiag(Complete ? diag::err_deduced_class_template_ctor_no_viable
+ : diag::err_deduced_class_template_incomplete)
+ << TemplateName << !Guides.empty()),
+ *this, OCD_AllCandidates, Inits);
return QualType();
}
@@ -9430,5 +9544,15 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
Diag(TSInfo->getTypeLoc().getBeginLoc(),
diag::warn_cxx14_compat_class_template_argument_deduction)
<< TSInfo->getTypeLoc().getSourceRange() << 1 << DeducedType;
+
+ // Warn if CTAD was used on a type that does not have any user-defined
+ // deduction guides.
+ if (!HasAnyDeductionGuide) {
+ Diag(TSInfo->getTypeLoc().getBeginLoc(),
+ diag::warn_ctad_maybe_unsupported)
+ << TemplateName;
+ Diag(Template->getLocation(), diag::note_suppress_ctad_maybe_unsupported);
+ }
+
return DeducedType;
}