diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp | 925 |
1 files changed, 572 insertions, 353 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp index 953bfe484a52..de50786f4d6c 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaExprCXX.cpp @@ -38,12 +38,16 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaLambda.h" +#include "clang/Sema/SemaObjC.h" +#include "clang/Sema/SemaPPC.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TypeSize.h" @@ -51,13 +55,9 @@ using namespace clang; using namespace sema; -/// Handle the result of the special case name lookup for inheriting -/// constructor declarations. 'NS::X::X' and 'NS::X<...>::X' are treated as -/// constructor names in member using declarations, even if 'X' is not the -/// name of the corresponding type. ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, SourceLocation NameLoc, - IdentifierInfo &Name) { + const IdentifierInfo &Name) { NestedNameSpecifier *NNS = SS.getScopeRep(); // Convert the nested-name-specifier into a type. @@ -89,10 +89,9 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, Context.getTrivialTypeSourceInfo(Type, NameLoc)); } -ParsedType Sema::getConstructorName(IdentifierInfo &II, - SourceLocation NameLoc, - Scope *S, CXXScopeSpec &SS, - bool EnteringContext) { +ParsedType Sema::getConstructorName(const IdentifierInfo &II, + SourceLocation NameLoc, Scope *S, + CXXScopeSpec &SS, bool EnteringContext) { CXXRecordDecl *CurClass = getCurrentClass(S, &SS); assert(CurClass && &II == CurClass->getIdentifier() && "not a constructor name"); @@ -140,9 +139,9 @@ ParsedType Sema::getConstructorName(IdentifierInfo &II, return ParsedType::make(T); } -ParsedType Sema::getDestructorName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec &SS, - ParsedType ObjectTypePtr, +ParsedType Sema::getDestructorName(const IdentifierInfo &II, + SourceLocation NameLoc, Scope *S, + CXXScopeSpec &SS, ParsedType ObjectTypePtr, bool EnteringContext) { // Determine where to perform name lookup. @@ -500,7 +499,7 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, // // double operator""_Bq(long double); // OK: not a reserved identifier // double operator"" _Bq(long double); // ill-formed, no diagnostic required - IdentifierInfo *II = Name.Identifier; + const IdentifierInfo *II = Name.Identifier; ReservedIdentifierStatus Status = II->isReserved(PP.getLangOpts()); SourceLocation Loc = Name.getEndLoc(); if (!PP.getSourceManager().isInSystemHeader(Loc)) { @@ -541,7 +540,6 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, llvm_unreachable("unknown nested name specifier kind"); } -/// Build a C++ typeid expression with a type operand. ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, @@ -569,7 +567,6 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceRange(TypeidLoc, RParenLoc)); } -/// Build a C++ typeid expression with an expression operand. ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *E, @@ -744,7 +741,6 @@ getUuidAttrOfType(Sema &SemaRef, QualType QT, } } -/// Build a Microsoft __uuidof expression with a type operand. ExprResult Sema::BuildCXXUuidof(QualType Type, SourceLocation TypeidLoc, TypeSourceInfo *Operand, @@ -764,7 +760,6 @@ ExprResult Sema::BuildCXXUuidof(QualType Type, CXXUuidofExpr(Type, Operand, Guid, SourceRange(TypeidLoc, RParenLoc)); } -/// Build a Microsoft __uuidof expression with an expression operand. ExprResult Sema::BuildCXXUuidof(QualType Type, SourceLocation TypeidLoc, Expr *E, SourceLocation RParenLoc) { MSGuidDecl *Guid = nullptr; @@ -812,7 +807,6 @@ Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc, return BuildCXXUuidof(GuidType, OpLoc, (Expr*)TyOrExpr, RParenLoc); } -/// ActOnCXXBoolLiteral - Parse {true,false} literals. ExprResult Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { assert((Kind == tok::kw_true || Kind == tok::kw_false) && @@ -821,13 +815,11 @@ Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { CXXBoolLiteralExpr(Kind == tok::kw_true, Context.BoolTy, OpLoc); } -/// ActOnCXXNullPtrLiteral - Parse 'nullptr'. ExprResult Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { return new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc); } -/// ActOnCXXThrow - Parse throw expressions. ExprResult Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) { bool IsThrownVarInScope = false; @@ -884,12 +876,18 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) - CUDADiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions) - << "throw" << CurrentCUDATarget(); + CUDA().DiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions) + << "throw" << llvm::to_underlying(CUDA().CurrentTarget()); if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw"; + // Exceptions that escape a compute construct are ill-formed. + if (getLangOpts().OpenACC && getCurScope() && + getCurScope()->isInOpenACCComputeConstructScope(Scope::TryScope)) + Diag(OpLoc, diag::err_acc_branch_in_out_compute_construct) + << /*throw*/ 2 << /*out of*/ 0; + if (Ex && !Ex->isTypeDependent()) { // Initialize the exception result. This implicitly weeds out // abstract types or types with inaccessible copy constructors. @@ -923,7 +921,7 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, // PPC MMA non-pointer types are not allowed as throw expr types. if (Ex && Context.getTargetInfo().getTriple().isPPC64()) - CheckPPCMMAType(Ex->getType(), Ex->getBeginLoc()); + PPC().CheckPPCMMAType(Ex->getType(), Ex->getBeginLoc()); return new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope); @@ -978,7 +976,6 @@ static void getUnambiguousPublicSubobjects( } } -/// CheckCXXThrowOperand - Validate the operand of a throw. bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ExceptionObjectTy, Expr *E) { // If the type of the exception would be an incomplete type or a pointer @@ -1220,7 +1217,7 @@ static QualType adjustCVQualifiersForCXXThisWithinLambda( : nullptr; } } - return ASTCtx.getPointerType(ClassType); + return ThisTy; } QualType Sema::getCurrentThisType() { @@ -1409,26 +1406,42 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, } ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { - /// C++ 9.3.2: In the body of a non-static member function, the keyword this - /// is a non-lvalue expression whose value is the address of the object for - /// which the function is called. + // C++20 [expr.prim.this]p1: + // The keyword this names a pointer to the object for which an + // implicit object member function is invoked or a non-static + // data member's initializer is evaluated. QualType ThisTy = getCurrentThisType(); - if (ThisTy.isNull()) { - DeclContext *DC = getFunctionLevelDeclContext(); + if (CheckCXXThisType(Loc, ThisTy)) + return ExprError(); - if (const auto *Method = dyn_cast<CXXMethodDecl>(DC); - Method && Method->isExplicitObjectMemberFunction()) { - return Diag(Loc, diag::err_invalid_this_use) << 1; - } + return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); +} - if (isLambdaCallWithExplicitObjectParameter(CurContext)) - return Diag(Loc, diag::err_invalid_this_use) << 1; +bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) { + if (!Type.isNull()) + return false; - return Diag(Loc, diag::err_invalid_this_use) << 0; + // C++20 [expr.prim.this]p3: + // If a declaration declares a member function or member function template + // of a class X, the expression this is a prvalue of type + // "pointer to cv-qualifier-seq X" wherever X is the current class between + // the optional cv-qualifier-seq and the end of the function-definition, + // member-declarator, or declarator. It shall not appear within the + // declaration of either a static member function or an explicit object + // member function of the current class (although its type and value + // category are defined within such member functions as they are within + // an implicit object member function). + DeclContext *DC = getFunctionLevelDeclContext(); + const auto *Method = dyn_cast<CXXMethodDecl>(DC); + if (Method && Method->isExplicitObjectMemberFunction()) { + Diag(Loc, diag::err_invalid_this_use) << 1; + } else if (Method && isLambdaCallWithExplicitObjectParameter(CurContext)) { + Diag(Loc, diag::err_invalid_this_use) << 1; + } else { + Diag(Loc, diag::err_invalid_this_use) << 0; } - - return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); + return true; } Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, @@ -1440,6 +1453,42 @@ Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, void Sema::MarkThisReferenced(CXXThisExpr *This) { CheckCXXThisCapture(This->getExprLoc()); + if (This->isTypeDependent()) + return; + + // Check if 'this' is captured by value in a lambda with a dependent explicit + // object parameter, and mark it as type-dependent as well if so. + auto IsDependent = [&]() { + for (auto *Scope : llvm::reverse(FunctionScopes)) { + auto *LSI = dyn_cast<sema::LambdaScopeInfo>(Scope); + if (!LSI) + continue; + + if (LSI->Lambda && !LSI->Lambda->Encloses(CurContext) && + LSI->AfterParameterList) + return false; + + // If this lambda captures 'this' by value, then 'this' is dependent iff + // this lambda has a dependent explicit object parameter. If we can't + // determine whether it does (e.g. because the CXXMethodDecl's type is + // null), assume it doesn't. + if (LSI->isCXXThisCaptured()) { + if (!LSI->getCXXThisCapture().isCopyCapture()) + continue; + + const auto *MD = LSI->CallOperator; + if (MD->getType().isNull()) + return false; + + const auto *Ty = MD->getType()->getAs<FunctionProtoType>(); + return Ty && MD->isExplicitObjectMemberFunction() && + Ty->getParamType(0)->isDependentType(); + } + } + return false; + }(); + + This->setCapturedByCopyInLambdaWithExplicitObjectParameter(IsDependent); } bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) { @@ -1454,10 +1503,6 @@ bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) { return Class && Class->isBeingDefined(); } -/// Parse construction of a specified type. -/// Can be interpreted either as function-style casting ("int(x)") -/// or class type construction ("ClassType(x,y,z)") -/// or creation of a value-initialized type ("int()"). ExprResult Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, SourceLocation LParenOrBraceLoc, @@ -1554,12 +1599,13 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, TemplateDeductionInfo Info(Deduce->getExprLoc()); TemplateDeductionResult Result = DeduceAutoType(TInfo->getTypeLoc(), Deduce, DeducedType, Info); - if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) + if (Result != TemplateDeductionResult::Success && + Result != TemplateDeductionResult::AlreadyDiagnosed) return ExprError(Diag(TyBeginLoc, diag::err_auto_expr_deduction_failure) << Ty << Deduce->getType() << FullRange << Deduce->getSourceRange()); if (DeducedType.isNull()) { - assert(Result == TDK_AlreadyDiagnosed); + assert(Result == TemplateDeductionResult::AlreadyDiagnosed); return ExprError(); } @@ -1649,17 +1695,17 @@ bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) { // [CUDA] Ignore this function, if we can't call it. const FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); if (getLangOpts().CUDA) { - auto CallPreference = IdentifyCUDAPreference(Caller, Method); + auto CallPreference = CUDA().IdentifyPreference(Caller, Method); // If it's not callable at all, it's not the right function. - if (CallPreference < CFP_WrongSide) + if (CallPreference < SemaCUDA::CFP_WrongSide) return false; - if (CallPreference == CFP_WrongSide) { + if (CallPreference == SemaCUDA::CFP_WrongSide) { // Maybe. We have to check if there are better alternatives. DeclContext::lookup_result R = Method->getDeclContext()->lookup(Method->getDeclName()); for (const auto *D : R) { if (const auto *FD = dyn_cast<FunctionDecl>(D)) { - if (IdentifyCUDAPreference(Caller, FD) > CFP_WrongSide) + if (CUDA().IdentifyPreference(Caller, FD) > SemaCUDA::CFP_WrongSide) return false; } } @@ -1678,7 +1724,7 @@ bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) { return llvm::none_of(PreventedBy, [&](const FunctionDecl *FD) { assert(FD->getNumParams() == 1 && "Only single-operand functions should be in PreventedBy"); - return IdentifyCUDAPreference(Caller, FD) >= CFP_HostDevice; + return CUDA().IdentifyPreference(Caller, FD) >= SemaCUDA::CFP_HostDevice; }); } @@ -1715,7 +1761,7 @@ namespace { UsualDeallocFnInfo(Sema &S, DeclAccessPair Found) : Found(Found), FD(dyn_cast<FunctionDecl>(Found->getUnderlyingDecl())), Destroying(false), HasSizeT(false), HasAlignValT(false), - CUDAPref(Sema::CFP_Native) { + CUDAPref(SemaCUDA::CFP_Native) { // A function template declaration is never a usual deallocation function. if (!FD) return; @@ -1741,7 +1787,7 @@ namespace { // In CUDA, determine how much we'd like / dislike to call this. if (S.getLangOpts().CUDA) - CUDAPref = S.IdentifyCUDAPreference( + CUDAPref = S.CUDA().IdentifyPreference( S.getCurFunctionDecl(/*AllowLambda=*/true), FD); } @@ -1772,7 +1818,7 @@ namespace { DeclAccessPair Found; FunctionDecl *FD; bool Destroying, HasSizeT, HasAlignValT; - Sema::CUDAFunctionPreference CUDAPref; + SemaCUDA::CUDAFunctionPreference CUDAPref; }; } @@ -1796,7 +1842,7 @@ static UsualDeallocFnInfo resolveDeallocationOverload( for (auto I = R.begin(), E = R.end(); I != E; ++I) { UsualDeallocFnInfo Info(S, I.getPair()); if (!Info || !isNonPlacementDeallocationFunction(S, Info.FD) || - Info.CUDAPref == Sema::CFP_Never) + Info.CUDAPref == SemaCUDA::CFP_Never) continue; if (!Best) { @@ -1858,22 +1904,6 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, return Best && Best.HasSizeT; } -/// Parsed a C++ 'new' expression (C++ 5.3.4). -/// -/// E.g.: -/// @code new (memory) int[size][4] @endcode -/// or -/// @code ::new Foo(23, "hello") @endcode -/// -/// \param StartLoc The first location of the expression. -/// \param UseGlobal True if 'new' was prefixed with '::'. -/// \param PlacementLParen Opening paren of the placement arguments. -/// \param PlacementArgs Placement new arguments. -/// \param PlacementRParen Closing paren of the placement arguments. -/// \param TypeIdParens If the type is in parens, the source range. -/// \param D The type to be allocated, as well as array dimensions. -/// \param Initializer The initializing expression or initializer-list, or null -/// if there is none. ExprResult Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, @@ -2012,7 +2042,7 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, if (DirectInitRange.isValid()) { assert(Initializer && "Have parens but no initializer."); InitStyle = CXXNewInitializationStyle::Parens; - } else if (Initializer && isa<InitListExpr>(Initializer)) + } else if (isa_and_nonnull<InitListExpr>(Initializer)) InitStyle = CXXNewInitializationStyle::Braces; else { assert((!Initializer || isa<ImplicitValueInitExpr>(Initializer) || @@ -2098,12 +2128,13 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, TemplateDeductionInfo Info(Deduce->getExprLoc()); TemplateDeductionResult Result = DeduceAutoType(AllocTypeInfo->getTypeLoc(), Deduce, DeducedType, Info); - if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) + if (Result != TemplateDeductionResult::Success && + Result != TemplateDeductionResult::AlreadyDiagnosed) return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) << AllocType << Deduce->getType() << TypeRange << Deduce->getSourceRange()); if (DeducedType.isNull()) { - assert(Result == TDK_AlreadyDiagnosed); + assert(Result == TemplateDeductionResult::AlreadyDiagnosed); return ExprError(); } AllocType = DeducedType; @@ -2482,8 +2513,6 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, DirectInitRange); } -/// Checks that a type is suitable as the allocated type -/// in a new-expression. bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R) { // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an @@ -2655,13 +2684,9 @@ static bool resolveAllocationOverload( return true; case OR_Deleted: { - if (Diagnose) { - Candidates.NoteCandidates( - PartialDiagnosticAt(R.getNameLoc(), - S.PDiag(diag::err_ovl_deleted_call) - << R.getLookupName() << Range), - S, OCD_AllCandidates, Args); - } + if (Diagnose) + S.DiagnoseUseOfDeletedFunction(R.getNameLoc(), Range, R.getLookupName(), + Candidates, Best->Function, Args); return true; } } @@ -2883,7 +2908,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // expected function type. TemplateDeductionInfo Info(StartLoc); if (DeduceTemplateArguments(FnTmpl, nullptr, ExpectedFunctionType, Fn, - Info)) + Info) != TemplateDeductionResult::Success) continue; } else Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl()); @@ -2896,8 +2921,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, } if (getLangOpts().CUDA) - EraseUnwantedCUDAMatches(getCurFunctionDecl(/*AllowLambda=*/true), - Matches); + CUDA().EraseUnwantedMatches(getCurFunctionDecl(/*AllowLambda=*/true), + Matches); } else { // C++1y [expr.new]p22: // For a non-placement allocation function, the normal deallocation @@ -2981,29 +3006,6 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, return false; } -/// DeclareGlobalNewDelete - Declare the global forms of operator new and -/// delete. These are: -/// @code -/// // C++03: -/// void* operator new(std::size_t) throw(std::bad_alloc); -/// void* operator new[](std::size_t) throw(std::bad_alloc); -/// void operator delete(void *) throw(); -/// void operator delete[](void *) throw(); -/// // C++11: -/// void* operator new(std::size_t); -/// void* operator new[](std::size_t); -/// void operator delete(void *) noexcept; -/// void operator delete[](void *) noexcept; -/// // C++1y: -/// void* operator new(std::size_t); -/// void* operator new[](std::size_t); -/// void operator delete(void *) noexcept; -/// void operator delete[](void *) noexcept; -/// void operator delete(void *, std::size_t) noexcept; -/// void operator delete[](void *, std::size_t) noexcept; -/// @endcode -/// Note that the placement and nothrow forms of new are *not* implicitly -/// declared. Their use requires including \<new\>. void Sema::DeclareGlobalNewDelete() { if (GlobalNewDeleteDeclared) return; @@ -3315,7 +3317,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, // FIXME: DiagnoseUseOfDecl? if (Operator->isDeleted()) { if (Diagnose) { - Diag(StartLoc, diag::err_deleted_function_use); + StringLiteral *Msg = Operator->getDeletedMessage(); + Diag(StartLoc, diag::err_deleted_function_use) + << (Msg != nullptr) << (Msg ? Msg->getString() : StringRef()); NoteDeletedFunction(Operator); } return true; @@ -3615,10 +3619,6 @@ void Sema::AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc, } } -/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: -/// @code ::delete ptr; @endcode -/// or -/// @code delete [] ptr; @endcode ExprResult Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, bool ArrayForm, Expr *ExE) { @@ -3719,8 +3719,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // The C++ standard bans deleting a pointer to a non-object type, which // effectively bans deletion of "void*". However, most compilers support // this, so we treat it as a warning unless we're in a SFINAE context. - Diag(StartLoc, diag::ext_delete_void_ptr_operand) - << Type << Ex.get()->getSourceRange(); + // But we still prohibit this since C++26. + Diag(StartLoc, LangOpts.CPlusPlus26 ? diag::err_delete_incomplete + : diag::ext_delete_void_ptr_operand) + << (LangOpts.CPlusPlus26 ? Pointee : Type) + << Ex.get()->getSourceRange(); } else if (Pointee->isFunctionType() || Pointee->isVoidType() || Pointee->isSizelessType()) { return ExprError(Diag(StartLoc, diag::err_delete_operand) @@ -3729,7 +3732,10 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // FIXME: This can result in errors if the definition was imported from a // module but is hidden. if (!RequireCompleteType(StartLoc, Pointee, - diag::warn_delete_incomplete, Ex.get())) { + LangOpts.CPlusPlus26 + ? diag::err_delete_incomplete + : diag::warn_delete_incomplete, + Ex.get())) { if (const RecordType *RT = PointeeElem->getAs<RecordType>()) PointeeRD = cast<CXXRecordDecl>(RT->getDecl()); } @@ -3762,7 +3768,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // Otherwise, the usual operator delete[] should be the // function we just found. - else if (OperatorDelete && isa<CXXMethodDecl>(OperatorDelete)) + else if (isa_and_nonnull<CXXMethodDecl>(OperatorDelete)) UsualArrayDeleteWantsSize = UsualDeallocFnInfo(*this, DeclAccessPair::make(OperatorDelete, AS_public)) @@ -3919,20 +3925,16 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall, S, OCD_AmbiguousCandidates, Args); return true; - case OR_Deleted: { - Candidates.NoteCandidates( - PartialDiagnosticAt(R.getNameLoc(), S.PDiag(diag::err_ovl_deleted_call) - << R.getLookupName() << Range), - S, OCD_AllCandidates, Args); + case OR_Deleted: + S.DiagnoseUseOfDeletedFunction(R.getNameLoc(), Range, R.getLookupName(), + Candidates, Best->Function, Args); return true; } - } llvm_unreachable("Unreachable, bad result from BestViableFunction"); } -ExprResult -Sema::SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult, - bool IsDelete) { +ExprResult Sema::BuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult, + bool IsDelete) { CallExpr *TheCall = cast<CallExpr>(TheCallResult.get()); if (!getLangOpts().CPlusPlus) { Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language) @@ -4028,8 +4030,6 @@ Sema::ConditionResult Sema::ActOnConditionVariable(Decl *ConditionVar, CK == ConditionKind::ConstexprIf); } -/// Check the use of the given variable as a C++ condition in an if, -/// while, do-while, or switch statement. ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, SourceLocation StmtLoc, ConditionKind CK) { @@ -4067,7 +4067,6 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, llvm_unreachable("unexpected condition kind"); } -/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr) { // C++11 6.4p4: // The value of a condition that is an initialized declaration in a statement @@ -4095,10 +4094,6 @@ ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr) { return E; } -/// Helper function to determine whether this is the (deprecated) C++ -/// conversion from a string literal to a pointer to non-const char or -/// non-const wchar_t (for narrow and wide string literals, -/// respectively). bool Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { // Look inside the implicit cast, if it exists. @@ -4200,18 +4195,14 @@ static ExprResult BuildCXXCastArgument(Sema &S, } } -/// PerformImplicitConversion - Perform an implicit conversion of the -/// expression From to the type ToType using the pre-computed implicit -/// conversion sequence ICS. Returns the converted -/// expression. Action is the kind of conversion we're performing, -/// used in the error message. ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK) { // C++ [over.match.oper]p7: [...] operands of class type are converted [...] - if (CCK == CCK_ForBuiltinOverloadedOp && !From->getType()->isRecordType()) + if (CCK == CheckedConversionKind::ForBuiltinOverloadedOp && + !From->getType()->isRecordType()) return From; switch (ICS.getKind()) { @@ -4272,7 +4263,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // C++ [over.match.oper]p7: // [...] the second standard conversion sequence of a user-defined // conversion sequence is not applied. - if (CCK == CCK_ForBuiltinOverloadedOp) + if (CCK == CheckedConversionKind::ForBuiltinOverloadedOp) return From; return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, @@ -4303,17 +4294,27 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, return From; } -/// PerformImplicitConversion - Perform an implicit conversion of the -/// expression From to the type ToType by following the standard -/// conversion sequence SCS. Returns the converted -/// expression. Flavor is the context in which we're performing this -/// conversion, for use in error messages. +// adjustVectorType - Compute the intermediate cast type casting elements of the +// from type to the elements of the to type without resizing the vector. +static QualType adjustVectorType(ASTContext &Context, QualType FromTy, + QualType ToType, QualType *ElTy = nullptr) { + auto *ToVec = ToType->castAs<VectorType>(); + QualType ElType = ToVec->getElementType(); + if (ElTy) + *ElTy = ElType; + if (!FromTy->isVectorType()) + return ElType; + auto *FromVec = FromTy->castAs<VectorType>(); + return Context.getExtVectorType(ElType, FromVec->getNumElements()); +} + ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, const StandardConversionSequence& SCS, AssignmentAction Action, CheckedConversionKind CCK) { - bool CStyle = (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast); + bool CStyle = (CCK == CheckedConversionKind::CStyleCast || + CCK == CheckedConversionKind::FunctionalCast); // Overall FIXME: we are recomputing too many types here and doing far too // much extra work. What this means is that we need to keep track of more @@ -4408,6 +4409,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, .get(); break; + case ICK_HLSL_Array_RValue: + FromType = Context.getArrayParameterType(FromType); + From = ImpCastExprToType(From, FromType, CK_HLSLArrayRValue, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + case ICK_Function_To_Pointer: FromType = Context.getPointerType(FromType); From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay, @@ -4449,27 +4457,36 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, break; case ICK_Integral_Promotion: - case ICK_Integral_Conversion: - if (ToType->isBooleanType()) { + case ICK_Integral_Conversion: { + QualType ElTy = ToType; + QualType StepTy = ToType; + if (ToType->isVectorType()) + StepTy = adjustVectorType(Context, FromType, ToType, &ElTy); + if (ElTy->isBooleanType()) { assert(FromType->castAs<EnumType>()->getDecl()->isFixed() && SCS.Second == ICK_Integral_Promotion && "only enums with fixed underlying type can promote to bool"); - From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean, VK_PRValue, + From = ImpCastExprToType(From, StepTy, CK_IntegralToBoolean, VK_PRValue, /*BasePath=*/nullptr, CCK) .get(); } else { - From = ImpCastExprToType(From, ToType, CK_IntegralCast, VK_PRValue, + From = ImpCastExprToType(From, StepTy, CK_IntegralCast, VK_PRValue, /*BasePath=*/nullptr, CCK) .get(); } break; + } case ICK_Floating_Promotion: - case ICK_Floating_Conversion: - From = ImpCastExprToType(From, ToType, CK_FloatingCast, VK_PRValue, + case ICK_Floating_Conversion: { + QualType StepTy = ToType; + if (ToType->isVectorType()) + StepTy = adjustVectorType(Context, FromType, ToType); + From = ImpCastExprToType(From, StepTy, CK_FloatingCast, VK_PRValue, /*BasePath=*/nullptr, CCK) .get(); break; + } case ICK_Complex_Promotion: case ICK_Complex_Conversion: { @@ -4492,16 +4509,21 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, break; } - case ICK_Floating_Integral: - if (ToType->isRealFloatingType()) - From = ImpCastExprToType(From, ToType, CK_IntegralToFloating, VK_PRValue, + case ICK_Floating_Integral: { + QualType ElTy = ToType; + QualType StepTy = ToType; + if (ToType->isVectorType()) + StepTy = adjustVectorType(Context, FromType, ToType, &ElTy); + if (ElTy->isRealFloatingType()) + From = ImpCastExprToType(From, StepTy, CK_IntegralToFloating, VK_PRValue, /*BasePath=*/nullptr, CCK) .get(); else - From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral, VK_PRValue, + From = ImpCastExprToType(From, StepTy, CK_FloatingToIntegral, VK_PRValue, /*BasePath=*/nullptr, CCK) .get(); break; + } case ICK_Fixed_Point_Conversion: assert((FromType->isFixedPointType() || ToType->isFixedPointType()) && @@ -4555,10 +4577,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (From->getType()->isObjCObjectPointerType() && ToType->isObjCObjectPointerType()) - EmitRelatedResultTypeNote(From); + ObjC().EmitRelatedResultTypeNote(From); } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - !CheckObjCARCUnavailableWeakConversion(ToType, - From->getType())) { + !ObjC().CheckObjCARCUnavailableWeakConversion(ToType, + From->getType())) { if (Action == AA_Initializing) Diag(From->getBeginLoc(), diag::err_arc_weak_unavailable_assign); else @@ -4593,11 +4615,11 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // FIXME: doing this here is really ugly. if (Kind == CK_BlockPointerToObjCPointerCast) { ExprResult E = From; - (void) PrepareCastToObjCObjectPointer(E); + (void)ObjC().PrepareCastToObjCObjectPointer(E); From = E.get(); } if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) - CheckObjCConversion(SourceRange(), NewToType, From, CCK); + ObjC().CheckObjCConversion(SourceRange(), NewToType, From, CCK); From = ImpCastExprToType(From, NewToType, Kind, VK_PRValue, &BasePath, CCK) .get(); break; @@ -4623,18 +4645,26 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, break; } - case ICK_Boolean_Conversion: + case ICK_Boolean_Conversion: { // Perform half-to-boolean conversion via float. if (From->getType()->isHalfType()) { From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).get(); FromType = Context.FloatTy; } + QualType ElTy = FromType; + QualType StepTy = ToType; + if (FromType->isVectorType()) { + if (getLangOpts().HLSL) + StepTy = adjustVectorType(Context, FromType, ToType); + ElTy = FromType->castAs<VectorType>()->getElementType(); + } - From = ImpCastExprToType(From, Context.BoolTy, - ScalarTypeToBooleanCastKind(FromType), VK_PRValue, + From = ImpCastExprToType(From, StepTy, ScalarTypeToBooleanCastKind(ElTy), + VK_PRValue, /*BasePath=*/nullptr, CCK) .get(); break; + } case ICK_Derived_To_Base: { CXXCastPath BasePath; @@ -4769,9 +4799,52 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, case ICK_Num_Conversion_Kinds: case ICK_C_Only_Conversion: case ICK_Incompatible_Pointer_Conversion: + case ICK_HLSL_Array_RValue: + case ICK_HLSL_Vector_Truncation: + case ICK_HLSL_Vector_Splat: llvm_unreachable("Improper second standard conversion"); } + if (SCS.Dimension != ICK_Identity) { + // If SCS.Element is not ICK_Identity the To and From types must be HLSL + // vectors or matrices. + + // TODO: Support HLSL matrices. + assert((!From->getType()->isMatrixType() && !ToType->isMatrixType()) && + "Dimension conversion for matrix types is not implemented yet."); + assert(ToType->isVectorType() && + "Dimension conversion is only supported for vector types."); + switch (SCS.Dimension) { + case ICK_HLSL_Vector_Splat: { + // Vector splat from any arithmetic type to a vector. + Expr *Elem = prepareVectorSplat(ToType, From).get(); + From = ImpCastExprToType(Elem, ToType, CK_VectorSplat, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + } + case ICK_HLSL_Vector_Truncation: { + // Note: HLSL built-in vectors are ExtVectors. Since this truncates a + // vector to a smaller vector, this can only operate on arguments where + // the source and destination types are ExtVectors. + assert(From->getType()->isExtVectorType() && ToType->isExtVectorType() && + "HLSL vector truncation should only apply to ExtVectors"); + auto *FromVec = From->getType()->castAs<VectorType>(); + auto *ToVec = ToType->castAs<VectorType>(); + QualType ElType = FromVec->getElementType(); + QualType TruncTy = + Context.getExtVectorType(ElType, ToVec->getNumElements()); + From = ImpCastExprToType(From, TruncTy, CK_HLSLVectorTruncation, + From->getValueKind()) + .get(); + break; + } + case ICK_Identity: + default: + llvm_unreachable("Improper element standard conversion"); + } + } + switch (SCS.Third) { case ICK_Identity: // Nothing to do. @@ -4858,6 +4931,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, return From; } +/// Checks that type T is not a VLA. +/// +/// @returns @c true if @p T is VLA and a diagnostic was emitted, +/// @c false otherwise. +static bool DiagnoseVLAInCXXTypeTrait(Sema &S, const TypeSourceInfo *T, + clang::tok::TokenKind TypeTraitID) { + if (!T->getType()->isVariableArrayType()) + return false; + + S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported) + << 1 << TypeTraitID; + return true; +} + /// Check the completeness of a type in a unary type trait. /// /// If the particular type trait requires a complete type, tries to complete @@ -4962,6 +5049,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsStandardLayout: case UTT_IsPOD: case UTT_IsLiteral: + case UTT_IsBitwiseCloneable: // By analogy, is_trivially_relocatable and is_trivially_equality_comparable // impose the same constraints. case UTT_IsTriviallyRelocatable: @@ -4981,6 +5069,10 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_HasTrivialCopy: case UTT_HasTrivialDestructor: case UTT_HasVirtualDestructor: + // has_unique_object_representations<T> when T is an array is defined in terms + // of has_unique_object_representations<remove_all_extents_t<T>>, so the base + // type needs to be complete even if the type is an incomplete array type. + case UTT_HasUniqueObjectRepresentations: ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0); [[fallthrough]]; @@ -4989,7 +5081,6 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsDestructible: case UTT_IsNothrowDestructible: case UTT_IsTriviallyDestructible: - case UTT_HasUniqueObjectRepresentations: if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType()) return true; @@ -5033,8 +5124,88 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, return false; } +static bool HasNonDeletedDefaultedEqualityComparison(Sema &S, + const CXXRecordDecl *Decl, + SourceLocation KeyLoc) { + if (Decl->isUnion()) + return false; + if (Decl->isLambda()) + return Decl->isCapturelessLambda(); + + { + EnterExpressionEvaluationContext UnevaluatedContext( + S, Sema::ExpressionEvaluationContext::Unevaluated); + Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl()); + + // const ClassT& obj; + OpaqueValueExpr Operand( + KeyLoc, + Decl->getTypeForDecl()->getCanonicalTypeUnqualified().withConst(), + ExprValueKind::VK_LValue); + UnresolvedSet<16> Functions; + // obj == obj; + S.LookupBinOp(S.TUScope, {}, BinaryOperatorKind::BO_EQ, Functions); + + auto Result = S.CreateOverloadedBinOp(KeyLoc, BinaryOperatorKind::BO_EQ, + Functions, &Operand, &Operand); + if (Result.isInvalid() || SFINAE.hasErrorOccurred()) + return false; + + const auto *CallExpr = dyn_cast<CXXOperatorCallExpr>(Result.get()); + if (!CallExpr) + return false; + const auto *Callee = CallExpr->getDirectCallee(); + auto ParamT = Callee->getParamDecl(0)->getType(); + if (!Callee->isDefaulted()) + return false; + if (!ParamT->isReferenceType() && !Decl->isTriviallyCopyable()) + return false; + if (ParamT.getNonReferenceType()->getUnqualifiedDesugaredType() != + Decl->getTypeForDecl()) + return false; + } + + return llvm::all_of(Decl->bases(), + [&](const CXXBaseSpecifier &BS) { + if (const auto *RD = BS.getType()->getAsCXXRecordDecl()) + return HasNonDeletedDefaultedEqualityComparison( + S, RD, KeyLoc); + return true; + }) && + llvm::all_of(Decl->fields(), [&](const FieldDecl *FD) { + auto Type = FD->getType(); + if (Type->isArrayType()) + Type = Type->getBaseElementTypeUnsafe() + ->getCanonicalTypeUnqualified(); + + if (Type->isReferenceType() || Type->isEnumeralType()) + return false; + if (const auto *RD = Type->getAsCXXRecordDecl()) + return HasNonDeletedDefaultedEqualityComparison(S, RD, KeyLoc); + return true; + }); +} + +static bool isTriviallyEqualityComparableType(Sema &S, QualType Type, SourceLocation KeyLoc) { + QualType CanonicalType = Type.getCanonicalType(); + if (CanonicalType->isIncompleteType() || CanonicalType->isDependentType() || + CanonicalType->isEnumeralType() || CanonicalType->isArrayType()) + return false; + + if (const auto *RD = CanonicalType->getAsCXXRecordDecl()) { + if (!HasNonDeletedDefaultedEqualityComparison(S, RD, KeyLoc)) + return false; + } + + return S.getASTContext().hasUniqueObjectRepresentations( + CanonicalType, /*CheckIfTriviallyCopyable=*/false); +} + static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, - SourceLocation KeyLoc, QualType T) { + SourceLocation KeyLoc, + TypeSourceInfo *TInfo) { + QualType T = TInfo->getType(); assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); ASTContext &C = Self.Context; @@ -5049,23 +5220,23 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, case UTT_IsFloatingPoint: return T->isFloatingType(); case UTT_IsArray: + // Zero-sized arrays aren't considered arrays in partial specializations, + // so __is_array shouldn't consider them arrays either. + if (const auto *CAT = C.getAsConstantArrayType(T)) + return CAT->getSize() != 0; return T->isArrayType(); case UTT_IsBoundedArray: - if (!T->isVariableArrayType()) { - return T->isArrayType() && !T->isIncompleteArrayType(); - } - - Self.Diag(KeyLoc, diag::err_vla_unsupported) - << 1 << tok::kw___is_bounded_array; - return false; + if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_bounded_array)) + return false; + // Zero-sized arrays aren't considered arrays in partial specializations, + // so __is_bounded_array shouldn't consider them arrays either. + if (const auto *CAT = C.getAsConstantArrayType(T)) + return CAT->getSize() != 0; + return T->isArrayType() && !T->isIncompleteArrayType(); case UTT_IsUnboundedArray: - if (!T->isVariableArrayType()) { - return T->isIncompleteArrayType(); - } - - Self.Diag(KeyLoc, diag::err_vla_unsupported) - << 1 << tok::kw___is_unbounded_array; - return false; + if (DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___is_unbounded_array)) + return false; + return T->isIncompleteArrayType(); case UTT_IsPointer: return T->isAnyPointerType(); case UTT_IsNullPointer: @@ -5453,6 +5624,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return C.hasUniqueObjectRepresentations(T); case UTT_IsTriviallyRelocatable: return T.isTriviallyRelocatableType(C); + case UTT_IsBitwiseCloneable: + return T.isBitwiseCloneableType(C); case UTT_IsReferenceable: return T.isReferenceable(); case UTT_CanPassInRegs: @@ -5461,12 +5634,82 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, Self.Diag(KeyLoc, diag::err_builtin_pass_in_regs_non_class) << T; return false; case UTT_IsTriviallyEqualityComparable: - return T.isTriviallyEqualityComparableType(C); + return isTriviallyEqualityComparableType(Self, T, KeyLoc); } } -static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, - QualType RhsT, SourceLocation KeyLoc); +static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceInfo *Lhs, + const TypeSourceInfo *Rhs, SourceLocation KeyLoc); + +static ExprResult CheckConvertibilityForTypeTraits( + Sema &Self, const TypeSourceInfo *Lhs, const TypeSourceInfo *Rhs, + SourceLocation KeyLoc, llvm::BumpPtrAllocator &OpaqueExprAllocator) { + + QualType LhsT = Lhs->getType(); + QualType RhsT = Rhs->getType(); + + // C++0x [meta.rel]p4: + // Given the following function prototype: + // + // template <class T> + // typename add_rvalue_reference<T>::type create(); + // + // the predicate condition for a template specialization + // is_convertible<From, To> shall be satisfied if and only if + // the return expression in the following code would be + // well-formed, including any implicit conversions to the return + // type of the function: + // + // To test() { + // return create<From>(); + // } + // + // Access checking is performed as if in a context unrelated to To and + // From. Only the validity of the immediate context of the expression + // of the return-statement (including conversions to the return type) + // is considered. + // + // We model the initialization as a copy-initialization of a temporary + // of the appropriate type, which for this expression is identical to the + // return statement (since NRVO doesn't apply). + + // Functions aren't allowed to return function or array types. + if (RhsT->isFunctionType() || RhsT->isArrayType()) + return ExprError(); + + // A function definition requires a complete, non-abstract return type. + if (!Self.isCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT) || + Self.isAbstractType(Rhs->getTypeLoc().getBeginLoc(), RhsT)) + return ExprError(); + + // Compute the result of add_rvalue_reference. + if (LhsT->isObjectType() || LhsT->isFunctionType()) + LhsT = Self.Context.getRValueReferenceType(LhsT); + + // Build a fake source and destination for initialization. + InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT)); + Expr *From = new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>()) + OpaqueValueExpr(KeyLoc, LhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(LhsT)); + InitializationKind Kind = + InitializationKind::CreateCopy(KeyLoc, SourceLocation()); + + // Perform the initialization in an unevaluated context within a SFINAE + // trap at translation unit scope. + EnterExpressionEvaluationContext Unevaluated( + Self, Sema::ExpressionEvaluationContext::Unevaluated); + Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl()); + InitializationSequence Init(Self, To, Kind, From); + if (Init.Failed()) + return ExprError(); + + ExprResult Result = Init.Perform(Self, To, Kind, From); + if (Result.isInvalid() || SFINAE.hasErrorOccurred()) + return ExprError(); + + return Result; +} static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, @@ -5477,17 +5720,20 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, return false; if (Kind <= UTT_Last) - return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType()); + return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]); // Evaluate ReferenceBindsToTemporary and ReferenceConstructsFromTemporary // alongside the IsConstructible traits to avoid duplication. - if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary && Kind != BTT_ReferenceConstructsFromTemporary) - return EvaluateBinaryTypeTrait(S, Kind, Args[0]->getType(), - Args[1]->getType(), RParenLoc); + if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary && + Kind != BTT_ReferenceConstructsFromTemporary && + Kind != BTT_ReferenceConvertsFromTemporary) + return EvaluateBinaryTypeTrait(S, Kind, Args[0], + Args[1], RParenLoc); switch (Kind) { case clang::BTT_ReferenceBindsToTemporary: case clang::BTT_ReferenceConstructsFromTemporary: + case clang::BTT_ReferenceConvertsFromTemporary: case clang::TT_IsConstructible: case clang::TT_IsNothrowConstructible: case clang::TT_IsTriviallyConstructible: { @@ -5551,8 +5797,10 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl()); InitializedEntity To( InitializedEntity::InitializeTemporary(S.Context, Args[0])); - InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc, - RParenLoc)); + InitializationKind InitKind( + Kind == clang::BTT_ReferenceConvertsFromTemporary + ? InitializationKind::CreateCopy(KWLoc, KWLoc) + : InitializationKind::CreateDirect(KWLoc, KWLoc, RParenLoc)); InitializationSequence Init(S, To, InitKind, ArgExprs); if (Init.Failed()) return false; @@ -5564,7 +5812,9 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, if (Kind == clang::TT_IsConstructible) return true; - if (Kind == clang::BTT_ReferenceBindsToTemporary || Kind == clang::BTT_ReferenceConstructsFromTemporary) { + if (Kind == clang::BTT_ReferenceBindsToTemporary || + Kind == clang::BTT_ReferenceConstructsFromTemporary || + Kind == clang::BTT_ReferenceConvertsFromTemporary) { if (!T->isReferenceType()) return false; @@ -5578,9 +5828,13 @@ static bool EvaluateBooleanTypeTrait(Sema &S, TypeTrait Kind, if (U->isReferenceType()) return false; - QualType TPtr = S.Context.getPointerType(S.BuiltinRemoveReference(T, UnaryTransformType::RemoveCVRef, {})); - QualType UPtr = S.Context.getPointerType(S.BuiltinRemoveReference(U, UnaryTransformType::RemoveCVRef, {})); - return EvaluateBinaryTypeTrait(S, TypeTrait::BTT_IsConvertibleTo, UPtr, TPtr, RParenLoc); + TypeSourceInfo *TPtr = S.Context.CreateTypeSourceInfo( + S.Context.getPointerType(T.getNonReferenceType())); + TypeSourceInfo *UPtr = S.Context.CreateTypeSourceInfo( + S.Context.getPointerType(U.getNonReferenceType())); + return !CheckConvertibilityForTypeTraits(S, UPtr, TPtr, RParenLoc, + OpaqueExprAllocator) + .isInvalid(); } if (Kind == clang::TT_IsNothrowConstructible) @@ -5713,8 +5967,11 @@ ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc); } -static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, - QualType RhsT, SourceLocation KeyLoc) { +static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceInfo *Lhs, + const TypeSourceInfo *Rhs, SourceLocation KeyLoc) { + QualType LhsT = Lhs->getType(); + QualType RhsT = Rhs->getType(); + assert(!LhsT->isDependentType() && !RhsT->isDependentType() && "Cannot evaluate traits of dependent types"); @@ -5739,7 +5996,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, return false; if (Self.RequireCompleteType( - KeyLoc, RhsT, diag::err_incomplete_type_used_in_type_trait_expr)) + Rhs->getTypeLoc().getBeginLoc(), RhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) return false; return BaseInterface->isSuperClassOf(DerivedInterface); @@ -5762,8 +6020,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, // If Base and Derived are class types and are different types // (ignoring possible cv-qualifiers) then Derived shall be a // complete type. - if (Self.RequireCompleteType(KeyLoc, RhsT, - diag::err_incomplete_type_used_in_type_trait_expr)) + if (Self.RequireCompleteType( + Rhs->getTypeLoc().getBeginLoc(), RhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) return false; return cast<CXXRecordDecl>(rhsRecord->getDecl()) @@ -5779,68 +6038,20 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, return Self.Context.typesAreCompatible(Lhs, Rhs); } case BTT_IsConvertible: - case BTT_IsConvertibleTo: { - // C++0x [meta.rel]p4: - // Given the following function prototype: - // - // template <class T> - // typename add_rvalue_reference<T>::type create(); - // - // the predicate condition for a template specialization - // is_convertible<From, To> shall be satisfied if and only if - // the return expression in the following code would be - // well-formed, including any implicit conversions to the return - // type of the function: - // - // To test() { - // return create<From>(); - // } - // - // Access checking is performed as if in a context unrelated to To and - // From. Only the validity of the immediate context of the expression - // of the return-statement (including conversions to the return type) - // is considered. - // - // We model the initialization as a copy-initialization of a temporary - // of the appropriate type, which for this expression is identical to the - // return statement (since NRVO doesn't apply). - - // Functions aren't allowed to return function or array types. - if (RhsT->isFunctionType() || RhsT->isArrayType()) - return false; - - // A return statement in a void function must have void type. + case BTT_IsConvertibleTo: + case BTT_IsNothrowConvertible: { if (RhsT->isVoidType()) return LhsT->isVoidType(); - - // A function definition requires a complete, non-abstract return type. - if (!Self.isCompleteType(KeyLoc, RhsT) || Self.isAbstractType(KeyLoc, RhsT)) + llvm::BumpPtrAllocator OpaqueExprAllocator; + ExprResult Result = CheckConvertibilityForTypeTraits(Self, Lhs, Rhs, KeyLoc, + OpaqueExprAllocator); + if (Result.isInvalid()) return false; - // Compute the result of add_rvalue_reference. - if (LhsT->isObjectType() || LhsT->isFunctionType()) - LhsT = Self.Context.getRValueReferenceType(LhsT); - - // Build a fake source and destination for initialization. - InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT)); - OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context), - Expr::getValueKindForType(LhsT)); - Expr *FromPtr = &From; - InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, - SourceLocation())); - - // Perform the initialization in an unevaluated context within a SFINAE - // trap at translation unit scope. - EnterExpressionEvaluationContext Unevaluated( - Self, Sema::ExpressionEvaluationContext::Unevaluated); - Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true); - Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl()); - InitializationSequence Init(Self, To, Kind, FromPtr); - if (Init.Failed()) - return false; + if (BTT != BTT_IsNothrowConvertible) + return true; - ExprResult Result = Init.Perform(Self, To, Kind, FromPtr); - return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); + return Self.canThrow(Result.get()) == CT_Cannot; } case BTT_IsAssignable: @@ -5858,12 +6069,14 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, // For both, T and U shall be complete types, (possibly cv-qualified) // void, or arrays of unknown bound. if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType() && - Self.RequireCompleteType(KeyLoc, LhsT, - diag::err_incomplete_type_used_in_type_trait_expr)) + Self.RequireCompleteType( + Lhs->getTypeLoc().getBeginLoc(), LhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) return false; if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType() && - Self.RequireCompleteType(KeyLoc, RhsT, - diag::err_incomplete_type_used_in_type_trait_expr)) + Self.RequireCompleteType( + Rhs->getTypeLoc().getBeginLoc(), RhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) return false; // cv void is never assignable. @@ -5916,7 +6129,42 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, llvm_unreachable("unhandled type trait"); return false; } - default: llvm_unreachable("not a BTT"); + case BTT_IsLayoutCompatible: { + if (!LhsT->isVoidType() && !LhsT->isIncompleteArrayType()) + Self.RequireCompleteType(Lhs->getTypeLoc().getBeginLoc(), LhsT, + diag::err_incomplete_type); + if (!RhsT->isVoidType() && !RhsT->isIncompleteArrayType()) + Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT, + diag::err_incomplete_type); + + DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___is_layout_compatible); + DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___is_layout_compatible); + + return Self.IsLayoutCompatible(LhsT, RhsT); + } + case BTT_IsPointerInterconvertibleBaseOf: { + if (LhsT->isStructureOrClassType() && RhsT->isStructureOrClassType() && + !Self.getASTContext().hasSameUnqualifiedType(LhsT, RhsT)) { + Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT, + diag::err_incomplete_type); + } + + DiagnoseVLAInCXXTypeTrait(Self, Lhs, + tok::kw___is_pointer_interconvertible_base_of); + DiagnoseVLAInCXXTypeTrait(Self, Rhs, + tok::kw___is_pointer_interconvertible_base_of); + + return Self.IsPointerInterconvertibleBaseOf(Lhs, Rhs); + } + case BTT_IsDeducible: { + const auto *TSTToBeDeduced = cast<DeducedTemplateSpecializationType>(LhsT); + sema::TemplateDeductionInfo Info(KeyLoc); + return Self.DeduceTemplateArgumentsFromType( + TSTToBeDeduced->getTemplateName().getAsTemplateDecl(), RhsT, + Info) == TemplateDeductionResult::Success; + } + default: + llvm_unreachable("not a BTT"); } llvm_unreachable("Unknown type trait or not implemented"); } @@ -5979,7 +6227,7 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, if (Matched && T->isArrayType()) { if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T)) - return CAT->getSize().getLimitedValue(); + return CAT->getLimitedSize(); } } return 0; @@ -6568,26 +6816,6 @@ QualType Sema::CheckSizelessVectorConditionalTypes(ExprResult &Cond, return ResultType; } -/// Check the operands of ?: under C++ semantics. -/// -/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y -/// extension. In this case, LHS == Cond. (But they're not aliases.) -/// -/// This function also implements GCC's vector extension and the -/// OpenCL/ext_vector_type extension for conditionals. The vector extensions -/// permit the use of a?b:c where the type of a is that of a integer vector with -/// the same number of elements and size as the vectors of b and c. If one of -/// either b or c is a scalar it is implicitly converted to match the type of -/// the vector. Otherwise the expression is ill-formed. If both b and c are -/// scalars, then b and c are checked and converted to the type of a if -/// possible. -/// -/// The expressions are evaluated differently for GCC's and OpenCL's extensions. -/// For the GCC extension, the ?: operator is evaluated as -/// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]). -/// For the OpenCL extensions, the ?: operator is evaluated as -/// (most-significant-bit-set(a[0]) ? b[0] : c[0], .. , -/// most-significant-bit-set(a[n]) ? b[n] : c[n]). QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, ExprObjectKind &OK, @@ -6872,7 +7100,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, return Composite; // Similarly, attempt to find composite type of two objective-c pointers. - Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); + Composite = ObjC().FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); if (!Composite.isNull()) @@ -6888,17 +7116,6 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, return QualType(); } -/// Find a merged pointer type and convert the two expressions to it. -/// -/// This finds the composite pointer type for \p E1 and \p E2 according to -/// C++2a [expr.type]p3. It converts both expressions to this type and returns -/// it. It does not emit diagnostics (FIXME: that's not true if \p ConvertArgs -/// is \c true). -/// -/// \param Loc The location of the operator requiring these two expressions to -/// be converted to the composite pointer type. -/// -/// \param ConvertArgs If \c false, do not convert E1 and E2 to the target type. QualType Sema::FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, bool ConvertArgs) { @@ -7485,10 +7702,6 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { return MaybeCreateExprWithCleanups(E); } -/// Process the expression contained within a decltype. For such expressions, -/// certain semantic checks on temporaries are delayed until this point, and -/// are omitted for the 'topmost' call in the decltype expression. If the -/// topmost call bound a temporary, strip that temporary off the expression. ExprResult Sema::ActOnDecltypeExpression(Expr *E) { assert(ExprEvalContexts.back().ExprContext == ExpressionEvaluationContextRecord::EK_Decltype && @@ -8099,20 +8312,36 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SourceLocation TildeLoc, const DeclSpec& DS) { QualType ObjectType; + QualType T; + TypeLocBuilder TLB; if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) return ExprError(); - if (DS.getTypeSpecType() == DeclSpec::TST_decltype_auto) { + switch (DS.getTypeSpecType()) { + case DeclSpec::TST_decltype_auto: { Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid); return true; } - - QualType T = BuildDecltypeType(DS.getRepAsExpr(), /*AsUnevaluated=*/false); - - TypeLocBuilder TLB; - DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); - DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc()); - DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd()); + case DeclSpec::TST_decltype: { + T = BuildDecltypeType(DS.getRepAsExpr(), /*AsUnevaluated=*/false); + DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); + DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc()); + DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd()); + break; + } + case DeclSpec::TST_typename_pack_indexing: { + T = ActOnPackIndexingType(DS.getRepAsType().get(), DS.getPackIndexingExpr(), + DS.getBeginLoc(), DS.getEllipsisLoc()); + TLB.pushTrivial(getASTContext(), + cast<PackIndexingType>(T.getTypePtr())->getPattern(), + DS.getBeginLoc()); + PackIndexingTypeLoc PITL = TLB.push<PackIndexingTypeLoc>(T); + PITL.setEllipsisLoc(DS.getEllipsisLoc()); + break; + } + default: + llvm_unreachable("Unsupported type in pseudo destructor"); + } TypeSourceInfo *DestructedTypeInfo = TLB.getTypeSourceInfo(Context, T); PseudoDestructorTypeStorage Destructed(DestructedTypeInfo); @@ -8206,21 +8435,6 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { E = result.get(); } - // C99 6.3.2.1: - // [Except in specific positions,] an lvalue that does not have - // array type is converted to the value stored in the - // designated object (and is no longer an lvalue). - if (E->isPRValue()) { - // In C, function designators (i.e. expressions of function type) - // are r-values, but we still want to do function-to-pointer decay - // on them. This is both technically correct and convenient for - // some clients. - if (!getLangOpts().CPlusPlus && E->getType()->isFunctionType()) - return DefaultFunctionArrayConversion(E); - - return E; - } - if (getLangOpts().CPlusPlus) { // The C++11 standard defines the notion of a discarded-value expression; // normally, we don't need to do anything to handle it, but if it is a @@ -8241,11 +8455,32 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { // If the expression is a prvalue after this optional conversion, the // temporary materialization conversion is applied. // - // We skip this step: IR generation is able to synthesize the storage for - // itself in the aggregate case, and adding the extra node to the AST is - // just clutter. - // FIXME: We don't emit lifetime markers for the temporaries due to this. - // FIXME: Do any other AST consumers care about this? + // We do not materialize temporaries by default in order to avoid creating + // unnecessary temporary objects. If we skip this step, IR generation is + // able to synthesize the storage for itself in the aggregate case, and + // adding the extra node to the AST is just clutter. + if (isInLifetimeExtendingContext() && getLangOpts().CPlusPlus17 && + E->isPRValue() && !E->getType()->isVoidType()) { + ExprResult Res = TemporaryMaterializationConversion(E); + if (Res.isInvalid()) + return E; + E = Res.get(); + } + return E; + } + + // C99 6.3.2.1: + // [Except in specific positions,] an lvalue that does not have + // array type is converted to the value stored in the + // designated object (and is no longer an lvalue). + if (E->isPRValue()) { + // In C, function designators (i.e. expressions of function type) + // are r-values, but we still want to do function-to-pointer decay + // on them. This is both technically correct and convenient for + // some clients. + if (!getLangOpts().CPlusPlus && E->getType()->isFunctionType()) + return DefaultFunctionArrayConversion(E); + return E; } @@ -8326,7 +8561,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures( assert(S.CurContext->isDependentContext()); #ifndef NDEBUG DeclContext *DC = S.CurContext; - while (DC && isa<CapturedDecl>(DC)) + while (isa_and_nonnull<CapturedDecl>(DC)) DC = DC->getParent(); assert( CurrentLSI->CallOperator == DC && @@ -8437,27 +8672,14 @@ static ExprResult attemptRecovery(Sema &SemaRef, // Detect and handle the case where the decl might be an implicit // member. - bool MightBeImplicitMember; - if (!Consumer.isAddressOfOperand()) - MightBeImplicitMember = true; - else if (!NewSS.isEmpty()) - MightBeImplicitMember = false; - else if (R.isOverloadedResult()) - MightBeImplicitMember = false; - else if (R.isUnresolvableResult()) - MightBeImplicitMember = true; - else - MightBeImplicitMember = isa<FieldDecl>(ND) || - isa<IndirectFieldDecl>(ND) || - isa<MSPropertyDecl>(ND); - - if (MightBeImplicitMember) + if (SemaRef.isPotentialImplicitMemberAccess( + NewSS, R, Consumer.isAddressOfOperand())) return SemaRef.BuildPossibleImplicitMemberExpr( NewSS, /*TemplateKWLoc*/ SourceLocation(), R, /*TemplateArgs*/ nullptr, /*S*/ nullptr); } else if (auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) { - return SemaRef.LookupInObjCMethod(R, Consumer.getScope(), - Ivar->getIdentifier()); + return SemaRef.ObjC().LookupInObjCMethod(R, Consumer.getScope(), + Ivar->getIdentifier()); } } @@ -8916,7 +9138,7 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, // - Teach the handful of places that iterate over FunctionScopes to // stop at the outermost enclosing lexical scope." DeclContext *DC = CurContext; - while (DC && isa<CapturedDecl>(DC)) + while (isa_and_nonnull<CapturedDecl>(DC)) DC = DC->getParent(); const bool IsInLambdaDeclContext = isLambdaCallOperator(DC); if (IsInLambdaDeclContext && CurrentLSI && @@ -8946,8 +9168,8 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, // Do the redeclaration lookup in the current scope. LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName, - Sema::NotForRedeclaration); - LookupParsedName(R, S, &SS); + RedeclarationKind::NotForRedeclaration); + LookupParsedName(R, S, &SS, /*ObjectType=*/QualType()); R.suppressDiagnostics(); switch (R.getResultKind()) { @@ -8988,10 +9210,9 @@ concepts::Requirement *Sema::ActOnSimpleRequirement(Expr *E) { /*ReturnTypeRequirement=*/{}); } -concepts::Requirement * -Sema::ActOnTypeRequirement(SourceLocation TypenameKWLoc, CXXScopeSpec &SS, - SourceLocation NameLoc, IdentifierInfo *TypeName, - TemplateIdAnnotation *TemplateId) { +concepts::Requirement *Sema::ActOnTypeRequirement( + SourceLocation TypenameKWLoc, CXXScopeSpec &SS, SourceLocation NameLoc, + const IdentifierInfo *TypeName, TemplateIdAnnotation *TemplateId) { assert(((!TypeName && TemplateId) || (TypeName && !TemplateId)) && "Exactly one of TypeName and TemplateId must be specified."); TypeSourceInfo *TSI = nullptr; @@ -9091,9 +9312,7 @@ Sema::BuildExprRequirement( auto *Param = cast<TemplateTypeParmDecl>(TPL->getParam(0)); - TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args); - MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray(), - /*Final=*/false); + MultiLevelTemplateArgumentList MLTAL(Param, Args, /*Final=*/false); MLTAL.addOuterRetainedLevels(TPL->getDepth()); const TypeConstraint *TC = Param->getTypeConstraint(); assert(TC && "Type Constraint cannot be null here"); |