diff options
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 284 |
1 files changed, 141 insertions, 143 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 32c9215184eb..5ca6b232df66 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -15,9 +15,11 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" +#include "clang/AST/IgnoreExpr.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/Designator.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" @@ -91,7 +93,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, }; switch (SL->getKind()) { - case StringLiteral::UTF8: + case StringLiteralKind::UTF8: // char8_t array can be initialized with a UTF-8 string. // - C++20 [dcl.init.string] (DR) // Additionally, an array of char or unsigned char may be initialized @@ -101,11 +103,11 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, IsCharOrUnsignedChar(ElemTy.getCanonicalType()))) return SIF_None; [[fallthrough]]; - case StringLiteral::Ordinary: + case StringLiteralKind::Ordinary: // char array can be initialized with a narrow string. // Only allow char x[] = "foo"; not char x[] = L"foo"; if (ElemTy->isCharType()) - return (SL->getKind() == StringLiteral::UTF8 && + return (SL->getKind() == StringLiteralKind::UTF8 && Context.getLangOpts().Char8) ? SIF_UTF8StringIntoPlainChar : SIF_None; @@ -119,7 +121,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, // version of wchar_t, char16_t, or char32_t may be initialized by a wide // string literal with the corresponding encoding prefix (L, u, or U, // respectively), optionally enclosed in braces. - case StringLiteral::UTF16: + case StringLiteralKind::UTF16: if (Context.typesAreCompatible(Context.Char16Ty, ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) @@ -127,7 +129,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; - case StringLiteral::UTF32: + case StringLiteralKind::UTF32: if (Context.typesAreCompatible(Context.Char32Ty, ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) @@ -135,7 +137,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; - case StringLiteral::Wide: + case StringLiteralKind::Wide: if (Context.typesAreCompatible(Context.getWideCharType(), ElemTy)) return SIF_None; if (ElemTy->isCharType() || ElemTy->isChar8Type()) @@ -143,7 +145,7 @@ static StringInitFailureKind IsStringInit(Expr *Init, const ArrayType *AT, if (IsWideCharCompatible(ElemTy, Context)) return SIF_IncompatWideStringIntoWideChar; return SIF_Other; - case StringLiteral::Unevaluated: + case StringLiteralKind::Unevaluated: assert(false && "Unevaluated string literal in initialization"); break; } @@ -169,22 +171,9 @@ static void updateStringLiteralType(Expr *E, QualType Ty) { while (true) { E->setType(Ty); E->setValueKind(VK_PRValue); - if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E)) { + if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(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 if (PredefinedExpr *PE = dyn_cast<PredefinedExpr>(E)) { - E = PE->getFunctionName(); - } else { - llvm_unreachable("unexpected expr in string literal init"); - } + E = IgnoreParensSingleStep(E); } } @@ -193,20 +182,9 @@ static void updateStringLiteralType(Expr *E, QualType Ty) { static void updateGNUCompoundLiteralRValue(Expr *E) { while (true) { E->setValueKind(VK_PRValue); - if (isa<CompoundLiteralExpr>(E)) { + 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"); - } + E = IgnoreParensSingleStep(E); } } @@ -222,9 +200,8 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, // being initialized to a string literal. llvm::APInt ConstVal(32, StrLength); // Return a new array type (C99 6.7.8p22). - DeclT = S.Context.getConstantArrayType(IAT->getElementType(), - ConstVal, nullptr, - ArrayType::Normal, 0); + DeclT = S.Context.getConstantArrayType( + IAT->getElementType(), ConstVal, nullptr, ArraySizeModifier::Normal, 0); updateStringLiteralType(Str, DeclT); return; } @@ -1831,8 +1808,8 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, bool isBigEndian = SemaRef.Context.getTargetInfo().isBigEndian(); const VectorType *T = Entity.getType()->castAs<VectorType>(); - if (isBigEndian && (T->getVectorKind() == VectorType::NeonVector || - T->getVectorKind() == VectorType::NeonPolyVector)) { + if (isBigEndian && (T->getVectorKind() == VectorKind::Neon || + T->getVectorKind() == VectorKind::NeonPoly)) { // The ability to use vector initializer lists is a GNU vector extension // and is unrelated to the NEON intrinsics in arm_neon.h. On little // endian machines it works fine, however on big endian machines it @@ -1980,7 +1957,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, // them in all sorts of strange places). bool HasErr = IList->getNumInits() != 0 || SemaRef.getLangOpts().CPlusPlus; if (!VerifyOnly) { - // C2x 6.7.9p4: An entity of variable length array type shall not be + // C23 6.7.10p4: An entity of variable length array type shall not be // initialized except by an empty initializer. // // The C extension warnings are issued from ParseBraceInitializer() and @@ -2075,7 +2052,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, } DeclType = SemaRef.Context.getConstantArrayType( - elementType, maxElements, nullptr, ArrayType::Normal, 0); + elementType, maxElements, nullptr, ArraySizeModifier::Normal, 0); } if (!hadError) { // If there are any members of the array that get value-initialized, check @@ -2252,6 +2229,8 @@ void InitListChecker::CheckStructUnionTypes( !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()); bool HasDesignatedInit = false; + llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields; + while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); SourceLocation InitLoc = Init->getBeginLoc(); @@ -2267,20 +2246,23 @@ void InitListChecker::CheckStructUnionTypes( // Handle this designated initializer. Field will be updated to // the next field that we'll be initializing. - if (CheckDesignatedInitializer(Entity, IList, DIE, 0, - DeclType, &Field, nullptr, Index, - StructuredList, StructuredIndex, - true, TopLevelObject)) + bool DesignatedInitFailed = CheckDesignatedInitializer( + Entity, IList, DIE, 0, DeclType, &Field, nullptr, Index, + StructuredList, StructuredIndex, true, TopLevelObject); + if (DesignatedInitFailed) hadError = true; - else if (!VerifyOnly) { - // Find the field named by the designated initializer. - RecordDecl::field_iterator F = RD->field_begin(); - while (std::next(F) != Field) - ++F; - QualType ET = SemaRef.Context.getBaseElementType(F->getType()); - if (checkDestructorReference(ET, InitLoc, SemaRef)) { - hadError = true; - return; + + // Find the field named by the designated initializer. + DesignatedInitExpr::Designator *D = DIE->getDesignator(0); + if (!VerifyOnly && D->isFieldDesignator()) { + FieldDecl *F = D->getFieldDecl(); + InitializedFields.insert(F); + if (!DesignatedInitFailed) { + QualType ET = SemaRef.Context.getBaseElementType(F->getType()); + if (checkDestructorReference(ET, InitLoc, SemaRef)) { + hadError = true; + return; + } } } @@ -2288,7 +2270,8 @@ void InitListChecker::CheckStructUnionTypes( // Disable check for missing fields when designators are used. // This matches gcc behaviour. - CheckForMissingFields = false; + if (!SemaRef.getLangOpts().CPlusPlus) + CheckForMissingFields = false; continue; } @@ -2367,6 +2350,7 @@ void InitListChecker::CheckStructUnionTypes( CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); InitializedSomething = true; + InitializedFields.insert(*Field); if (RD->isUnion() && StructuredList) { // Initialize the first field within the union. @@ -2378,15 +2362,21 @@ void InitListChecker::CheckStructUnionTypes( // Emit warnings for missing struct field initializers. if (!VerifyOnly && InitializedSomething && CheckForMissingFields && - Field != FieldEnd && !Field->getType()->isIncompleteArrayType() && !RD->isUnion()) { // It is possible we have one or more unnamed bitfields remaining. // Find first (if any) named field and emit warning. - for (RecordDecl::field_iterator it = Field, end = RD->field_end(); + for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin() + : Field, + end = RD->field_end(); it != end; ++it) { - if (!it->isUnnamedBitfield() && !it->hasInClassInitializer()) { + if (HasDesignatedInit && InitializedFields.count(*it)) + continue; + + if (!it->isUnnamedBitfield() && !it->hasInClassInitializer() && + !it->getType()->isIncompleteArrayType()) { SemaRef.Diag(IList->getSourceRange().getEnd(), - diag::warn_missing_field_initializers) << *it; + diag::warn_missing_field_initializers) + << *it; break; } } @@ -2691,21 +2681,16 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, FieldDecl *KnownField = D->getFieldDecl(); if (!KnownField) { const IdentifierInfo *FieldName = D->getFieldName(); - DeclContext::lookup_result Lookup = RD->lookup(FieldName); - for (NamedDecl *ND : Lookup) { - if (auto *FD = dyn_cast<FieldDecl>(ND)) { - KnownField = FD; - break; - } - if (auto *IFD = dyn_cast<IndirectFieldDecl>(ND)) { - // In verify mode, don't modify the original. - if (VerifyOnly) - DIE = CloneDesignatedInitExpr(SemaRef, DIE); - ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IFD); - D = DIE->getDesignator(DesigIdx); - KnownField = cast<FieldDecl>(*IFD->chain_begin()); - break; - } + ValueDecl *VD = SemaRef.tryLookupUnambiguousFieldDecl(RD, FieldName); + if (auto *FD = dyn_cast_if_present<FieldDecl>(VD)) { + KnownField = FD; + } else if (auto *IFD = dyn_cast_if_present<IndirectFieldDecl>(VD)) { + // In verify mode, don't modify the original. + if (VerifyOnly) + DIE = CloneDesignatedInitExpr(SemaRef, DIE); + ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IFD); + D = DIE->getDesignator(DesigIdx); + KnownField = cast<FieldDecl>(*IFD->chain_begin()); } if (!KnownField) { if (VerifyOnly) { @@ -2713,10 +2698,17 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, return true; // No typo correction when just trying this out. } + // We found a placeholder variable + if (SemaRef.DiagRedefinedPlaceholderFieldDecl(DIE->getBeginLoc(), RD, + FieldName)) { + ++Index; + return true; + } // Name lookup found something, but it wasn't a field. - if (!Lookup.empty()) { + if (DeclContextLookupResult Lookup = RD->lookup(FieldName); + !Lookup.empty()) { SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield) - << FieldName; + << FieldName; SemaRef.Diag(Lookup.front()->getLocation(), diag::note_field_designator_found); ++Index; @@ -2844,7 +2836,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (PrevField && PrevField->getFieldIndex() > KnownField->getFieldIndex()) { - SemaRef.Diag(DIE->getBeginLoc(), diag::ext_designated_init_reordered) + SemaRef.Diag(DIE->getInit()->getBeginLoc(), + diag::ext_designated_init_reordered) << KnownField << PrevField << DIE->getSourceRange(); unsigned OldIndex = StructuredIndex - 1; @@ -4063,7 +4056,7 @@ static bool TryInitializerListConstruction(Sema &S, E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), List->getNumInits()), - nullptr, clang::ArrayType::Normal, 0); + nullptr, clang::ArraySizeModifier::Normal, 0); InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(ArrayType); InitializationKind Kind = InitializationKind::CreateDirectList( @@ -4092,16 +4085,13 @@ static bool hasCopyOrMoveCtorParam(ASTContext &Ctx, return Ctx.hasSameUnqualifiedType(ParmT, ClassT); } -static OverloadingResult -ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, - MultiExprArg Args, - OverloadCandidateSet &CandidateSet, - QualType DestType, - DeclContext::lookup_result Ctors, - OverloadCandidateSet::iterator &Best, - bool CopyInitializing, bool AllowExplicit, - bool OnlyListConstructors, bool IsListInit, - bool SecondStepOfCopyInit = false) { +static OverloadingResult ResolveConstructorOverload( + Sema &S, SourceLocation DeclLoc, MultiExprArg Args, + OverloadCandidateSet &CandidateSet, QualType DestType, + DeclContext::lookup_result Ctors, OverloadCandidateSet::iterator &Best, + bool CopyInitializing, bool AllowExplicit, bool OnlyListConstructors, + bool IsListInit, bool RequireActualConstructor, + bool SecondStepOfCopyInit = false) { CandidateSet.clear(OverloadCandidateSet::CSK_InitByConstructor); CandidateSet.setDestAS(DestType.getQualifiers().getAddressSpace()); @@ -4164,7 +4154,7 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, // Note: SecondStepOfCopyInit is only ever true in this case when // evaluating whether to produce a C++98 compatibility warning. if (S.getLangOpts().CPlusPlus17 && Args.size() == 1 && - !SecondStepOfCopyInit) { + !RequireActualConstructor && !SecondStepOfCopyInit) { Expr *Initializer = Args[0]; auto *SourceRD = Initializer->getType()->getAsCXXRecordDecl(); if (SourceRD && S.isCompleteType(DeclLoc, Initializer->getType())) { @@ -4232,6 +4222,12 @@ static void TryConstructorInitialization(Sema &S, return; } + bool RequireActualConstructor = + !(Entity.getKind() != InitializedEntity::EK_Base && + Entity.getKind() != InitializedEntity::EK_Delegating && + Entity.getKind() != + InitializedEntity::EK_LambdaToBlockConversionBlockElement); + // C++17 [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 @@ -4241,11 +4237,7 @@ static void TryConstructorInitialization(Sema &S, // class or delegating to another constructor from a mem-initializer. // ObjC++: Lambda captured by the block in the lambda to block conversion // should avoid copy elision. - if (S.getLangOpts().CPlusPlus17 && - Entity.getKind() != InitializedEntity::EK_Base && - Entity.getKind() != InitializedEntity::EK_Delegating && - Entity.getKind() != - InitializedEntity::EK_LambdaToBlockConversionBlockElement && + if (S.getLangOpts().CPlusPlus17 && !RequireActualConstructor && UnwrappedArgs.size() == 1 && UnwrappedArgs[0]->isPRValue() && S.Context.hasSameUnqualifiedType(UnwrappedArgs[0]->getType(), DestType)) { // Convert qualifications if necessary. @@ -4293,11 +4285,10 @@ static void TryConstructorInitialization(Sema &S, // If the initializer list has no elements and T has a default constructor, // the first phase is omitted. if (!(UnwrappedArgs.empty() && S.LookupDefaultConstructor(DestRecordDecl))) - Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, - CandidateSet, DestType, Ctors, Best, - CopyInitialization, AllowExplicit, - /*OnlyListConstructors=*/true, - IsListInit); + Result = ResolveConstructorOverload( + S, Kind.getLocation(), Args, CandidateSet, DestType, Ctors, Best, + CopyInitialization, AllowExplicit, + /*OnlyListConstructors=*/true, IsListInit, RequireActualConstructor); } // C++11 [over.match.list]p1: @@ -4307,11 +4298,10 @@ static void TryConstructorInitialization(Sema &S, // elements of the initializer list. if (Result == OR_No_Viable_Function) { AsInitializerList = false; - Result = ResolveConstructorOverload(S, Kind.getLocation(), UnwrappedArgs, - CandidateSet, DestType, Ctors, Best, - CopyInitialization, AllowExplicit, - /*OnlyListConstructors=*/false, - IsListInit); + Result = ResolveConstructorOverload( + S, Kind.getLocation(), UnwrappedArgs, CandidateSet, DestType, Ctors, + Best, CopyInitialization, AllowExplicit, + /*OnlyListConstructors=*/false, IsListInit, RequireActualConstructor); } if (Result) { Sequence.SetOverloadFailure( @@ -4512,6 +4502,17 @@ static void TryReferenceListInitialization(Sema &S, if (Sequence) { if (DestType->isRValueReferenceType() || (T1Quals.hasConst() && !T1Quals.hasVolatile())) { + if (S.getLangOpts().CPlusPlus20 && + isa<IncompleteArrayType>(T1->getUnqualifiedDesugaredType()) && + DestType->isRValueReferenceType()) { + // C++20 [dcl.init.list]p3.10: + // List-initialization of an object or reference of type T is defined as + // follows: + // ..., unless T is “reference to array of unknown bound of U”, in which + // case the type of the prvalue is the type of x in the declaration U + // x[] H, where H is the initializer list. + Sequence.AddQualificationConversionStep(cv1T1, clang::VK_PRValue); + } Sequence.AddReferenceBindingStep(cv1T1IgnoreAS, /*BindingTemporary=*/true); if (T1Quals.hasAddressSpace()) @@ -5508,7 +5509,7 @@ static void TryOrBuildParenListInitialization( if (ResultType.isNull()) { ResultType = S.Context.getConstantArrayType( AT->getElementType(), llvm::APInt(/*numBits=*/32, ArrayLength), - /*SizeExpr=*/nullptr, ArrayType::Normal, 0); + /*SizeExpr=*/nullptr, ArraySizeModifier::Normal, 0); } } else if (auto *RT = Entity.getType()->getAs<RecordType>()) { bool IsUnion = RT->isUnionType(); @@ -5657,8 +5658,6 @@ static void TryOrBuildParenListInitialization( diag::warn_cxx17_compat_aggregate_init_paren_list) << Kind.getLocation() << SR << ResultType; } - - return; } /// Attempt a user-defined conversion between two types (C++ [dcl.init]), @@ -6776,6 +6775,7 @@ static ExprResult CopyObject(Sema &S, S, Loc, CurInitExpr, CandidateSet, T, Ctors, Best, /*CopyInitializing=*/false, /*AllowExplicit=*/true, /*OnlyListConstructors=*/false, /*IsListInit=*/false, + /*RequireActualConstructor=*/false, /*SecondStepOfCopyInit=*/true)) { case OR_Success: break; @@ -6878,15 +6878,12 @@ static ExprResult CopyObject(Sema &S, CurInitExpr->getType()); // Actually perform the constructor call. - CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor, - Elidable, - ConstructorArgs, - HadMultipleCandidates, - /*ListInit*/ false, - /*StdInitListInit*/ false, - /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete, - SourceRange()); + CurInit = S.BuildCXXConstructExpr( + Loc, T, Best->FoundDecl, Constructor, Elidable, ConstructorArgs, + HadMultipleCandidates, + /*ListInit*/ false, + /*StdInitListInit*/ false, + /*ZeroInit*/ false, CXXConstructionKind::Complete, SourceRange()); // If we're supposed to bind temporaries, do so. if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity)) @@ -6921,6 +6918,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, S, Loc, CurInitExpr, CandidateSet, CurInitExpr->getType(), Ctors, Best, /*CopyInitializing=*/false, /*AllowExplicit=*/true, /*OnlyListConstructors=*/false, /*IsListInit=*/false, + /*RequireActualConstructor=*/false, /*SecondStepOfCopyInit=*/true); PartialDiagnostic Diag = S.PDiag(diag::warn_cxx98_compat_temp_copy) @@ -7080,15 +7078,14 @@ PerformConstructorInitialization(Sema &S, ConstructorInitRequiresZeroInit), CalleeDecl); } else { - CXXConstructExpr::ConstructionKind ConstructKind = - CXXConstructExpr::CK_Complete; + CXXConstructionKind ConstructKind = CXXConstructionKind::Complete; if (Entity.getKind() == InitializedEntity::EK_Base) { - ConstructKind = Entity.getBaseSpecifier()->isVirtual() ? - CXXConstructExpr::CK_VirtualBase : - CXXConstructExpr::CK_NonVirtualBase; + ConstructKind = Entity.getBaseSpecifier()->isVirtual() + ? CXXConstructionKind::VirtualBase + : CXXConstructionKind::NonVirtualBase; } else if (Entity.getKind() == InitializedEntity::EK_Delegating) { - ConstructKind = CXXConstructExpr::CK_Delegating; + ConstructKind = CXXConstructionKind::Delegating; } // Only get the parenthesis or brace range if it is a list initialization or @@ -7395,8 +7392,9 @@ static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) { return true; if (!isInStlNamespace(Callee->getParent())) return false; - if (!isRecordWithAttr<PointerAttr>(Callee->getThisObjectType()) && - !isRecordWithAttr<OwnerAttr>(Callee->getThisObjectType())) + if (!isRecordWithAttr<PointerAttr>( + Callee->getFunctionObjectParameterType()) && + !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType())) return false; if (Callee->getReturnType()->isPointerType() || isRecordWithAttr<PointerAttr>(Callee->getReturnType())) { @@ -7531,7 +7529,7 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) { QualType LHST; auto *MD = dyn_cast<CXXMethodDecl>(FD); if (MD && MD->isCXXInstanceMember()) - LHST = Ctx.getLValueReferenceType(MD->getThisObjectType()); + LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType()); else LHST = MD->getParamDecl(0)->getType(); if (Ctx.hasSameType(RetT, LHST)) @@ -7581,10 +7579,15 @@ static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call, if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee)) VisitLifetimeBoundArg(Callee, ObjectArg); + bool CheckCoroCall = false; + if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) { + CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() && + RD->hasAttr<CoroReturnTypeAttr>(); + } for (unsigned I = 0, N = std::min<unsigned>(Callee->getNumParams(), Args.size()); I != N; ++I) { - if (Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>()) + if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>()) VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]); } } @@ -8868,15 +8871,12 @@ ExprResult InitializationSequence::Perform(Sema &S, return ExprError(); // Build an expression that constructs a temporary. - CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, - FoundFn, Constructor, - ConstructorArgs, - HadMultipleCandidates, - /*ListInit*/ false, - /*StdInitListInit*/ false, - /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete, - SourceRange()); + CurInit = S.BuildCXXConstructExpr( + Loc, Step->Type, FoundFn, Constructor, ConstructorArgs, + HadMultipleCandidates, + /*ListInit*/ false, + /*StdInitListInit*/ false, + /*ZeroInit*/ false, CXXConstructionKind::Complete, SourceRange()); if (CurInit.isInvalid()) return ExprError(); @@ -9233,10 +9233,8 @@ ExprResult InitializationSequence::Perform(Sema &S, if (const ConstantArrayType *ConstantSource = S.Context.getAsConstantArrayType(CurInit.get()->getType())) { *ResultType = S.Context.getConstantArrayType( - IncompleteDest->getElementType(), - ConstantSource->getSize(), - ConstantSource->getSizeExpr(), - ArrayType::Normal, 0); + IncompleteDest->getElementType(), ConstantSource->getSize(), + ConstantSource->getSizeExpr(), ArraySizeModifier::Normal, 0); } } } @@ -9504,7 +9502,7 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity, E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), InitList->getNumInits()), - nullptr, clang::ArrayType::Normal, 0); + nullptr, clang::ArraySizeModifier::Normal, 0); InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(ArrayType); return diagnoseListInit(S, HiddenArray, InitList); @@ -10574,7 +10572,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( diag::err_deduced_non_class_template_specialization_type) << (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName; if (auto *TD = TemplateName.getAsTemplateDecl()) - Diag(TD->getLocation(), diag::note_template_decl_here); + NoteTemplateLocation(*TD); return QualType(); } @@ -10629,7 +10627,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( bool AllowExplicit = !Kind.isCopyInit() || ListInit; - // Return true is the candidate is added successfully, false otherwise. + // Return true if the candidate is added successfully, false otherwise. auto addDeductionCandidate = [&](FunctionTemplateDecl *TD, CXXDeductionGuideDecl *GD, DeclAccessPair FoundDecl, |
