diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
commit | 2298981669bf3bd63335a4be179bc0f96823a8f4 (patch) | |
tree | 1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/Sema/SemaInit.cpp | |
parent | 9a83721404652cea39e9f02ae3e3b5c964602a5c (diff) |
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 480 |
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; } |