diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaExpr.cpp | 1778 |
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); } |