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