aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp1778
1 files changed, 1406 insertions, 372 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp
index 04a7038d6754..ccae79636f32 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "TreeTransform.h"
+#include "UsedDeclVisitor.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
@@ -46,8 +47,10 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace sema;
+using llvm::RoundingMode;
/// Determine whether the use of this declaration is valid, without
/// emitting diagnostics.
@@ -290,6 +293,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD))
return true;
+
+ if (getLangOpts().SYCLIsDevice && !checkSYCLDeviceFunction(Loc, FD))
+ return true;
}
if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
@@ -349,6 +355,16 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc);
+ if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)) {
+ if (const auto *VD = dyn_cast<ValueDecl>(D))
+ checkDeviceDecl(VD, Loc);
+
+ if (!Context.getTargetInfo().isTLSSupported())
+ if (const auto *VD = dyn_cast<VarDecl>(D))
+ if (VD->getTLSKind() != VarDecl::TLS_None)
+ targetDiag(*Locs.begin(), diag::err_thread_unsupported);
+ }
+
if (isa<ParmVarDecl>(D) && isa<RequiresExprBodyDecl>(D->getDeclContext()) &&
!isUnevaluatedContext()) {
// C++ [expr.prim.req.nested] p3
@@ -603,6 +619,10 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
QualType T = E->getType();
assert(!T.isNull() && "r-value conversion on typeless expression?");
+ // lvalue-to-rvalue conversion cannot be applied to function or array types.
+ if (T->isFunctionType() || T->isArrayType())
+ return E;
+
// We don't want to throw lvalue-to-rvalue casts on top of
// expressions of certain types in C++.
if (getLangOpts().CPlusPlus &&
@@ -671,6 +691,9 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
Cleanup.setExprNeedsCleanups(true);
+ if (E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)
+ Cleanup.setExprNeedsCleanups(true);
+
// C++ [conv.lval]p3:
// If T is cv std::nullptr_t, the result is a null pointer constant.
CastKind CK = T->isNullPtrType() ? CK_NullToPointer : CK_LValueToRValue;
@@ -707,7 +730,7 @@ ExprResult Sema::CallExprUnaryConversions(Expr *E) {
// to function type.
if (Ty->isFunctionType()) {
Res = ImpCastExprToType(E, Context.getPointerType(Ty),
- CK_FunctionToPointerDecay).get();
+ CK_FunctionToPointerDecay);
if (Res.isInvalid())
return ExprError();
}
@@ -941,6 +964,11 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
ExprResult ExprRes = DefaultArgumentPromotion(E);
if (ExprRes.isInvalid())
return ExprError();
+
+ // Copy blocks to the heap.
+ if (ExprRes.get()->getType()->isBlockPointerType())
+ maybeExtendBlockObject(ExprRes);
+
E = ExprRes.get();
// Diagnostics regarding non-POD argument types are
@@ -1385,8 +1413,8 @@ static void checkEnumArithmeticConversions(Sema &S, Expr *LHS, Expr *RHS,
bool IsCompAssign = ACK == Sema::ACK_CompAssign;
if ((!IsCompAssign && LEnum && R->isFloatingType()) ||
(REnum && L->isFloatingType())) {
- S.Diag(Loc, S.getLangOpts().CPlusPlus2a
- ? diag::warn_arith_conv_enum_float_cxx2a
+ S.Diag(Loc, S.getLangOpts().CPlusPlus20
+ ? diag::warn_arith_conv_enum_float_cxx20
: diag::warn_arith_conv_enum_float)
<< LHS->getSourceRange() << RHS->getSourceRange()
<< (int)ACK << LEnum << L << R;
@@ -1398,24 +1426,24 @@ static void checkEnumArithmeticConversions(Sema &S, Expr *LHS, Expr *RHS,
// If either enumeration type is unnamed, it's less likely that the
// user cares about this, but this situation is still deprecated in
// C++2a. Use a different warning group.
- DiagID = S.getLangOpts().CPlusPlus2a
- ? diag::warn_arith_conv_mixed_anon_enum_types_cxx2a
+ DiagID = S.getLangOpts().CPlusPlus20
+ ? diag::warn_arith_conv_mixed_anon_enum_types_cxx20
: diag::warn_arith_conv_mixed_anon_enum_types;
} else if (ACK == Sema::ACK_Conditional) {
// Conditional expressions are separated out because they have
// historically had a different warning flag.
- DiagID = S.getLangOpts().CPlusPlus2a
- ? diag::warn_conditional_mixed_enum_types_cxx2a
+ DiagID = S.getLangOpts().CPlusPlus20
+ ? diag::warn_conditional_mixed_enum_types_cxx20
: diag::warn_conditional_mixed_enum_types;
} else if (ACK == Sema::ACK_Comparison) {
// Comparison expressions are separated out because they have
// historically had a different warning flag.
- DiagID = S.getLangOpts().CPlusPlus2a
- ? diag::warn_comparison_mixed_enum_types_cxx2a
+ DiagID = S.getLangOpts().CPlusPlus20
+ ? diag::warn_comparison_mixed_enum_types_cxx20
: diag::warn_comparison_mixed_enum_types;
} else {
- DiagID = S.getLangOpts().CPlusPlus2a
- ? diag::warn_arith_conv_mixed_enum_types_cxx2a
+ DiagID = S.getLangOpts().CPlusPlus20
+ ? diag::warn_arith_conv_mixed_enum_types_cxx20
: diag::warn_arith_conv_mixed_enum_types;
}
S.Diag(Loc, DiagID) << LHS->getSourceRange() << RHS->getSourceRange()
@@ -1476,6 +1504,11 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
if (LHSType == RHSType)
return LHSType;
+ // ExtInt types aren't subject to conversions between them or normal integers,
+ // so this fails.
+ if(LHSType->isExtIntType() || RHSType->isExtIntType())
+ return QualType();
+
// At this point, we have two different arithmetic types.
// Diagnose attempts to convert between __float128 and long double where
@@ -1760,15 +1793,15 @@ Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
// Warn on initializing an array of char from a u8 string literal; this
// becomes ill-formed in C++2a.
- if (getLangOpts().CPlusPlus && !getLangOpts().CPlusPlus2a &&
+ if (getLangOpts().CPlusPlus && !getLangOpts().CPlusPlus20 &&
!getLangOpts().Char8 && Kind == StringLiteral::UTF8) {
- Diag(StringTokLocs.front(), diag::warn_cxx2a_compat_utf8_string);
+ Diag(StringTokLocs.front(), diag::warn_cxx20_compat_utf8_string);
// Create removals for all 'u8' prefixes in the string literal(s). This
// ensures C++2a compatibility (but may change the program behavior when
// built by non-Clang compilers for which the execution character set is
// not always UTF-8).
- auto RemovalDiag = PDiag(diag::note_cxx2a_compat_utf8_string_remove_u8);
+ auto RemovalDiag = PDiag(diag::note_cxx20_compat_utf8_string_remove_u8);
SourceLocation RemovalDiagLoc;
for (const Token &Tok : StringToks) {
if (Tok.getKind() == tok::utf8_string_literal) {
@@ -1914,7 +1947,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
bool RefersToCapturedVariable =
isa<VarDecl>(D) &&
NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc());
-
+
DeclRefExpr *E = DeclRefExpr::Create(
Context, NNS, TemplateKWLoc, D, RefersToCapturedVariable, NameInfo, Ty,
VK, FoundD, TemplateArgs, getNonOdrUseReasonInCurrentContext(D));
@@ -3123,6 +3156,11 @@ ExprResult Sema::BuildDeclarationNameExpr(
return ExprError();
ExprValueKind valueKind = VK_RValue;
+ // In 'T ...V;', the type of the declaration 'V' is 'T...', but the type of
+ // a reference to 'V' is simply (unexpanded) 'T'. The type, like the value,
+ // is expanded by some outer '...' in the context of the use.
+ type = type.getNonPackExpansionType();
+
switch (D->getKind()) {
// Ignore all the non-ValueDecl kinds.
#define ABSTRACT_DECL(kind)
@@ -3268,6 +3306,9 @@ ExprResult Sema::BuildDeclarationNameExpr(
llvm_unreachable("building reference to deduction guide");
case Decl::MSProperty:
+ case Decl::MSGuid:
+ // FIXME: Should MSGuidDecl be subject to capture in OpenMP,
+ // or duplicated between host and device?
valueKind = VK_LValue;
break;
@@ -3368,6 +3409,70 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL);
}
+static std::pair<QualType, StringLiteral *>
+GetUniqueStableNameInfo(ASTContext &Context, QualType OpType,
+ SourceLocation OpLoc, PredefinedExpr::IdentKind K) {
+ std::pair<QualType, StringLiteral*> Result{{}, nullptr};
+
+ if (OpType->isDependentType()) {
+ Result.first = Context.DependentTy;
+ return Result;
+ }
+
+ std::string Str = PredefinedExpr::ComputeName(Context, K, OpType);
+ llvm::APInt Length(32, Str.length() + 1);
+ Result.first =
+ Context.adjustStringLiteralBaseType(Context.CharTy.withConst());
+ Result.first = Context.getConstantArrayType(
+ Result.first, Length, nullptr, ArrayType::Normal, /*IndexTypeQuals*/ 0);
+ Result.second = StringLiteral::Create(Context, Str, StringLiteral::Ascii,
+ /*Pascal*/ false, Result.first, OpLoc);
+ return Result;
+}
+
+ExprResult Sema::BuildUniqueStableName(SourceLocation OpLoc,
+ TypeSourceInfo *Operand) {
+ QualType ResultTy;
+ StringLiteral *SL;
+ std::tie(ResultTy, SL) = GetUniqueStableNameInfo(
+ Context, Operand->getType(), OpLoc, PredefinedExpr::UniqueStableNameType);
+
+ return PredefinedExpr::Create(Context, OpLoc, ResultTy,
+ PredefinedExpr::UniqueStableNameType, SL,
+ Operand);
+}
+
+ExprResult Sema::BuildUniqueStableName(SourceLocation OpLoc,
+ Expr *E) {
+ QualType ResultTy;
+ StringLiteral *SL;
+ std::tie(ResultTy, SL) = GetUniqueStableNameInfo(
+ Context, E->getType(), OpLoc, PredefinedExpr::UniqueStableNameExpr);
+
+ return PredefinedExpr::Create(Context, OpLoc, ResultTy,
+ PredefinedExpr::UniqueStableNameExpr, SL, E);
+}
+
+ExprResult Sema::ActOnUniqueStableNameExpr(SourceLocation OpLoc,
+ SourceLocation L, SourceLocation R,
+ ParsedType Ty) {
+ TypeSourceInfo *TInfo = nullptr;
+ QualType T = GetTypeFromParser(Ty, &TInfo);
+
+ if (T.isNull())
+ return ExprError();
+ if (!TInfo)
+ TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc);
+
+ return BuildUniqueStableName(OpLoc, TInfo);
+}
+
+ExprResult Sema::ActOnUniqueStableNameExpr(SourceLocation OpLoc,
+ SourceLocation L, SourceLocation R,
+ Expr *E) {
+ return BuildUniqueStableName(OpLoc, E);
+}
+
ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
PredefinedExpr::IdentKind IK;
@@ -3529,7 +3634,9 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (Invalid)
return ExprError();
- NumericLiteralParser Literal(TokSpelling, Tok.getLocation(), PP);
+ NumericLiteralParser Literal(TokSpelling, Tok.getLocation(),
+ PP.getSourceManager(), PP.getLangOpts(),
+ PP.getTargetInfo(), PP.getDiagnostics());
if (Literal.hadError)
return ExprError();
@@ -3882,7 +3989,7 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
TraitKind == UETT_PreferredAlignOf)) {
// sizeof(function)/alignof(function) is allowed as an extension.
S.Diag(Loc, diag::ext_sizeof_alignof_function_type)
- << TraitKind << ArgRange;
+ << getTraitSpelling(TraitKind) << ArgRange;
return false;
}
@@ -3891,7 +3998,7 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
if (T->isVoidType()) {
unsigned DiagID = S.LangOpts.OpenCL ? diag::err_opencl_sizeof_alignof_type
: diag::ext_sizeof_alignof_void_type;
- S.Diag(Loc, DiagID) << TraitKind << ArgRange;
+ S.Diag(Loc, DiagID) << getTraitSpelling(TraitKind) << ArgRange;
return false;
}
@@ -3958,7 +4065,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
return CheckVecStepTraitOperandType(*this, ExprTy, E->getExprLoc(),
E->getSourceRange());
- // Whitelist some types as extensions
+ // Explicitly list some types as extensions.
if (!CheckExtensionTraitOperandType(*this, ExprTy, E->getExprLoc(),
E->getSourceRange(), ExprKind))
return false;
@@ -3968,14 +4075,15 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
// be complete (and will attempt to complete it if it's an array of unknown
// bound).
if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
- if (RequireCompleteType(E->getExprLoc(),
- Context.getBaseElementType(E->getType()),
- diag::err_sizeof_alignof_incomplete_type, ExprKind,
- E->getSourceRange()))
+ if (RequireCompleteSizedType(
+ E->getExprLoc(), Context.getBaseElementType(E->getType()),
+ diag::err_sizeof_alignof_incomplete_or_sizeless_type,
+ getTraitSpelling(ExprKind), E->getSourceRange()))
return true;
} else {
- if (RequireCompleteExprType(E, diag::err_sizeof_alignof_incomplete_type,
- ExprKind, E->getSourceRange()))
+ if (RequireCompleteSizedExprType(
+ E, diag::err_sizeof_alignof_incomplete_or_sizeless_type,
+ getTraitSpelling(ExprKind), E->getSourceRange()))
return true;
}
@@ -3985,7 +4093,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
if (ExprTy->isFunctionType()) {
Diag(E->getExprLoc(), diag::err_sizeof_alignof_function_type)
- << ExprKind << E->getSourceRange();
+ << getTraitSpelling(ExprKind) << E->getSourceRange();
return true;
}
@@ -4067,19 +4175,19 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
if (ExprKind == UETT_VecStep)
return CheckVecStepTraitOperandType(*this, ExprType, OpLoc, ExprRange);
- // Whitelist some types as extensions
+ // Explicitly list some types as extensions.
if (!CheckExtensionTraitOperandType(*this, ExprType, OpLoc, ExprRange,
ExprKind))
return false;
- if (RequireCompleteType(OpLoc, ExprType,
- diag::err_sizeof_alignof_incomplete_type,
- ExprKind, ExprRange))
+ if (RequireCompleteSizedType(
+ OpLoc, ExprType, diag::err_sizeof_alignof_incomplete_or_sizeless_type,
+ getTraitSpelling(ExprKind), ExprRange))
return true;
if (ExprType->isFunctionType()) {
Diag(OpLoc, diag::err_sizeof_alignof_function_type)
- << ExprKind << ExprRange;
+ << getTraitSpelling(ExprKind) << ExprRange;
return true;
}
@@ -4178,6 +4286,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
case Type::Complex:
case Type::Vector:
case Type::ExtVector:
+ case Type::ConstantMatrix:
case Type::Record:
case Type::Enum:
case Type::Elaborated:
@@ -4187,6 +4296,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T,
case Type::ObjCObjectPointer:
case Type::ObjCTypeParam:
case Type::Pipe:
+ case Type::ExtInt:
llvm_unreachable("type class is never variably-modified!");
case Type::Adjusted:
T = cast<AdjustedType>(Ty)->getOriginalType();
@@ -4452,7 +4562,8 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
if (base && !base->getType().isNull() &&
base->getType()->isSpecificPlaceholderType(BuiltinType::OMPArraySection))
return ActOnOMPArraySectionExpr(base, lbLoc, idx, SourceLocation(),
- /*Length=*/nullptr, rbLoc);
+ SourceLocation(), /*Length*/ nullptr,
+ /*Stride=*/nullptr, rbLoc);
// Since this might be a postfix expression, get rid of ParenListExprs.
if (isa<ParenListExpr>(base)) {
@@ -4461,8 +4572,55 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
base = result.get();
}
+ // Check if base and idx form a MatrixSubscriptExpr.
+ //
+ // Helper to check for comma expressions, which are not allowed as indices for
+ // matrix subscript expressions.
+ auto CheckAndReportCommaError = [this, base, rbLoc](Expr *E) {
+ if (isa<BinaryOperator>(E) && cast<BinaryOperator>(E)->isCommaOp()) {
+ Diag(E->getExprLoc(), diag::err_matrix_subscript_comma)
+ << SourceRange(base->getBeginLoc(), rbLoc);
+ return true;
+ }
+ return false;
+ };
+ // The matrix subscript operator ([][])is considered a single operator.
+ // Separating the index expressions by parenthesis is not allowed.
+ if (base->getType()->isSpecificPlaceholderType(
+ BuiltinType::IncompleteMatrixIdx) &&
+ !isa<MatrixSubscriptExpr>(base)) {
+ Diag(base->getExprLoc(), diag::err_matrix_separate_incomplete_index)
+ << SourceRange(base->getBeginLoc(), rbLoc);
+ return ExprError();
+ }
+ // If the base is either a MatrixSubscriptExpr or a matrix type, try to create
+ // a new MatrixSubscriptExpr.
+ auto *matSubscriptE = dyn_cast<MatrixSubscriptExpr>(base);
+ if (matSubscriptE) {
+ if (CheckAndReportCommaError(idx))
+ return ExprError();
+
+ assert(matSubscriptE->isIncomplete() &&
+ "base has to be an incomplete matrix subscript");
+ return CreateBuiltinMatrixSubscriptExpr(
+ matSubscriptE->getBase(), matSubscriptE->getRowIdx(), idx, rbLoc);
+ }
+ Expr *matrixBase = base;
+ bool IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base);
+ if (!IsMSPropertySubscript) {
+ ExprResult result = CheckPlaceholderExpr(base);
+ if (!result.isInvalid())
+ matrixBase = result.get();
+ }
+ if (matrixBase->getType()->isMatrixType()) {
+ if (CheckAndReportCommaError(idx))
+ return ExprError();
+
+ return CreateBuiltinMatrixSubscriptExpr(matrixBase, idx, nullptr, rbLoc);
+ }
+
// A comma-expression as the index is deprecated in C++2a onwards.
- if (getLangOpts().CPlusPlus2a &&
+ if (getLangOpts().CPlusPlus20 &&
((isa<BinaryOperator>(idx) && cast<BinaryOperator>(idx)->isCommaOp()) ||
(isa<CXXOperatorCallExpr>(idx) &&
cast<CXXOperatorCallExpr>(idx)->getOperator() == OO_Comma))) {
@@ -4475,7 +4633,6 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
// operand might be an overloadable type, in which case the overload
// resolution for the operator overload should get the first crack
// at the overload.
- bool IsMSPropertySubscript = false;
if (base->getType()->isNonOverloadPlaceholderType()) {
IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base);
if (!IsMSPropertySubscript) {
@@ -4536,6 +4693,79 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
return Res;
}
+ExprResult Sema::tryConvertExprToType(Expr *E, QualType Ty) {
+ InitializedEntity Entity = InitializedEntity::InitializeTemporary(Ty);
+ InitializationKind Kind =
+ InitializationKind::CreateCopy(E->getBeginLoc(), SourceLocation());
+ InitializationSequence InitSeq(*this, Entity, Kind, E);
+ return InitSeq.Perform(*this, Entity, Kind, E);
+}
+
+ExprResult Sema::CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
+ Expr *ColumnIdx,
+ SourceLocation RBLoc) {
+ ExprResult BaseR = CheckPlaceholderExpr(Base);
+ if (BaseR.isInvalid())
+ return BaseR;
+ Base = BaseR.get();
+
+ ExprResult RowR = CheckPlaceholderExpr(RowIdx);
+ if (RowR.isInvalid())
+ return RowR;
+ RowIdx = RowR.get();
+
+ if (!ColumnIdx)
+ return new (Context) MatrixSubscriptExpr(
+ Base, RowIdx, ColumnIdx, Context.IncompleteMatrixIdxTy, RBLoc);
+
+ // Build an unanalyzed expression if any of the operands is type-dependent.
+ if (Base->isTypeDependent() || RowIdx->isTypeDependent() ||
+ ColumnIdx->isTypeDependent())
+ return new (Context) MatrixSubscriptExpr(Base, RowIdx, ColumnIdx,
+ Context.DependentTy, RBLoc);
+
+ ExprResult ColumnR = CheckPlaceholderExpr(ColumnIdx);
+ if (ColumnR.isInvalid())
+ return ColumnR;
+ ColumnIdx = ColumnR.get();
+
+ // Check that IndexExpr is an integer expression. If it is a constant
+ // expression, check that it is less than Dim (= the number of elements in the
+ // corresponding dimension).
+ auto IsIndexValid = [&](Expr *IndexExpr, unsigned Dim,
+ bool IsColumnIdx) -> Expr * {
+ if (!IndexExpr->getType()->isIntegerType() &&
+ !IndexExpr->isTypeDependent()) {
+ Diag(IndexExpr->getBeginLoc(), diag::err_matrix_index_not_integer)
+ << IsColumnIdx;
+ return nullptr;
+ }
+
+ llvm::APSInt Idx;
+ if (IndexExpr->isIntegerConstantExpr(Idx, Context) &&
+ (Idx < 0 || Idx >= Dim)) {
+ Diag(IndexExpr->getBeginLoc(), diag::err_matrix_index_outside_range)
+ << IsColumnIdx << Dim;
+ return nullptr;
+ }
+
+ ExprResult ConvExpr =
+ tryConvertExprToType(IndexExpr, Context.getSizeType());
+ assert(!ConvExpr.isInvalid() &&
+ "should be able to convert any integer type to size type");
+ return ConvExpr.get();
+ };
+
+ auto *MTy = Base->getType()->getAs<ConstantMatrixType>();
+ RowIdx = IsIndexValid(RowIdx, MTy->getNumRows(), false);
+ ColumnIdx = IsIndexValid(ColumnIdx, MTy->getNumColumns(), true);
+ if (!RowIdx || !ColumnIdx)
+ return ExprError();
+
+ return new (Context) MatrixSubscriptExpr(Base, RowIdx, ColumnIdx,
+ MTy->getElementType(), RBLoc);
+}
+
void Sema::CheckAddressOfNoDeref(const Expr *E) {
ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back();
const Expr *StrippedExpr = E->IgnoreParenImpCasts();
@@ -4583,7 +4813,9 @@ void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) {
ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
Expr *LowerBound,
- SourceLocation ColonLoc, Expr *Length,
+ SourceLocation ColonLocFirst,
+ SourceLocation ColonLocSecond,
+ Expr *Length, Expr *Stride,
SourceLocation RBLoc) {
if (Base->getType()->isPlaceholderType() &&
!Base->getType()->isSpecificPlaceholderType(
@@ -4611,15 +4843,25 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
return ExprError();
Length = Result.get();
}
+ if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(Stride);
+ if (Result.isInvalid())
+ return ExprError();
+ Result = DefaultLvalueConversion(Result.get());
+ if (Result.isInvalid())
+ return ExprError();
+ Stride = Result.get();
+ }
// Build an unanalyzed expression if either operand is type-dependent.
if (Base->isTypeDependent() ||
(LowerBound &&
(LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
- (Length && (Length->isTypeDependent() || Length->isValueDependent()))) {
- return new (Context)
- OMPArraySectionExpr(Base, LowerBound, Length, Context.DependentTy,
- VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
+ (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
+ (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
+ return new (Context) OMPArraySectionExpr(
+ Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
+ OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
}
// Perform default conversions.
@@ -4663,6 +4905,20 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
<< 1 << Length->getSourceRange();
}
+ if (Stride) {
+ ExprResult Res =
+ PerformOpenMPImplicitIntegerConversion(Stride->getExprLoc(), Stride);
+ if (Res.isInvalid())
+ return ExprError(Diag(Stride->getExprLoc(),
+ diag::err_omp_typecheck_section_not_integer)
+ << 1 << Stride->getSourceRange());
+ Stride = Res.get();
+
+ if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+ Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
+ << 1 << Stride->getSourceRange();
+ }
// C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
// C++ [expr.sub]p1: The type "T" shall be a completely-defined object
@@ -4681,7 +4937,7 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
if (LowerBound && !OriginalTy->isAnyPointerType()) {
Expr::EvalResult Result;
if (LowerBound->EvaluateAsInt(Result, Context)) {
- // OpenMP 4.5, [2.4 Array Sections]
+ // OpenMP 5.0, [2.1.5 Array Sections]
// The array section must be a subset of the original array.
llvm::APSInt LowerBoundValue = Result.Val.getInt();
if (LowerBoundValue.isNegative()) {
@@ -4695,7 +4951,7 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
if (Length) {
Expr::EvalResult Result;
if (Length->EvaluateAsInt(Result, Context)) {
- // OpenMP 4.5, [2.4 Array Sections]
+ // OpenMP 5.0, [2.1.5 Array Sections]
// The length must evaluate to non-negative integers.
llvm::APSInt LengthValue = Result.Val.getInt();
if (LengthValue.isNegative()) {
@@ -4705,17 +4961,32 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
return ExprError();
}
}
- } else if (ColonLoc.isValid() &&
+ } else if (ColonLocFirst.isValid() &&
(OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
!OriginalTy->isVariableArrayType()))) {
- // OpenMP 4.5, [2.4 Array Sections]
+ // OpenMP 5.0, [2.1.5 Array Sections]
// When the size of the array dimension is not known, the length must be
// specified explicitly.
- Diag(ColonLoc, diag::err_omp_section_length_undefined)
+ Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
<< (!OriginalTy.isNull() && OriginalTy->isArrayType());
return ExprError();
}
+ if (Stride) {
+ Expr::EvalResult Result;
+ if (Stride->EvaluateAsInt(Result, Context)) {
+ // OpenMP 5.0, [2.1.5 Array Sections]
+ // The stride must evaluate to a positive integer.
+ llvm::APSInt StrideValue = Result.Val.getInt();
+ if (!StrideValue.isStrictlyPositive()) {
+ Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
+ << StrideValue.toString(/*Radix=*/10, /*Signed=*/true)
+ << Stride->getSourceRange();
+ return ExprError();
+ }
+ }
+ }
+
if (!Base->getType()->isSpecificPlaceholderType(
BuiltinType::OMPArraySection)) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(Base);
@@ -4723,9 +4994,371 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
return ExprError();
Base = Result.get();
}
- return new (Context)
- OMPArraySectionExpr(Base, LowerBound, Length, Context.OMPArraySectionTy,
- VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
+ return new (Context) OMPArraySectionExpr(
+ Base, LowerBound, Length, Stride, Context.OMPArraySectionTy, VK_LValue,
+ OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
+}
+
+ExprResult Sema::ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ ArrayRef<Expr *> Dims,
+ ArrayRef<SourceRange> Brackets) {
+ if (Base->getType()->isPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(Base);
+ if (Result.isInvalid())
+ return ExprError();
+ Result = DefaultLvalueConversion(Result.get());
+ if (Result.isInvalid())
+ return ExprError();
+ Base = Result.get();
+ }
+ QualType BaseTy = Base->getType();
+ // Delay analysis of the types/expressions if instantiation/specialization is
+ // required.
+ if (!BaseTy->isPointerType() && Base->isTypeDependent())
+ return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
+ LParenLoc, RParenLoc, Dims, Brackets);
+ if (!BaseTy->isPointerType() ||
+ (!Base->isTypeDependent() &&
+ BaseTy->getPointeeType()->isIncompleteType()))
+ return ExprError(Diag(Base->getExprLoc(),
+ diag::err_omp_non_pointer_type_array_shaping_base)
+ << Base->getSourceRange());
+
+ SmallVector<Expr *, 4> NewDims;
+ bool ErrorFound = false;
+ for (Expr *Dim : Dims) {
+ if (Dim->getType()->isPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(Dim);
+ if (Result.isInvalid()) {
+ ErrorFound = true;
+ continue;
+ }
+ Result = DefaultLvalueConversion(Result.get());
+ if (Result.isInvalid()) {
+ ErrorFound = true;
+ continue;
+ }
+ Dim = Result.get();
+ }
+ if (!Dim->isTypeDependent()) {
+ ExprResult Result =
+ PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim);
+ if (Result.isInvalid()) {
+ ErrorFound = true;
+ Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
+ << Dim->getSourceRange();
+ continue;
+ }
+ Dim = Result.get();
+ Expr::EvalResult EvResult;
+ if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
+ // OpenMP 5.0, [2.1.4 Array Shaping]
+ // Each si is an integral type expression that must evaluate to a
+ // positive integer.
+ llvm::APSInt Value = EvResult.Val.getInt();
+ if (!Value.isStrictlyPositive()) {
+ Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
+ << Value.toString(/*Radix=*/10, /*Signed=*/true)
+ << Dim->getSourceRange();
+ ErrorFound = true;
+ continue;
+ }
+ }
+ }
+ NewDims.push_back(Dim);
+ }
+ if (ErrorFound)
+ return ExprError();
+ return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
+ LParenLoc, RParenLoc, NewDims, Brackets);
+}
+
+ExprResult Sema::ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
+ SourceLocation LLoc, SourceLocation RLoc,
+ ArrayRef<OMPIteratorData> Data) {
+ SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
+ bool IsCorrect = true;
+ for (const OMPIteratorData &D : Data) {
+ TypeSourceInfo *TInfo = nullptr;
+ SourceLocation StartLoc;
+ QualType DeclTy;
+ if (!D.Type.getAsOpaquePtr()) {
+ // OpenMP 5.0, 2.1.6 Iterators
+ // In an iterator-specifier, if the iterator-type is not specified then
+ // the type of that iterator is of int type.
+ DeclTy = Context.IntTy;
+ StartLoc = D.DeclIdentLoc;
+ } else {
+ DeclTy = GetTypeFromParser(D.Type, &TInfo);
+ StartLoc = TInfo->getTypeLoc().getBeginLoc();
+ }
+
+ bool IsDeclTyDependent = DeclTy->isDependentType() ||
+ DeclTy->containsUnexpandedParameterPack() ||
+ DeclTy->isInstantiationDependentType();
+ if (!IsDeclTyDependent) {
+ if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
+ // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
+ // The iterator-type must be an integral or pointer type.
+ Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
+ << DeclTy;
+ IsCorrect = false;
+ continue;
+ }
+ if (DeclTy.isConstant(Context)) {
+ // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
+ // The iterator-type must not be const qualified.
+ Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
+ << DeclTy;
+ IsCorrect = false;
+ continue;
+ }
+ }
+
+ // Iterator declaration.
+ assert(D.DeclIdent && "Identifier expected.");
+ // Always try to create iterator declarator to avoid extra error messages
+ // about unknown declarations use.
+ auto *VD = VarDecl::Create(Context, CurContext, StartLoc, D.DeclIdentLoc,
+ D.DeclIdent, DeclTy, TInfo, SC_None);
+ VD->setImplicit();
+ if (S) {
+ // Check for conflicting previous declaration.
+ DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+ ForVisibleRedeclaration);
+ Previous.suppressDiagnostics();
+ LookupName(Previous, S);
+
+ FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage=*/false,
+ /*AllowInlineNamespace=*/false);
+ if (!Previous.empty()) {
+ NamedDecl *Old = Previous.getRepresentativeDecl();
+ Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ } else {
+ PushOnScopeChains(VD, S);
+ }
+ } else {
+ CurContext->addDecl(VD);
+ }
+ Expr *Begin = D.Range.Begin;
+ if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
+ ExprResult BeginRes =
+ PerformImplicitConversion(Begin, DeclTy, AA_Converting);
+ Begin = BeginRes.get();
+ }
+ Expr *End = D.Range.End;
+ if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
+ ExprResult EndRes = PerformImplicitConversion(End, DeclTy, AA_Converting);
+ End = EndRes.get();
+ }
+ Expr *Step = D.Range.Step;
+ if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
+ if (!Step->getType()->isIntegralType(Context)) {
+ Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
+ << Step << Step->getSourceRange();
+ IsCorrect = false;
+ continue;
+ }
+ llvm::APSInt Result;
+ bool IsConstant = Step->isIntegerConstantExpr(Result, Context);
+ // OpenMP 5.0, 2.1.6 Iterators, Restrictions
+ // If the step expression of a range-specification equals zero, the
+ // behavior is unspecified.
+ if (IsConstant && Result.isNullValue()) {
+ Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
+ << Step << Step->getSourceRange();
+ IsCorrect = false;
+ continue;
+ }
+ }
+ if (!Begin || !End || !IsCorrect) {
+ IsCorrect = false;
+ continue;
+ }
+ OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
+ IDElem.IteratorDecl = VD;
+ IDElem.AssignmentLoc = D.AssignLoc;
+ IDElem.Range.Begin = Begin;
+ IDElem.Range.End = End;
+ IDElem.Range.Step = Step;
+ IDElem.ColonLoc = D.ColonLoc;
+ IDElem.SecondColonLoc = D.SecColonLoc;
+ }
+ if (!IsCorrect) {
+ // Invalidate all created iterator declarations if error is found.
+ for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
+ if (Decl *ID = D.IteratorDecl)
+ ID->setInvalidDecl();
+ }
+ return ExprError();
+ }
+ SmallVector<OMPIteratorHelperData, 4> Helpers;
+ if (!CurContext->isDependentContext()) {
+ // Build number of ityeration for each iteration range.
+ // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
+ // ((Begini-Stepi-1-Endi) / -Stepi);
+ for (OMPIteratorExpr::IteratorDefinition &D : ID) {
+ // (Endi - Begini)
+ ExprResult Res = CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub, D.Range.End,
+ D.Range.Begin);
+ if(!Res.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ ExprResult St, St1;
+ if (D.Range.Step) {
+ St = D.Range.Step;
+ // (Endi - Begini) + Stepi
+ Res = CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(), St.get());
+ if (!Res.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ // (Endi - Begini) + Stepi - 1
+ Res =
+ CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub, Res.get(),
+ ActOnIntegerConstant(D.AssignmentLoc, 1).get());
+ if (!Res.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ // ((Endi - Begini) + Stepi - 1) / Stepi
+ Res = CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(), St.get());
+ if (!Res.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ St1 = CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus, D.Range.Step);
+ // (Begini - Endi)
+ ExprResult Res1 = CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
+ D.Range.Begin, D.Range.End);
+ if (!Res1.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ // (Begini - Endi) - Stepi
+ Res1 =
+ CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(), St1.get());
+ if (!Res1.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ // (Begini - Endi) - Stepi - 1
+ Res1 =
+ CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub, Res1.get(),
+ ActOnIntegerConstant(D.AssignmentLoc, 1).get());
+ if (!Res1.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ // ((Begini - Endi) - Stepi - 1) / (-Stepi)
+ Res1 =
+ CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(), St1.get());
+ if (!Res1.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ // Stepi > 0.
+ ExprResult CmpRes =
+ CreateBuiltinBinOp(D.AssignmentLoc, BO_GT, D.Range.Step,
+ ActOnIntegerConstant(D.AssignmentLoc, 0).get());
+ if (!CmpRes.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ Res = ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc, CmpRes.get(),
+ Res.get(), Res1.get());
+ if (!Res.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ }
+ Res = ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
+ if (!Res.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+
+ // Build counter update.
+ // Build counter.
+ auto *CounterVD =
+ VarDecl::Create(Context, CurContext, D.IteratorDecl->getBeginLoc(),
+ D.IteratorDecl->getBeginLoc(), nullptr,
+ Res.get()->getType(), nullptr, SC_None);
+ CounterVD->setImplicit();
+ ExprResult RefRes =
+ BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
+ D.IteratorDecl->getBeginLoc());
+ // Build counter update.
+ // I = Begini + counter * Stepi;
+ ExprResult UpdateRes;
+ if (D.Range.Step) {
+ UpdateRes = CreateBuiltinBinOp(
+ D.AssignmentLoc, BO_Mul,
+ DefaultLvalueConversion(RefRes.get()).get(), St.get());
+ } else {
+ UpdateRes = DefaultLvalueConversion(RefRes.get());
+ }
+ if (!UpdateRes.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ UpdateRes = CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, D.Range.Begin,
+ UpdateRes.get());
+ if (!UpdateRes.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ ExprResult VDRes =
+ BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
+ cast<VarDecl>(D.IteratorDecl)->getType(), VK_LValue,
+ D.IteratorDecl->getBeginLoc());
+ UpdateRes = CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign, VDRes.get(),
+ UpdateRes.get());
+ if (!UpdateRes.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ UpdateRes =
+ ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
+ if (!UpdateRes.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ ExprResult CounterUpdateRes =
+ CreateBuiltinUnaryOp(D.AssignmentLoc, UO_PreInc, RefRes.get());
+ if (!CounterUpdateRes.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ CounterUpdateRes =
+ ActOnFinishFullExpr(CounterUpdateRes.get(), /*DiscardedValue=*/true);
+ if (!CounterUpdateRes.isUsable()) {
+ IsCorrect = false;
+ continue;
+ }
+ OMPIteratorHelperData &HD = Helpers.emplace_back();
+ HD.CounterVD = CounterVD;
+ HD.Upper = Res.get();
+ HD.Update = UpdateRes.get();
+ HD.CounterUpdate = CounterUpdateRes.get();
+ }
+ } else {
+ Helpers.assign(ID.size(), {});
+ }
+ if (!IsCorrect) {
+ // Invalidate all created iterator declarations if error is found.
+ for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
+ if (Decl *ID = D.IteratorDecl)
+ ID->setInvalidDecl();
+ }
+ return ExprError();
+ }
+ return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
+ LLoc, RLoc, ID, Helpers);
}
ExprResult
@@ -4883,8 +5516,9 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
// See IsCForbiddenLValueType.
if (!ResultType.hasQualifiers()) VK = VK_RValue;
} else if (!ResultType->isDependentType() &&
- RequireCompleteType(LLoc, ResultType,
- diag::err_subscript_incomplete_type, BaseExpr))
+ RequireCompleteSizedType(
+ LLoc, ResultType,
+ diag::err_subscript_incomplete_or_sizeless_type, BaseExpr))
return ExprError();
assert(VK == VK_RValue || LangOpts.CPlusPlus ||
@@ -4924,6 +5558,15 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
ParmVarDecl *Param) {
if (Param->hasUnparsedDefaultArg()) {
+ // If we've already cleared out the location for the default argument,
+ // that means we're parsing it right now.
+ if (!UnparsedDefaultArgLocs.count(Param)) {
+ Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
+ Diag(CallLoc, diag::note_recursive_default_argument_used_here);
+ Param->setInvalidDecl();
+ return true;
+ }
+
Diag(CallLoc,
diag::err_use_of_default_argument_to_function_declared_later) <<
FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName();
@@ -4932,90 +5575,11 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
return true;
}
- if (Param->hasUninstantiatedDefaultArg()) {
- Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
-
- EnterExpressionEvaluationContext EvalContext(
- *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param);
-
- // Instantiate the expression.
- //
- // FIXME: Pass in a correct Pattern argument, otherwise
- // getTemplateInstantiationArgs uses the lexical context of FD, e.g.
- //
- // template<typename T>
- // struct A {
- // static int FooImpl();
- //
- // template<typename Tp>
- // // bug: default argument A<T>::FooImpl() is evaluated with 2-level
- // // template argument list [[T], [Tp]], should be [[Tp]].
- // friend A<Tp> Foo(int a);
- // };
- //
- // template<typename T>
- // A<T> Foo(int a = A<T>::FooImpl());
- MultiLevelTemplateArgumentList MutiLevelArgList
- = getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true);
-
- InstantiatingTemplate Inst(*this, CallLoc, Param,
- MutiLevelArgList.getInnermost());
- if (Inst.isInvalid())
- return true;
- if (Inst.isAlreadyInstantiating()) {
- Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
- Param->setInvalidDecl();
- return true;
- }
-
- ExprResult Result;
- {
- // C++ [dcl.fct.default]p5:
- // The names in the [default argument] expression are bound, and
- // the semantic constraints are checked, at the point where the
- // default argument expression appears.
- ContextRAII SavedContext(*this, FD);
- LocalInstantiationScope Local(*this);
- runWithSufficientStackSpace(CallLoc, [&] {
- Result = SubstInitializer(UninstExpr, MutiLevelArgList,
- /*DirectInit*/false);
- });
- }
- if (Result.isInvalid())
- return true;
-
- // Check the expression as an initializer for the parameter.
- InitializedEntity Entity
- = InitializedEntity::InitializeParameter(Context, Param);
- InitializationKind Kind = InitializationKind::CreateCopy(
- Param->getLocation(),
- /*FIXME:EqualLoc*/ UninstExpr->getBeginLoc());
- Expr *ResultE = Result.getAs<Expr>();
-
- InitializationSequence InitSeq(*this, Entity, Kind, ResultE);
- Result = InitSeq.Perform(*this, Entity, Kind, ResultE);
- if (Result.isInvalid())
- return true;
-
- Result =
- ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(),
- /*DiscardedValue*/ false);
- if (Result.isInvalid())
- return true;
-
- // Remember the instantiated default argument.
- Param->setDefaultArg(Result.getAs<Expr>());
- if (ASTMutationListener *L = getASTMutationListener()) {
- L->DefaultArgumentInstantiated(Param);
- }
- }
-
- // If the default argument expression is not set yet, we are building it now.
- if (!Param->hasInit()) {
- Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
- Param->setInvalidDecl();
+ if (Param->hasUninstantiatedDefaultArg() &&
+ InstantiateDefaultArgument(CallLoc, FD, Param))
return true;
- }
+
+ assert(Param->hasInit() && "default argument but no initializer?");
// If the default expression creates temporaries, we need to
// push them to the current stack of expression temporaries so they'll
@@ -5048,6 +5612,7 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
FunctionDecl *FD, ParmVarDecl *Param) {
+ assert(Param->hasDefaultArg() && "can't build nonexistent default arg");
if (CheckCXXDefaultArgExpr(CallLoc, FD, Param))
return ExprError();
return CXXDefaultArgExpr::Create(Context, CallLoc, Param, CurContext);
@@ -5193,7 +5758,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
- Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl;
+ Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl;
return true;
}
@@ -5238,7 +5803,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
- Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl;
+ Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl;
// This deletes the extra arguments.
Call->shrinkNumArgs(NumParams);
@@ -5351,9 +5916,6 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
for (Expr *A : Args.slice(ArgIx)) {
ExprResult Arg = DefaultVariadicArgumentPromotion(A, CallType, FDecl);
Invalid |= Arg.isInvalid();
- // Copy blocks to the heap.
- if (A->getType()->isBlockPointerType())
- maybeExtendBlockObject(Arg);
AllArgs.push_back(Arg.get());
}
}
@@ -5486,7 +6048,10 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
// These are always invalid as call arguments and should be reported.
case BuiltinType::BoundMember:
case BuiltinType::BuiltinFn:
+ case BuiltinType::IncompleteMatrixIdx:
case BuiltinType::OMPArraySection:
+ case BuiltinType::OMPArrayShaping:
+ case BuiltinType::OMPIterator:
return true;
}
@@ -5609,7 +6174,8 @@ static void checkDirectCallValidity(Sema &S, const Expr *Fn,
if (Callee->getMinRequiredArguments() > ArgExprs.size())
return;
- if (const EnableIfAttr *Attr = S.CheckEnableIf(Callee, ArgExprs, true)) {
+ if (const EnableIfAttr *Attr =
+ S.CheckEnableIf(Callee, Fn->getBeginLoc(), ArgExprs, true)) {
S.Diag(Fn->getBeginLoc(),
isa<CXXMethodDecl>(Callee)
? diag::err_ovl_no_viable_member_function_in_call
@@ -5716,13 +6282,17 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(Fn)) {
if (ULE->hasExplicitTemplateArgs() &&
ULE->decls_begin() == ULE->decls_end()) {
- Diag(Fn->getExprLoc(), getLangOpts().CPlusPlus2a
+ Diag(Fn->getExprLoc(), getLangOpts().CPlusPlus20
? diag::warn_cxx17_compat_adl_only_template_id
: diag::ext_adl_only_template_id)
<< ULE->getName();
}
}
+ if (LangOpts.OpenMP)
+ Call = ActOnOpenMPCall(Call, Scope, LParenLoc, ArgExprs, RParenLoc,
+ ExecConfig);
+
return Call;
}
@@ -6133,6 +6703,18 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
if (NDecl)
DiagnoseSentinelCalls(NDecl, LParenLoc, Args);
+ // Warn for unions passing across security boundary (CMSE).
+ if (FuncT != nullptr && FuncT->getCmseNSCallAttr()) {
+ for (unsigned i = 0, e = Args.size(); i != e; i++) {
+ if (const auto *RT =
+ dyn_cast<RecordType>(Args[i]->getType().getCanonicalType())) {
+ if (RT->getDecl()->isOrContainsUnion())
+ Diag(Args[i]->getBeginLoc(), diag::warn_cmse_nonsecure_union)
+ << 0 << i;
+ }
+ }
+ }
+
// Do special checking on direct calls to functions.
if (FDecl) {
if (CheckFunctionCall(FDecl, TheCall, Proto))
@@ -6150,7 +6732,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
return ExprError();
}
- return MaybeBindToTemporary(TheCall);
+ return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), FDecl);
}
ExprResult
@@ -6173,10 +6755,10 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
QualType literalType = TInfo->getType();
if (literalType->isArrayType()) {
- if (RequireCompleteType(LParenLoc, Context.getBaseElementType(literalType),
- diag::err_illegal_decl_array_incomplete_type,
- SourceRange(LParenLoc,
- LiteralExpr->getSourceRange().getEnd())))
+ if (RequireCompleteSizedType(
+ LParenLoc, Context.getBaseElementType(literalType),
+ diag::err_array_incomplete_or_sizeless_type,
+ SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd())))
return ExprError();
if (literalType->isVariableArrayType())
return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init)
@@ -6250,14 +6832,24 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
return ExprError();
}
- // Compound literals that have automatic storage duration are destroyed at
- // the end of the scope. Emit diagnostics if it is or contains a C union type
- // that is non-trivial to destruct.
- if (!isFileScope)
+ if (!isFileScope && !getLangOpts().CPlusPlus) {
+ // Compound literals that have automatic storage duration are destroyed at
+ // the end of the scope in C; in C++, they're just temporaries.
+
+ // Emit diagnostics if it is or contains a C union type that is non-trivial
+ // to destruct.
if (E->getType().hasNonTrivialToPrimitiveDestructCUnion())
checkNonTrivialCUnion(E->getType(), E->getExprLoc(),
NTCUC_CompoundLiteral, NTCUK_Destruct);
+ // Diagnose jumps that enter or exit the lifetime of the compound literal.
+ if (literalType.isDestructedType()) {
+ Cleanup.setExprNeedsCleanups(true);
+ ExprCleanupObjects.push_back(E);
+ getCurFunction()->setHasBranchProtectedScope();
+ }
+ }
+
if (E->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
E->getType().hasNonTrivialToPrimitiveCopyCUnion())
checkNonTrivialCUnionInInitializer(E->getInitializer(),
@@ -6323,7 +6915,7 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
// already diagnose use of (non-C++20) C99 designator syntax.
if (getLangOpts().CPlusPlus && !DiagnosedArrayDesignator &&
!DiagnosedNestedDesignator && !DiagnosedMixedDesignator) {
- Diag(FirstDesignator, getLangOpts().CPlusPlus2a
+ Diag(FirstDesignator, getLangOpts().CPlusPlus20
? diag::warn_cxx17_compat_designated_init
: diag::ext_cxx_designated_init);
} else if (!getLangOpts().CPlusPlus && !getLangOpts().C99) {
@@ -7469,7 +8061,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
// The OpenCL operator with a vector condition is sufficiently
// different to merit its own checker.
- if (getLangOpts().OpenCL && Cond.get()->getType()->isVectorType())
+ if ((getLangOpts().OpenCL && Cond.get()->getType()->isVectorType()) ||
+ Cond.get()->getType()->isExtVectorType())
return OpenCLCheckVectorConditional(*this, Cond, LHS, RHS, QuestionLoc);
// First, check the condition.
@@ -7519,6 +8112,11 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
return ResTy;
}
+ // And if they're both bfloat (which isn't arithmetic), that's fine too.
+ if (LHSTy->isBFloat16Type() && RHSTy->isBFloat16Type()) {
+ return LHSTy;
+ }
+
// If both operands are the same structure or union type, the result is that
// type.
if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) { // C99 6.5.15p3
@@ -7569,6 +8167,11 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
/*IsIntFirstExpr=*/false))
return LHSTy;
+ // Allow ?: operations in which both operands have the same
+ // built-in sizeless type.
+ if (LHSTy->isSizelessBuiltinType() && LHSTy == RHSTy)
+ return LHSTy;
+
// Emit a better diagnostic if one of the expressions is a null pointer
// constant and the other is not a pointer type. In this case, the user most
// likely forgot to take the address of the other expression.
@@ -8012,6 +8615,24 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
ColonLoc, result, VK, OK);
}
+// Check if we have a conversion between incompatible cmse function pointer
+// types, that is, a conversion between a function pointer with the
+// cmse_nonsecure_call attribute and one without.
+static bool IsInvalidCmseNSCallConversion(Sema &S, QualType FromType,
+ QualType ToType) {
+ if (const auto *ToFn =
+ dyn_cast<FunctionType>(S.Context.getCanonicalType(ToType))) {
+ if (const auto *FromFn =
+ dyn_cast<FunctionType>(S.Context.getCanonicalType(FromType))) {
+ FunctionType::ExtInfo ToEInfo = ToFn->getExtInfo();
+ FunctionType::ExtInfo FromEInfo = FromFn->getExtInfo();
+
+ return ToEInfo.getCmseNSCall() != FromEInfo.getCmseNSCall();
+ }
+ }
+ return false;
+}
+
// checkPointerTypesForAssignment - This is a very tricky routine (despite
// being closely modeled after the C99 spec:-). The odd characteristic of this
// routine is it effectively iqnores the qualifiers on the top level pointee.
@@ -8143,11 +8764,15 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) {
}
// General pointer incompatibility takes priority over qualifiers.
+ if (RHSType->isFunctionPointerType() && LHSType->isFunctionPointerType())
+ return Sema::IncompatibleFunctionPointer;
return Sema::IncompatiblePointer;
}
if (!S.getLangOpts().CPlusPlus &&
S.IsFunctionConversion(ltrans, rtrans, ltrans))
- return Sema::IncompatiblePointer;
+ return Sema::IncompatibleFunctionPointer;
+ if (IsInvalidCmseNSCallConversion(S, ltrans, rtrans))
+ return Sema::IncompatibleFunctionPointer;
return ConvTy;
}
@@ -8258,7 +8883,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc,
/// type ElementType.
static bool isVector(QualType QT, QualType ElementType) {
if (const VectorType *VT = QT->getAs<VectorType>())
- return VT->getElementType() == ElementType;
+ return VT->getElementType().getCanonicalType() == ElementType;
return false;
}
@@ -8701,7 +9326,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
ImplicitConversionSequence ICS =
TryImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
/*SuppressUserConversions=*/false,
- /*AllowExplicit=*/false,
+ AllowedExplicit::None,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
/*AllowObjCWritebackConversion=*/false);
@@ -8796,7 +9421,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
if (getLangOpts().ObjC &&
(CheckObjCBridgeRelatedConversions(E->getBeginLoc(), LHSType,
E->getType(), E, Diagnose) ||
- ConversionToObjCStringLiteralCheck(LHSType, E, Diagnose))) {
+ CheckConversionToObjCLiteral(LHSType, E, Diagnose))) {
if (!Diagnose)
return Incompatible;
// Replace the expression with a corrected version and continue so we
@@ -9093,7 +9718,13 @@ static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar,
// Reject cases where the scalar type is not a constant and has a higher
// Order than the vector element type.
llvm::APFloat Result(0.0);
- bool CstScalar = Scalar->get()->EvaluateAsFloat(Result, S.Context);
+
+ // Determine whether this is a constant scalar. In the event that the
+ // value is dependent (and thus cannot be evaluated by the constant
+ // evaluator), skip the evaluation. This will then diagnose once the
+ // expression is instantiated.
+ bool CstScalar = Scalar->get()->isValueDependent() ||
+ Scalar->get()->EvaluateAsFloat(Result, S.Context);
int Order = S.Context.getFloatingTypeOrder(VectorEltTy, ScalarTy);
if (!CstScalar && Order < 0)
return true;
@@ -9116,7 +9747,8 @@ static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar,
ScalarCast = CK_IntegralToFloating;
} else
return true;
- }
+ } else if (ScalarTy->isEnumeralType())
+ return true;
// Adjust scalar if desired.
if (Scalar) {
@@ -9405,6 +10037,9 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
/*AllowBothBool*/getLangOpts().AltiVec,
/*AllowBoolConversions*/false);
+ if (!IsDiv && (LHS.get()->getType()->isConstantMatrixType() ||
+ RHS.get()->getType()->isConstantMatrixType()))
+ return CheckMatrixMultiplyOperands(LHS, RHS, Loc, IsCompAssign);
QualType compType = UsualArithmeticConversions(
LHS, RHS, Loc, IsCompAssign ? ACK_CompAssign : ACK_Arithmetic);
@@ -9519,9 +10154,10 @@ static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
assert(ResType->isAnyPointerType() && !ResType->isDependentType());
QualType PointeeTy = ResType->getPointeeType();
- return S.RequireCompleteType(Loc, PointeeTy,
- diag::err_typecheck_arithmetic_incomplete_type,
- PointeeTy, Operand->getSourceRange());
+ return S.RequireCompleteSizedType(
+ Loc, PointeeTy,
+ diag::err_typecheck_arithmetic_incomplete_or_sizeless_type,
+ Operand->getSourceRange());
}
/// Check the validity of an arithmetic pointer operand.
@@ -9575,10 +10211,8 @@ static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType();
// if both are pointers check if operation is valid wrt address spaces
- if (S.getLangOpts().OpenCL && isLHSPointer && isRHSPointer) {
- const PointerType *lhsPtr = LHSExpr->getType()->castAs<PointerType>();
- const PointerType *rhsPtr = RHSExpr->getType()->castAs<PointerType>();
- if (!lhsPtr->isAddressSpaceOverlapping(*rhsPtr)) {
+ if (isLHSPointer && isRHSPointer) {
+ if (!LHSPointeeTy.isAddressSpaceOverlapping(RHSPointeeTy)) {
S.Diag(Loc,
diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
<< LHSExpr->getType() << RHSExpr->getType() << 1 /*arithmetic op*/
@@ -9725,6 +10359,11 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
return compType;
}
+ if (LHS.get()->getType()->isConstantMatrixType() ||
+ RHS.get()->getType()->isConstantMatrixType()) {
+ return CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy);
+ }
+
QualType compType = UsualArithmeticConversions(
LHS, RHS, Loc, CompLHSTy ? ACK_CompAssign : ACK_Arithmetic);
if (LHS.isInvalid() || RHS.isInvalid())
@@ -9820,6 +10459,11 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
return compType;
}
+ if (LHS.get()->getType()->isConstantMatrixType() ||
+ RHS.get()->getType()->isConstantMatrixType()) {
+ return CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy);
+ }
+
QualType compType = UsualArithmeticConversions(
LHS, RHS, Loc, CompLHSTy ? ACK_CompAssign : ACK_Arithmetic);
if (LHS.isInvalid() || RHS.isInvalid())
@@ -9943,14 +10587,19 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
<< RHS.get()->getSourceRange());
return;
}
- llvm::APInt LeftBits(Right.getBitWidth(),
- S.Context.getTypeSize(LHS.get()->getType()));
+
+ QualType LHSExprType = LHS.get()->getType();
+ uint64_t LeftSize = LHSExprType->isExtIntType()
+ ? S.Context.getIntWidth(LHSExprType)
+ : S.Context.getTypeSize(LHSExprType);
+ llvm::APInt LeftBits(Right.getBitWidth(), LeftSize);
if (Right.uge(LeftBits)) {
S.DiagRuntimeBehavior(Loc, RHS.get(),
S.PDiag(diag::warn_shift_gt_typewidth)
<< RHS.get()->getSourceRange());
return;
}
+
if (Opc != BO_Shl)
return;
@@ -9970,7 +10619,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
// If LHS does not have a signed type and non-negative value
// then, the behavior is undefined before C++2a. Warn about it.
if (Left.isNegative() && !S.getLangOpts().isSignedOverflowDefined() &&
- !S.getLangOpts().CPlusPlus2a) {
+ !S.getLangOpts().CPlusPlus20) {
S.DiagRuntimeBehavior(Loc, LHS.get(),
S.PDiag(diag::warn_shift_lhs_negative)
<< LHS.get()->getSourceRange());
@@ -10450,7 +11099,7 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
// C++2a [depr.array.comp]:
// Equality and relational comparisons ([expr.eq], [expr.rel]) between two
// operands of array type are deprecated.
- if (S.getLangOpts().CPlusPlus2a && LHSStripped->getType()->isArrayType() &&
+ if (S.getLangOpts().CPlusPlus20 && LHSStripped->getType()->isArrayType() &&
RHSStripped->getType()->isArrayType()) {
S.Diag(Loc, diag::warn_depr_array_comparison)
<< LHS->getSourceRange() << RHS->getSourceRange()
@@ -10907,11 +11556,22 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
// C99 6.5.9p2 and C99 6.5.8p2
if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
RCanPointeeTy.getUnqualifiedType())) {
- // Valid unless a relational comparison of function pointers
- if (IsRelational && LCanPointeeTy->isFunctionType()) {
- Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers)
- << LHSType << RHSType << LHS.get()->getSourceRange()
- << RHS.get()->getSourceRange();
+ if (IsRelational) {
+ // Pointers both need to point to complete or incomplete types
+ if ((LCanPointeeTy->isIncompleteType() !=
+ RCanPointeeTy->isIncompleteType()) &&
+ !getLangOpts().C11) {
+ Diag(Loc, diag::ext_typecheck_compare_complete_incomplete_pointers)
+ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange()
+ << LHSType << RHSType << LCanPointeeTy->isIncompleteType()
+ << RCanPointeeTy->isIncompleteType();
+ }
+ if (LCanPointeeTy->isFunctionType()) {
+ // Valid unless a relational comparison of function pointers
+ Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers)
+ << LHSType << RHSType << LHS.get()->getSourceRange()
+ << RHS.get()->getSourceRange();
+ }
}
} else if (!IsRelational &&
(LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
@@ -10927,8 +11587,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
if (LCanPointeeTy != RCanPointeeTy) {
// Treat NULL constant as a special case in OpenCL.
if (getLangOpts().OpenCL && !LHSIsNull && !RHSIsNull) {
- const PointerType *LHSPtr = LHSType->castAs<PointerType>();
- if (!LHSPtr->isAddressSpaceOverlapping(*RHSType->castAs<PointerType>())) {
+ if (!LCanPointeeTy.isAddressSpaceOverlapping(RCanPointeeTy)) {
Diag(Loc,
diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
<< LHSType << RHSType << 0 /* comparison */
@@ -11326,12 +11985,12 @@ static void diagnoseXorMisusedAsPow(Sema &S, const ExprResult &XorLHS,
if (XorStr == "xor")
return;
- std::string LHSStr = Lexer::getSourceText(
+ std::string LHSStr = std::string(Lexer::getSourceText(
CharSourceRange::getTokenRange(LHSInt->getSourceRange()),
- S.getSourceManager(), S.getLangOpts());
- std::string RHSStr = Lexer::getSourceText(
+ S.getSourceManager(), S.getLangOpts()));
+ std::string RHSStr = std::string(Lexer::getSourceText(
CharSourceRange::getTokenRange(RHSInt->getSourceRange()),
- S.getSourceManager(), S.getLangOpts());
+ S.getSourceManager(), S.getLangOpts()));
if (Negative) {
RightSideValue = -RightSideValue;
@@ -11411,6 +12070,83 @@ QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
return GetSignedVectorType(LHS.get()->getType());
}
+QualType Sema::CheckMatrixElementwiseOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc,
+ bool IsCompAssign) {
+ if (!IsCompAssign) {
+ LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
+ if (LHS.isInvalid())
+ return QualType();
+ }
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
+ if (RHS.isInvalid())
+ return QualType();
+
+ // For conversion purposes, we ignore any qualifiers.
+ // For example, "const float" and "float" are equivalent.
+ QualType LHSType = LHS.get()->getType().getUnqualifiedType();
+ QualType RHSType = RHS.get()->getType().getUnqualifiedType();
+
+ const MatrixType *LHSMatType = LHSType->getAs<MatrixType>();
+ const MatrixType *RHSMatType = RHSType->getAs<MatrixType>();
+ assert((LHSMatType || RHSMatType) && "At least one operand must be a matrix");
+
+ if (Context.hasSameType(LHSType, RHSType))
+ return LHSType;
+
+ // Type conversion may change LHS/RHS. Keep copies to the original results, in
+ // case we have to return InvalidOperands.
+ ExprResult OriginalLHS = LHS;
+ ExprResult OriginalRHS = RHS;
+ if (LHSMatType && !RHSMatType) {
+ RHS = tryConvertExprToType(RHS.get(), LHSMatType->getElementType());
+ if (!RHS.isInvalid())
+ return LHSType;
+
+ return InvalidOperands(Loc, OriginalLHS, OriginalRHS);
+ }
+
+ if (!LHSMatType && RHSMatType) {
+ LHS = tryConvertExprToType(LHS.get(), RHSMatType->getElementType());
+ if (!LHS.isInvalid())
+ return RHSType;
+ return InvalidOperands(Loc, OriginalLHS, OriginalRHS);
+ }
+
+ return InvalidOperands(Loc, LHS, RHS);
+}
+
+QualType Sema::CheckMatrixMultiplyOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc,
+ bool IsCompAssign) {
+ if (!IsCompAssign) {
+ LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
+ if (LHS.isInvalid())
+ return QualType();
+ }
+ RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
+ if (RHS.isInvalid())
+ return QualType();
+
+ auto *LHSMatType = LHS.get()->getType()->getAs<ConstantMatrixType>();
+ auto *RHSMatType = RHS.get()->getType()->getAs<ConstantMatrixType>();
+ assert((LHSMatType || RHSMatType) && "At least one operand must be a matrix");
+
+ if (LHSMatType && RHSMatType) {
+ if (LHSMatType->getNumColumns() != RHSMatType->getNumRows())
+ return InvalidOperands(Loc, LHS, RHS);
+
+ if (!Context.hasSameType(LHSMatType->getElementType(),
+ RHSMatType->getElementType()))
+ return InvalidOperands(Loc, LHS, RHS);
+
+ return Context.getConstantMatrixType(LHSMatType->getElementType(),
+ LHSMatType->getNumRows(),
+ RHSMatType->getNumColumns());
+ }
+ return CheckMatrixElementwiseOperands(LHS, RHS, Loc, IsCompAssign);
+}
+
inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
@@ -12096,7 +12832,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
CheckForNullPointerDereference(*this, LHSExpr);
- if (getLangOpts().CPlusPlus2a && LHSType.isVolatileQualified()) {
+ if (getLangOpts().CPlusPlus20 && LHSType.isVolatileQualified()) {
if (CompoundType.isNull()) {
// C++2a [expr.ass]p5:
// A simple-assignment whose left operand is of a volatile-qualified
@@ -12142,8 +12878,8 @@ static bool IgnoreCommaOperand(const Expr *E) {
}
// Look for instances where it is likely the comma operator is confused with
-// another operator. There is a whitelist of acceptable expressions for the
-// left hand side of the comma operator, otherwise emit a warning.
+// another operator. There is an explicit list of acceptable expressions for
+// the left hand side of the comma operator, otherwise emit a warning.
void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) {
// No warnings in macros
if (Loc.isMacroID())
@@ -12153,10 +12889,10 @@ void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) {
if (inTemplateInstantiation())
return;
- // Scope isn't fine-grained enough to whitelist the specific cases, so
+ // Scope isn't fine-grained enough to explicitly list the specific cases, so
// instead, skip more than needed, then call back into here with the
// CommaVisitor in SemaStmt.cpp.
- // The whitelisted locations are the initialization and increment portions
+ // The listed locations are the initialization and increment portions
// of a for loop. The additional checks are on the condition of
// if statements, do/while loops, and for loops.
// Differences in scope flags for C89 mode requires the extra logic.
@@ -12299,7 +13035,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
// Now make sure the operand is a modifiable lvalue.
if (CheckForModifiableLvalue(Op, OpLoc, S))
return QualType();
- if (S.getLangOpts().CPlusPlus2a && ResType.isVolatileQualified()) {
+ if (S.getLangOpts().CPlusPlus20 && ResType.isVolatileQualified()) {
// C++2a [expr.pre.inc]p1, [expr.post.inc]p1:
// An operand with volatile-qualified type is deprecated
S.Diag(OpLoc, diag::warn_deprecated_increment_decrement_volatile)
@@ -12331,6 +13067,9 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
/// - *(x + 1) -> x, if x is an array
/// - &"123"[2] -> 0
/// - & __real__ x -> x
+///
+/// FIXME: We don't recurse to the RHS of a comma, nor handle pointers to
+/// members.
static ValueDecl *getPrimaryDecl(Expr *E) {
switch (E->getStmtClass()) {
case Stmt::DeclRefExprClass:
@@ -12371,19 +13110,22 @@ static ValueDecl *getPrimaryDecl(Expr *E) {
// If the result of an implicit cast is an l-value, we care about
// the sub-expression; otherwise, the result here doesn't matter.
return getPrimaryDecl(cast<ImplicitCastExpr>(E)->getSubExpr());
+ case Stmt::CXXUuidofExprClass:
+ return cast<CXXUuidofExpr>(E)->getGuidDecl();
default:
return nullptr;
}
}
namespace {
- enum {
- AO_Bit_Field = 0,
- AO_Vector_Element = 1,
- AO_Property_Expansion = 2,
- AO_Register_Variable = 3,
- AO_No_Error = 4
- };
+enum {
+ AO_Bit_Field = 0,
+ AO_Vector_Element = 1,
+ AO_Property_Expansion = 2,
+ AO_Register_Variable = 3,
+ AO_Matrix_Element = 4,
+ AO_No_Error = 5
+};
}
/// Diagnose invalid operand for address of operations.
///
@@ -12550,6 +13292,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
} else if (op->getObjectKind() == OK_VectorComponent) {
// The operand cannot be an element of a vector
AddressOfError = AO_Vector_Element;
+ } else if (op->getObjectKind() == OK_MatrixComponent) {
+ // The operand cannot be an element of a matrix.
+ AddressOfError = AO_Matrix_Element;
} else if (dcl) { // C99 6.5.3.2p1
// We have an lvalue with a decl. Make sure the decl is not declared
// with the register storage-class specifier.
@@ -12591,7 +13336,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
}
}
} else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl) &&
- !isa<BindingDecl>(dcl))
+ !isa<BindingDecl>(dcl) && !isa<MSGuidDecl>(dcl))
llvm_unreachable("Unknown/unexpected decl type");
}
@@ -12855,7 +13600,7 @@ static ExprResult convertHalfVecBinOp(Sema &S, ExprResult LHS, ExprResult RHS,
BinaryOperatorKind Opc, QualType ResultTy,
ExprValueKind VK, ExprObjectKind OK,
bool IsCompAssign, SourceLocation OpLoc,
- FPOptions FPFeatures) {
+ FPOptionsOverride FPFeatures) {
auto &Context = S.getASTContext();
assert((isVector(ResultTy, Context.HalfTy) ||
isVector(ResultTy, Context.ShortTy)) &&
@@ -12873,13 +13618,13 @@ static ExprResult convertHalfVecBinOp(Sema &S, ExprResult LHS, ExprResult RHS,
BinOpResTy = S.GetSignedVectorType(BinOpResTy);
if (IsCompAssign)
- return new (Context) CompoundAssignOperator(
- LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, BinOpResTy, BinOpResTy,
- OpLoc, FPFeatures);
+ return CompoundAssignOperator::Create(Context, LHS.get(), RHS.get(), Opc,
+ ResultTy, VK, OK, OpLoc, FPFeatures,
+ BinOpResTy, BinOpResTy);
LHS = convertVector(LHS.get(), Context.FloatTy, S);
- auto *BO = new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, BinOpResTy,
- VK, OK, OpLoc, FPFeatures);
+ auto *BO = BinaryOperator::Create(Context, LHS.get(), RHS.get(), Opc,
+ BinOpResTy, VK, OK, OpLoc, FPFeatures);
return convertVector(BO, ResultTy->castAs<VectorType>()->getElementType(), S);
}
@@ -12892,13 +13637,15 @@ CorrectDelayedTyposInBinOp(Sema &S, BinaryOperatorKind Opc, Expr *LHSExpr,
// doesn't handle dependent types properly, so make sure any TypoExprs have
// been dealt with before checking the operands.
LHS = S.CorrectDelayedTyposInExpr(LHS);
- RHS = S.CorrectDelayedTyposInExpr(RHS, [Opc, LHS](Expr *E) {
- if (Opc != BO_Assign)
- return ExprResult(E);
- // Avoid correcting the RHS to the same Expr as the LHS.
- Decl *D = getDeclFromExpr(E);
- return (D && D == getDeclFromExpr(LHS.get())) ? ExprError() : E;
- });
+ RHS = S.CorrectDelayedTyposInExpr(
+ RHS, /*InitDecl=*/nullptr, /*RecoverUncorrectedTypos=*/false,
+ [Opc, LHS](Expr *E) {
+ if (Opc != BO_Assign)
+ return ExprResult(E);
+ // Avoid correcting the RHS to the same Expr as the LHS.
+ Decl *D = getDeclFromExpr(E);
+ return (D && D == getDeclFromExpr(LHS.get())) ? ExprError() : E;
+ });
}
return std::make_pair(LHS, RHS);
}
@@ -12906,10 +13653,27 @@ CorrectDelayedTyposInBinOp(Sema &S, BinaryOperatorKind Opc, Expr *LHSExpr,
/// Returns true if conversion between vectors of halfs and vectors of floats
/// is needed.
static bool needsConversionOfHalfVec(bool OpRequiresConversion, ASTContext &Ctx,
- QualType SrcType) {
- return OpRequiresConversion && !Ctx.getLangOpts().NativeHalfType &&
- !Ctx.getTargetInfo().useFP16ConversionIntrinsics() &&
- isVector(SrcType, Ctx.HalfTy);
+ Expr *E0, Expr *E1 = nullptr) {
+ if (!OpRequiresConversion || Ctx.getLangOpts().NativeHalfType ||
+ Ctx.getTargetInfo().useFP16ConversionIntrinsics())
+ return false;
+
+ auto HasVectorOfHalfType = [&Ctx](Expr *E) {
+ QualType Ty = E->IgnoreImplicit()->getType();
+
+ // Don't promote half precision neon vectors like float16x4_t in arm_neon.h
+ // to vectors of floats. Although the element type of the vectors is __fp16,
+ // the vectors shouldn't be treated as storage-only types. See the
+ // discussion here: https://reviews.llvm.org/rG825235c140e7
+ if (const VectorType *VT = Ty->getAs<VectorType>()) {
+ if (VT->getVectorKind() == VectorType::NeonVector)
+ return false;
+ return VT->getElementType().getCanonicalType() == Ctx.HalfTy;
+ }
+ return false;
+ };
+
+ return HasVectorOfHalfType(E0) && (!E1 || HasVectorOfHalfType(E1));
}
/// CreateBuiltinBinOp - Creates a new built-in binary operation with
@@ -12974,14 +13738,6 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
}
}
- // Diagnose operations on the unsupported types for OpenMP device compilation.
- if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice) {
- if (Opc != BO_Assign && Opc != BO_Comma) {
- checkOpenMPDeviceExpr(LHSExpr);
- checkOpenMPDeviceExpr(RHSExpr);
- }
- }
-
switch (Opc) {
case BO_Assign:
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
@@ -13129,14 +13885,6 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
if (ResultTy.isNull() || LHS.isInvalid() || RHS.isInvalid())
return ExprError();
- if (ResultTy->isRealFloatingType() &&
- (getLangOpts().getFPRoundingMode() != LangOptions::FPR_ToNearest ||
- getLangOpts().getFPExceptionMode() != LangOptions::FPE_Ignore))
- // Mark the current function as usng floating point constrained intrinsics
- if (FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext)) {
- F->setUsesFPIntrin(true);
- }
-
// Some of the binary operations require promoting operands of half vector to
// float vectors and truncating the result back to half vector. For now, we do
// this only when HalfArgsAndReturn is set (that is, when the target is arm or
@@ -13144,8 +13892,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
assert(isVector(RHS.get()->getType(), Context.HalfTy) ==
isVector(LHS.get()->getType(), Context.HalfTy) &&
"both sides are half vectors or neither sides are");
- ConvertHalfVec = needsConversionOfHalfVec(ConvertHalfVec, Context,
- LHS.get()->getType());
+ ConvertHalfVec =
+ needsConversionOfHalfVec(ConvertHalfVec, Context, LHS.get(), RHS.get());
// Check for array bounds violations for both sides of the BinaryOperator
CheckArrayAccess(LHS.get());
@@ -13175,9 +13923,9 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
if (CompResultTy.isNull()) {
if (ConvertHalfVec)
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, false,
- OpLoc, FPFeatures);
- return new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, ResultTy, VK,
- OK, OpLoc, FPFeatures);
+ OpLoc, CurFPFeatureOverrides());
+ return BinaryOperator::Create(Context, LHS.get(), RHS.get(), Opc, ResultTy,
+ VK, OK, OpLoc, CurFPFeatureOverrides());
}
// Handle compound assignments.
@@ -13187,13 +13935,19 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
OK = LHS.get()->getObjectKind();
}
+ // The LHS is not converted to the result type for fixed-point compound
+ // assignment as the common type is computed on demand. Reset the CompLHSTy
+ // to the LHS type we would have gotten after unary conversions.
+ if (CompResultTy->isFixedPointType())
+ CompLHSTy = UsualUnaryConversions(LHS.get()).get()->getType();
+
if (ConvertHalfVec)
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, true,
- OpLoc, FPFeatures);
+ OpLoc, CurFPFeatureOverrides());
- return new (Context) CompoundAssignOperator(
- LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, CompLHSTy, CompResultTy,
- OpLoc, FPFeatures);
+ return CompoundAssignOperator::Create(
+ Context, LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, OpLoc,
+ CurFPFeatureOverrides(), CompLHSTy, CompResultTy);
}
/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
@@ -13446,7 +14200,7 @@ static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
RHS->getType(), Functions);
// In C++20 onwards, we may have a second operator to look up.
- if (S.getLangOpts().CPlusPlus2a) {
+ if (S.getLangOpts().CPlusPlus20) {
if (OverloadedOperatorKind ExtraOp = getRewrittenOverloadedOperator(OverOp))
S.LookupOverloadedOperatorName(ExtraOp, Sc, LHS->getType(),
RHS->getType(), Functions);
@@ -13596,12 +14350,6 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
<< Input.get()->getSourceRange());
}
}
- // Diagnose operations on the unsupported types for OpenMP device compilation.
- if (getLangOpts().OpenMP && getLangOpts().OpenMPIsDevice) {
- if (UnaryOperator::isIncrementDecrementOp(Opc) ||
- UnaryOperator::isArithmeticOp(Opc))
- checkOpenMPDeviceExpr(InputExpr);
- }
switch (Opc) {
case UO_PreInc:
@@ -13637,8 +14385,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
// float vector and truncating the result back to a half vector. For now, we
// do this only when HalfArgsAndReturns is set (that is, when the target is
// arm or arm64).
- ConvertHalfVec =
- needsConversionOfHalfVec(true, Context, Input.get()->getType());
+ ConvertHalfVec = needsConversionOfHalfVec(true, Context, Input.get());
// If the operand is a half vector, promote it to a float vector.
if (ConvertHalfVec)
@@ -13732,9 +14479,16 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
// Vector logical not returns the signed variant of the operand type.
resultType = GetSignedVectorType(resultType);
break;
+ } else if (Context.getLangOpts().CPlusPlus && resultType->isVectorType()) {
+ const VectorType *VTy = resultType->castAs<VectorType>();
+ if (VTy->getVectorKind() != VectorType::GenericVector)
+ return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
+ << resultType << Input.get()->getSourceRange());
+
+ // Vector logical not returns the signed variant of the operand type.
+ resultType = GetSignedVectorType(resultType);
+ break;
} else {
- // FIXME: GCC's vector extension permits the usage of '!' with a vector
- // type in C++. We should allow that here too.
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
}
@@ -13781,8 +14535,9 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
if (Opc != UO_AddrOf && Opc != UO_Deref)
CheckArrayAccess(Input.get());
- auto *UO = new (Context)
- UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc, CanOverflow);
+ auto *UO =
+ UnaryOperator::Create(Context, Input.get(), Opc, resultType, VK, OK,
+ OpLoc, CanOverflow, CurFPFeatureOverrides());
if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) &&
!isa<ArrayType>(UO->getType().getDesugaredType(Context)))
@@ -14174,11 +14929,9 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resType;
- bool ValueDependent = false;
bool CondIsTrue = false;
if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) {
resType = Context.DependentTy;
- ValueDependent = true;
} else {
// The conditional expression is required to be a constant expression.
llvm::APSInt condEval(32);
@@ -14194,14 +14947,12 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr;
resType = ActiveExpr->getType();
- ValueDependent = ActiveExpr->isValueDependent();
VK = ActiveExpr->getValueKind();
OK = ActiveExpr->getObjectKind();
}
- return new (Context)
- ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, VK, OK, RPLoc,
- CondIsTrue, resType->isDependentType(), ValueDependent);
+ return new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
+ resType, VK, OK, RPLoc, CondIsTrue);
}
//===----------------------------------------------------------------------===//
@@ -14312,11 +15063,12 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
if (ExplicitSignature) {
for (unsigned I = 0, E = ExplicitSignature.getNumParams(); I != E; ++I) {
ParmVarDecl *Param = ExplicitSignature.getParam(I);
- if (Param->getIdentifier() == nullptr &&
- !Param->isImplicit() &&
- !Param->isInvalidDecl() &&
- !getLangOpts().CPlusPlus)
- Diag(Param->getLocation(), diag::err_parameter_name_omitted);
+ if (Param->getIdentifier() == nullptr && !Param->isImplicit() &&
+ !Param->isInvalidDecl() && !getLangOpts().CPlusPlus) {
+ // Diagnose this as an extension in C17 and earlier.
+ if (!getLangOpts().C2x)
+ Diag(Param->getLocation(), diag::ext_parameter_name_omitted_c2x);
+ }
Params.push_back(Param);
}
@@ -14705,21 +15457,15 @@ ExprResult Sema::BuildSourceLocExpr(SourceLocExpr::IdentKind Kind,
SourceLocExpr(Context, Kind, BuiltinLoc, RPLoc, ParentContext);
}
-bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp,
- bool Diagnose) {
+bool Sema::CheckConversionToObjCLiteral(QualType DstType, Expr *&Exp,
+ bool Diagnose) {
if (!getLangOpts().ObjC)
return false;
const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
if (!PT)
return false;
-
- if (!PT->isObjCIdType()) {
- // Check if the destination is the 'NSString' interface.
- const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
- if (!ID || !ID->getIdentifier()->isStr("NSString"))
- return false;
- }
+ const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
// Ignore any parens, implicit casts (should only be
// array-to-pointer decays), and not-so-opaque values. The last is
@@ -14729,15 +15475,41 @@ bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp,
if (OV->getSourceExpr())
SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();
- StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr);
- if (!SL || !SL->isAscii())
- return false;
- if (Diagnose) {
- Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix)
- << FixItHint::CreateInsertion(SL->getBeginLoc(), "@");
- Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get();
+ if (auto *SL = dyn_cast<StringLiteral>(SrcExpr)) {
+ if (!PT->isObjCIdType() &&
+ !(ID && ID->getIdentifier()->isStr("NSString")))
+ return false;
+ if (!SL->isAscii())
+ return false;
+
+ if (Diagnose) {
+ Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix)
+ << /*string*/0 << FixItHint::CreateInsertion(SL->getBeginLoc(), "@");
+ Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get();
+ }
+ return true;
}
- return true;
+
+ if ((isa<IntegerLiteral>(SrcExpr) || isa<CharacterLiteral>(SrcExpr) ||
+ isa<FloatingLiteral>(SrcExpr) || isa<ObjCBoolLiteralExpr>(SrcExpr) ||
+ isa<CXXBoolLiteralExpr>(SrcExpr)) &&
+ !SrcExpr->isNullPointerConstant(
+ getASTContext(), Expr::NPC_NeverValueDependent)) {
+ if (!ID || !ID->getIdentifier()->isStr("NSNumber"))
+ return false;
+ if (Diagnose) {
+ Diag(SrcExpr->getBeginLoc(), diag::err_missing_atsign_prefix)
+ << /*number*/1
+ << FixItHint::CreateInsertion(SrcExpr->getBeginLoc(), "@");
+ Expr *NumLit =
+ BuildObjCNumericLiteral(SrcExpr->getBeginLoc(), SrcExpr).get();
+ if (NumLit)
+ Exp = NumLit;
+ }
+ return true;
+ }
+
+ return false;
}
static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType,
@@ -14784,24 +15556,44 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
return false;
case PointerToInt:
- DiagKind = diag::ext_typecheck_convert_pointer_int;
+ if (getLangOpts().CPlusPlus) {
+ DiagKind = diag::err_typecheck_convert_pointer_int;
+ isInvalid = true;
+ } else {
+ DiagKind = diag::ext_typecheck_convert_pointer_int;
+ }
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
MayHaveConvFixit = true;
break;
case IntToPointer:
- DiagKind = diag::ext_typecheck_convert_int_pointer;
+ if (getLangOpts().CPlusPlus) {
+ DiagKind = diag::err_typecheck_convert_int_pointer;
+ isInvalid = true;
+ } else {
+ DiagKind = diag::ext_typecheck_convert_int_pointer;
+ }
+ ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
+ MayHaveConvFixit = true;
+ break;
+ case IncompatibleFunctionPointer:
+ if (getLangOpts().CPlusPlus) {
+ DiagKind = diag::err_typecheck_convert_incompatible_function_pointer;
+ isInvalid = true;
+ } else {
+ DiagKind = diag::ext_typecheck_convert_incompatible_function_pointer;
+ }
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
MayHaveConvFixit = true;
break;
case IncompatiblePointer:
- if (Action == AA_Passing_CFAudited)
+ if (Action == AA_Passing_CFAudited) {
DiagKind = diag::err_arc_typecheck_convert_incompatible_pointer;
- else if (SrcType->isFunctionPointerType() &&
- DstType->isFunctionPointerType())
- DiagKind = diag::ext_typecheck_convert_incompatible_function_pointer;
- else
+ } else if (getLangOpts().CPlusPlus) {
+ DiagKind = diag::err_typecheck_convert_incompatible_pointer;
+ isInvalid = true;
+ } else {
DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
-
+ }
CheckInferredResultType = DstType->isObjCObjectPointerType() &&
SrcType->isObjCObjectPointerType();
if (Hint.isNull() && !CheckInferredResultType) {
@@ -14814,15 +15606,27 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
MayHaveConvFixit = true;
break;
case IncompatiblePointerSign:
- DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign;
+ if (getLangOpts().CPlusPlus) {
+ DiagKind = diag::err_typecheck_convert_incompatible_pointer_sign;
+ isInvalid = true;
+ } else {
+ DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign;
+ }
break;
case FunctionVoidPointer:
- DiagKind = diag::ext_typecheck_convert_pointer_void_func;
+ if (getLangOpts().CPlusPlus) {
+ DiagKind = diag::err_typecheck_convert_pointer_void_func;
+ isInvalid = true;
+ } else {
+ DiagKind = diag::ext_typecheck_convert_pointer_void_func;
+ }
break;
case IncompatiblePointerDiscardsQualifiers: {
// Perform array-to-pointer decay if necessary.
if (SrcType->isArrayType()) SrcType = Context.getArrayDecayedType(SrcType);
+ isInvalid = true;
+
Qualifiers lhq = SrcType->getPointeeType().getQualifiers();
Qualifiers rhq = DstType->getPointeeType().getQualifiers();
if (lhq.getAddressSpace() != rhq.getAddressSpace()) {
@@ -14850,19 +15654,33 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
if (getLangOpts().CPlusPlus &&
IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType))
return false;
- DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
+ if (getLangOpts().CPlusPlus) {
+ DiagKind = diag::err_typecheck_convert_discards_qualifiers;
+ isInvalid = true;
+ } else {
+ DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
+ }
+
break;
case IncompatibleNestedPointerQualifiers:
- DiagKind = diag::ext_nested_pointer_qualifier_mismatch;
+ if (getLangOpts().CPlusPlus) {
+ isInvalid = true;
+ DiagKind = diag::err_nested_pointer_qualifier_mismatch;
+ } else {
+ DiagKind = diag::ext_nested_pointer_qualifier_mismatch;
+ }
break;
case IncompatibleNestedPointerAddressSpaceMismatch:
DiagKind = diag::err_typecheck_incompatible_nested_address_space;
+ isInvalid = true;
break;
case IntToBlockPointer:
DiagKind = diag::err_int_to_block_pointer;
+ isInvalid = true;
break;
case IncompatibleBlockPointer:
DiagKind = diag::err_typecheck_convert_incompatible_block_pointer;
+ isInvalid = true;
break;
case IncompatibleObjCQualifiedId: {
if (SrcType->isObjCQualifiedIdType()) {
@@ -14887,14 +15705,25 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SrcType->castAs<ObjCObjectPointerType>()->getInterfaceType())
IFace = IFaceT->getDecl();
}
- DiagKind = diag::warn_incompatible_qualified_id;
+ if (getLangOpts().CPlusPlus) {
+ DiagKind = diag::err_incompatible_qualified_id;
+ isInvalid = true;
+ } else {
+ DiagKind = diag::warn_incompatible_qualified_id;
+ }
break;
}
case IncompatibleVectors:
- DiagKind = diag::warn_incompatible_vectors;
+ if (getLangOpts().CPlusPlus) {
+ DiagKind = diag::err_incompatible_vectors;
+ isInvalid = true;
+ } else {
+ DiagKind = diag::warn_incompatible_vectors;
+ }
break;
case IncompatibleObjCWeakRef:
DiagKind = diag::err_arc_weak_unavailable_assign;
+ isInvalid = true;
break;
case Incompatible:
if (maybeDiagnoseAssignmentToFunction(*this, DstType, SrcExpr)) {
@@ -14952,9 +15781,10 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
HandleFunctionTypeMismatch(FDiag, SecondType, FirstType);
Diag(Loc, FDiag);
- if (DiagKind == diag::warn_incompatible_qualified_id &&
+ if ((DiagKind == diag::warn_incompatible_qualified_id ||
+ DiagKind == diag::err_incompatible_qualified_id) &&
PDecl && IFace && !IFace->hasDefinition())
- Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id)
+ Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id)
<< IFace << PDecl;
if (SecondType == Context.OverloadTy)
@@ -15079,6 +15909,12 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
return ExprError();
}
+ ExprResult RValueExpr = DefaultLvalueConversion(E);
+ if (RValueExpr.isInvalid())
+ return ExprError();
+
+ E = RValueExpr.get();
+
// Circumvent ICE checking in C++11 to avoid evaluating the expression twice
// in the non-ICE case.
if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
@@ -15266,7 +16102,7 @@ void Sema::WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec) {
/// and if so, remove it from the list of volatile-qualified assignments that
/// we are going to warn are deprecated.
void Sema::CheckUnusedVolatileAssignment(Expr *E) {
- if (!E->getType().isVolatileQualified() || !getLangOpts().CPlusPlus2a)
+ if (!E->getType().isVolatileQualified() || !getLangOpts().CPlusPlus20)
return;
// Note: ignoring parens here is not justified by the standard rules, but
@@ -15281,6 +16117,186 @@ void Sema::CheckUnusedVolatileAssignment(Expr *E) {
}
}
+ExprResult Sema::CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl) {
+ if (!E.isUsable() || !Decl || !Decl->isConsteval() || isConstantEvaluated() ||
+ RebuildingImmediateInvocation)
+ return E;
+
+ /// Opportunistically remove the callee from ReferencesToConsteval if we can.
+ /// It's OK if this fails; we'll also remove this in
+ /// HandleImmediateInvocations, but catching it here allows us to avoid
+ /// walking the AST looking for it in simple cases.
+ if (auto *Call = dyn_cast<CallExpr>(E.get()->IgnoreImplicit()))
+ if (auto *DeclRef =
+ dyn_cast<DeclRefExpr>(Call->getCallee()->IgnoreImplicit()))
+ ExprEvalContexts.back().ReferenceToConsteval.erase(DeclRef);
+
+ E = MaybeCreateExprWithCleanups(E);
+
+ ConstantExpr *Res = ConstantExpr::Create(
+ getASTContext(), E.get(),
+ ConstantExpr::getStorageKind(Decl->getReturnType().getTypePtr(),
+ getASTContext()),
+ /*IsImmediateInvocation*/ true);
+ ExprEvalContexts.back().ImmediateInvocationCandidates.emplace_back(Res, 0);
+ return Res;
+}
+
+static void EvaluateAndDiagnoseImmediateInvocation(
+ Sema &SemaRef, Sema::ImmediateInvocationCandidate Candidate) {
+ llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ Expr::EvalResult Eval;
+ Eval.Diag = &Notes;
+ ConstantExpr *CE = Candidate.getPointer();
+ bool Result = CE->EvaluateAsConstantExpr(Eval, Expr::EvaluateForCodeGen,
+ SemaRef.getASTContext(), true);
+ if (!Result || !Notes.empty()) {
+ Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit();
+ if (auto *FunctionalCast = dyn_cast<CXXFunctionalCastExpr>(InnerExpr))
+ InnerExpr = FunctionalCast->getSubExpr();
+ FunctionDecl *FD = nullptr;
+ if (auto *Call = dyn_cast<CallExpr>(InnerExpr))
+ FD = cast<FunctionDecl>(Call->getCalleeDecl());
+ else if (auto *Call = dyn_cast<CXXConstructExpr>(InnerExpr))
+ FD = Call->getConstructor();
+ else
+ llvm_unreachable("unhandled decl kind");
+ assert(FD->isConsteval());
+ SemaRef.Diag(CE->getBeginLoc(), diag::err_invalid_consteval_call) << FD;
+ for (auto &Note : Notes)
+ SemaRef.Diag(Note.first, Note.second);
+ return;
+ }
+ CE->MoveIntoResult(Eval.Val, SemaRef.getASTContext());
+}
+
+static void RemoveNestedImmediateInvocation(
+ Sema &SemaRef, Sema::ExpressionEvaluationContextRecord &Rec,
+ SmallVector<Sema::ImmediateInvocationCandidate, 4>::reverse_iterator It) {
+ struct ComplexRemove : TreeTransform<ComplexRemove> {
+ using Base = TreeTransform<ComplexRemove>;
+ llvm::SmallPtrSetImpl<DeclRefExpr *> &DRSet;
+ SmallVector<Sema::ImmediateInvocationCandidate, 4> &IISet;
+ SmallVector<Sema::ImmediateInvocationCandidate, 4>::reverse_iterator
+ CurrentII;
+ ComplexRemove(Sema &SemaRef, llvm::SmallPtrSetImpl<DeclRefExpr *> &DR,
+ SmallVector<Sema::ImmediateInvocationCandidate, 4> &II,
+ SmallVector<Sema::ImmediateInvocationCandidate,
+ 4>::reverse_iterator Current)
+ : Base(SemaRef), DRSet(DR), IISet(II), CurrentII(Current) {}
+ void RemoveImmediateInvocation(ConstantExpr* E) {
+ auto It = std::find_if(CurrentII, IISet.rend(),
+ [E](Sema::ImmediateInvocationCandidate Elem) {
+ return Elem.getPointer() == E;
+ });
+ assert(It != IISet.rend() &&
+ "ConstantExpr marked IsImmediateInvocation should "
+ "be present");
+ It->setInt(1); // Mark as deleted
+ }
+ ExprResult TransformConstantExpr(ConstantExpr *E) {
+ if (!E->isImmediateInvocation())
+ return Base::TransformConstantExpr(E);
+ RemoveImmediateInvocation(E);
+ return Base::TransformExpr(E->getSubExpr());
+ }
+ /// Base::TransfromCXXOperatorCallExpr doesn't traverse the callee so
+ /// we need to remove its DeclRefExpr from the DRSet.
+ ExprResult TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ DRSet.erase(cast<DeclRefExpr>(E->getCallee()->IgnoreImplicit()));
+ return Base::TransformCXXOperatorCallExpr(E);
+ }
+ /// Base::TransformInitializer skip ConstantExpr so we need to visit them
+ /// here.
+ ExprResult TransformInitializer(Expr *Init, bool NotCopyInit) {
+ if (!Init)
+ return Init;
+ /// ConstantExpr are the first layer of implicit node to be removed so if
+ /// Init isn't a ConstantExpr, no ConstantExpr will be skipped.
+ if (auto *CE = dyn_cast<ConstantExpr>(Init))
+ if (CE->isImmediateInvocation())
+ RemoveImmediateInvocation(CE);
+ return Base::TransformInitializer(Init, NotCopyInit);
+ }
+ ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
+ DRSet.erase(E);
+ return E;
+ }
+ bool AlwaysRebuild() { return false; }
+ bool ReplacingOriginal() { return true; }
+ bool AllowSkippingCXXConstructExpr() {
+ bool Res = AllowSkippingFirstCXXConstructExpr;
+ AllowSkippingFirstCXXConstructExpr = true;
+ return Res;
+ }
+ bool AllowSkippingFirstCXXConstructExpr = true;
+ } Transformer(SemaRef, Rec.ReferenceToConsteval,
+ Rec.ImmediateInvocationCandidates, It);
+
+ /// CXXConstructExpr with a single argument are getting skipped by
+ /// TreeTransform in some situtation because they could be implicit. This
+ /// can only occur for the top-level CXXConstructExpr because it is used
+ /// nowhere in the expression being transformed therefore will not be rebuilt.
+ /// Setting AllowSkippingFirstCXXConstructExpr to false will prevent from
+ /// skipping the first CXXConstructExpr.
+ if (isa<CXXConstructExpr>(It->getPointer()->IgnoreImplicit()))
+ Transformer.AllowSkippingFirstCXXConstructExpr = false;
+
+ ExprResult Res = Transformer.TransformExpr(It->getPointer()->getSubExpr());
+ assert(Res.isUsable());
+ Res = SemaRef.MaybeCreateExprWithCleanups(Res);
+ It->getPointer()->setSubExpr(Res.get());
+}
+
+static void
+HandleImmediateInvocations(Sema &SemaRef,
+ Sema::ExpressionEvaluationContextRecord &Rec) {
+ if ((Rec.ImmediateInvocationCandidates.size() == 0 &&
+ Rec.ReferenceToConsteval.size() == 0) ||
+ SemaRef.RebuildingImmediateInvocation)
+ return;
+
+ /// When we have more then 1 ImmediateInvocationCandidates we need to check
+ /// for nested ImmediateInvocationCandidates. when we have only 1 we only
+ /// need to remove ReferenceToConsteval in the immediate invocation.
+ if (Rec.ImmediateInvocationCandidates.size() > 1) {
+
+ /// Prevent sema calls during the tree transform from adding pointers that
+ /// are already in the sets.
+ llvm::SaveAndRestore<bool> DisableIITracking(
+ SemaRef.RebuildingImmediateInvocation, true);
+
+ /// Prevent diagnostic during tree transfrom as they are duplicates
+ Sema::TentativeAnalysisScope DisableDiag(SemaRef);
+
+ for (auto It = Rec.ImmediateInvocationCandidates.rbegin();
+ It != Rec.ImmediateInvocationCandidates.rend(); It++)
+ if (!It->getInt())
+ RemoveNestedImmediateInvocation(SemaRef, Rec, It);
+ } else if (Rec.ImmediateInvocationCandidates.size() == 1 &&
+ Rec.ReferenceToConsteval.size()) {
+ struct SimpleRemove : RecursiveASTVisitor<SimpleRemove> {
+ llvm::SmallPtrSetImpl<DeclRefExpr *> &DRSet;
+ SimpleRemove(llvm::SmallPtrSetImpl<DeclRefExpr *> &S) : DRSet(S) {}
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
+ DRSet.erase(E);
+ return DRSet.size();
+ }
+ } Visitor(Rec.ReferenceToConsteval);
+ Visitor.TraverseStmt(
+ Rec.ImmediateInvocationCandidates.front().getPointer()->getSubExpr());
+ }
+ for (auto CE : Rec.ImmediateInvocationCandidates)
+ if (!CE.getInt())
+ EvaluateAndDiagnoseImmediateInvocation(SemaRef, CE);
+ for (auto DR : Rec.ReferenceToConsteval) {
+ auto *FD = cast<FunctionDecl>(DR->getDecl());
+ SemaRef.Diag(DR->getBeginLoc(), diag::err_invalid_consteval_take_address)
+ << FD;
+ SemaRef.Diag(FD->getLocation(), diag::note_declared_at);
+ }
+}
+
void Sema::PopExpressionEvaluationContext() {
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
unsigned NumTypos = Rec.NumTypos;
@@ -15314,6 +16330,7 @@ void Sema::PopExpressionEvaluationContext() {
}
WarnOnPendingNoDerefs(Rec);
+ HandleImmediateInvocations(*this, Rec);
// Warn on any volatile-qualified simple-assignments that are not discarded-
// value expressions nor unevaluated operands (those cases get removed from
@@ -15599,6 +16616,9 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
if (getLangOpts().CUDA)
CheckCUDACall(Loc, Func);
+ if (getLangOpts().SYCLIsDevice)
+ checkSYCLDeviceFunction(Loc, Func);
+
// If we need a definition, try to create one.
if (NeedDefinition && !Func->getBody()) {
runWithSufficientStackSpace(Loc, [&] {
@@ -15737,15 +16757,21 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
if (funcHasParameterSizeMangling(*this, Func))
CheckCompleteParameterTypesForMangler(*this, Func, Loc);
- Func->markUsed(Context);
- }
+ // In the MS C++ ABI, the compiler emits destructor variants where they are
+ // used. If the destructor is used here but defined elsewhere, mark the
+ // virtual base destructors referenced. If those virtual base destructors
+ // are inline, this will ensure they are defined when emitting the complete
+ // destructor variant. This checking may be redundant if the destructor is
+ // provided later in this TU.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (auto *Dtor = dyn_cast<CXXDestructorDecl>(Func)) {
+ CXXRecordDecl *Parent = Dtor->getParent();
+ if (Parent->getNumVBases() > 0 && !Dtor->getBody())
+ CheckCompleteDestructorVariant(Loc, Dtor);
+ }
+ }
- if (LangOpts.OpenMP) {
- markOpenMPDeclareVariantFuncsReferenced(Loc, Func, MightBeOdrUse);
- if (LangOpts.OpenMPIsDevice)
- checkOpenMPDeviceFunction(Loc, Func);
- else
- checkOpenMPHostFunction(Loc, Func);
+ Func->markUsed(Context);
}
}
@@ -16037,6 +17063,10 @@ static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
if (HasConst)
DeclRefType.addConst();
}
+ // Do not capture firstprivates in tasks.
+ if (S.isOpenMPPrivateDecl(Var, RSI->OpenMPLevel, RSI->OpenMPCaptureLevel) !=
+ OMPC_unknown)
+ return true;
ByRef = S.isOpenMPCapturedByRef(Var, RSI->OpenMPLevel,
RSI->OpenMPCaptureLevel);
}
@@ -16121,9 +17151,10 @@ static bool captureInLambda(LambdaScopeInfo *LSI,
// Make sure that by-copy captures are of a complete and non-abstract type.
if (!Invalid && BuildAndDiagnose) {
if (!CaptureType->isDependentType() &&
- S.RequireCompleteType(Loc, CaptureType,
- diag::err_capture_of_incomplete_type,
- Var->getDeclName()))
+ S.RequireCompleteSizedType(
+ Loc, CaptureType,
+ diag::err_capture_of_incomplete_or_sizeless_type,
+ Var->getDeclName()))
Invalid = true;
else if (S.RequireNonAbstractType(Loc, CaptureType,
diag::err_capture_of_abstract_type))
@@ -16265,12 +17296,14 @@ bool Sema::tryCaptureVariable(
// just break here. Similarly, global variables that are captured in a
// target region should not be captured outside the scope of the region.
if (RSI->CapRegionKind == CR_OpenMP) {
- bool IsOpenMPPrivateDecl = isOpenMPPrivateDecl(Var, RSI->OpenMPLevel);
+ OpenMPClauseKind IsOpenMPPrivateDecl = isOpenMPPrivateDecl(
+ Var, RSI->OpenMPLevel, RSI->OpenMPCaptureLevel);
// If the variable is private (i.e. not captured) and has variably
// modified type, we still need to capture the type for correct
// codegen in all regions, associated with the construct. Currently,
// it is captured in the innermost captured region only.
- if (IsOpenMPPrivateDecl && Var->getType()->isVariablyModifiedType()) {
+ if (IsOpenMPPrivateDecl != OMPC_unknown &&
+ Var->getType()->isVariablyModifiedType()) {
QualType QTy = Var->getType();
if (ParmVarDecl *PVD = dyn_cast_or_null<ParmVarDecl>(Var))
QTy = PVD->getOriginalType();
@@ -16284,15 +17317,23 @@ bool Sema::tryCaptureVariable(
captureVariablyModifiedType(Context, QTy, OuterRSI);
}
}
- bool IsTargetCap = !IsOpenMPPrivateDecl &&
- isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel);
+ bool IsTargetCap =
+ IsOpenMPPrivateDecl != OMPC_private &&
+ isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel,
+ RSI->OpenMPCaptureLevel);
+ // Do not capture global if it is not privatized in outer regions.
+ bool IsGlobalCap =
+ IsGlobal && isOpenMPGlobalCapturedDecl(Var, RSI->OpenMPLevel,
+ RSI->OpenMPCaptureLevel);
+
// When we detect target captures we are looking from inside the
// target region, therefore we need to propagate the capture from the
// enclosing region. Therefore, the capture is not initially nested.
if (IsTargetCap)
adjustOpenMPTargetScopeIndex(FunctionScopesIndex, RSI->OpenMPLevel);
- if (IsTargetCap || IsOpenMPPrivateDecl) {
+ if (IsTargetCap || IsOpenMPPrivateDecl == OMPC_private ||
+ (IsGlobal && !IsGlobalCap)) {
Nested = !IsTargetCap;
DeclRefType = DeclRefType.getUnqualifiedType();
CaptureType = Context.getLValueReferenceType(DeclRefType);
@@ -16508,7 +17549,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
// Mark that this expression does not constitute an odr-use.
auto MarkNotOdrUsed = [&] {
- S.MaybeODRUseExprs.erase(E);
+ S.MaybeODRUseExprs.remove(E);
if (LambdaScopeInfo *LSI = S.getCurLambda())
LSI->markVariableExprAsNonODRUsed(E);
};
@@ -17040,6 +18081,11 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
if (Method->isVirtual() &&
!Method->getDevirtualizedMethod(Base, getLangOpts().AppleKext))
OdrUse = false;
+
+ if (auto *FD = dyn_cast<FunctionDecl>(E->getDecl()))
+ if (!isConstantEvaluated() && FD->isConsteval() &&
+ !RebuildingImmediateInvocation)
+ ExprEvalContexts.back().ReferenceToConsteval.insert(E);
MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse);
}
@@ -17131,71 +18177,36 @@ void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
}
namespace {
- /// Helper class that marks all of the declarations referenced by
- /// potentially-evaluated subexpressions as "referenced".
- class EvaluatedExprMarker : public EvaluatedExprVisitor<EvaluatedExprMarker> {
- Sema &S;
- bool SkipLocalVariables;
-
- public:
- typedef EvaluatedExprVisitor<EvaluatedExprMarker> Inherited;
-
- EvaluatedExprMarker(Sema &S, bool SkipLocalVariables)
- : Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { }
-
- void VisitDeclRefExpr(DeclRefExpr *E) {
- // If we were asked not to visit local variables, don't.
- if (SkipLocalVariables) {
- if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
- if (VD->hasLocalStorage())
- return;
- }
-
- S.MarkDeclRefReferenced(E);
- }
-
- void VisitMemberExpr(MemberExpr *E) {
- S.MarkMemberReferenced(E);
- Inherited::VisitMemberExpr(E);
- }
-
- void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
- S.MarkFunctionReferenced(
- E->getBeginLoc(),
- const_cast<CXXDestructorDecl *>(E->getTemporary()->getDestructor()));
- Visit(E->getSubExpr());
- }
-
- void VisitCXXNewExpr(CXXNewExpr *E) {
- if (E->getOperatorNew())
- S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorNew());
- if (E->getOperatorDelete())
- S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete());
- Inherited::VisitCXXNewExpr(E);
- }
+/// Helper class that marks all of the declarations referenced by
+/// potentially-evaluated subexpressions as "referenced".
+class EvaluatedExprMarker : public UsedDeclVisitor<EvaluatedExprMarker> {
+public:
+ typedef UsedDeclVisitor<EvaluatedExprMarker> Inherited;
+ bool SkipLocalVariables;
- void VisitCXXDeleteExpr(CXXDeleteExpr *E) {
- if (E->getOperatorDelete())
- S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete());
- QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
- if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
- S.MarkFunctionReferenced(E->getBeginLoc(), S.LookupDestructor(Record));
- }
+ EvaluatedExprMarker(Sema &S, bool SkipLocalVariables)
+ : Inherited(S), SkipLocalVariables(SkipLocalVariables) {}
- Inherited::VisitCXXDeleteExpr(E);
- }
+ void visitUsedDecl(SourceLocation Loc, Decl *D) {
+ S.MarkFunctionReferenced(Loc, cast<FunctionDecl>(D));
+ }
- void VisitCXXConstructExpr(CXXConstructExpr *E) {
- S.MarkFunctionReferenced(E->getBeginLoc(), E->getConstructor());
- Inherited::VisitCXXConstructExpr(E);
+ void VisitDeclRefExpr(DeclRefExpr *E) {
+ // If we were asked not to visit local variables, don't.
+ if (SkipLocalVariables) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
+ if (VD->hasLocalStorage())
+ return;
}
+ S.MarkDeclRefReferenced(E);
+ }
- void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
- Visit(E->getExpr());
- }
- };
-}
+ void VisitMemberExpr(MemberExpr *E) {
+ S.MarkMemberReferenced(E);
+ Visit(E->getBase());
+ }
+};
+} // namespace
/// Mark any declarations that appear within this expression or any
/// potentially-evaluated subexpressions as "referenced".
@@ -18075,11 +19086,25 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
return ExprError();
}
+ case BuiltinType::IncompleteMatrixIdx:
+ Diag(cast<MatrixSubscriptExpr>(E->IgnoreParens())
+ ->getRowIdx()
+ ->getBeginLoc(),
+ diag::err_matrix_incomplete_index);
+ return ExprError();
+
// Expressions of unknown type.
case BuiltinType::OMPArraySection:
Diag(E->getBeginLoc(), diag::err_omp_array_section_use);
return ExprError();
+ // Expressions of unknown type.
+ case BuiltinType::OMPArrayShaping:
+ return ExprError(Diag(E->getBeginLoc(), diag::err_omp_array_shaping_use));
+
+ case BuiltinType::OMPIterator:
+ return ExprError(Diag(E->getBeginLoc(), diag::err_omp_iterator_use));
+
// Everything else should be impossible.
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
@@ -18153,7 +19178,16 @@ ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);
}
-bool Sema::IsDependentFunctionNameExpr(Expr *E) {
- assert(E->isTypeDependent());
- return isa<UnresolvedLookupExpr>(E);
+ExprResult Sema::CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
+ ArrayRef<Expr *> SubExprs, QualType T) {
+ if (!Context.getLangOpts().RecoveryAST)
+ return ExprError();
+
+ if (isSFINAEContext())
+ return ExprError();
+
+ if (T.isNull() || !Context.getLangOpts().RecoveryASTType)
+ // We don't know the concrete type, fallback to dependent type.
+ T = Context.DependentTy;
+ return RecoveryExpr::Create(Context, T, Begin, End, SubExprs);
}