diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp | 572 |
1 files changed, 401 insertions, 171 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index 89055aecd4b6..a1168fa34d56 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Implements semantic analysis for C++ expressions. +/// Implements semantic analysis for C++ expressions. /// //===----------------------------------------------------------------------===// @@ -42,7 +42,7 @@ using namespace clang; using namespace sema; -/// \brief Handle the result of the special case name lookup for inheriting +/// 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. @@ -80,6 +80,50 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, Context.getTrivialTypeSourceInfo(Type, NameLoc)); } +ParsedType Sema::getConstructorName(IdentifierInfo &II, + SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS, + bool EnteringContext) { + CXXRecordDecl *CurClass = getCurrentClass(S, &SS); + assert(CurClass && &II == CurClass->getIdentifier() && + "not a constructor name"); + + // When naming a constructor as a member of a dependent context (eg, in a + // friend declaration or an inherited constructor declaration), form an + // unresolved "typename" type. + if (CurClass->isDependentContext() && !EnteringContext) { + QualType T = Context.getDependentNameType(ETK_None, SS.getScopeRep(), &II); + return ParsedType::make(T); + } + + if (SS.isNotEmpty() && RequireCompleteDeclContext(SS, CurClass)) + return ParsedType(); + + // Find the injected-class-name declaration. Note that we make no attempt to + // diagnose cases where the injected-class-name is shadowed: the only + // declaration that can validly shadow the injected-class-name is a + // non-static data member, and if the class contains both a non-static data + // member and a constructor then it is ill-formed (we check that in + // CheckCompletedCXXClass). + CXXRecordDecl *InjectedClassName = nullptr; + for (NamedDecl *ND : CurClass->lookup(&II)) { + auto *RD = dyn_cast<CXXRecordDecl>(ND); + if (RD && RD->isInjectedClassName()) { + InjectedClassName = RD; + break; + } + } + if (!InjectedClassName && CurClass->isInvalidDecl()) + return ParsedType(); + assert(InjectedClassName && "couldn't find injected class name"); + + QualType T = Context.getTypeDeclType(InjectedClassName); + DiagnoseUseOfDecl(InjectedClassName, NameLoc); + MarkAnyDeclReferenced(NameLoc, InjectedClassName, /*OdrUse=*/false); + + return ParsedType::make(T); +} + ParsedType Sema::getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, @@ -383,7 +427,7 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, llvm_unreachable("unknown nested name specifier kind"); } -/// \brief Build a C++ typeid expression with a type operand. +/// Build a C++ typeid expression with a type operand. ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, @@ -408,7 +452,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceRange(TypeidLoc, RParenLoc)); } -/// \brief Build a C++ typeid expression with an expression operand. +/// Build a C++ typeid expression with an expression operand. ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *E, @@ -480,6 +524,12 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, ExprResult Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, bool isType, void *TyOrExpr, SourceLocation RParenLoc) { + // OpenCL C++ 1.0 s2.9: typeid is not supported. + if (getLangOpts().OpenCLCPlusPlus) { + return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported) + << "typeid"); + } + // Find the std::type_info type. if (!getStdNamespace()) return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); @@ -560,7 +610,7 @@ getUuidAttrOfType(Sema &SemaRef, QualType QT, } } -/// \brief Build a Microsoft __uuidof expression with a type operand. +/// Build a Microsoft __uuidof expression with a type operand. ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, @@ -580,7 +630,7 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceRange(TypeidLoc, RParenLoc)); } -/// \brief Build a Microsoft __uuidof expression with an expression operand. +/// Build a Microsoft __uuidof expression with an expression operand. ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *E, @@ -695,7 +745,11 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, bool IsThrownVarInScope) { // Don't report an error if 'throw' is used in system headers. if (!getLangOpts().CXXExceptions && - !getSourceManager().isInSystemHeader(OpLoc)) + !getSourceManager().isInSystemHeader(OpLoc) && + (!getLangOpts().OpenMPIsDevice || + !getLangOpts().OpenMPHostCXXExceptions || + isInOpenMPTargetExecutionDirective() || + isInOpenMPDeclareTargetContext())) Diag(OpLoc, diag::err_exceptions_disabled) << "throw"; // Exceptions aren't allowed in CUDA device code. @@ -728,7 +782,7 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, // exception object const VarDecl *NRVOVariable = nullptr; if (IsThrownVarInScope) - NRVOVariable = getCopyElisionCandidate(QualType(), Ex, false); + NRVOVariable = getCopyElisionCandidate(QualType(), Ex, CES_Strict); InitializedEntity Entity = InitializedEntity::InitializeException( OpLoc, ExceptionObjectTy, @@ -1114,8 +1168,9 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, assert((!ByCopy || Explicit) && "cannot implicitly capture *this by value"); - const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ? - *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1; + const int MaxFunctionScopesIndex = FunctionScopeIndexToStopAt + ? *FunctionScopeIndexToStopAt + : FunctionScopes.size() - 1; // Check that we can capture the *enclosing object* (referred to by '*this') // by the capturing-entity/closure (lambda/block/etc) at @@ -1141,7 +1196,7 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, unsigned NumCapturingClosures = 0; - for (unsigned idx = MaxFunctionScopesIndex; idx != 0; idx--) { + for (int idx = MaxFunctionScopesIndex; idx >= 0; idx--) { if (CapturingScopeInfo *CSI = dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) { if (CSI->CXXThisCaptureIndex != 0) { @@ -1196,8 +1251,8 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated // contexts. QualType ThisTy = getCurrentThisType(); - for (unsigned idx = MaxFunctionScopesIndex; NumCapturingClosures; - --idx, --NumCapturingClosures) { + for (int idx = MaxFunctionScopesIndex; NumCapturingClosures; + --idx, --NumCapturingClosures) { CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]); Expr *ThisExpr = nullptr; @@ -1244,11 +1299,16 @@ 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 LParenLoc, + SourceLocation LParenOrBraceLoc, MultiExprArg exprs, - SourceLocation RParenLoc) { + SourceLocation RParenOrBraceLoc, + bool ListInitialization) { if (!TypeRep) return ExprError(); @@ -1257,7 +1317,8 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation()); - auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); + auto Result = BuildCXXTypeConstructExpr(TInfo, LParenOrBraceLoc, exprs, + RParenOrBraceLoc, ListInitialization); // Avoid creating a non-type-dependent expression that contains typos. // Non-type-dependent expressions are liable to be discarded without // checking for embedded typos. @@ -1267,38 +1328,40 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, return Result; } -/// ActOnCXXTypeConstructExpr - 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::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, - SourceLocation LParenLoc, + SourceLocation LParenOrBraceLoc, MultiExprArg Exprs, - SourceLocation RParenLoc) { + SourceLocation RParenOrBraceLoc, + bool ListInitialization) { QualType Ty = TInfo->getType(); SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc(); if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) { - return CXXUnresolvedConstructExpr::Create(Context, TInfo, LParenLoc, Exprs, - RParenLoc); + // FIXME: CXXUnresolvedConstructExpr does not model list-initialization + // directly. We work around this by dropping the locations of the braces. + SourceRange Locs = ListInitialization + ? SourceRange() + : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); + return CXXUnresolvedConstructExpr::Create(Context, TInfo, Locs.getBegin(), + Exprs, Locs.getEnd()); } - bool ListInitialization = LParenLoc.isInvalid(); assert((!ListInitialization || (Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) && "List initialization must have initializer list as expression."); - SourceRange FullRange = SourceRange(TyBeginLoc, - ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc); + SourceRange FullRange = SourceRange(TyBeginLoc, RParenOrBraceLoc); InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo); InitializationKind Kind = Exprs.size() ? ListInitialization - ? InitializationKind::CreateDirectList(TyBeginLoc) - : InitializationKind::CreateDirect(TyBeginLoc, LParenLoc, - RParenLoc) - : InitializationKind::CreateValue(TyBeginLoc, LParenLoc, RParenLoc); + ? InitializationKind::CreateDirectList( + TyBeginLoc, LParenOrBraceLoc, RParenOrBraceLoc) + : InitializationKind::CreateDirect(TyBeginLoc, LParenOrBraceLoc, + RParenOrBraceLoc) + : InitializationKind::CreateValue(TyBeginLoc, LParenOrBraceLoc, + RParenOrBraceLoc); // C++1z [expr.type.conv]p1: // If the type is a placeholder for a deduced class type, [...perform class @@ -1319,7 +1382,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, if (Exprs.size() == 1 && !ListInitialization && !isa<InitListExpr>(Exprs[0])) { Expr *Arg = Exprs[0]; - return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenLoc, Arg, RParenLoc); + return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenOrBraceLoc, Arg, + RParenOrBraceLoc); } // For an expression of the form T(), T shall not be an array type. @@ -1367,15 +1431,18 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, // CXXTemporaryObjectExpr. It's also weird that the functional cast // is sometimes handled by initialization and sometimes not. QualType ResultType = Result.get()->getType(); + SourceRange Locs = ListInitialization + ? SourceRange() + : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); Result = CXXFunctionalCastExpr::Create( - Context, ResultType, Expr::getValueKindForType(Ty), TInfo, - CK_NoOp, Result.get(), /*Path=*/nullptr, LParenLoc, RParenLoc); + Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, + Result.get(), /*Path=*/nullptr, Locs.getBegin(), Locs.getEnd()); } return Result; } -/// \brief Determine whether the given function is a non-placement +/// Determine whether the given function is a non-placement /// deallocation function. static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) { if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) @@ -1430,7 +1497,7 @@ namespace { CUDAPref = S.IdentifyCUDAPreference(Caller, FD); } - operator bool() const { return FD; } + explicit operator bool() const { return FD; } bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize, bool WantAlign) const { @@ -1543,7 +1610,7 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, return Best && Best.HasSizeT; } -/// \brief Parsed a C++ 'new' expression (C++ 5.3.4). +/// Parsed a C++ 'new' expression (C++ 5.3.4). /// /// E.g.: /// @code new (memory) int[size][4] @endcode @@ -1593,9 +1660,9 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (Expr *NumElts = (Expr *)Array.NumElts) { if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { if (getLangOpts().CPlusPlus14) { - // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator - // shall be a converted constant expression (5.19) of type std::size_t - // and shall evaluate to a strictly positive value. + // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator + // shall be a converted constant expression (5.19) of type std::size_t + // and shall evaluate to a strictly positive value. unsigned IntWidth = Context.getTargetInfo().getIntWidth(); assert(IntWidth && "Builtin type of size 0?"); llvm::APSInt Value(IntWidth); @@ -1728,7 +1795,9 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // - Otherwise, the new-initializer is interpreted according to the // initialization rules of 8.5 for direct-initialization. : initStyle == CXXNewExpr::ListInit - ? InitializationKind::CreateDirectList(TypeRange.getBegin()) + ? InitializationKind::CreateDirectList(TypeRange.getBegin(), + Initializer->getLocStart(), + Initializer->getLocEnd()) : InitializationKind::CreateDirect(TypeRange.getBegin(), DirectInitRange.getBegin(), DirectInitRange.getEnd()); @@ -1795,13 +1864,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange)) return ExprError(); - if (initStyle == CXXNewExpr::ListInit && - isStdInitializerList(AllocType, nullptr)) { - Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(), - diag::warn_dangling_std_initializer_list) - << /*at end of FE*/0 << Inits[0]->getSourceRange(); - } - // In ARC, infer 'retaining' for the allocated if (getLangOpts().ObjCAutoRefCount && AllocType.getObjCLifetime() == Qualifiers::OCL_None && @@ -1831,7 +1893,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?"); ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(), - AA_Converting); + AA_Converting); if (!ConvertedSize.isInvalid() && ArraySize->getType()->getAs<RecordType>()) @@ -1960,11 +2022,12 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, bool PassAlignment = getLangOpts().AlignedAllocation && Alignment > NewAlignment; + AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both; if (!AllocType->isDependentType() && !Expr::hasAnyTypeDependentArguments(PlacementArgs) && FindAllocationFunctions(StartLoc, SourceRange(PlacementLParen, PlacementRParen), - UseGlobal, AllocType, ArraySize, PassAlignment, + Scope, Scope, AllocType, ArraySize, PassAlignment, PlacementArgs, OperatorNew, OperatorDelete)) return ExprError(); @@ -2099,7 +2162,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, Range, DirectInitRange); } -/// \brief Checks that a type is suitable as the allocated type +/// Checks that a type is suitable as the allocated type /// in a new-expression. bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R) { @@ -2120,7 +2183,8 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, else if (AllocType->isVariablyModifiedType()) return Diag(Loc, diag::err_variably_modified_new_type) << AllocType; - else if (AllocType.getAddressSpace() != LangAS::Default) + else if (AllocType.getAddressSpace() != LangAS::Default && + !getLangOpts().OpenCLCPlusPlus) return Diag(Loc, diag::err_address_space_qualified_new) << AllocType.getUnqualifiedType() << AllocType.getQualifiers().getAddressSpaceAttributePrintValue(); @@ -2137,12 +2201,10 @@ bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, return false; } -static bool -resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range, - SmallVectorImpl<Expr *> &Args, bool &PassAlignment, - FunctionDecl *&Operator, - OverloadCandidateSet *AlignedCandidates = nullptr, - Expr *AlignArg = nullptr) { +static bool resolveAllocationOverload( + Sema &S, LookupResult &R, SourceRange Range, SmallVectorImpl<Expr *> &Args, + bool &PassAlignment, FunctionDecl *&Operator, + OverloadCandidateSet *AlignedCandidates, Expr *AlignArg, bool Diagnose) { OverloadCandidateSet Candidates(R.getNameLoc(), OverloadCandidateSet::CSK_Normal); for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end(); @@ -2188,7 +2250,8 @@ resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range, AlignArg = Args[1]; Args.erase(Args.begin() + 1); return resolveAllocationOverload(S, R, Range, Args, PassAlignment, - Operator, &Candidates, AlignArg); + Operator, &Candidates, AlignArg, + Diagnose); } // MSVC will fall back on trying to find a matching global operator new @@ -2204,67 +2267,72 @@ resolveAllocationOverload(Sema &S, LookupResult &R, SourceRange Range, S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl()); // FIXME: This will give bad diagnostics pointing at the wrong functions. return resolveAllocationOverload(S, R, Range, Args, PassAlignment, - Operator, nullptr); + Operator, /*Candidates=*/nullptr, + /*AlignArg=*/nullptr, Diagnose); } - S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call) - << R.getLookupName() << Range; - - // If we have aligned candidates, only note the align_val_t candidates - // from AlignedCandidates and the non-align_val_t candidates from - // Candidates. - if (AlignedCandidates) { - auto IsAligned = [](OverloadCandidate &C) { - return C.Function->getNumParams() > 1 && - C.Function->getParamDecl(1)->getType()->isAlignValT(); - }; - auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); }; - - // This was an overaligned allocation, so list the aligned candidates - // first. - Args.insert(Args.begin() + 1, AlignArg); - AlignedCandidates->NoteCandidates(S, OCD_AllCandidates, Args, "", - R.getNameLoc(), IsAligned); - Args.erase(Args.begin() + 1); - Candidates.NoteCandidates(S, OCD_AllCandidates, Args, "", R.getNameLoc(), - IsUnaligned); - } else { - Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + if (Diagnose) { + S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call) + << R.getLookupName() << Range; + + // If we have aligned candidates, only note the align_val_t candidates + // from AlignedCandidates and the non-align_val_t candidates from + // Candidates. + if (AlignedCandidates) { + auto IsAligned = [](OverloadCandidate &C) { + return C.Function->getNumParams() > 1 && + C.Function->getParamDecl(1)->getType()->isAlignValT(); + }; + auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); }; + + // This was an overaligned allocation, so list the aligned candidates + // first. + Args.insert(Args.begin() + 1, AlignArg); + AlignedCandidates->NoteCandidates(S, OCD_AllCandidates, Args, "", + R.getNameLoc(), IsAligned); + Args.erase(Args.begin() + 1); + Candidates.NoteCandidates(S, OCD_AllCandidates, Args, "", R.getNameLoc(), + IsUnaligned); + } else { + Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + } } return true; case OR_Ambiguous: - S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) - << R.getLookupName() << Range; - Candidates.NoteCandidates(S, OCD_ViableCandidates, Args); + if (Diagnose) { + S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) + << R.getLookupName() << Range; + Candidates.NoteCandidates(S, OCD_ViableCandidates, Args); + } return true; case OR_Deleted: { - S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call) - << Best->Function->isDeleted() - << R.getLookupName() - << S.getDeletedOrUnavailableSuffix(Best->Function) - << Range; - Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + if (Diagnose) { + S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call) + << Best->Function->isDeleted() << R.getLookupName() + << S.getDeletedOrUnavailableSuffix(Best->Function) << Range; + Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + } return true; } } llvm_unreachable("Unreachable, bad result from BestViableFunction"); } - -/// FindAllocationFunctions - Finds the overloads of operator new and delete -/// that are appropriate for the allocation. bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, - bool UseGlobal, QualType AllocType, - bool IsArray, bool &PassAlignment, - MultiExprArg PlaceArgs, + AllocationFunctionScope NewScope, + AllocationFunctionScope DeleteScope, + QualType AllocType, bool IsArray, + bool &PassAlignment, MultiExprArg PlaceArgs, FunctionDecl *&OperatorNew, - FunctionDecl *&OperatorDelete) { + FunctionDecl *&OperatorDelete, + bool Diagnose) { // --- Choosing an allocation function --- // C++ 5.3.4p8 - 14 & 18 - // 1) If UseGlobal is true, only look in the global scope. Else, also look - // in the scope of the allocated class. + // 1) If looking in AFS_Global scope for allocation functions, only look in + // the global scope. Else, if AFS_Class, only look in the scope of the + // allocated class. If AFS_Both, look in both. // 2) If an array size is given, look for operator new[], else look for // operator new. // 3) The first argument is always size_t. Append the arguments from the @@ -2314,7 +2382,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // function's name is looked up in the global scope. Otherwise, if the // allocated type is a class type T or array thereof, the allocation // function's name is looked up in the scope of T. - if (AllocElemType->isRecordType() && !UseGlobal) + if (AllocElemType->isRecordType() && NewScope != AFS_Global) LookupQualifiedName(R, AllocElemType->getAsCXXRecordDecl()); // We can see ambiguity here if the allocation function is found in @@ -2325,8 +2393,17 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // If this lookup fails to find the name, or if the allocated type is not // a class type, the allocation function's name is looked up in the // global scope. - if (R.empty()) + if (R.empty()) { + if (NewScope == AFS_Class) + return true; + LookupQualifiedName(R, Context.getTranslationUnitDecl()); + } + + if (getLangOpts().OpenCLCPlusPlus && R.empty()) { + Diag(StartLoc, diag::err_openclcxx_not_supported) << "default new"; + return true; + } assert(!R.empty() && "implicitly declared allocation functions not found"); assert(!R.isAmbiguous() && "global allocation functions are ambiguous"); @@ -2335,7 +2412,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, R.suppressDiagnostics(); if (resolveAllocationOverload(*this, R, Range, AllocArgs, PassAlignment, - OperatorNew)) + OperatorNew, /*Candidates=*/nullptr, + /*AlignArg=*/nullptr, Diagnose)) return true; } @@ -2362,7 +2440,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // the allocated type is not a class type or array thereof, the // deallocation function's name is looked up in the global scope. LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName); - if (AllocElemType->isRecordType() && !UseGlobal) { + if (AllocElemType->isRecordType() && DeleteScope != AFS_Global) { CXXRecordDecl *RD = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl()); LookupQualifiedName(FoundDelete, RD); @@ -2372,6 +2450,9 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, bool FoundGlobalDelete = FoundDelete.empty(); if (FoundDelete.empty()) { + if (DeleteScope == AFS_Class) + return true; + DeclareGlobalNewDelete(); LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl()); } @@ -2559,6 +2640,11 @@ void Sema::DeclareGlobalNewDelete() { if (GlobalNewDeleteDeclared) return; + // OpenCL C++ 1.0 s2.9: the implicitly declared new and delete operators + // are not supported. + if (getLangOpts().OpenCLCPlusPlus) + return; + // C++ [basic.std.dynamic]p2: // [...] The following allocation and deallocation functions (18.4) are // implicitly declared in global scope in each translation unit of a @@ -2845,7 +2931,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, } namespace { -/// \brief Checks whether delete-expression, and new-expression used for +/// Checks whether delete-expression, and new-expression used for /// initializing deletee have the same array form. class MismatchingNewDeleteDetector { public: @@ -2868,7 +2954,7 @@ public: : Field(nullptr), IsArrayForm(false), EndOfTU(EndOfTU), HasUndefinedConstructors(false) {} - /// \brief Checks whether pointee of a delete-expression is initialized with + /// Checks whether pointee of a delete-expression is initialized with /// matching form of new-expression. /// /// If return value is \c VarInitMismatches or \c MemberInitMismatches at the @@ -2879,7 +2965,7 @@ public: /// couldn't be analyzed. If at least one constructor initializes the member /// with matching type of new, the return value is \c NoMismatch. MismatchResult analyzeDeleteExpr(const CXXDeleteExpr *DE); - /// \brief Analyzes a class member. + /// Analyzes a class member. /// \param Field Class member to analyze. /// \param DeleteWasArrayForm Array form-ness of the delete-expression used /// for deleting the \p Field. @@ -2892,13 +2978,13 @@ public: private: const bool EndOfTU; - /// \brief Indicates that there is at least one constructor without body. + /// Indicates that there is at least one constructor without body. bool HasUndefinedConstructors; - /// \brief Returns \c CXXNewExpr from given initialization expression. + /// Returns \c CXXNewExpr from given initialization expression. /// \param E Expression used for initializing pointee in delete-expression. /// E can be a single-element \c InitListExpr consisting of new-expression. const CXXNewExpr *getNewExprFromInitListOrExpr(const Expr *E); - /// \brief Returns whether member is initialized with mismatching form of + /// Returns whether member is initialized with mismatching form of /// \c new either by the member initializer or in-class initialization. /// /// If bodies of all constructors are not visible at the end of translation @@ -2906,7 +2992,7 @@ private: /// form of \c new, mismatch cannot be proven, and this function will return /// \c NoMismatch. MismatchResult analyzeMemberExpr(const MemberExpr *ME); - /// \brief Returns whether variable is initialized with mismatching form of + /// Returns whether variable is initialized with mismatching form of /// \c new. /// /// If variable is initialized with matching form of \c new or variable is not @@ -2914,7 +3000,7 @@ private: /// If variable is initialized with mismatching form of \c new, returns false. /// \param D Variable to analyze. bool hasMatchingVarInit(const DeclRefExpr *D); - /// \brief Checks whether the constructor initializes pointee with mismatching + /// Checks whether the constructor initializes pointee with mismatching /// form of \c new. /// /// Returns true, if member is initialized with matching form of \c new in @@ -2923,7 +3009,7 @@ private: /// constructor isn't defined at the point where delete-expression is seen, or /// member isn't initialized by the constructor. bool hasMatchingNewInCtor(const CXXConstructorDecl *CD); - /// \brief Checks whether member is initialized with matching form of + /// Checks whether member is initialized with matching form of /// \c new in member initializer list. bool hasMatchingNewInCtorInit(const CXXCtorInitializer *CI); /// Checks whether member is initialized with mismatching form of \c new by @@ -3192,7 +3278,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, QualType Pointee = Type->getAs<PointerType>()->getPointeeType(); QualType PointeeElem = Context.getBaseElementType(Pointee); - if (Pointee.getAddressSpace() != LangAS::Default) + if (Pointee.getAddressSpace() != LangAS::Default && + !getLangOpts().OpenCLCPlusPlus) return Diag(Ex.get()->getLocStart(), diag::err_address_space_qualified_delete) << Pointee.getUnqualifiedType() @@ -3267,6 +3354,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } if (!OperatorDelete) { + if (getLangOpts().OpenCLCPlusPlus) { + Diag(StartLoc, diag::err_openclcxx_not_supported) << "default delete"; + return ExprError(); + } + bool IsComplete = isCompleteType(StartLoc, Pointee); bool CanProvideSize = IsComplete && (!ArrayForm || UsualArrayDeleteWantsSize || @@ -3322,6 +3414,128 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return Result; } +static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall, + bool IsDelete, + FunctionDecl *&Operator) { + + DeclarationName NewName = S.Context.DeclarationNames.getCXXOperatorName( + IsDelete ? OO_Delete : OO_New); + + LookupResult R(S, NewName, TheCall->getLocStart(), Sema::LookupOrdinaryName); + S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl()); + assert(!R.empty() && "implicitly declared allocation functions not found"); + assert(!R.isAmbiguous() && "global allocation functions are ambiguous"); + + // We do our own custom access checks below. + R.suppressDiagnostics(); + + SmallVector<Expr *, 8> Args(TheCall->arg_begin(), TheCall->arg_end()); + OverloadCandidateSet Candidates(R.getNameLoc(), + OverloadCandidateSet::CSK_Normal); + for (LookupResult::iterator FnOvl = R.begin(), FnOvlEnd = R.end(); + FnOvl != FnOvlEnd; ++FnOvl) { + // Even member operator new/delete are implicitly treated as + // static, so don't use AddMemberCandidate. + NamedDecl *D = (*FnOvl)->getUnderlyingDecl(); + + if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) { + S.AddTemplateOverloadCandidate(FnTemplate, FnOvl.getPair(), + /*ExplicitTemplateArgs=*/nullptr, Args, + Candidates, + /*SuppressUserConversions=*/false); + continue; + } + + FunctionDecl *Fn = cast<FunctionDecl>(D); + S.AddOverloadCandidate(Fn, FnOvl.getPair(), Args, Candidates, + /*SuppressUserConversions=*/false); + } + + SourceRange Range = TheCall->getSourceRange(); + + // Do the resolution. + OverloadCandidateSet::iterator Best; + switch (Candidates.BestViableFunction(S, R.getNameLoc(), Best)) { + case OR_Success: { + // Got one! + FunctionDecl *FnDecl = Best->Function; + assert(R.getNamingClass() == nullptr && + "class members should not be considered"); + + if (!FnDecl->isReplaceableGlobalAllocationFunction()) { + S.Diag(R.getNameLoc(), diag::err_builtin_operator_new_delete_not_usual) + << (IsDelete ? 1 : 0) << Range; + S.Diag(FnDecl->getLocation(), diag::note_non_usual_function_declared_here) + << R.getLookupName() << FnDecl->getSourceRange(); + return true; + } + + Operator = FnDecl; + return false; + } + + case OR_No_Viable_Function: + S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call) + << R.getLookupName() << Range; + Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + return true; + + case OR_Ambiguous: + S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) + << R.getLookupName() << Range; + Candidates.NoteCandidates(S, OCD_ViableCandidates, Args); + return true; + + case OR_Deleted: { + S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call) + << Best->Function->isDeleted() << R.getLookupName() + << S.getDeletedOrUnavailableSuffix(Best->Function) << Range; + Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + return true; + } + } + llvm_unreachable("Unreachable, bad result from BestViableFunction"); +} + +ExprResult +Sema::SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult, + bool IsDelete) { + CallExpr *TheCall = cast<CallExpr>(TheCallResult.get()); + if (!getLangOpts().CPlusPlus) { + Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language) + << (IsDelete ? "__builtin_operator_delete" : "__builtin_operator_new") + << "C++"; + return ExprError(); + } + // CodeGen assumes it can find the global new and delete to call, + // so ensure that they are declared. + DeclareGlobalNewDelete(); + + FunctionDecl *OperatorNewOrDelete = nullptr; + if (resolveBuiltinNewDeleteOverload(*this, TheCall, IsDelete, + OperatorNewOrDelete)) + return ExprError(); + assert(OperatorNewOrDelete && "should be found"); + + TheCall->setType(OperatorNewOrDelete->getReturnType()); + for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) { + QualType ParamTy = OperatorNewOrDelete->getParamDecl(i)->getType(); + InitializedEntity Entity = + InitializedEntity::InitializeParameter(Context, ParamTy, false); + ExprResult Arg = PerformCopyInitialization( + Entity, TheCall->getArg(i)->getLocStart(), TheCall->getArg(i)); + if (Arg.isInvalid()) + return ExprError(); + TheCall->setArg(i, Arg.get()); + } + auto Callee = dyn_cast<ImplicitCastExpr>(TheCall->getCallee()); + assert(Callee && Callee->getCastKind() == CK_BuiltinFnToFnPtr && + "Callee expected to be implicit cast to a builtin function pointer"); + Callee->setType(OperatorNewOrDelete->getType()); + + return TheCallResult; +} + void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc, bool IsDelete, bool CallCanBeVirtual, bool WarnOnNonAbstractTypes, @@ -3378,7 +3592,7 @@ Sema::ConditionResult Sema::ActOnConditionVariable(Decl *ConditionVar, CK == ConditionKind::ConstexprIf); } -/// \brief Check the use of the given variable as a C++ condition in an if, +/// 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, @@ -3548,6 +3762,10 @@ 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()) + return From; + switch (ICS.getKind()) { case ImplicitConversionSequence::StandardConversion: { ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard, @@ -3607,6 +3825,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, From = CastArg.get(); + // C++ [over.match.oper]p7: + // [...] the second standard conversion sequence of a user-defined + // conversion sequence is not applied. + if (CCK == CCK_ForBuiltinOverloadedOp) + return From; + return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, AA_Converting, CCK); } @@ -4070,14 +4294,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // If this conversion sequence succeeded and involved implicitly converting a // _Nullable type to a _Nonnull one, complain. - if (CCK == CCK_ImplicitConversion) + if (!isCast(CCK)) diagnoseNullableToNonnullConversion(ToType, InitialFromType, From->getLocStart()); return From; } -/// \brief Check the completeness of a type in a unary type trait. +/// Check the completeness of a type in a unary type trait. /// /// If the particular type trait requires a complete type, tries to complete /// it. If completing the type fails, a diagnostic is emitted and false @@ -4227,7 +4451,7 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, const FunctionProtoType *CPT = Operator->getType()->getAs<FunctionProtoType>(); CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); - if (!CPT || !CPT->isNothrow(C)) + if (!CPT || !CPT->isNothrow()) return false; } } @@ -4475,7 +4699,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, const FunctionProtoType *CPT = Destructor->getType()->getAs<FunctionProtoType>(); CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); - if (!CPT || !CPT->isNothrow(C)) + if (!CPT || !CPT->isNothrow()) return false; } } @@ -4568,7 +4792,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return false; // TODO: check whether evaluating default arguments can throw. // For now, we'll be conservative and assume that they can throw. - if (!CPT->isNothrow(C) || CPT->getNumParams() > 1) + if (!CPT->isNothrow() || CPT->getNumParams() > 1) return false; } } @@ -4607,7 +4831,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return false; // FIXME: check whether evaluating default arguments can throw. // For now, we'll be conservative and assume that they can throw. - if (!CPT->isNothrow(C) || CPT->getNumParams() > 0) + if (!CPT->isNothrow() || CPT->getNumParams() > 0) return false; } } @@ -4645,11 +4869,14 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, if (Kind <= UTT_Last) return EvaluateUnaryTypeTrait(S, Kind, KWLoc, Args[0]->getType()); - if (Kind <= BTT_Last) + // Evaluate BTT_ReferenceBindsToTemporary alongside the IsConstructible + // traits to avoid duplication. + if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary) return EvaluateBinaryTypeTrait(S, Kind, Args[0]->getType(), Args[1]->getType(), RParenLoc); switch (Kind) { + case clang::BTT_ReferenceBindsToTemporary: case clang::TT_IsConstructible: case clang::TT_IsNothrowConstructible: case clang::TT_IsTriviallyConstructible: { @@ -4726,6 +4953,13 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, if (Kind == clang::TT_IsConstructible) return true; + if (Kind == clang::BTT_ReferenceBindsToTemporary) { + if (!T->isReferenceType()) + return false; + + return !Init.isDirectReferenceBinding(); + } + if (Kind == clang::TT_IsNothrowConstructible) return S.canThrow(Result.get()) == CT_Cannot; @@ -5231,8 +5465,9 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, case RQ_LValue: if (!isIndirect && !LHS.get()->Classify(Context).isLValue()) { - // C++2a allows functions with ref-qualifier & if they are also 'const'. - if (Proto->isConst()) + // C++2a allows functions with ref-qualifier & if their cv-qualifier-seq + // is (exactly) 'const'. + if (Proto->isConst() && !Proto->isVolatile()) Diag(Loc, getLangOpts().CPlusPlus2a ? diag::warn_cxx17_compat_pointer_to_const_ref_member_on_rvalue : diag::ext_pointer_to_const_ref_member_on_rvalue); @@ -5269,7 +5504,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, return Result; } -/// \brief Try to convert a type to another according to C++11 5.16p3. +/// Try to convert a type to another according to C++11 5.16p3. /// /// This is part of the parameter validation for the ? operator. If either /// value operand is a class type, the two operands are attempted to be @@ -5294,7 +5529,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, // constraint that in the conversion the reference must bind directly to // an lvalue. // -- If E2 is an xvalue: E1 can be converted to match E2 if E1 can be - // implicitly conveted to the type "rvalue reference to R2", subject to + // implicitly converted to the type "rvalue reference to R2", subject to // the constraint that the reference must bind directly. if (To->isLValue() || To->isXValue()) { QualType T = To->isLValue() ? Self.Context.getLValueReferenceType(ToType) @@ -5363,7 +5598,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, return false; } -/// \brief Try to find a common type for two according to C++0x 5.16p5. +/// Try to find a common type for two according to C++0x 5.16p5. /// /// This is part of the parameter validation for the ? operator. If either /// value operand is a class type, overload resolution is used to find a @@ -5425,7 +5660,7 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS return true; } -/// \brief Perform an "extended" implicit conversion as returned by +/// Perform an "extended" implicit conversion as returned by /// TryClassUnification. static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) { InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); @@ -5441,7 +5676,7 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) { return false; } -/// \brief Check the operands of ?: under C++ semantics. +/// 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.) @@ -5745,27 +5980,23 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1, if (EST2 == EST_None) return ESI2; if (EST1 == EST_MSAny) return ESI1; if (EST2 == EST_MSAny) return ESI2; + if (EST1 == EST_NoexceptFalse) return ESI1; + if (EST2 == EST_NoexceptFalse) return ESI2; // If either of them is non-throwing, the result is the other. if (EST1 == EST_DynamicNone) return ESI2; if (EST2 == EST_DynamicNone) return ESI1; if (EST1 == EST_BasicNoexcept) return ESI2; if (EST2 == EST_BasicNoexcept) return ESI1; + if (EST1 == EST_NoexceptTrue) return ESI2; + if (EST2 == EST_NoexceptTrue) return ESI1; - // If either of them is a non-value-dependent computed noexcept, that - // determines the result. - if (EST2 == EST_ComputedNoexcept && ESI2.NoexceptExpr && - !ESI2.NoexceptExpr->isValueDependent()) - return !ESI2.NoexceptExpr->EvaluateKnownConstInt(S.Context) ? ESI2 : ESI1; - if (EST1 == EST_ComputedNoexcept && ESI1.NoexceptExpr && - !ESI1.NoexceptExpr->isValueDependent()) - return !ESI1.NoexceptExpr->EvaluateKnownConstInt(S.Context) ? ESI1 : ESI2; // If we're left with value-dependent computed noexcept expressions, we're // stuck. Before C++17, we can just drop the exception specification entirely, // since it's not actually part of the canonical type. And this should never // happen in C++17, because it would mean we were computing the composite // pointer type of dependent types, which should never happen. - if (EST1 == EST_ComputedNoexcept || EST2 == EST_ComputedNoexcept) { + if (EST1 == EST_DependentNoexcept || EST2 == EST_DependentNoexcept) { assert(!S.getLangOpts().CPlusPlus17 && "computing composite pointer type of dependent types"); return FunctionProtoType::ExceptionSpecInfo(); @@ -5778,7 +6009,9 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1, case EST_DynamicNone: case EST_MSAny: case EST_BasicNoexcept: - case EST_ComputedNoexcept: + case EST_DependentNoexcept: + case EST_NoexceptFalse: + case EST_NoexceptTrue: llvm_unreachable("handled above"); case EST_Dynamic: { @@ -5805,7 +6038,7 @@ mergeExceptionSpecs(Sema &S, FunctionProtoType::ExceptionSpecInfo ESI1, llvm_unreachable("invalid ExceptionSpecificationType"); } -/// \brief Find a merged pointer type and convert the two expressions to it. +/// Find a merged pointer type and convert the two expressions to it. /// /// This finds the composite pointer type (or member pointer type) for @p E1 /// and @p E2 according to C++1z 5p14. It converts both expressions to this @@ -6195,7 +6428,8 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { if (RD->isInvalidDecl() || RD->isDependentContext()) return E; - bool IsDecltype = ExprEvalContexts.back().IsDecltype; + bool IsDecltype = ExprEvalContexts.back().ExprContext == + ExpressionEvaluationContextRecord::EK_Decltype; CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD); if (Destructor) { @@ -6277,7 +6511,9 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { /// 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().IsDecltype && "not in a decltype expression"); + assert(ExprEvalContexts.back().ExprContext == + ExpressionEvaluationContextRecord::EK_Decltype && + "not in a decltype expression"); // C++11 [expr.call]p11: // If a function call is a prvalue of object type, @@ -6319,7 +6555,8 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { TopBind = nullptr; // Disable the special decltype handling now. - ExprEvalContexts.back().IsDecltype = false; + ExprEvalContexts.back().ExprContext = + ExpressionEvaluationContextRecord::EK_Other; // In MS mode, don't perform any extra checking of call return types within a // decltype expression. @@ -6572,7 +6809,7 @@ static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, return false; } -/// \brief Check if it's ok to try and recover dot pseudo destructor calls on +/// Check if it's ok to try and recover dot pseudo destructor calls on /// pointer objects. static bool canRecoverDotPseudoDestructorCallsOnPointerObjects(Sema &SemaRef, @@ -6877,10 +7114,17 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, CXXConversionDecl *Method, bool HadMultipleCandidates) { + // Convert the expression to match the conversion function's implicit object + // parameter. + ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr, + FoundDecl, Method); + if (Exp.isInvalid()) + return true; + if (Method->getParent()->isLambda() && Method->getConversionType()->isBlockPointerType()) { // This is a lambda coversion to block pointer; check if the argument - // is a LambdaExpr. + // was a LambdaExpr. Expr *SubE = E; CastExpr *CE = dyn_cast<CastExpr>(SubE); if (CE && CE->getCastKind() == CK_NoOp) @@ -6897,22 +7141,16 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, DiagnosticErrorTrap Trap(Diags); PushExpressionEvaluationContext( ExpressionEvaluationContext::PotentiallyEvaluated); - ExprResult Exp = BuildBlockForLambdaConversion(E->getExprLoc(), - E->getExprLoc(), - Method, E); + ExprResult BlockExp = BuildBlockForLambdaConversion( + Exp.get()->getExprLoc(), Exp.get()->getExprLoc(), Method, Exp.get()); PopExpressionEvaluationContext(); - if (Exp.isInvalid()) - Diag(E->getExprLoc(), diag::note_lambda_to_block_conv); - return Exp; + if (BlockExp.isInvalid()) + Diag(Exp.get()->getExprLoc(), diag::note_lambda_to_block_conv); + return BlockExp; } } - ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/nullptr, - FoundDecl, Method); - if (Exp.isInvalid()) - return true; - MemberExpr *ME = new (Context) MemberExpr( Exp.get(), /*IsArrow=*/false, SourceLocation(), Method, SourceLocation(), Context.BoundMemberTy, VK_RValue, OK_Ordinary); @@ -7123,7 +7361,7 @@ static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var, return !IsVariableAConstantExpression(Var, Context); } -/// \brief Check if the current lambda has any potential captures +/// Check if the current lambda has any potential captures /// that must be captured by any of its enclosing lambdas that are ready to /// capture. If there is a lambda that can capture a nested /// potential-capture, go ahead and do so. Also, check to see if any @@ -7146,9 +7384,6 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures( const bool IsFullExprInstantiationDependent = FE->isInstantiationDependent(); - ArrayRef<const FunctionScopeInfo *> FunctionScopesArrayRef( - S.FunctionScopes.data(), S.FunctionScopes.size()); - // All the potentially captureable variables in the current nested // lambda (within a generic outer lambda), must be captured by an // outer lambda that is enclosed within a non-dependent context. @@ -7177,7 +7412,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures( // capture the variable in that lambda (and all its enclosing lambdas). if (const Optional<unsigned> Index = getStackIndexOfNearestEnclosingCaptureCapableLambda( - FunctionScopesArrayRef, Var, S)) { + S.FunctionScopes, Var, S)) { const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue(); MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(), S, &FunctionScopeIndexOfCapturableLambda); @@ -7213,7 +7448,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures( // 'this' in that lambda (and all its enclosing lambdas). if (const Optional<unsigned> Index = getStackIndexOfNearestEnclosingCaptureCapableLambda( - FunctionScopesArrayRef, /*0 is 'this'*/ nullptr, S)) { + S.FunctionScopes, /*0 is 'this'*/ nullptr, S)) { const unsigned FunctionScopeIndexOfCapturableLambda = Index.getValue(); S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation, /*Explicit*/ false, /*BuildAndDiagnose*/ true, @@ -7306,13 +7541,12 @@ class TransformTypos : public TreeTransform<TransformTypos> { llvm::SmallDenseMap<TypoExpr *, ExprResult, 2> TransformCache; llvm::SmallDenseMap<OverloadExpr *, Expr *, 4> OverloadResolution; - /// \brief Emit diagnostics for all of the TypoExprs encountered. + /// Emit diagnostics for all of the TypoExprs encountered. /// If the TypoExprs were successfully corrected, then the diagnostics should /// suggest the corrections. Otherwise the diagnostics will not suggest /// anything (having been passed an empty TypoCorrection). void EmitAllDiagnostics() { - for (auto E : TypoExprs) { - TypoExpr *TE = cast<TypoExpr>(E); + for (TypoExpr *TE : TypoExprs) { auto &State = SemaRef.getTypoExprState(TE); if (State.DiagHandler) { TypoCorrection TC = State.Consumer->getCurrentCorrection(); @@ -7333,7 +7567,7 @@ class TransformTypos : public TreeTransform<TransformTypos> { } } - /// \brief If corrections for the first TypoExpr have been exhausted for a + /// If corrections for the first TypoExpr have been exhausted for a /// given combination of the other TypoExprs, retry those corrections against /// the next combination of substitutions for the other TypoExprs by advancing /// to the next potential correction of the second TypoExpr. For the second @@ -7504,12 +7738,8 @@ Sema::CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl, if (E && !ExprEvalContexts.empty() && ExprEvalContexts.back().NumTypos && (E->isTypeDependent() || E->isValueDependent() || E->isInstantiationDependent())) { - auto TyposInContext = ExprEvalContexts.back().NumTypos; - assert(TyposInContext < ~0U && "Recursive call of CorrectDelayedTyposInExpr"); - ExprEvalContexts.back().NumTypos = ~0U; auto TyposResolved = DelayedTypos.size(); auto Result = TransformTypos(*this, InitDecl, Filter).Transform(E); - ExprEvalContexts.back().NumTypos = TyposInContext; TyposResolved -= DelayedTypos.size(); if (Result.isInvalid() || Result.get() != E) { ExprEvalContexts.back().NumTypos -= TyposResolved; |