diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 873 |
1 files changed, 646 insertions, 227 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 45616dadcbee..0e6c933cd4f3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -46,8 +46,11 @@ #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/SaveAndRestore.h" + using namespace clang; using namespace sema; using llvm::RoundingMode; @@ -82,6 +85,9 @@ bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) { cast<Decl>(CurContext)->getAvailability() != AR_Unavailable) return false; + if (isa<UnresolvedUsingIfExistsDecl>(D)) + return false; + return true; } @@ -347,6 +353,12 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, return true; } + if (const auto *EmptyD = dyn_cast<UnresolvedUsingIfExistsDecl>(D)) { + Diag(Loc, diag::err_use_of_empty_using_if_exists); + Diag(EmptyD->getLocation(), diag::note_empty_using_if_exists_here); + return true; + } + DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess, AvoidPartialAvailabilityChecks, ClassReceiver); @@ -354,26 +366,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc); - // CUDA/HIP: Diagnose invalid references of host global variables in device - // functions. Reference of device global variables in host functions is - // allowed through shadow variables therefore it is not diagnosed. - if (LangOpts.CUDAIsDevice) { - auto *FD = dyn_cast_or_null<FunctionDecl>(CurContext); - auto Target = IdentifyCUDATarget(FD); - if (FD && Target != CFT_Host) { - const auto *VD = dyn_cast<VarDecl>(D); - if (VD && VD->hasGlobalStorage() && !VD->hasAttr<CUDADeviceAttr>() && - !VD->hasAttr<CUDAConstantAttr>() && !VD->hasAttr<CUDASharedAttr>() && - !VD->getType()->isCUDADeviceBuiltinSurfaceType() && - !VD->getType()->isCUDADeviceBuiltinTextureType() && - !VD->isConstexpr() && !VD->getType().isConstQualified()) - targetDiag(*Locs.begin(), diag::err_ref_bad_target) - << /*host*/ 2 << /*variable*/ 1 << VD << Target; - } - } - if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)) { - if (const auto *VD = dyn_cast<ValueDecl>(D)) + if (auto *VD = dyn_cast<ValueDecl>(D)) checkDeviceDecl(VD, Loc); if (!Context.getTargetInfo().isTLSSupported()) @@ -531,9 +525,13 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) { // An lvalue or rvalue of type "array of N T" or "array of unknown bound of // T" can be converted to an rvalue of type "pointer to T". // - if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue()) - E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty), - CK_ArrayToPointerDecay).get(); + if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue()) { + ExprResult Res = ImpCastExprToType(E, Context.getArrayDecayedType(Ty), + CK_ArrayToPointerDecay); + if (Res.isInvalid()) + return ExprError(); + E = Res.get(); + } } return E; } @@ -657,7 +655,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { return E; // OpenCL usually rejects direct accesses to values of 'half' type. - if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") && + if (getLangOpts().OpenCL && + !getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()) && T->isHalfType()) { Diag(E->getExprLoc(), diag::err_opencl_half_load_store) << 0 << T; @@ -714,7 +713,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // 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; - Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_RValue, + Res = ImplicitCastExpr::Create(Context, T, CK, E, nullptr, VK_PRValue, CurFPFeatureOverrides()); // C11 6.3.2.1p2: @@ -723,7 +722,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { if (const AtomicType *Atomic = T->getAs<AtomicType>()) { T = Atomic->getValueType().getUnqualifiedType(); Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(), - nullptr, VK_RValue, FPOptionsOverride()); + nullptr, VK_PRValue, FPOptionsOverride()); } return Res; @@ -829,14 +828,27 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { if (BTy && (BTy->getKind() == BuiltinType::Half || BTy->getKind() == BuiltinType::Float)) { if (getLangOpts().OpenCL && - !getOpenCLOptions().isEnabled("cl_khr_fp64")) { - if (BTy->getKind() == BuiltinType::Half) { - E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get(); - } + !getOpenCLOptions().isAvailableOption("cl_khr_fp64", getLangOpts())) { + if (BTy->getKind() == BuiltinType::Half) { + E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get(); + } } else { E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get(); } } + if (BTy && + getLangOpts().getExtendIntArgs() == + LangOptions::ExtendArgsKind::ExtendTo64 && + Context.getTargetInfo().supportsExtendIntArgs() && Ty->isIntegerType() && + Context.getTypeSizeInChars(BTy) < + Context.getTypeSizeInChars(Context.LongLongTy)) { + E = (Ty->isUnsignedIntegerType()) + ? ImpCastExprToType(E, Context.UnsignedLongLongTy, CK_IntegralCast) + .get() + : ImpCastExprToType(E, Context.LongLongTy, CK_IntegralCast).get(); + assert(8 == Context.getTypeSizeInChars(Context.LongLongTy).getQuantity() && + "Unexpected typesize for LongLongTy"); + } // C++ performs lvalue-to-rvalue conversion as a default argument // promotion, even on class types, but note: @@ -1533,11 +1545,6 @@ 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 @@ -3211,8 +3218,7 @@ ExprResult Sema::BuildDeclarationNameExpr( } // Make sure that we're referring to a value. - ValueDecl *VD = dyn_cast<ValueDecl>(D); - if (!VD) { + if (!isa<ValueDecl, UnresolvedUsingIfExistsDecl>(D)) { Diag(Loc, diag::err_ref_non_value) << D << SS.getRange(); Diag(D->getLocation(), diag::note_declared_at); @@ -3223,9 +3229,11 @@ ExprResult Sema::BuildDeclarationNameExpr( // this check when we're going to perform argument-dependent lookup // on this function name, because this might not be the function // that overload resolution actually selects. - if (DiagnoseUseOfDecl(VD, Loc)) + if (DiagnoseUseOfDecl(D, Loc)) return ExprError(); + auto *VD = cast<ValueDecl>(D); + // Only create DeclRefExpr's for valid Decl's. if (VD->isInvalidDecl() && !AcceptInvalidDecl) return ExprError(); @@ -3242,7 +3250,7 @@ ExprResult Sema::BuildDeclarationNameExpr( QualType type = VD->getType(); if (type.isNull()) return ExprError(); - ExprValueKind valueKind = VK_RValue; + ExprValueKind valueKind = VK_PRValue; // 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, @@ -3268,7 +3276,7 @@ ExprResult Sema::BuildDeclarationNameExpr( case Decl::UnresolvedUsingValue: case Decl::OMPDeclareReduction: case Decl::OMPDeclareMapper: - valueKind = VK_RValue; + valueKind = VK_PRValue; break; // Fields and indirect fields that got here must be for @@ -3309,7 +3317,7 @@ ExprResult Sema::BuildDeclarationNameExpr( // For non-references, we need to strip qualifiers just in case // the template parameter was declared as 'const int' or whatever. - valueKind = VK_RValue; + valueKind = VK_PRValue; type = type.getUnqualifiedType(); break; } @@ -3323,7 +3331,7 @@ ExprResult Sema::BuildDeclarationNameExpr( if (!getLangOpts().CPlusPlus && !type.hasQualifiers() && type->isVoidType()) { - valueKind = VK_RValue; + valueKind = VK_PRValue; break; } LLVM_FALLTHROUGH; @@ -3365,7 +3373,7 @@ ExprResult Sema::BuildDeclarationNameExpr( if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) { if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) { type = Context.BuiltinFnTy; - valueKind = VK_RValue; + valueKind = VK_PRValue; break; } } @@ -3376,7 +3384,7 @@ ExprResult Sema::BuildDeclarationNameExpr( // result type, make the entire expression __unknown_anytype. if (fty->getReturnType() == Context.UnknownAnyTy) { type = Context.UnknownAnyTy; - valueKind = VK_RValue; + valueKind = VK_PRValue; break; } @@ -3397,7 +3405,7 @@ ExprResult Sema::BuildDeclarationNameExpr( fty->getExtInfo()); // Functions are r-values in C. - valueKind = VK_RValue; + valueKind = VK_PRValue; break; } @@ -3420,7 +3428,7 @@ ExprResult Sema::BuildDeclarationNameExpr( = dyn_cast<FunctionProtoType>(VD->getType())) if (proto->getReturnType() == Context.UnknownAnyTy) { type = Context.UnknownAnyTy; - valueKind = VK_RValue; + valueKind = VK_PRValue; break; } @@ -3434,7 +3442,7 @@ ExprResult Sema::BuildDeclarationNameExpr( case Decl::CXXConversion: case Decl::CXXDestructor: case Decl::CXXConstructor: - valueKind = VK_RValue; + valueKind = VK_PRValue; break; } @@ -3509,6 +3517,28 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL); } +ExprResult Sema::BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc, + SourceLocation LParen, + SourceLocation RParen, + TypeSourceInfo *TSI) { + return SYCLUniqueStableNameExpr::Create(Context, OpLoc, LParen, RParen, TSI); +} + +ExprResult Sema::ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc, + SourceLocation LParen, + SourceLocation RParen, + ParsedType ParsedTy) { + TypeSourceInfo *TSI = nullptr; + QualType Ty = GetTypeFromParser(ParsedTy, &TSI); + + if (Ty.isNull()) + return ExprError(); + if (!TSI) + TSI = Context.getTrivialTypeSourceInfo(Ty, LParen); + + return BuildSYCLUniqueStableNameExpr(OpLoc, LParen, RParen, TSI); +} + ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { PredefinedExpr::IdentKind IK; @@ -3642,7 +3672,7 @@ bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) { bool ValueIsPositive = ValueAPS.isStrictlyPositive(); if (!ValueIsPositive || ValueAPS.getActiveBits() > 31) { Diag(E->getExprLoc(), diag::err_pragma_loop_invalid_argument_value) - << ValueAPS.toString(10) << ValueIsPositive; + << toString(ValueAPS, 10) << ValueIsPositive; return true; } @@ -3819,7 +3849,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } else if (Literal.isFloatingLiteral()) { QualType Ty; if (Literal.isHalf){ - if (getOpenCLOptions().isEnabled("cl_khr_fp16")) + if (getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts())) Ty = Context.HalfTy; else { Diag(Tok.getLocation(), diag::err_half_const_requires_fp16); @@ -3843,10 +3873,11 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { if (Ty->castAs<BuiltinType>()->getKind() != BuiltinType::Float) { Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); } - } else if (getLangOpts().OpenCL && - !getOpenCLOptions().isEnabled("cl_khr_fp64")) { + } else if (getLangOpts().OpenCL && !getOpenCLOptions().isAvailableOption( + "cl_khr_fp64", getLangOpts())) { // Impose single-precision float type when cl_khr_fp64 is not enabled. - Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64); + Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64) + << (getLangOpts().OpenCLVersion >= 300); Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); } } @@ -3865,6 +3896,14 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { Diag(Tok.getLocation(), diag::ext_c99_longlong); } + // 'z/uz' literals are a C++2b feature. + if (Literal.isSizeT) + Diag(Tok.getLocation(), getLangOpts().CPlusPlus + ? getLangOpts().CPlusPlus2b + ? diag::warn_cxx20_compat_size_t_suffix + : diag::ext_cxx2b_size_t_suffix + : diag::err_cxx2b_size_t_suffix); + // Get the value in the widest-possible width. unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth(); llvm::APInt ResultVal(MaxWidth, 0); @@ -3899,7 +3938,26 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } } - if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong) { + // Check C++2b size_t literals. + if (Literal.isSizeT) { + assert(!Literal.MicrosoftInteger && + "size_t literals can't be Microsoft literals"); + unsigned SizeTSize = Context.getTargetInfo().getTypeWidth( + Context.getTargetInfo().getSizeType()); + + // Does it fit in size_t? + if (ResultVal.isIntN(SizeTSize)) { + // Does it fit in ssize_t? + if (!Literal.isUnsigned && ResultVal[SizeTSize - 1] == 0) + Ty = Context.getSignedSizeType(); + else if (AllowUnsigned) + Ty = Context.getSizeType(); + Width = SizeTSize; + } + } + + if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong && + !Literal.isSizeT) { // Are int/unsigned possibilities? unsigned IntSize = Context.getTargetInfo().getIntWidth(); @@ -3915,7 +3973,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } // Are long/unsigned long possibilities? - if (Ty.isNull() && !Literal.isLongLong) { + if (Ty.isNull() && !Literal.isLongLong && !Literal.isSizeT) { unsigned LongSize = Context.getTargetInfo().getLongWidth(); // Does it fit in a unsigned long? @@ -3946,7 +4004,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } // Check long long if needed. - if (Ty.isNull()) { + if (Ty.isNull() && !Literal.isSizeT) { unsigned LongLongSize = Context.getTargetInfo().getLongLongWidth(); // Does it fit in a unsigned long long? @@ -3963,10 +4021,16 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } } - // If we still couldn't decide a type, we probably have something that - // does not fit in a signed long long, but has no U suffix. + // If we still couldn't decide a type, we either have 'size_t' literal + // that is out of range, or a decimal literal that does not fit in a + // signed long long and has no U suffix. if (Ty.isNull()) { - Diag(Tok.getLocation(), diag::ext_integer_literal_too_large_for_signed); + if (Literal.isSizeT) + Diag(Tok.getLocation(), diag::err_size_t_literal_too_large) + << Literal.isUnsigned; + else + Diag(Tok.getLocation(), + diag::ext_integer_literal_too_large_for_signed); Ty = Context.UnsignedLongLongTy; Width = Context.getTargetInfo().getLongLongWidth(); } @@ -3989,6 +4053,10 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E) { assert(E && "ActOnParenExpr() missing expr"); + QualType ExprTy = E->getType(); + if (getLangOpts().ProtectParens && CurFPFeatures.getAllowFPReassociate() && + !E->isLValue() && ExprTy->hasFloatingRepresentation()) + return BuildBuiltinCallExpr(R, Builtin::BI__arithmetic_fence, E); return new (Context) ParenExpr(L, R, E); } @@ -4995,7 +5063,7 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, llvm::APSInt LengthValue = Result.Val.getInt(); if (LengthValue.isNegative()) { Diag(Length->getExprLoc(), diag::err_omp_section_length_negative) - << LengthValue.toString(/*Radix=*/10, /*Signed=*/true) + << toString(LengthValue, /*Radix=*/10, /*Signed=*/true) << Length->getSourceRange(); return ExprError(); } @@ -5019,7 +5087,7 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, 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) + << toString(StrideValue, /*Radix=*/10, /*Signed=*/true) << Stride->getSourceRange(); return ExprError(); } @@ -5098,7 +5166,7 @@ ExprResult Sema::ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, 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) + << toString(Value, /*Radix=*/10, /*Signed=*/true) << Dim->getSourceRange(); ErrorFound = true; continue; @@ -5478,14 +5546,14 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, BaseExpr = LHSExp; // vectors: V[123] IndexExpr = RHSExp; // We apply C++ DR1213 to vector subscripting too. - if (getLangOpts().CPlusPlus11 && LHSExp->getValueKind() == VK_RValue) { + if (getLangOpts().CPlusPlus11 && LHSExp->isPRValue()) { ExprResult Materialized = TemporaryMaterializationConversion(LHSExp); if (Materialized.isInvalid()) return ExprError(); LHSExp = Materialized.get(); } VK = LHSExp->getValueKind(); - if (VK != VK_RValue) + if (VK != VK_PRValue) OK = OK_VectorComponent; ResultType = VTy->getElementType(); @@ -5509,7 +5577,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, BaseExpr = LHSExp; IndexExpr = RHSExp; - ResultType = LHSTy->getAs<PointerType>()->getPointeeType(); + ResultType = LHSTy->castAs<PointerType>()->getPointeeType(); } else if (RHSTy->isArrayType()) { // Same as previous, except for 123[f().a] case Diag(RHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue) @@ -5520,7 +5588,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, BaseExpr = RHSExp; IndexExpr = LHSExp; - ResultType = RHSTy->getAs<PointerType>()->getPointeeType(); + ResultType = RHSTy->castAs<PointerType>()->getPointeeType(); } else { return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value) << LHSExp->getSourceRange() << RHSExp->getSourceRange()); @@ -5552,14 +5620,15 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, // C forbids expressions of unqualified void type from being l-values. // See IsCForbiddenLValueType. - if (!ResultType.hasQualifiers()) VK = VK_RValue; + if (!ResultType.hasQualifiers()) + VK = VK_PRValue; } else if (!ResultType->isDependentType() && RequireCompleteSizedType( LLoc, ResultType, diag::err_subscript_incomplete_or_sizeless_type, BaseExpr)) return ExprError(); - assert(VK == VK_RValue || LangOpts.CPlusPlus || + assert(VK == VK_PRValue || LangOpts.CPlusPlus || !ResultType.isCForbiddenLValueType()); if (LHSExp->IgnoreParenImpCasts()->getType()->isVariablyModifiedType() && @@ -5858,6 +5927,7 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, for (unsigned i = 0; i < TotalNumArgs; ++i) Call->setArg(i, AllArgs[i]); + Call->computeDependence(); return false; } @@ -5894,7 +5964,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, (!Param || !Param->hasAttr<CFConsumedAttr>())) CFAudited = true; - if (Proto->getExtParameterInfo(i).isNoEscape()) + if (Proto->getExtParameterInfo(i).isNoEscape() && + ProtoArgType->isBlockPointerType()) if (auto *BE = dyn_cast<BlockExpr>(Arg->IgnoreParenNoopCasts(Context))) BE->getBlockDecl()->setDoesNotEscape(); @@ -6061,6 +6132,8 @@ static bool isPlaceholderToRemoveAsArg(QualType type) { #define PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: #include "clang/Basic/PPCTypes.def" +#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/RISCVVTypes.def" #define PLACEHOLDER_TYPE(ID, SINGLETON_ID) #define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: #include "clang/AST/BuiltinTypes.def" @@ -6363,7 +6436,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, } return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy, - VK_RValue, RParenLoc, CurFPFeatureOverrides()); + VK_PRValue, RParenLoc, CurFPFeatureOverrides()); } if (Fn->getType() == Context.PseudoObjectTy) { ExprResult result = CheckPlaceholderExpr(Fn); @@ -6375,9 +6448,10 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, // in which case we won't do any semantic analysis now. if (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs)) { if (ExecConfig) { - return CUDAKernelCallExpr::Create( - Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs, - Context.DependentTy, VK_RValue, RParenLoc, CurFPFeatureOverrides()); + return CUDAKernelCallExpr::Create(Context, Fn, + cast<CallExpr>(ExecConfig), ArgExprs, + Context.DependentTy, VK_PRValue, + RParenLoc, CurFPFeatureOverrides()); } else { tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs( @@ -6385,7 +6459,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, Fn->getBeginLoc()); return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, - VK_RValue, RParenLoc, CurFPFeatureOverrides()); + VK_PRValue, RParenLoc, CurFPFeatureOverrides()); } } @@ -6414,7 +6488,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (!find.HasFormOfMemberPointer) { if (Expr::hasAnyTypeDependentArguments(ArgExprs)) return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, - VK_RValue, RParenLoc, CurFPFeatureOverrides()); + VK_PRValue, RParenLoc, CurFPFeatureOverrides()); OverloadExpr *ovl = find.Expression; if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl)) return BuildOverloadedCallExpr( @@ -6468,9 +6542,6 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, FD, /*Complain=*/true, Fn->getBeginLoc())) return ExprError(); - if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn)) - return ExprError(); - checkDirectCallValidity(*this, Fn, FD, ArgExprs); } @@ -6493,24 +6564,53 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, ExecConfig, IsExecConfig); } -/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments. +/// BuildBuiltinCallExpr - Create a call to a builtin function specified by Id +// with the specified CallArgs +Expr *Sema::BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, + MultiExprArg CallArgs) { + StringRef Name = Context.BuiltinInfo.getName(Id); + LookupResult R(*this, &Context.Idents.get(Name), Loc, + Sema::LookupOrdinaryName); + LookupName(R, TUScope, /*AllowBuiltinCreation=*/true); + + auto *BuiltInDecl = R.getAsSingle<FunctionDecl>(); + assert(BuiltInDecl && "failed to find builtin declaration"); + + ExprResult DeclRef = + BuildDeclRefExpr(BuiltInDecl, BuiltInDecl->getType(), VK_LValue, Loc); + assert(DeclRef.isUsable() && "Builtin reference cannot fail"); + + ExprResult Call = + BuildCallExpr(/*Scope=*/nullptr, DeclRef.get(), Loc, CallArgs, Loc); + + assert(!Call.isInvalid() && "Call to builtin cannot fail!"); + return Call.get(); +} + +/// Parse a __builtin_astype expression. /// /// __builtin_astype( value, dst type ) /// ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc) { - ExprValueKind VK = VK_RValue; - ExprObjectKind OK = OK_Ordinary; QualType DstTy = GetTypeFromParser(ParsedDestTy); + return BuildAsTypeExpr(E, DstTy, BuiltinLoc, RParenLoc); +} + +/// Create a new AsTypeExpr node (bitcast) from the arguments. +ExprResult Sema::BuildAsTypeExpr(Expr *E, QualType DestTy, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + ExprValueKind VK = VK_PRValue; + ExprObjectKind OK = OK_Ordinary; QualType SrcTy = E->getType(); - if (Context.getTypeSize(DstTy) != Context.getTypeSize(SrcTy)) - return ExprError(Diag(BuiltinLoc, - diag::err_invalid_astype_of_different_size) - << DstTy - << SrcTy - << E->getSourceRange()); - return new (Context) AsTypeExpr(E, DstTy, VK, OK, BuiltinLoc, RParenLoc); + if (!SrcTy->isDependentType() && + Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) + return ExprError( + Diag(BuiltinLoc, diag::err_invalid_astype_of_different_size) + << DestTy << SrcTy << E->getSourceRange()); + return new (Context) AsTypeExpr(E, DestTy, VK, OK, BuiltinLoc, RParenLoc); } /// ActOnConvertVectorExpr - create a new convert-vector expression from the @@ -6550,12 +6650,25 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // so there's some risk when calling out to non-interrupt handler functions // that the callee might not preserve them. This is easy to diagnose here, // but can be very challenging to debug. - if (auto *Caller = getCurFunctionDecl()) + // Likewise, X86 interrupt handlers may only call routines with attribute + // no_caller_saved_registers since there is no efficient way to + // save and restore the non-GPR state. + if (auto *Caller = getCurFunctionDecl()) { if (Caller->hasAttr<ARMInterruptAttr>()) { bool VFP = Context.getTargetInfo().hasFeature("vfp"); - if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>())) + if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>())) { Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_calling_convention); + if (FDecl) + Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl; + } } + if (Caller->hasAttr<AnyX86InterruptAttr>() && + ((!FDecl || !FDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>()))) { + Diag(Fn->getExprLoc(), diag::warn_anyx86_interrupt_regsave); + if (FDecl) + Diag(FDecl->getLocation(), diag::note_callee_decl) << FDecl; + } + } // Promote the function operand. // We special-case function promotion here because we only allow promoting @@ -6621,11 +6734,11 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, assert(UsesADL == ADLCallKind::NotADL && "CUDAKernelCallExpr should not use ADL"); TheCall = CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config), - Args, ResultTy, VK_RValue, RParenLoc, + Args, ResultTy, VK_PRValue, RParenLoc, CurFPFeatureOverrides(), NumParams); } else { TheCall = - CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc, + CallExpr::Create(Context, Fn, Args, ResultTy, VK_PRValue, RParenLoc, CurFPFeatureOverrides(), NumParams, UsesADL); } @@ -6652,11 +6765,11 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (CorrectedTypos && Args.size() < NumParams) { if (Config) TheCall = CUDAKernelCallExpr::Create( - Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_RValue, + Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_PRValue, RParenLoc, CurFPFeatureOverrides(), NumParams); else TheCall = - CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc, + CallExpr::Create(Context, Fn, Args, ResultTy, VK_PRValue, RParenLoc, CurFPFeatureOverrides(), NumParams, UsesADL); } // We can now handle the nulled arguments for the default arguments. @@ -6750,6 +6863,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, TheCall->setArg(i, Arg); } + TheCall->computeDependence(); } if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl)) @@ -6818,9 +6932,12 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, 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) - << SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd())); + if (literalType->isVariableArrayType()) { + if (!tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc, + diag::err_variable_object_no_init)) { + return ExprError(); + } + } } else if (!literalType->isDependentType() && RequireCompleteType(LParenLoc, literalType, diag::err_typecheck_decl_incomplete_type, @@ -6862,7 +6979,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, // obviously have a value kind derived from the kind of reference involved. ExprValueKind VK = (getLangOpts().CPlusPlus && !(isFileScope && literalType->isArrayType())) - ? VK_RValue + ? VK_PRValue : VK_LValue; if (isFileScope) @@ -7013,14 +7130,14 @@ Sema::BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, /// Do an explicit extend of the given block pointer if we're in ARC. void Sema::maybeExtendBlockObject(ExprResult &E) { assert(E.get()->getType()->isBlockPointerType()); - assert(E.get()->isRValue()); + assert(E.get()->isPRValue()); // Only do this in an r-value context. if (!getLangOpts().ObjCAutoRefCount) return; E = ImplicitCastExpr::Create( Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(), - /*base path*/ nullptr, VK_RValue, FPOptionsOverride()); + /*base path*/ nullptr, VK_PRValue, FPOptionsOverride()); Cleanup.setExprNeedsCleanups(true); } @@ -7289,6 +7406,38 @@ bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) { ValidScalableConversion(destTy, srcTy); } +/// Are the two types matrix types and do they have the same dimensions i.e. +/// do they have the same number of rows and the same number of columns? +bool Sema::areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy) { + if (!destTy->isMatrixType() || !srcTy->isMatrixType()) + return false; + + const ConstantMatrixType *matSrcType = srcTy->getAs<ConstantMatrixType>(); + const ConstantMatrixType *matDestType = destTy->getAs<ConstantMatrixType>(); + + return matSrcType->getNumRows() == matDestType->getNumRows() && + matSrcType->getNumColumns() == matDestType->getNumColumns(); +} + +bool Sema::areVectorTypesSameSize(QualType SrcTy, QualType DestTy) { + assert(DestTy->isVectorType() || SrcTy->isVectorType()); + + uint64_t SrcLen, DestLen; + QualType SrcEltTy, DestEltTy; + if (!breakDownVectorType(SrcTy, SrcLen, SrcEltTy)) + return false; + if (!breakDownVectorType(DestTy, DestLen, DestEltTy)) + return false; + + // ASTContext::getTypeSize will return the size rounded up to a + // power of 2, so instead of using that, we need to use the raw + // element size multiplied by the element count. + uint64_t SrcEltSize = Context.getTypeSize(SrcEltTy); + uint64_t DestEltSize = Context.getTypeSize(DestEltTy); + + return (SrcLen * SrcEltSize == DestLen * DestEltSize); +} + /// Are the two types lax-compatible vector types? That is, given /// that one of them is a vector, do they have equal storage sizes, /// where the storage size is the number of elements times the element @@ -7307,18 +7456,7 @@ bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) { if (srcTy->isScalarType() && destTy->isExtVectorType()) return false; if (destTy->isScalarType() && srcTy->isExtVectorType()) return false; - uint64_t srcLen, destLen; - QualType srcEltTy, destEltTy; - if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false; - if (!breakDownVectorType(destTy, destLen, destEltTy)) return false; - - // ASTContext::getTypeSize will return the size rounded up to a - // power of 2, so instead of using that, we need to use the raw - // element size multiplied by the element count. - uint64_t srcEltSize = Context.getTypeSize(srcEltTy); - uint64_t destEltSize = Context.getTypeSize(destEltTy); - - return (srcLen * srcEltSize == destLen * destEltSize); + return areVectorTypesSameSize(srcTy, destTy); } /// Is this a legal conversion between two types, one of which is @@ -7351,6 +7489,27 @@ bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) { return areLaxCompatibleVectorTypes(srcTy, destTy); } +bool Sema::CheckMatrixCast(SourceRange R, QualType DestTy, QualType SrcTy, + CastKind &Kind) { + if (SrcTy->isMatrixType() && DestTy->isMatrixType()) { + if (!areMatrixTypesOfTheSameDimension(SrcTy, DestTy)) { + return Diag(R.getBegin(), diag::err_invalid_conversion_between_matrixes) + << DestTy << SrcTy << R; + } + } else if (SrcTy->isMatrixType()) { + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_matrix_and_type) + << SrcTy << DestTy << R; + } else if (DestTy->isMatrixType()) { + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_matrix_and_type) + << DestTy << SrcTy << R; + } + + Kind = CK_MatrixCast; + return false; +} + bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, CastKind &Kind) { assert(VectorTy->isVectorType() && "Not a vector type!"); @@ -7547,7 +7706,7 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, // initializers must be one or must match the size of the vector. // If a single value is specified in the initializer then it will be // replicated to all the components of the vector - if (VTy->getVectorKind() == VectorType::AltiVecVector) { + if (ShouldSplatAltivecScalarInCast(VTy)) { // The number of initializers must be one or must match the size of the // vector. If a single value is specified in the initializer then it will // be replicated to all the components of the vector @@ -8134,7 +8293,7 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, if (getLangOpts().CPlusPlus) return CXXCheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc); - VK = VK_RValue; + VK = VK_PRValue; OK = OK_Ordinary; if (Context.isDependenceAllowed() && @@ -8266,7 +8425,7 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // Allow ?: operations in which both operands have the same // built-in sizeless type. - if (LHSTy->isSizelessBuiltinType() && LHSTy == RHSTy) + if (LHSTy->isSizelessBuiltinType() && Context.hasSameType(LHSTy, RHSTy)) return LHSTy; // Emit a better diagnostic if one of the expressions is a null pointer @@ -8672,8 +8831,8 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, // If the common expression is a class or array prvalue, materialize it // so that we can safely refer to it multiple times. - if (commonExpr->isRValue() && (commonExpr->getType()->isRecordType() || - commonExpr->getType()->isArrayType())) { + if (commonExpr->isPRValue() && (commonExpr->getType()->isRecordType() || + commonExpr->getType()->isArrayType())) { ExprResult MatExpr = TemporaryMaterializationConversion(commonExpr); if (MatExpr.isInvalid()) return ExprError(); @@ -8689,7 +8848,7 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, } QualType LHSTy = LHSExpr->getType(), RHSTy = RHSExpr->getType(); - ExprValueKind VK = VK_RValue; + ExprValueKind VK = VK_PRValue; ExprObjectKind OK = OK_Ordinary; ExprResult Cond = CondExpr, LHS = LHSExpr, RHS = RHSExpr; QualType result = CheckConditionalOperands(Cond, LHS, RHS, @@ -8973,7 +9132,7 @@ Sema::CheckAssignmentConstraints(SourceLocation Loc, // cast operations are required, so if CheckAssignmentConstraints // adds casts to this they'll be wasted, but fortunately that doesn't // usually happen on valid code. - OpaqueValueExpr RHSExpr(Loc, RHSType, VK_RValue); + OpaqueValueExpr RHSExpr(Loc, RHSType, VK_PRValue); ExprResult RHSPtr = &RHSExpr; CastKind K; @@ -9342,7 +9501,7 @@ static void ConstructTransparentUnion(Sema &S, ASTContext &C, // union type from this initializer list. TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType); EResult = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType, - VK_RValue, Initializer, false); + VK_PRValue, Initializer, false); } Sema::AssignConvertType @@ -9481,7 +9640,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS, CheckPointerConversion(RHS.get(), LHSType, Kind, Path, /*IgnoreBaseAccess=*/false, Diagnose); if (ConvertRHS) - RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path); + RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_PRValue, &Path); } return Compatible; } @@ -10000,7 +10159,7 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, RHSType, DiagID)) return RHSType; } else { - if (LHS.get()->getValueKind() == VK_LValue || + if (LHS.get()->isLValue() || !tryGCCVectorConvertAndSplat(*this, &LHS, &RHS)) return RHSType; } @@ -10184,14 +10343,19 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, bool IsCompAssign, bool IsDiv) { checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false); - if (LHS.get()->getType()->isVectorType() || - RHS.get()->getType()->isVectorType()) + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + if (LHSTy->isVectorType() || RHSTy->isVectorType()) return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign, /*AllowBothBool*/getLangOpts().AltiVec, /*AllowBoolConversions*/false); - if (!IsDiv && (LHS.get()->getType()->isConstantMatrixType() || - RHS.get()->getType()->isConstantMatrixType())) + if (!IsDiv && + (LHSTy->isConstantMatrixType() || RHSTy->isConstantMatrixType())) return CheckMatrixMultiplyOperands(LHS, RHS, Loc, IsCompAssign); + // For division, only matrix-by-scalar is supported. Other combinations with + // matrix types are invalid. + if (IsDiv && LHSTy->isConstantMatrixType() && RHSTy->isArithmeticType()) + return CheckMatrixElementwiseOperands(LHS, RHS, Loc, IsCompAssign); QualType compType = UsualArithmeticConversions( LHS, RHS, Loc, IsCompAssign ? ACK_CompAssign : ACK_Arithmetic); @@ -10267,6 +10431,22 @@ static void diagnoseArithmeticOnNullPointer(Sema &S, SourceLocation Loc, << S.getLangOpts().CPlusPlus << Pointer->getSourceRange(); } +/// Diagnose invalid subraction on a null pointer. +/// +static void diagnoseSubtractionOnNullPointer(Sema &S, SourceLocation Loc, + Expr *Pointer, bool BothNull) { + // Null - null is valid in C++ [expr.add]p7 + if (BothNull && S.getLangOpts().CPlusPlus) + return; + + // Is this s a macro from a system header? + if (S.Diags.getSuppressSystemWarnings() && S.SourceMgr.isInSystemMacro(Loc)) + return; + + S.Diag(Loc, diag::warn_pointer_sub_null_ptr) + << S.getLangOpts().CPlusPlus << Pointer->getSourceRange(); +} + /// Diagnose invalid arithmetic on two function pointers. static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc, Expr *LHS, Expr *RHS) { @@ -10513,7 +10693,11 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS, if (LHS.get()->getType()->isConstantMatrixType() || RHS.get()->getType()->isConstantMatrixType()) { - return CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy); + QualType compType = + CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy); + if (CompLHSTy) + *CompLHSTy = compType; + return compType; } QualType compType = UsualArithmeticConversions( @@ -10613,7 +10797,11 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, if (LHS.get()->getType()->isConstantMatrixType() || RHS.get()->getType()->isConstantMatrixType()) { - return CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy); + QualType compType = + CheckMatrixElementwiseOperands(LHS, RHS, Loc, CompLHSTy); + if (CompLHSTy) + *CompLHSTy = compType; + return compType; } QualType compType = UsualArithmeticConversions( @@ -10690,7 +10878,16 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, LHS.get(), RHS.get())) return QualType(); - // FIXME: Add warnings for nullptr - ptr. + bool LHSIsNullPtr = LHS.get()->IgnoreParenCasts()->isNullPointerConstant( + Context, Expr::NPC_ValueDependentIsNotNull); + bool RHSIsNullPtr = RHS.get()->IgnoreParenCasts()->isNullPointerConstant( + Context, Expr::NPC_ValueDependentIsNotNull); + + // Subtracting nullptr or from nullptr is suspect + if (LHSIsNullPtr) + diagnoseSubtractionOnNullPointer(*this, Loc, LHS.get(), RHSIsNullPtr); + if (RHSIsNullPtr) + diagnoseSubtractionOnNullPointer(*this, Loc, RHS.get(), LHSIsNullPtr); // The pointee type may have zero size. As an extension, a structure or // union may have zero size or an array may have zero length. In this @@ -11658,6 +11855,21 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, LHS.get()->getSourceRange()); } + if (IsOrdered && LHSType->isFunctionPointerType() && + RHSType->isFunctionPointerType()) { + // Valid unless a relational comparison of function pointers + bool IsError = Opc == BO_Cmp; + auto DiagID = + IsError ? diag::err_typecheck_ordered_comparison_of_function_pointers + : getLangOpts().CPlusPlus + ? diag::warn_typecheck_ordered_comparison_of_function_pointers + : diag::ext_typecheck_ordered_comparison_of_function_pointers; + Diag(Loc, DiagID) << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + if (IsError) + return QualType(); + } + if ((LHSType->isIntegerType() && !LHSIsNull) || (RHSType->isIntegerType() && !RHSIsNull)) { // Skip normal pointer conversion checks in this case; we have better @@ -11725,12 +11937,6 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, << 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())) { @@ -12071,11 +12277,30 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, QualType LHSType = LHS.get()->getType(); - // If AltiVec, the comparison results in a numeric type, i.e. - // bool for C++, int for C - if (getLangOpts().AltiVec && - vType->castAs<VectorType>()->getVectorKind() == VectorType::AltiVecVector) - return Context.getLogicalOperationType(); + // Determine the return type of a vector compare. By default clang will return + // a scalar for all vector compares except vector bool and vector pixel. + // With the gcc compiler we will always return a vector type and with the xl + // compiler we will always return a scalar type. This switch allows choosing + // which behavior is prefered. + if (getLangOpts().AltiVec) { + switch (getLangOpts().getAltivecSrcCompat()) { + case LangOptions::AltivecSrcCompatKind::Mixed: + // If AltiVec, the comparison results in a numeric type, i.e. + // bool for C++, int for C + if (vType->castAs<VectorType>()->getVectorKind() == + VectorType::AltiVecVector) + return Context.getLogicalOperationType(); + else + Diag(Loc, diag::warn_deprecated_altivec_src_compat); + break; + case LangOptions::AltivecSrcCompatKind::GCC: + // For GCC we always return the vector type. + break; + case LangOptions::AltivecSrcCompatKind::XL: + return Context.getLogicalOperationType(); + break; + } + } // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and @@ -12100,6 +12325,11 @@ static void diagnoseXorMisusedAsPow(Sema &S, const ExprResult &XorLHS, if (Loc.isMacroID()) return; + // Do not diagnose if both LHS and RHS are macros. + if (XorLHS.get()->getExprLoc().isMacroID() && + XorRHS.get()->getExprLoc().isMacroID()) + return; + bool Negative = false; bool ExplicitPlus = false; const auto *LHSInt = dyn_cast<IntegerLiteral>(XorLHS.get()); @@ -12172,7 +12402,8 @@ static void diagnoseXorMisusedAsPow(Sema &S, const ExprResult &XorLHS, RHSStrRef.find('\'') != StringRef::npos) return; - bool SuggestXor = S.getLangOpts().CPlusPlus || S.getPreprocessor().isMacroDefined("xor"); + bool SuggestXor = + S.getLangOpts().CPlusPlus || S.getPreprocessor().isMacroDefined("xor"); const llvm::APInt XorValue = LeftSideValue ^ RightSideValue; int64_t RightSideIntValue = RightSideValue.getSExtValue(); if (LeftSideValue == 2 && RightSideIntValue >= 0) { @@ -12183,27 +12414,30 @@ static void diagnoseXorMisusedAsPow(Sema &S, const ExprResult &XorLHS, if (Overflow) { if (RightSideIntValue < 64) S.Diag(Loc, diag::warn_xor_used_as_pow_base) - << ExprStr << XorValue.toString(10, true) << ("1LL << " + RHSStr) + << ExprStr << toString(XorValue, 10, true) << ("1LL << " + RHSStr) << FixItHint::CreateReplacement(ExprRange, "1LL << " + RHSStr); else if (RightSideIntValue == 64) - S.Diag(Loc, diag::warn_xor_used_as_pow) << ExprStr << XorValue.toString(10, true); + S.Diag(Loc, diag::warn_xor_used_as_pow) + << ExprStr << toString(XorValue, 10, true); else return; } else { S.Diag(Loc, diag::warn_xor_used_as_pow_base_extra) - << ExprStr << XorValue.toString(10, true) << SuggestedExpr - << PowValue.toString(10, true) + << ExprStr << toString(XorValue, 10, true) << SuggestedExpr + << toString(PowValue, 10, true) << FixItHint::CreateReplacement( ExprRange, (RightSideIntValue == 0) ? "1" : SuggestedExpr); } - S.Diag(Loc, diag::note_xor_used_as_pow_silence) << ("0x2 ^ " + RHSStr) << SuggestXor; + S.Diag(Loc, diag::note_xor_used_as_pow_silence) + << ("0x2 ^ " + RHSStr) << SuggestXor; } else if (LeftSideValue == 10) { std::string SuggestedValue = "1e" + std::to_string(RightSideIntValue); S.Diag(Loc, diag::warn_xor_used_as_pow_base) - << ExprStr << XorValue.toString(10, true) << SuggestedValue + << ExprStr << toString(XorValue, 10, true) << SuggestedValue << FixItHint::CreateReplacement(ExprRange, SuggestedValue); - S.Diag(Loc, diag::note_xor_used_as_pow_silence) << ("0xA ^ " + RHSStr) << SuggestXor; + S.Diag(Loc, diag::note_xor_used_as_pow_silence) + << ("0xA ^ " + RHSStr) << SuggestXor; } } @@ -12900,8 +13134,9 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, // OpenCL v1.2 s6.1.1.1 p2: // The half data type can only be used to declare a pointer to a buffer that // contains half values - if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") && - LHSType->isHalfType()) { + if (getLangOpts().OpenCL && + !getOpenCLOptions().isAvailableOption("cl_khr_fp16", getLangOpts()) && + LHSType->isHalfType()) { Diag(Loc, diag::err_opencl_half_load_store) << 1 << LHSType.getUnqualifiedType(); return QualType(); @@ -13208,7 +13443,7 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, OK = Op->getObjectKind(); return ResType; } else { - VK = VK_RValue; + VK = VK_PRValue; return ResType.getUnqualifiedType(); } } @@ -13595,7 +13830,7 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, // ...except that certain expressions are never l-values in C. if (!S.getLangOpts().CPlusPlus && Result.isCForbiddenLValueType()) - VK = VK_RValue; + VK = VK_PRValue; return Result; } @@ -13864,7 +14099,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, // The following two variables are used for compound assignment operators QualType CompLHSTy; // Type of LHS after promotions for computation QualType CompResultTy; // Type of computation result - ExprValueKind VK = VK_RValue; + ExprValueKind VK = VK_PRValue; ExprObjectKind OK = OK_Ordinary; bool ConvertHalfVec = false; @@ -14483,7 +14718,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, // assignment, but is not an lvalue. return CompoundAssignOperator::Create( Context, LHSExpr, RHSExpr, Opc, - LHSExpr->getType().getUnqualifiedType(), VK_RValue, OK_Ordinary, + LHSExpr->getType().getUnqualifiedType(), VK_PRValue, OK_Ordinary, OpLoc, CurFPFeatureOverrides()); QualType ResultType; switch (Opc) { @@ -14509,7 +14744,7 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, break; } return BinaryOperator::Create(Context, LHSExpr, RHSExpr, Opc, ResultType, - VK_RValue, OK_Ordinary, OpLoc, + VK_PRValue, OK_Ordinary, OpLoc, CurFPFeatureOverrides()); } @@ -14531,7 +14766,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr) { ExprResult Input = InputExpr; - ExprValueKind VK = VK_RValue; + ExprValueKind VK = VK_PRValue; ExprObjectKind OK = OK_Ordinary; QualType resultType; bool CanOverflow = false; @@ -14704,7 +14939,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, // complex l-values to ordinary l-values and all other values to r-values. if (Input.isInvalid()) return ExprError(); if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) { - if (Input.get()->getValueKind() != VK_RValue && + if (Input.get()->isGLValue() && Input.get()->getObjectKind() == OK_Ordinary) VK = Input.get()->getValueKind(); } else if (!getLangOpts().CPlusPlus) { @@ -15123,7 +15358,7 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, SourceLocation RPLoc) { assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)"); - ExprValueKind VK = VK_RValue; + ExprValueKind VK = VK_PRValue; ExprObjectKind OK = OK_Ordinary; QualType resType; bool CondIsTrue = false; @@ -15604,8 +15839,46 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, QualType PromoteType; if (TInfo->getType()->isPromotableIntegerType()) { PromoteType = Context.getPromotedIntegerType(TInfo->getType()); - if (Context.typesAreCompatible(PromoteType, TInfo->getType())) + // [cstdarg.syn]p1 defers the C++ behavior to what the C standard says, + // and C2x 7.16.1.1p2 says, in part: + // If type is not compatible with the type of the actual next argument + // (as promoted according to the default argument promotions), the + // behavior is undefined, except for the following cases: + // - both types are pointers to qualified or unqualified versions of + // compatible types; + // - one type is a signed integer type, the other type is the + // corresponding unsigned integer type, and the value is + // representable in both types; + // - one type is pointer to qualified or unqualified void and the + // other is a pointer to a qualified or unqualified character type. + // Given that type compatibility is the primary requirement (ignoring + // qualifications), you would think we could call typesAreCompatible() + // directly to test this. However, in C++, that checks for *same type*, + // which causes false positives when passing an enumeration type to + // va_arg. Instead, get the underlying type of the enumeration and pass + // that. + QualType UnderlyingType = TInfo->getType(); + if (const auto *ET = UnderlyingType->getAs<EnumType>()) + UnderlyingType = ET->getDecl()->getIntegerType(); + if (Context.typesAreCompatible(PromoteType, UnderlyingType, + /*CompareUnqualified*/ true)) PromoteType = QualType(); + + // If the types are still not compatible, we need to test whether the + // promoted type and the underlying type are the same except for + // signedness. Ask the AST for the correctly corresponding type and see + // if that's compatible. + if (!PromoteType.isNull() && + PromoteType->isUnsignedIntegerType() != + UnderlyingType->isUnsignedIntegerType()) { + UnderlyingType = + UnderlyingType->isUnsignedIntegerType() + ? Context.getCorrespondingSignedType(UnderlyingType) + : Context.getCorrespondingUnsignedType(UnderlyingType); + if (Context.typesAreCompatible(PromoteType, UnderlyingType, + /*CompareUnqualified*/ true)) + PromoteType = QualType(); + } } if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float)) PromoteType = Context.DoubleTy; @@ -16138,7 +16411,8 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, if (Result) *Result = E->EvaluateKnownConstIntCheckOverflow(Context); if (!isa<ConstantExpr>(E)) - E = ConstantExpr::Create(Context, E); + E = Result ? ConstantExpr::Create(Context, E, APValue(*Result)) + : ConstantExpr::Create(Context, E); return E; } @@ -16520,8 +16794,10 @@ void Sema::PopExpressionEvaluationContext() { if (!Rec.Lambdas.empty()) { using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind; - if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument || Rec.isUnevaluated() || - (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17)) { + if (!getLangOpts().CPlusPlus20 && + (Rec.ExprContext == ExpressionKind::EK_TemplateArgument || + Rec.isUnevaluated() || + (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17))) { unsigned D; if (Rec.isUnevaluated()) { // C++11 [expr.prim.lambda]p2: @@ -17030,6 +17306,42 @@ MarkVarDeclODRUsed(VarDecl *Var, SourceLocation Loc, Sema &SemaRef, CaptureType, DeclRefType, FunctionScopeIndexToStopAt); + if (SemaRef.LangOpts.CUDA && Var && Var->hasGlobalStorage()) { + auto *FD = dyn_cast_or_null<FunctionDecl>(SemaRef.CurContext); + auto VarTarget = SemaRef.IdentifyCUDATarget(Var); + auto UserTarget = SemaRef.IdentifyCUDATarget(FD); + if (VarTarget == Sema::CVT_Host && + (UserTarget == Sema::CFT_Device || UserTarget == Sema::CFT_HostDevice || + UserTarget == Sema::CFT_Global)) { + // Diagnose ODR-use of host global variables in device functions. + // Reference of device global variables in host functions is allowed + // through shadow variables therefore it is not diagnosed. + if (SemaRef.LangOpts.CUDAIsDevice) { + SemaRef.targetDiag(Loc, diag::err_ref_bad_target) + << /*host*/ 2 << /*variable*/ 1 << Var << UserTarget; + SemaRef.targetDiag(Var->getLocation(), + Var->getType().isConstQualified() + ? diag::note_cuda_const_var_unpromoted + : diag::note_cuda_host_var); + } + } else if (VarTarget == Sema::CVT_Device && + (UserTarget == Sema::CFT_Host || + UserTarget == Sema::CFT_HostDevice) && + !Var->hasExternalStorage()) { + // Record a CUDA/HIP device side variable if it is ODR-used + // by host code. This is done conservatively, when the variable is + // referenced in any of the following contexts: + // - a non-function context + // - a host function + // - a host device function + // This makes the ODR-use of the device side variable by host code to + // be visible in the device compilation for the compiler to be able to + // emit template variables instantiated by host code only and to + // externalize the static device side variable ODR-used by host code. + SemaRef.getASTContext().CUDADeviceVarODRUsedByHost.insert(Var); + } + } + Var->markUsed(SemaRef.Context); } @@ -17263,18 +17575,17 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var, /// Capture the given variable in the captured region. -static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI, - VarDecl *Var, - SourceLocation Loc, - const bool BuildAndDiagnose, - QualType &CaptureType, - QualType &DeclRefType, - const bool RefersToCapturedVariable, - Sema &S, bool Invalid) { +static bool captureInCapturedRegion( + CapturedRegionScopeInfo *RSI, VarDecl *Var, SourceLocation Loc, + const bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType, + const bool RefersToCapturedVariable, Sema::TryCaptureKind Kind, + bool IsTopScope, Sema &S, bool Invalid) { // By default, capture variables by reference. bool ByRef = true; - // Using an LValue reference type is consistent with Lambdas (see below). - if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) { + if (IsTopScope && Kind != Sema::TryCapture_Implicit) { + ByRef = (Kind == Sema::TryCapture_ExplicitByRef); + } else if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) { + // Using an LValue reference type is consistent with Lambdas (see below). if (S.isOpenMPCapturedDecl(Var)) { bool HasConst = DeclRefType.isConstQualified(); DeclRefType = DeclRefType.getUnqualifiedType(); @@ -17403,6 +17714,107 @@ static bool captureInLambda(LambdaScopeInfo *LSI, return !Invalid; } +static bool canCaptureVariableByCopy(VarDecl *Var, const ASTContext &Context) { + // Offer a Copy fix even if the type is dependent. + if (Var->getType()->isDependentType()) + return true; + QualType T = Var->getType().getNonReferenceType(); + if (T.isTriviallyCopyableType(Context)) + return true; + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) { + + if (!(RD = RD->getDefinition())) + return false; + if (RD->hasSimpleCopyConstructor()) + return true; + if (RD->hasUserDeclaredCopyConstructor()) + for (CXXConstructorDecl *Ctor : RD->ctors()) + if (Ctor->isCopyConstructor()) + return !Ctor->isDeleted(); + } + return false; +} + +/// Create up to 4 fix-its for explicit reference and value capture of \p Var or +/// default capture. Fixes may be omitted if they aren't allowed by the +/// standard, for example we can't emit a default copy capture fix-it if we +/// already explicitly copy capture capture another variable. +static void buildLambdaCaptureFixit(Sema &Sema, LambdaScopeInfo *LSI, + VarDecl *Var) { + assert(LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None); + // Don't offer Capture by copy of default capture by copy fixes if Var is + // known not to be copy constructible. + bool ShouldOfferCopyFix = canCaptureVariableByCopy(Var, Sema.getASTContext()); + + SmallString<32> FixBuffer; + StringRef Separator = LSI->NumExplicitCaptures > 0 ? ", " : ""; + if (Var->getDeclName().isIdentifier() && !Var->getName().empty()) { + SourceLocation VarInsertLoc = LSI->IntroducerRange.getEnd(); + if (ShouldOfferCopyFix) { + // Offer fixes to insert an explicit capture for the variable. + // [] -> [VarName] + // [OtherCapture] -> [OtherCapture, VarName] + FixBuffer.assign({Separator, Var->getName()}); + Sema.Diag(VarInsertLoc, diag::note_lambda_variable_capture_fixit) + << Var << /*value*/ 0 + << FixItHint::CreateInsertion(VarInsertLoc, FixBuffer); + } + // As above but capture by reference. + FixBuffer.assign({Separator, "&", Var->getName()}); + Sema.Diag(VarInsertLoc, diag::note_lambda_variable_capture_fixit) + << Var << /*reference*/ 1 + << FixItHint::CreateInsertion(VarInsertLoc, FixBuffer); + } + + // Only try to offer default capture if there are no captures excluding this + // and init captures. + // [this]: OK. + // [X = Y]: OK. + // [&A, &B]: Don't offer. + // [A, B]: Don't offer. + if (llvm::any_of(LSI->Captures, [](Capture &C) { + return !C.isThisCapture() && !C.isInitCapture(); + })) + return; + + // The default capture specifiers, '=' or '&', must appear first in the + // capture body. + SourceLocation DefaultInsertLoc = + LSI->IntroducerRange.getBegin().getLocWithOffset(1); + + if (ShouldOfferCopyFix) { + bool CanDefaultCopyCapture = true; + // [=, *this] OK since c++17 + // [=, this] OK since c++20 + if (LSI->isCXXThisCaptured() && !Sema.getLangOpts().CPlusPlus20) + CanDefaultCopyCapture = Sema.getLangOpts().CPlusPlus17 + ? LSI->getCXXThisCapture().isCopyCapture() + : false; + // We can't use default capture by copy if any captures already specified + // capture by copy. + if (CanDefaultCopyCapture && llvm::none_of(LSI->Captures, [](Capture &C) { + return !C.isThisCapture() && !C.isInitCapture() && C.isCopyCapture(); + })) { + FixBuffer.assign({"=", Separator}); + Sema.Diag(DefaultInsertLoc, diag::note_lambda_default_capture_fixit) + << /*value*/ 0 + << FixItHint::CreateInsertion(DefaultInsertLoc, FixBuffer); + } + } + + // We can't use default capture by reference if any captures already specified + // capture by reference. + if (llvm::none_of(LSI->Captures, [](Capture &C) { + return !C.isInitCapture() && C.isReferenceCapture() && + !C.isThisCapture(); + })) { + FixBuffer.assign({"&", Separator}); + Sema.Diag(DefaultInsertLoc, diag::note_lambda_default_capture_fixit) + << /*reference*/ 1 + << FixItHint::CreateInsertion(DefaultInsertLoc, FixBuffer); + } +} + bool Sema::tryCaptureVariable( VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, @@ -17492,6 +17904,7 @@ bool Sema::tryCaptureVariable( Diag(ExprLoc, diag::err_lambda_impcap) << Var; Diag(Var->getLocation(), diag::note_previous_decl) << Var; Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl); + buildLambdaCaptureFixit(*this, LSI, Var); } else diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC); } @@ -17570,9 +17983,11 @@ bool Sema::tryCaptureVariable( if (BuildAndDiagnose) { Diag(ExprLoc, diag::err_lambda_impcap) << Var; Diag(Var->getLocation(), diag::note_previous_decl) << Var; - if (cast<LambdaScopeInfo>(CSI)->Lambda) - Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getBeginLoc(), - diag::note_lambda_decl); + auto *LSI = cast<LambdaScopeInfo>(CSI); + if (LSI->Lambda) { + Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl); + buildLambdaCaptureFixit(*this, LSI, Var); + } // FIXME: If we error out because an outer lambda can not implicitly // capture a variable that an inner lambda explicitly captures, we // should have the inner lambda do the explicit capture - because @@ -17620,9 +18035,9 @@ bool Sema::tryCaptureVariable( DeclRefType, Nested, *this, Invalid); Nested = true; } else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) { - Invalid = !captureInCapturedRegion(RSI, Var, ExprLoc, BuildAndDiagnose, - CaptureType, DeclRefType, Nested, - *this, Invalid); + Invalid = !captureInCapturedRegion( + RSI, Var, ExprLoc, BuildAndDiagnose, CaptureType, DeclRefType, Nested, + Kind, /*IsTopScope*/ I == N - 1, *this, Invalid); Nested = true; } else { LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI); @@ -18079,8 +18494,9 @@ void Sema::CleanupVarDeclMarking() { "MarkVarDeclODRUsed failed to cleanup MaybeODRUseExprs?"); } -static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, - VarDecl *Var, Expr *E) { +static void DoMarkVarDeclReferenced( + Sema &SemaRef, SourceLocation Loc, VarDecl *Var, Expr *E, + llvm::DenseMap<const VarDecl *, int> &RefsMinusAssignments) { assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E) || isa<FunctionParmPackExpr>(E)) && "Invalid Expr argument to DoMarkVarDeclReferenced"); @@ -18089,24 +18505,6 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, if (Var->isInvalidDecl()) return; - // Record a CUDA/HIP static device/constant variable if it is referenced - // by host code. This is done conservatively, when the variable is referenced - // in any of the following contexts: - // - a non-function context - // - a host function - // - a host device function - // This also requires the reference of the static device/constant variable by - // host code to be visible in the device compilation for the compiler to be - // able to externalize the static device/constant variable. - if (SemaRef.getASTContext().mayExternalizeStaticVar(Var)) { - auto *CurContext = SemaRef.CurContext; - if (!CurContext || !isa<FunctionDecl>(CurContext) || - cast<FunctionDecl>(CurContext)->hasAttr<CUDAHostAttr>() || - (!cast<FunctionDecl>(CurContext)->hasAttr<CUDADeviceAttr>() && - !cast<FunctionDecl>(CurContext)->hasAttr<CUDAGlobalAttr>())) - SemaRef.getASTContext().CUDAStaticDeviceVarReferencedByHost.insert(Var); - } - auto *MSI = Var->getMemberSpecializationInfo(); TemplateSpecializationKind TSK = MSI ? MSI->getTemplateSpecializationKind() : Var->getTemplateSpecializationKind(); @@ -18115,6 +18513,10 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, bool UsableInConstantExpr = Var->mightBeUsableInConstantExpressions(SemaRef.Context); + if (Var->isLocalVarDeclOrParm() && !Var->hasExternalStorage()) { + RefsMinusAssignments.insert({Var, 0}).first->getSecond()++; + } + // C++20 [expr.const]p12: // A variable [...] is needed for constant evaluation if it is [...] a // variable whose name appears as a potentially constant evaluated @@ -18270,16 +18672,18 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, /// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be /// used directly for normal expressions referring to VarDecl. void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) { - DoMarkVarDeclReferenced(*this, Loc, Var, nullptr); + DoMarkVarDeclReferenced(*this, Loc, Var, nullptr, RefsMinusAssignments); } -static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, - Decl *D, Expr *E, bool MightBeOdrUse) { +static void +MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E, + bool MightBeOdrUse, + llvm::DenseMap<const VarDecl *, int> &RefsMinusAssignments) { if (SemaRef.isInOpenMPDeclareTargetContext()) SemaRef.checkDeclIsAllowedInOpenMPTarget(E, D); if (VarDecl *Var = dyn_cast<VarDecl>(D)) { - DoMarkVarDeclReferenced(SemaRef, Loc, Var, E); + DoMarkVarDeclReferenced(SemaRef, Loc, Var, E, RefsMinusAssignments); return; } @@ -18325,7 +18729,8 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) { if (!isConstantEvaluated() && FD->isConsteval() && !RebuildingImmediateInvocation) ExprEvalContexts.back().ReferenceToConsteval.insert(E); - MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse); + MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse, + RefsMinusAssignments); } /// Perform reference-marking and odr-use handling for a MemberExpr. @@ -18344,13 +18749,15 @@ void Sema::MarkMemberReferenced(MemberExpr *E) { } SourceLocation Loc = E->getMemberLoc().isValid() ? E->getMemberLoc() : E->getBeginLoc(); - MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse); + MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse, + RefsMinusAssignments); } /// Perform reference-marking and odr-use handling for a FunctionParmPackExpr. void Sema::MarkFunctionParmPackReferenced(FunctionParmPackExpr *E) { for (VarDecl *VD : *E) - MarkExprReferenced(*this, E->getParameterPackLocation(), VD, E, true); + MarkExprReferenced(*this, E->getParameterPackLocation(), VD, E, true, + RefsMinusAssignments); } /// Perform marking for a reference to an arbitrary declaration. It @@ -18769,7 +19176,7 @@ namespace { Expr *SubExpr = SubResult.get(); E->setSubExpr(SubExpr); E->setType(S.Context.getPointerType(SubExpr->getType())); - assert(E->getValueKind() == VK_RValue); + assert(E->isPRValue()); assert(E->getObjectKind() == OK_Ordinary); return E; } @@ -18779,7 +19186,7 @@ namespace { E->setType(VD->getType()); - assert(E->getValueKind() == VK_RValue); + assert(E->isPRValue()); if (S.getLangOpts().CPlusPlus && !(isa<CXXMethodDecl>(VD) && cast<CXXMethodDecl>(VD)->isInstance())) @@ -18870,7 +19277,7 @@ namespace { return ExprError(); } - assert(E->getValueKind() == VK_RValue); + assert(E->isPRValue()); assert(E->getObjectKind() == OK_Ordinary); E->setType(DestType); @@ -19030,7 +19437,7 @@ ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *E) { ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) { // The only case we should ever see here is a function-to-pointer decay. if (E->getCastKind() == CK_FunctionToPointerDecay) { - assert(E->getValueKind() == VK_RValue); + assert(E->isPRValue()); assert(E->getObjectKind() == OK_Ordinary); E->setType(DestType); @@ -19044,7 +19451,7 @@ ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) { E->setSubExpr(Result.get()); return E; } else if (E->getCastKind() == CK_LValueToRValue) { - assert(E->getValueKind() == VK_RValue); + assert(E->isPRValue()); assert(E->getObjectKind() == OK_Ordinary); assert(isa<BlockPointerType>(E->getType())); @@ -19076,8 +19483,8 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { DestType = Ptr->getPointeeType(); ExprResult Result = resolveDecl(E, VD); if (Result.isInvalid()) return ExprError(); - return S.ImpCastExprToType(Result.get(), Type, - CK_FunctionToPointerDecay, VK_RValue); + return S.ImpCastExprToType(Result.get(), Type, CK_FunctionToPointerDecay, + VK_PRValue); } if (!Type->isFunctionType()) { @@ -19119,13 +19526,13 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) if (MD->isInstance()) { - ValueKind = VK_RValue; + ValueKind = VK_PRValue; Type = S.Context.BoundMemberTy; } // Function references aren't l-values in C. if (!S.getLangOpts().CPlusPlus) - ValueKind = VK_RValue; + ValueKind = VK_PRValue; // - variables } else if (isa<VarDecl>(VD)) { @@ -19324,7 +19731,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { CK_BuiltinFnToFnPtr) .get(); return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy, - VK_RValue, SourceLocation(), + VK_PRValue, SourceLocation(), FPOptionsOverride()); } } @@ -19365,6 +19772,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { #define PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: #include "clang/Basic/PPCTypes.def" +#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/RISCVVTypes.def" #define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id: #define PLACEHOLDER_TYPE(Id, SingletonId) #include "clang/AST/BuiltinTypes.def" @@ -19406,23 +19815,31 @@ Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { ExprResult Sema::ActOnObjCAvailabilityCheckExpr( llvm::ArrayRef<AvailabilitySpec> AvailSpecs, SourceLocation AtLoc, SourceLocation RParen) { - - StringRef Platform = getASTContext().getTargetInfo().getPlatformName(); - - auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { - return Spec.getPlatform() == Platform; - }); + auto FindSpecVersion = [&](StringRef Platform) -> Optional<VersionTuple> { + auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { + return Spec.getPlatform() == Platform; + }); + // Transcribe the "ios" availability check to "maccatalyst" when compiling + // for "maccatalyst" if "maccatalyst" is not specified. + if (Spec == AvailSpecs.end() && Platform == "maccatalyst") { + Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { + return Spec.getPlatform() == "ios"; + }); + } + if (Spec == AvailSpecs.end()) + return None; + return Spec->getVersion(); + }; VersionTuple Version; - if (Spec != AvailSpecs.end()) - Version = Spec->getVersion(); + if (auto MaybeVersion = + FindSpecVersion(Context.getTargetInfo().getPlatformName())) + Version = *MaybeVersion; - // The use of `@available` in the enclosing function should be analyzed to + // The use of `@available` in the enclosing context should be analyzed to // warn when it's used inappropriately (i.e. not if(@available)). - if (getCurFunctionOrMethodDecl()) - getEnclosingFunction()->HasPotentialAvailabilityViolations = true; - else if (getCurBlock() || getCurLambda()) - getCurFunction()->HasPotentialAvailabilityViolations = true; + if (FunctionScopeInfo *Context = getCurFunctionAvailabilityContext()) + Context->HasPotentialAvailabilityViolations = true; return new (Context) ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy); @@ -19436,8 +19853,10 @@ ExprResult Sema::CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, if (isSFINAEContext()) return ExprError(); - if (T.isNull() || !Context.getLangOpts().RecoveryASTType) + if (T.isNull() || T->isUndeducedType() || + !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); } |