summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r--lib/Sema/SemaExprCXX.cpp156
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;
}