diff options
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 156 |
1 files changed, 91 insertions, 65 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 8c89a3cee3..881e0f6546 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1,9 +1,8 @@ //===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -751,12 +750,10 @@ 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) && - (!getLangOpts().OpenMPIsDevice || - !getLangOpts().OpenMPHostCXXExceptions || - isInOpenMPTargetExecutionDirective() || - isInOpenMPDeclareTargetContext())) - Diag(OpLoc, diag::err_exceptions_disabled) << "throw"; + !getSourceManager().isInSystemHeader(OpLoc) && !getLangOpts().CUDA) { + // Delay error emission for the OpenMP device code. + targetDiag(OpLoc, diag::err_exceptions_disabled) << "throw"; + } // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) @@ -1666,7 +1663,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, SourceRange TypeIdParens, Declarator &D, Expr *Initializer) { - Expr *ArraySize = nullptr; + Optional<Expr *> ArraySize; // If the specified type is an array, unwrap it and save the expression. if (D.getNumTypeObjects() > 0 && D.getTypeObject(0).Kind == DeclaratorChunk::Array) { @@ -1677,7 +1674,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (Chunk.Arr.hasStatic) return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new) << D.getSourceRange()); - if (!Chunk.Arr.NumElts) + if (!Chunk.Arr.NumElts && !Initializer) return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size) << D.getSourceRange()); @@ -1790,7 +1787,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, SourceRange TypeIdParens, QualType AllocType, TypeSourceInfo *AllocTypeInfo, - Expr *ArraySize, + Optional<Expr *> ArraySize, SourceRange DirectInitRange, Expr *Initializer) { SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); @@ -1841,9 +1838,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, auto *Deduced = AllocType->getContainedDeducedType(); if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) { if (ArraySize) - return ExprError(Diag(ArraySize->getExprLoc(), - diag::err_deduced_class_template_compound_type) - << /*array*/ 2 << ArraySize->getSourceRange()); + return ExprError( + Diag(ArraySize ? (*ArraySize)->getExprLoc() : TypeRange.getBegin(), + diag::err_deduced_class_template_compound_type) + << /*array*/ 2 + << (ArraySize ? (*ArraySize)->getSourceRange() : TypeRange)); InitializedEntity Entity = InitializedEntity::InitializeNew(StartLoc, AllocType); @@ -1873,11 +1872,12 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, if (Braced && !getLangOpts().CPlusPlus17) Diag(Initializer->getBeginLoc(), diag::ext_auto_new_list_init) << AllocType << TypeRange; + Expr *Deduce = Inits[0]; QualType DeducedType; - if (DeduceAutoType(AllocTypeInfo, Inits[0], DeducedType) == DAR_Failed) + if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == DAR_Failed) return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) - << AllocType << Inits[0]->getType() - << TypeRange << Inits[0]->getSourceRange()); + << AllocType << Deduce->getType() + << TypeRange << Deduce->getSourceRange()); if (DeducedType.isNull()) return ExprError(); AllocType = DeducedType; @@ -1908,8 +1908,9 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, QualType ResultType = Context.getPointerType(AllocType); - if (ArraySize && ArraySize->getType()->isNonOverloadPlaceholderType()) { - ExprResult result = CheckPlaceholderExpr(ArraySize); + if (ArraySize && *ArraySize && + (*ArraySize)->getType()->isNonOverloadPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(*ArraySize); if (result.isInvalid()) return ExprError(); ArraySize = result.get(); } @@ -1921,19 +1922,19 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // C++1y [expr.new]p6: The expression [...] is implicitly converted to // std::size_t. llvm::Optional<uint64_t> KnownArraySize; - if (ArraySize && !ArraySize->isTypeDependent()) { + if (ArraySize && *ArraySize && !(*ArraySize)->isTypeDependent()) { ExprResult ConvertedSize; if (getLangOpts().CPlusPlus14) { assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?"); - ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(), + ConvertedSize = PerformImplicitConversion(*ArraySize, Context.getSizeType(), AA_Converting); if (!ConvertedSize.isInvalid() && - ArraySize->getType()->getAs<RecordType>()) + (*ArraySize)->getType()->getAs<RecordType>()) // Diagnose the compatibility of this conversion. Diag(StartLoc, diag::warn_cxx98_compat_array_size_conversion) - << ArraySize->getType() << 0 << "'size_t'"; + << (*ArraySize)->getType() << 0 << "'size_t'"; } else { class SizeConvertDiagnoser : public ICEConvertDiagnoser { protected: @@ -1987,16 +1988,16 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, : diag::ext_array_size_conversion) << T << ConvTy->isEnumeralType() << ConvTy; } - } SizeDiagnoser(ArraySize); + } SizeDiagnoser(*ArraySize); - ConvertedSize = PerformContextualImplicitConversion(StartLoc, ArraySize, + ConvertedSize = PerformContextualImplicitConversion(StartLoc, *ArraySize, SizeDiagnoser); } if (ConvertedSize.isInvalid()) return ExprError(); ArraySize = ConvertedSize.get(); - QualType SizeType = ArraySize->getType(); + QualType SizeType = (*ArraySize)->getType(); if (!SizeType->isIntegralOrUnscopedEnumerationType()) return ExprError(); @@ -2008,18 +2009,18 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // Let's see if this is a constant < 0. If so, we reject it out of hand, // per CWG1464. Otherwise, if it's not a constant, we must have an // unparenthesized array type. - if (!ArraySize->isValueDependent()) { + if (!(*ArraySize)->isValueDependent()) { llvm::APSInt Value; // We've already performed any required implicit conversion to integer or // unscoped enumeration type. // FIXME: Per CWG1464, we are required to check the value prior to // converting to size_t. This will never find a negative array size in // C++14 onwards, because Value is always unsigned here! - if (ArraySize->isIntegerConstantExpr(Value, Context)) { + if ((*ArraySize)->isIntegerConstantExpr(Value, Context)) { if (Value.isSigned() && Value.isNegative()) { - return ExprError(Diag(ArraySize->getBeginLoc(), + return ExprError(Diag((*ArraySize)->getBeginLoc(), diag::err_typecheck_negative_array_size) - << ArraySize->getSourceRange()); + << (*ArraySize)->getSourceRange()); } if (!AllocType->isDependentType()) { @@ -2027,15 +2028,15 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) return ExprError( - Diag(ArraySize->getBeginLoc(), diag::err_array_too_large) - << Value.toString(10) << ArraySize->getSourceRange()); + Diag((*ArraySize)->getBeginLoc(), diag::err_array_too_large) + << Value.toString(10) << (*ArraySize)->getSourceRange()); } KnownArraySize = Value.getZExtValue(); } else if (TypeIdParens.isValid()) { // Can't have dynamic array size when the type-id is in parentheses. - Diag(ArraySize->getBeginLoc(), diag::ext_new_paren_array_nonconst) - << ArraySize->getSourceRange() + Diag((*ArraySize)->getBeginLoc(), diag::ext_new_paren_array_nonconst) + << (*ArraySize)->getSourceRange() << FixItHint::CreateRemoval(TypeIdParens.getBegin()) << FixItHint::CreateRemoval(TypeIdParens.getEnd()); @@ -2058,10 +2059,10 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both; if (!AllocType->isDependentType() && !Expr::hasAnyTypeDependentArguments(PlacementArgs) && - FindAllocationFunctions(StartLoc, - SourceRange(PlacementLParen, PlacementRParen), - Scope, Scope, AllocType, ArraySize, PassAlignment, - PlacementArgs, OperatorNew, OperatorDelete)) + FindAllocationFunctions( + StartLoc, SourceRange(PlacementLParen, PlacementRParen), Scope, Scope, + AllocType, ArraySize.hasValue(), PassAlignment, PlacementArgs, + OperatorNew, OperatorDelete)) return ExprError(); // If this is an array allocation, compute whether the usual array @@ -2154,6 +2155,22 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, FullInit = Binder->getSubExpr(); Initializer = FullInit.get(); + + // FIXME: If we have a KnownArraySize, check that the array bound of the + // initializer is no greater than that constant value. + + if (ArraySize && !*ArraySize) { + auto *CAT = Context.getAsConstantArrayType(Initializer->getType()); + if (CAT) { + // FIXME: Track that the array size was inferred rather than explicitly + // specified. + ArraySize = IntegerLiteral::Create( + Context, CAT->getSize(), Context.getSizeType(), TypeRange.getEnd()); + } else { + Diag(TypeRange.getEnd(), diag::err_new_array_size_unknown_from_init) + << Initializer->getSourceRange(); + } + } } // Mark the new and delete operators as referenced. @@ -2303,8 +2320,8 @@ static bool resolveAllocationOverload( } if (Diagnose) { - S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call) - << R.getLookupName() << Range; + PartialDiagnosticAt PD(R.getNameLoc(), S.PDiag(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 @@ -2319,31 +2336,34 @@ static bool resolveAllocationOverload( // This was an overaligned allocation, so list the aligned candidates // first. Args.insert(Args.begin() + 1, AlignArg); - AlignedCandidates->NoteCandidates(S, OCD_AllCandidates, Args, "", + AlignedCandidates->NoteCandidates(PD, S, OCD_AllCandidates, Args, "", R.getNameLoc(), IsAligned); Args.erase(Args.begin() + 1); - Candidates.NoteCandidates(S, OCD_AllCandidates, Args, "", R.getNameLoc(), + Candidates.NoteCandidates(PD, S, OCD_AllCandidates, Args, "", R.getNameLoc(), IsUnaligned); } else { - Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + Candidates.NoteCandidates(PD, S, OCD_AllCandidates, Args); } } return true; case OR_Ambiguous: if (Diagnose) { - S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) - << R.getLookupName() << Range; - Candidates.NoteCandidates(S, OCD_ViableCandidates, Args); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), + S.PDiag(diag::err_ovl_ambiguous_call) + << R.getLookupName() << Range), + S, OCD_ViableCandidates, Args); } return true; case OR_Deleted: { 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); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), + S.PDiag(diag::err_ovl_deleted_call) + << R.getLookupName() << Range), + S, OCD_AllCandidates, Args); } return true; } @@ -2798,7 +2818,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, } } - FunctionProtoType::ExtProtoInfo EPI; + FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/false)); QualType BadAllocType; bool HasBadAllocExceptionSpec @@ -3506,22 +3527,26 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall, } 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); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), + S.PDiag(diag::err_ovl_no_viable_function_in_call) + << R.getLookupName() << Range), + 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); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), + S.PDiag(diag::err_ovl_ambiguous_call) + << R.getLookupName() << Range), + 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); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), S.PDiag(diag::err_ovl_deleted_call) + << R.getLookupName() << Range), + S, OCD_AllCandidates, Args); return true; } } @@ -6855,8 +6880,9 @@ canRecoverDotPseudoDestructorCallsOnPointerObjects(Sema &SemaRef, QualType DestructedType) { // If this is a record type, check if its destructor is callable. if (auto *RD = DestructedType->getAsCXXRecordDecl()) { - if (CXXDestructorDecl *D = SemaRef.LookupDestructor(RD)) - return SemaRef.CanUseDecl(D, /*TreatUnavailableAsInvalid=*/false); + if (RD->hasDefinition()) + if (CXXDestructorDecl *D = SemaRef.LookupDestructor(RD)) + return SemaRef.CanUseDecl(D, /*TreatUnavailableAsInvalid=*/false); return false; } |