aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r--clang/lib/Sema/SemaChecking.cpp839
1 files changed, 722 insertions, 117 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 2d3d36f4adad..de75c10417e7 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -91,6 +91,7 @@
#include <algorithm>
#include <bitset>
#include <cassert>
+#include <cctype>
#include <cstddef>
#include <cstdint>
#include <functional>
@@ -252,7 +253,7 @@ static bool SemaBuiltinAlignment(Sema &S, CallExpr *TheCall, unsigned ID) {
}
if (llvm::APSInt::compareValues(AlignValue, MaxValue) > 0) {
S.Diag(AlignOp->getExprLoc(), diag::err_alignment_too_big)
- << MaxValue.toString(10);
+ << toString(MaxValue, 10);
return true;
}
if (!AlignValue.isPowerOf2()) {
@@ -771,8 +772,8 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
PDiag(DiagID)
- << FunctionName << ObjectSize.toString(/*Radix=*/10)
- << UsedSize.getValue().toString(/*Radix=*/10));
+ << FunctionName << toString(ObjectSize, /*Radix=*/10)
+ << toString(UsedSize.getValue(), /*Radix=*/10));
}
static bool SemaBuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall,
@@ -837,7 +838,7 @@ static bool checkOpenCLBlockArgs(Sema &S, Expr *BlockArg) {
}
static bool checkOpenCLSubgroupExt(Sema &S, CallExpr *Call) {
- if (!S.getOpenCLOptions().isEnabled("cl_khr_subgroups")) {
+ if (!S.getOpenCLOptions().isSupported("cl_khr_subgroups", S.getLangOpts())) {
S.Diag(Call->getBeginLoc(), diag::err_opencl_requires_extension)
<< 1 << Call->getDirectCallee() << "cl_khr_subgroups";
return true;
@@ -1429,6 +1430,9 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
return CheckPPCBuiltinFunctionCall(TI, BuiltinID, TheCall);
case llvm::Triple::amdgcn:
return CheckAMDGCNBuiltinFunctionCall(BuiltinID, TheCall);
+ case llvm::Triple::riscv32:
+ case llvm::Triple::riscv64:
+ return CheckRISCVBuiltinFunctionCall(TI, BuiltinID, TheCall);
}
}
@@ -1550,6 +1554,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
Diag(TheCall->getBeginLoc(), diag::warn_alloca)
<< TheCall->getDirectCallee();
break;
+ case Builtin::BI__arithmetic_fence:
+ if (SemaBuiltinArithmeticFence(TheCall))
+ return ExprError();
+ break;
case Builtin::BI__assume:
case Builtin::BI__builtin_assume:
if (SemaBuiltinAssume(TheCall))
@@ -1962,6 +1970,26 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_matrix_column_major_store:
return SemaBuiltinMatrixColumnMajorStore(TheCall, TheCallResult);
+
+ case Builtin::BI__builtin_get_device_side_mangled_name: {
+ auto Check = [](CallExpr *TheCall) {
+ if (TheCall->getNumArgs() != 1)
+ return false;
+ auto *DRE = dyn_cast<DeclRefExpr>(TheCall->getArg(0)->IgnoreImpCasts());
+ if (!DRE)
+ return false;
+ auto *D = DRE->getDecl();
+ if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D))
+ return false;
+ return D->hasAttr<CUDAGlobalAttr>() || D->hasAttr<CUDADeviceAttr>() ||
+ D->hasAttr<CUDAConstantAttr>() || D->hasAttr<HIPManagedAttr>();
+ };
+ if (!Check(TheCall)) {
+ Diag(TheCall->getBeginLoc(),
+ diag::err_hip_invalid_args_builtin_mangled_name);
+ return ExprError();
+ }
+ }
}
// Since the target specific builtins for each arch overlap, only check those
@@ -2623,7 +2651,10 @@ static bool isValidBPFPreserveEnumValueArg(Expr *Arg) {
return false;
const auto *CE = dyn_cast<CStyleCastExpr>(UO->getSubExpr());
- if (!CE || CE->getCastKind() != CK_IntegralToPointer)
+ if (!CE)
+ return false;
+ if (CE->getCastKind() != CK_IntegralToPointer &&
+ CE->getCastKind() != CK_NullToPointer)
return false;
// The integer must be from an EnumConstantDecl.
@@ -3228,34 +3259,81 @@ static QualType DecodePPCMMATypeFromStr(ASTContext &Context, const char *&Str,
}
}
+static bool isPPC_64Builtin(unsigned BuiltinID) {
+ // These builtins only work on PPC 64bit targets.
+ switch (BuiltinID) {
+ case PPC::BI__builtin_divde:
+ case PPC::BI__builtin_divdeu:
+ case PPC::BI__builtin_bpermd:
+ case PPC::BI__builtin_ppc_ldarx:
+ case PPC::BI__builtin_ppc_stdcx:
+ case PPC::BI__builtin_ppc_tdw:
+ case PPC::BI__builtin_ppc_trapd:
+ case PPC::BI__builtin_ppc_cmpeqb:
+ case PPC::BI__builtin_ppc_setb:
+ case PPC::BI__builtin_ppc_mulhd:
+ case PPC::BI__builtin_ppc_mulhdu:
+ case PPC::BI__builtin_ppc_maddhd:
+ case PPC::BI__builtin_ppc_maddhdu:
+ case PPC::BI__builtin_ppc_maddld:
+ case PPC::BI__builtin_ppc_load8r:
+ case PPC::BI__builtin_ppc_store8r:
+ case PPC::BI__builtin_ppc_insert_exp:
+ case PPC::BI__builtin_ppc_extract_sig:
+ return true;
+ }
+ return false;
+}
+
+static bool SemaFeatureCheck(Sema &S, CallExpr *TheCall,
+ StringRef FeatureToCheck, unsigned DiagID,
+ StringRef DiagArg = "") {
+ if (S.Context.getTargetInfo().hasFeature(FeatureToCheck))
+ return false;
+
+ if (DiagArg.empty())
+ S.Diag(TheCall->getBeginLoc(), DiagID) << TheCall->getSourceRange();
+ else
+ S.Diag(TheCall->getBeginLoc(), DiagID)
+ << DiagArg << TheCall->getSourceRange();
+
+ return true;
+}
+
+/// Returns true if the argument consists of one contiguous run of 1s with any
+/// number of 0s on either side. The 1s are allowed to wrap from LSB to MSB, so
+/// 0x000FFF0, 0x0000FFFF, 0xFF0000FF, 0x0 are all runs. 0x0F0F0000 is not,
+/// since all 1s are not contiguous.
+bool Sema::SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum) {
+ llvm::APSInt Result;
+ // We can't check the value of a dependent argument.
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ // Check constant-ness first.
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
+ return true;
+
+ // Check contiguous run of 1s, 0xFF0000FF is also a run of 1s.
+ if (Result.isShiftedMask() || (~Result).isShiftedMask())
+ return false;
+
+ return Diag(TheCall->getBeginLoc(),
+ diag::err_argument_not_contiguous_bit_field)
+ << ArgNum << Arg->getSourceRange();
+}
+
bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
- bool Is64BitBltin = BuiltinID == PPC::BI__builtin_divde ||
- BuiltinID == PPC::BI__builtin_divdeu ||
- BuiltinID == PPC::BI__builtin_bpermd;
bool IsTarget64Bit = TI.getTypeWidth(TI.getIntPtrType()) == 64;
- bool IsBltinExtDiv = BuiltinID == PPC::BI__builtin_divwe ||
- BuiltinID == PPC::BI__builtin_divweu ||
- BuiltinID == PPC::BI__builtin_divde ||
- BuiltinID == PPC::BI__builtin_divdeu;
+ llvm::APSInt Result;
- if (Is64BitBltin && !IsTarget64Bit)
+ if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)
<< TheCall->getSourceRange();
- if ((IsBltinExtDiv && !TI.hasFeature("extdiv")) ||
- (BuiltinID == PPC::BI__builtin_bpermd && !TI.hasFeature("bpermd")))
- return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_only_on_pwr7)
- << TheCall->getSourceRange();
-
- auto SemaVSXCheck = [&](CallExpr *TheCall) -> bool {
- if (!TI.hasFeature("vsx"))
- return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_only_on_pwr7)
- << TheCall->getSourceRange();
- return false;
- };
-
switch (BuiltinID) {
default: return false;
case PPC::BI__builtin_altivec_crypto_vshasigmaw:
@@ -3281,11 +3359,22 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case PPC::BI__builtin_vsx_xxpermdi:
case PPC::BI__builtin_vsx_xxsldwi:
return SemaBuiltinVSX(TheCall);
+ case PPC::BI__builtin_divwe:
+ case PPC::BI__builtin_divweu:
+ case PPC::BI__builtin_divde:
+ case PPC::BI__builtin_divdeu:
+ return SemaFeatureCheck(*this, TheCall, "extdiv",
+ diag::err_ppc_builtin_only_on_arch, "7");
+ case PPC::BI__builtin_bpermd:
+ return SemaFeatureCheck(*this, TheCall, "bpermd",
+ diag::err_ppc_builtin_only_on_arch, "7");
case PPC::BI__builtin_unpack_vector_int128:
- return SemaVSXCheck(TheCall) ||
+ return SemaFeatureCheck(*this, TheCall, "vsx",
+ diag::err_ppc_builtin_only_on_arch, "7") ||
SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
case PPC::BI__builtin_pack_vector_int128:
- return SemaVSXCheck(TheCall);
+ return SemaFeatureCheck(*this, TheCall, "vsx",
+ diag::err_ppc_builtin_only_on_arch, "7");
case PPC::BI__builtin_altivec_vgnb:
return SemaBuiltinConstantArgRange(TheCall, 1, 2, 7);
case PPC::BI__builtin_altivec_vec_replace_elt:
@@ -3304,7 +3393,59 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
return SemaBuiltinConstantArgRange(TheCall, 2, 0, 7);
case PPC::BI__builtin_vsx_xxpermx:
return SemaBuiltinConstantArgRange(TheCall, 3, 0, 7);
-#define CUSTOM_BUILTIN(Name, Types, Acc) \
+ case PPC::BI__builtin_ppc_tw:
+ case PPC::BI__builtin_ppc_tdw:
+ return SemaBuiltinConstantArgRange(TheCall, 2, 1, 31);
+ case PPC::BI__builtin_ppc_cmpeqb:
+ case PPC::BI__builtin_ppc_setb:
+ case PPC::BI__builtin_ppc_maddhd:
+ case PPC::BI__builtin_ppc_maddhdu:
+ case PPC::BI__builtin_ppc_maddld:
+ return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions",
+ diag::err_ppc_builtin_only_on_arch, "9");
+ case PPC::BI__builtin_ppc_cmprb:
+ return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions",
+ diag::err_ppc_builtin_only_on_arch, "9") ||
+ SemaBuiltinConstantArgRange(TheCall, 0, 0, 1);
+ // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must
+ // be a constant that represents a contiguous bit field.
+ case PPC::BI__builtin_ppc_rlwnm:
+ return SemaBuiltinConstantArg(TheCall, 1, Result) ||
+ SemaValueIsRunOfOnes(TheCall, 2);
+ case PPC::BI__builtin_ppc_rlwimi:
+ case PPC::BI__builtin_ppc_rldimi:
+ return SemaBuiltinConstantArg(TheCall, 2, Result) ||
+ SemaValueIsRunOfOnes(TheCall, 3);
+ case PPC::BI__builtin_ppc_extract_exp:
+ case PPC::BI__builtin_ppc_extract_sig:
+ case PPC::BI__builtin_ppc_insert_exp:
+ return SemaFeatureCheck(*this, TheCall, "power9-vector",
+ diag::err_ppc_builtin_only_on_arch, "9");
+ case PPC::BI__builtin_ppc_mtfsb0:
+ case PPC::BI__builtin_ppc_mtfsb1:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31);
+ case PPC::BI__builtin_ppc_mtfsf:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 255);
+ case PPC::BI__builtin_ppc_mtfsfi:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 7) ||
+ SemaBuiltinConstantArgRange(TheCall, 1, 0, 15);
+ case PPC::BI__builtin_ppc_alignx:
+ return SemaBuiltinConstantArgPower2(TheCall, 0);
+ case PPC::BI__builtin_ppc_rdlam:
+ return SemaValueIsRunOfOnes(TheCall, 2);
+ case PPC::BI__builtin_ppc_icbt:
+ case PPC::BI__builtin_ppc_sthcx:
+ case PPC::BI__builtin_ppc_stbcx:
+ case PPC::BI__builtin_ppc_lharx:
+ case PPC::BI__builtin_ppc_lbarx:
+ return SemaFeatureCheck(*this, TheCall, "isa-v207-instructions",
+ diag::err_ppc_builtin_only_on_arch, "8");
+ case PPC::BI__builtin_vsx_ldrmb:
+ case PPC::BI__builtin_vsx_strmb:
+ return SemaFeatureCheck(*this, TheCall, "isa-v207-instructions",
+ diag::err_ppc_builtin_only_on_arch, "8") ||
+ SemaBuiltinConstantArgRange(TheCall, 1, 1, 16);
+#define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \
case PPC::BI__builtin_##Name: \
return SemaBuiltinPPCMMACall(TheCall, Types);
#include "clang/Basic/BuiltinsPPC.def"
@@ -3356,20 +3497,27 @@ bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
if (!ArgExpr->EvaluateAsInt(ArgResult, Context))
return Diag(ArgExpr->getExprLoc(), diag::err_typecheck_expect_int)
<< ArgExpr->getType();
- int ord = ArgResult.Val.getInt().getZExtValue();
+ auto Ord = ArgResult.Val.getInt().getZExtValue();
// Check valididty of memory ordering as per C11 / C++11's memody model.
- switch (static_cast<llvm::AtomicOrderingCABI>(ord)) {
+ // Only fence needs check. Atomic dec/inc allow all memory orders.
+ if (!llvm::isValidAtomicOrderingCABI(Ord))
+ return Diag(ArgExpr->getBeginLoc(),
+ diag::warn_atomic_op_has_invalid_memory_order)
+ << ArgExpr->getSourceRange();
+ switch (static_cast<llvm::AtomicOrderingCABI>(Ord)) {
+ case llvm::AtomicOrderingCABI::relaxed:
+ case llvm::AtomicOrderingCABI::consume:
+ if (BuiltinID == AMDGPU::BI__builtin_amdgcn_fence)
+ return Diag(ArgExpr->getBeginLoc(),
+ diag::warn_atomic_op_has_invalid_memory_order)
+ << ArgExpr->getSourceRange();
+ break;
case llvm::AtomicOrderingCABI::acquire:
case llvm::AtomicOrderingCABI::release:
case llvm::AtomicOrderingCABI::acq_rel:
case llvm::AtomicOrderingCABI::seq_cst:
break;
- default: {
- return Diag(ArgExpr->getBeginLoc(),
- diag::warn_atomic_op_has_invalid_memory_order)
- << ArgExpr->getSourceRange();
- }
}
Arg = TheCall->getArg(ScopeIndex);
@@ -3383,6 +3531,198 @@ bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
return false;
}
+bool Sema::CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum) {
+ llvm::APSInt Result;
+
+ // We can't check the value of a dependent argument.
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ // Check constant-ness first.
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
+ return true;
+
+ int64_t Val = Result.getSExtValue();
+ if ((Val >= 0 && Val <= 3) || (Val >= 5 && Val <= 7))
+ return false;
+
+ return Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_invalid_lmul)
+ << Arg->getSourceRange();
+}
+
+bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI,
+ unsigned BuiltinID,
+ CallExpr *TheCall) {
+ // CodeGenFunction can also detect this, but this gives a better error
+ // message.
+ bool FeatureMissing = false;
+ SmallVector<StringRef> ReqFeatures;
+ StringRef Features = Context.BuiltinInfo.getRequiredFeatures(BuiltinID);
+ Features.split(ReqFeatures, ',');
+
+ // Check if each required feature is included
+ for (StringRef F : ReqFeatures) {
+ if (TI.hasFeature(F))
+ continue;
+
+ // If the feature is 64bit, alter the string so it will print better in
+ // the diagnostic.
+ if (F == "64bit")
+ F = "RV64";
+
+ // Convert features like "zbr" and "experimental-zbr" to "Zbr".
+ F.consume_front("experimental-");
+ std::string FeatureStr = F.str();
+ FeatureStr[0] = std::toupper(FeatureStr[0]);
+
+ // Error message
+ FeatureMissing = true;
+ Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_requires_extension)
+ << TheCall->getSourceRange() << StringRef(FeatureStr);
+ }
+
+ if (FeatureMissing)
+ return true;
+
+ switch (BuiltinID) {
+ case RISCV::BI__builtin_rvv_vsetvli:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3) ||
+ CheckRISCVLMUL(TheCall, 2);
+ case RISCV::BI__builtin_rvv_vsetvlimax:
+ return SemaBuiltinConstantArgRange(TheCall, 0, 0, 3) ||
+ CheckRISCVLMUL(TheCall, 1);
+ case RISCV::BI__builtin_rvv_vget_v_i8m2_i8m1:
+ case RISCV::BI__builtin_rvv_vget_v_i16m2_i16m1:
+ case RISCV::BI__builtin_rvv_vget_v_i32m2_i32m1:
+ case RISCV::BI__builtin_rvv_vget_v_i64m2_i64m1:
+ case RISCV::BI__builtin_rvv_vget_v_f32m2_f32m1:
+ case RISCV::BI__builtin_rvv_vget_v_f64m2_f64m1:
+ case RISCV::BI__builtin_rvv_vget_v_u8m2_u8m1:
+ case RISCV::BI__builtin_rvv_vget_v_u16m2_u16m1:
+ case RISCV::BI__builtin_rvv_vget_v_u32m2_u32m1:
+ case RISCV::BI__builtin_rvv_vget_v_u64m2_u64m1:
+ case RISCV::BI__builtin_rvv_vget_v_i8m4_i8m2:
+ case RISCV::BI__builtin_rvv_vget_v_i16m4_i16m2:
+ case RISCV::BI__builtin_rvv_vget_v_i32m4_i32m2:
+ case RISCV::BI__builtin_rvv_vget_v_i64m4_i64m2:
+ case RISCV::BI__builtin_rvv_vget_v_f32m4_f32m2:
+ case RISCV::BI__builtin_rvv_vget_v_f64m4_f64m2:
+ case RISCV::BI__builtin_rvv_vget_v_u8m4_u8m2:
+ case RISCV::BI__builtin_rvv_vget_v_u16m4_u16m2:
+ case RISCV::BI__builtin_rvv_vget_v_u32m4_u32m2:
+ case RISCV::BI__builtin_rvv_vget_v_u64m4_u64m2:
+ case RISCV::BI__builtin_rvv_vget_v_i8m8_i8m4:
+ case RISCV::BI__builtin_rvv_vget_v_i16m8_i16m4:
+ case RISCV::BI__builtin_rvv_vget_v_i32m8_i32m4:
+ case RISCV::BI__builtin_rvv_vget_v_i64m8_i64m4:
+ case RISCV::BI__builtin_rvv_vget_v_f32m8_f32m4:
+ case RISCV::BI__builtin_rvv_vget_v_f64m8_f64m4:
+ case RISCV::BI__builtin_rvv_vget_v_u8m8_u8m4:
+ case RISCV::BI__builtin_rvv_vget_v_u16m8_u16m4:
+ case RISCV::BI__builtin_rvv_vget_v_u32m8_u32m4:
+ case RISCV::BI__builtin_rvv_vget_v_u64m8_u64m4:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
+ case RISCV::BI__builtin_rvv_vget_v_i8m4_i8m1:
+ case RISCV::BI__builtin_rvv_vget_v_i16m4_i16m1:
+ case RISCV::BI__builtin_rvv_vget_v_i32m4_i32m1:
+ case RISCV::BI__builtin_rvv_vget_v_i64m4_i64m1:
+ case RISCV::BI__builtin_rvv_vget_v_f32m4_f32m1:
+ case RISCV::BI__builtin_rvv_vget_v_f64m4_f64m1:
+ case RISCV::BI__builtin_rvv_vget_v_u8m4_u8m1:
+ case RISCV::BI__builtin_rvv_vget_v_u16m4_u16m1:
+ case RISCV::BI__builtin_rvv_vget_v_u32m4_u32m1:
+ case RISCV::BI__builtin_rvv_vget_v_u64m4_u64m1:
+ case RISCV::BI__builtin_rvv_vget_v_i8m8_i8m2:
+ case RISCV::BI__builtin_rvv_vget_v_i16m8_i16m2:
+ case RISCV::BI__builtin_rvv_vget_v_i32m8_i32m2:
+ case RISCV::BI__builtin_rvv_vget_v_i64m8_i64m2:
+ case RISCV::BI__builtin_rvv_vget_v_f32m8_f32m2:
+ case RISCV::BI__builtin_rvv_vget_v_f64m8_f64m2:
+ case RISCV::BI__builtin_rvv_vget_v_u8m8_u8m2:
+ case RISCV::BI__builtin_rvv_vget_v_u16m8_u16m2:
+ case RISCV::BI__builtin_rvv_vget_v_u32m8_u32m2:
+ case RISCV::BI__builtin_rvv_vget_v_u64m8_u64m2:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3);
+ case RISCV::BI__builtin_rvv_vget_v_i8m8_i8m1:
+ case RISCV::BI__builtin_rvv_vget_v_i16m8_i16m1:
+ case RISCV::BI__builtin_rvv_vget_v_i32m8_i32m1:
+ case RISCV::BI__builtin_rvv_vget_v_i64m8_i64m1:
+ case RISCV::BI__builtin_rvv_vget_v_f32m8_f32m1:
+ case RISCV::BI__builtin_rvv_vget_v_f64m8_f64m1:
+ case RISCV::BI__builtin_rvv_vget_v_u8m8_u8m1:
+ case RISCV::BI__builtin_rvv_vget_v_u16m8_u16m1:
+ case RISCV::BI__builtin_rvv_vget_v_u32m8_u32m1:
+ case RISCV::BI__builtin_rvv_vget_v_u64m8_u64m1:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 7);
+ case RISCV::BI__builtin_rvv_vset_v_i8m1_i8m2:
+ case RISCV::BI__builtin_rvv_vset_v_i16m1_i16m2:
+ case RISCV::BI__builtin_rvv_vset_v_i32m1_i32m2:
+ case RISCV::BI__builtin_rvv_vset_v_i64m1_i64m2:
+ case RISCV::BI__builtin_rvv_vset_v_f32m1_f32m2:
+ case RISCV::BI__builtin_rvv_vset_v_f64m1_f64m2:
+ case RISCV::BI__builtin_rvv_vset_v_u8m1_u8m2:
+ case RISCV::BI__builtin_rvv_vset_v_u16m1_u16m2:
+ case RISCV::BI__builtin_rvv_vset_v_u32m1_u32m2:
+ case RISCV::BI__builtin_rvv_vset_v_u64m1_u64m2:
+ case RISCV::BI__builtin_rvv_vset_v_i8m2_i8m4:
+ case RISCV::BI__builtin_rvv_vset_v_i16m2_i16m4:
+ case RISCV::BI__builtin_rvv_vset_v_i32m2_i32m4:
+ case RISCV::BI__builtin_rvv_vset_v_i64m2_i64m4:
+ case RISCV::BI__builtin_rvv_vset_v_f32m2_f32m4:
+ case RISCV::BI__builtin_rvv_vset_v_f64m2_f64m4:
+ case RISCV::BI__builtin_rvv_vset_v_u8m2_u8m4:
+ case RISCV::BI__builtin_rvv_vset_v_u16m2_u16m4:
+ case RISCV::BI__builtin_rvv_vset_v_u32m2_u32m4:
+ case RISCV::BI__builtin_rvv_vset_v_u64m2_u64m4:
+ case RISCV::BI__builtin_rvv_vset_v_i8m4_i8m8:
+ case RISCV::BI__builtin_rvv_vset_v_i16m4_i16m8:
+ case RISCV::BI__builtin_rvv_vset_v_i32m4_i32m8:
+ case RISCV::BI__builtin_rvv_vset_v_i64m4_i64m8:
+ case RISCV::BI__builtin_rvv_vset_v_f32m4_f32m8:
+ case RISCV::BI__builtin_rvv_vset_v_f64m4_f64m8:
+ case RISCV::BI__builtin_rvv_vset_v_u8m4_u8m8:
+ case RISCV::BI__builtin_rvv_vset_v_u16m4_u16m8:
+ case RISCV::BI__builtin_rvv_vset_v_u32m4_u32m8:
+ case RISCV::BI__builtin_rvv_vset_v_u64m4_u64m8:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
+ case RISCV::BI__builtin_rvv_vset_v_i8m1_i8m4:
+ case RISCV::BI__builtin_rvv_vset_v_i16m1_i16m4:
+ case RISCV::BI__builtin_rvv_vset_v_i32m1_i32m4:
+ case RISCV::BI__builtin_rvv_vset_v_i64m1_i64m4:
+ case RISCV::BI__builtin_rvv_vset_v_f32m1_f32m4:
+ case RISCV::BI__builtin_rvv_vset_v_f64m1_f64m4:
+ case RISCV::BI__builtin_rvv_vset_v_u8m1_u8m4:
+ case RISCV::BI__builtin_rvv_vset_v_u16m1_u16m4:
+ case RISCV::BI__builtin_rvv_vset_v_u32m1_u32m4:
+ case RISCV::BI__builtin_rvv_vset_v_u64m1_u64m4:
+ case RISCV::BI__builtin_rvv_vset_v_i8m2_i8m8:
+ case RISCV::BI__builtin_rvv_vset_v_i16m2_i16m8:
+ case RISCV::BI__builtin_rvv_vset_v_i32m2_i32m8:
+ case RISCV::BI__builtin_rvv_vset_v_i64m2_i64m8:
+ case RISCV::BI__builtin_rvv_vset_v_f32m2_f32m8:
+ case RISCV::BI__builtin_rvv_vset_v_f64m2_f64m8:
+ case RISCV::BI__builtin_rvv_vset_v_u8m2_u8m8:
+ case RISCV::BI__builtin_rvv_vset_v_u16m2_u16m8:
+ case RISCV::BI__builtin_rvv_vset_v_u32m2_u32m8:
+ case RISCV::BI__builtin_rvv_vset_v_u64m2_u64m8:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3);
+ case RISCV::BI__builtin_rvv_vset_v_i8m1_i8m8:
+ case RISCV::BI__builtin_rvv_vset_v_i16m1_i16m8:
+ case RISCV::BI__builtin_rvv_vset_v_i32m1_i32m8:
+ case RISCV::BI__builtin_rvv_vset_v_i64m1_i64m8:
+ case RISCV::BI__builtin_rvv_vset_v_f32m1_f32m8:
+ case RISCV::BI__builtin_rvv_vset_v_f64m1_f64m8:
+ case RISCV::BI__builtin_rvv_vset_v_u8m1_u8m8:
+ case RISCV::BI__builtin_rvv_vset_v_u16m1_u16m8:
+ case RISCV::BI__builtin_rvv_vset_v_u32m1_u32m8:
+ case RISCV::BI__builtin_rvv_vset_v_u64m1_u64m8:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 7);
+ }
+
+ return false;
+}
+
bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
if (BuiltinID == SystemZ::BI__builtin_tabort) {
@@ -3443,6 +3783,11 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID,
case SystemZ::BI__builtin_s390_vfmaxdb: i = 2; l = 0; u = 15; break;
case SystemZ::BI__builtin_s390_vsld: i = 2; l = 0; u = 7; break;
case SystemZ::BI__builtin_s390_vsrd: i = 2; l = 0; u = 7; break;
+ case SystemZ::BI__builtin_s390_vclfnhs:
+ case SystemZ::BI__builtin_s390_vclfnls:
+ case SystemZ::BI__builtin_s390_vcfn:
+ case SystemZ::BI__builtin_s390_vcnf: i = 1; l = 0; u = 15; break;
+ case SystemZ::BI__builtin_s390_vcrnfs: i = 2; l = 0; u = 15; break;
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
}
@@ -4448,6 +4793,45 @@ static void CheckNonNullArguments(Sema &S,
}
}
+/// Warn if a pointer or reference argument passed to a function points to an
+/// object that is less aligned than the parameter. This can happen when
+/// creating a typedef with a lower alignment than the original type and then
+/// calling functions defined in terms of the original type.
+void Sema::CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
+ StringRef ParamName, QualType ArgTy,
+ QualType ParamTy) {
+
+ // If a function accepts a pointer or reference type
+ if (!ParamTy->isPointerType() && !ParamTy->isReferenceType())
+ return;
+
+ // If the parameter is a pointer type, get the pointee type for the
+ // argument too. If the parameter is a reference type, don't try to get
+ // the pointee type for the argument.
+ if (ParamTy->isPointerType())
+ ArgTy = ArgTy->getPointeeType();
+
+ // Remove reference or pointer
+ ParamTy = ParamTy->getPointeeType();
+
+ // Find expected alignment, and the actual alignment of the passed object.
+ // getTypeAlignInChars requires complete types
+ if (ArgTy.isNull() || ParamTy->isIncompleteType() ||
+ ArgTy->isIncompleteType() || ParamTy->isUndeducedType() ||
+ ArgTy->isUndeducedType())
+ return;
+
+ CharUnits ParamAlign = Context.getTypeAlignInChars(ParamTy);
+ CharUnits ArgAlign = Context.getTypeAlignInChars(ArgTy);
+
+ // If the argument is less aligned than the parameter, there is a
+ // potential alignment issue.
+ if (ArgAlign < ParamAlign)
+ Diag(Loc, diag::warn_param_mismatched_alignment)
+ << (int)ArgAlign.getQuantity() << (int)ParamAlign.getQuantity()
+ << ParamName << FDecl;
+}
+
/// Handles the checks for format strings, non-POD arguments to vararg
/// functions, NULL arguments passed to non-NULL parameters, and diagnose_if
/// attributes.
@@ -4502,6 +4886,31 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
}
}
+ // Check that passed arguments match the alignment of original arguments.
+ // Try to get the missing prototype from the declaration.
+ if (!Proto && FDecl) {
+ const auto *FT = FDecl->getFunctionType();
+ if (isa_and_nonnull<FunctionProtoType>(FT))
+ Proto = cast<FunctionProtoType>(FDecl->getFunctionType());
+ }
+ if (Proto) {
+ // For variadic functions, we may have more args than parameters.
+ // For some K&R functions, we may have less args than parameters.
+ const auto N = std::min<unsigned>(Proto->getNumParams(), Args.size());
+ for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
+ // Args[ArgIdx] can be null in malformed code.
+ if (const Expr *Arg = Args[ArgIdx]) {
+ if (Arg->containsErrors())
+ continue;
+
+ QualType ParamTy = Proto->getParamType(ArgIdx);
+ QualType ArgTy = Arg->getType();
+ CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1),
+ ArgTy, ParamTy);
+ }
+ }
+ }
+
if (FDecl && FDecl->hasAttr<AllocAlignAttr>()) {
auto *AA = FDecl->getAttr<AllocAlignAttr>();
const Expr *Arg = Args[AA->getParamIndex().getASTIndex()];
@@ -4526,12 +4935,17 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
/// CheckConstructorCall - Check a constructor call for correctness and safety
/// properties not enforced by the C type system.
-void Sema::CheckConstructorCall(FunctionDecl *FDecl,
+void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,
ArrayRef<const Expr *> Args,
const FunctionProtoType *Proto,
SourceLocation Loc) {
VariadicCallType CallType =
- Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
+ Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
+
+ auto *Ctor = cast<CXXConstructorDecl>(FDecl);
+ CheckArgAlignment(Loc, FDecl, "'this'", Context.getPointerType(ThisType),
+ Context.getPointerType(Ctor->getThisObjectType()));
+
checkCall(FDecl, Proto, /*ThisArg=*/nullptr, Args, /*IsMemberFunction=*/true,
Loc, SourceRange(), CallType);
}
@@ -4561,6 +4975,22 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
ImplicitThis =
cast<CXXMemberCallExpr>(TheCall)->getImplicitObjectArgument();
+ if (ImplicitThis) {
+ // ImplicitThis may or may not be a pointer, depending on whether . or -> is
+ // used.
+ QualType ThisType = ImplicitThis->getType();
+ if (!ThisType->isPointerType()) {
+ assert(!ThisType->isReferenceType());
+ ThisType = Context.getPointerType(ThisType);
+ }
+
+ QualType ThisTypeFromDecl =
+ Context.getPointerType(cast<CXXMethodDecl>(FDecl)->getThisObjectType());
+
+ CheckArgAlignment(TheCall->getRParenLoc(), FDecl, "'this'", ThisType,
+ ThisTypeFromDecl);
+ }
+
checkCall(FDecl, Proto, ImplicitThis, llvm::makeArrayRef(Args, NumArgs),
IsMemberFunction, TheCall->getRParenLoc(),
TheCall->getCallee()->getSourceRange(), CallType);
@@ -4794,7 +5224,8 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
case AtomicExpr::AO__atomic_add_fetch:
case AtomicExpr::AO__atomic_sub_fetch:
IsAddSub = true;
- LLVM_FALLTHROUGH;
+ Form = Arithmetic;
+ break;
case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__c11_atomic_fetch_xor:
@@ -4809,6 +5240,8 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
case AtomicExpr::AO__atomic_or_fetch:
case AtomicExpr::AO__atomic_xor_fetch:
case AtomicExpr::AO__atomic_nand_fetch:
+ Form = Arithmetic;
+ break;
case AtomicExpr::AO__c11_atomic_fetch_min:
case AtomicExpr::AO__c11_atomic_fetch_max:
case AtomicExpr::AO__opencl_atomic_fetch_min:
@@ -4901,10 +5334,24 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
// For an arithmetic operation, the implied arithmetic must be well-formed.
if (Form == Arithmetic) {
- // gcc does not enforce these rules for GNU atomics, but we do so for sanity.
- if (IsAddSub && !ValType->isIntegerType()
- && !ValType->isPointerType()) {
- Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_atomic_int_or_ptr)
+ // gcc does not enforce these rules for GNU atomics, but we do so for
+ // sanity.
+ auto IsAllowedValueType = [&](QualType ValType) {
+ if (ValType->isIntegerType())
+ return true;
+ if (ValType->isPointerType())
+ return true;
+ if (!ValType->isFloatingType())
+ return false;
+ // LLVM Parser does not allow atomicrmw with x86_fp80 type.
+ if (ValType->isSpecificBuiltinType(BuiltinType::LongDouble) &&
+ &Context.getTargetInfo().getLongDoubleFormat() ==
+ &llvm::APFloat::x87DoubleExtended())
+ return false;
+ return true;
+ };
+ if (IsAddSub && !IsAllowedValueType(ValType)) {
+ Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_atomic_int_ptr_or_fp)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
}
@@ -5031,7 +5478,9 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
// passed by address. For the rest, GNU uses by-address and C11 uses
// by-value.
assert(Form != Load);
- if (Form == Init || (Form == Arithmetic && ValType->isIntegerType()))
+ if (Form == Arithmetic && ValType->isPointerType())
+ Ty = Context.getPointerDiffType();
+ else if (Form == Init || Form == Arithmetic)
Ty = ValType;
else if (Form == Copy || Form == Xchg) {
if (IsPassedByAddress) {
@@ -5040,9 +5489,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
ExprRange.getBegin());
}
Ty = ByValType;
- } else if (Form == Arithmetic)
- Ty = Context.getPointerDiffType();
- else {
+ } else {
Expr *ValArg = APIOrderedArgs[i];
// The value pointer is always dereferenced, a nullptr is undefined.
CheckNonNullArgument(*this, ValArg, ExprRange.getBegin());
@@ -6165,7 +6612,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
SourceLocation BuiltinLoc,
SourceLocation RParenLoc) {
- ExprValueKind VK = VK_RValue;
+ ExprValueKind VK = VK_PRValue;
ExprObjectKind OK = OK_Ordinary;
QualType DstTy = TInfo->getType();
QualType SrcTy = E->getType();
@@ -6211,6 +6658,29 @@ bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
return false;
}
+/// SemaBuiltinArithmeticFence - Handle __arithmetic_fence.
+bool Sema::SemaBuiltinArithmeticFence(CallExpr *TheCall) {
+ if (!Context.getTargetInfo().checkArithmeticFenceSupported())
+ return Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
+ << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
+ if (checkArgCount(*this, TheCall, 1))
+ return true;
+ Expr *Arg = TheCall->getArg(0);
+ if (Arg->isInstantiationDependent())
+ return false;
+
+ QualType ArgTy = Arg->getType();
+ if (!ArgTy->hasFloatingRepresentation())
+ return Diag(TheCall->getEndLoc(), diag::err_typecheck_expect_flt_or_vector)
+ << ArgTy;
+ if (Arg->isLValue()) {
+ ExprResult FirstArg = DefaultLvalueConversion(Arg);
+ TheCall->setArg(0, FirstArg.get());
+ }
+ TheCall->setType(TheCall->getArg(0)->getType());
+ return false;
+}
+
/// SemaBuiltinAssume - Handle __assume (MS Extension).
// __assume does not evaluate its arguments, and should warn if its argument
// has side effects.
@@ -6418,13 +6888,13 @@ bool Sema::SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum,
if (Result.getSExtValue() < Low || Result.getSExtValue() > High) {
if (RangeIsError)
return Diag(TheCall->getBeginLoc(), diag::err_argument_invalid_range)
- << Result.toString(10) << Low << High << Arg->getSourceRange();
+ << toString(Result, 10) << Low << High << Arg->getSourceRange();
else
// Defer the warning until we know if the code will be emitted so that
// dead code can ignore this.
DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
PDiag(diag::warn_argument_invalid_range)
- << Result.toString(10) << Low << High
+ << toString(Result, 10) << Low << High
<< Arg->getSourceRange());
}
@@ -6759,18 +7229,18 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
bool ValidString = true;
if (IsARMBuiltin) {
- ValidString &= Fields[0].startswith_lower("cp") ||
- Fields[0].startswith_lower("p");
+ ValidString &= Fields[0].startswith_insensitive("cp") ||
+ Fields[0].startswith_insensitive("p");
if (ValidString)
- Fields[0] =
- Fields[0].drop_front(Fields[0].startswith_lower("cp") ? 2 : 1);
+ Fields[0] = Fields[0].drop_front(
+ Fields[0].startswith_insensitive("cp") ? 2 : 1);
- ValidString &= Fields[2].startswith_lower("c");
+ ValidString &= Fields[2].startswith_insensitive("c");
if (ValidString)
Fields[2] = Fields[2].drop_front(1);
if (FiveFields) {
- ValidString &= Fields[3].startswith_lower("c");
+ ValidString &= Fields[3].startswith_insensitive("c");
if (ValidString)
Fields[3] = Fields[3].drop_front(1);
}
@@ -8630,8 +9100,11 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
} else if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E)) {
// Special case for 'a', which has type 'int' in C.
// Note, however, that we do /not/ want to treat multibyte constants like
- // 'MooV' as characters! This form is deprecated but still exists.
- if (ExprTy == S.Context.IntTy)
+ // 'MooV' as characters! This form is deprecated but still exists. In
+ // addition, don't treat expressions as of type 'char' if one byte length
+ // modifier is provided.
+ if (ExprTy == S.Context.IntTy &&
+ FS.getLengthModifier().getKind() != LengthModifier::AsChar)
if (llvm::isUIntN(S.Context.getCharWidth(), CL->getValue()))
ExprTy = S.Context.CharTy;
}
@@ -10250,64 +10723,116 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
namespace {
void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
- const UnaryOperator *UnaryExpr,
- const VarDecl *Var) {
- StorageClass Class = Var->getStorageClass();
- if (Class == StorageClass::SC_Extern ||
- Class == StorageClass::SC_PrivateExtern ||
- Var->getType()->isReferenceType())
- return;
-
- S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
- << CalleeName << Var;
-}
-
-void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
const UnaryOperator *UnaryExpr, const Decl *D) {
- if (const auto *Field = dyn_cast<FieldDecl>(D))
+ if (isa<FieldDecl, FunctionDecl, VarDecl>(D)) {
S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
- << CalleeName << Field;
+ << CalleeName << 0 /*object: */ << cast<NamedDecl>(D);
+ return;
+ }
}
void CheckFreeArgumentsAddressof(Sema &S, const std::string &CalleeName,
const UnaryOperator *UnaryExpr) {
- if (UnaryExpr->getOpcode() != UnaryOperator::Opcode::UO_AddrOf)
- return;
-
- if (const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr()))
- if (const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl()))
- return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, Var);
+ if (const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr())) {
+ const Decl *D = Lvalue->getDecl();
+ if (isa<DeclaratorDecl>(D))
+ if (!dyn_cast<DeclaratorDecl>(D)->getType()->isReferenceType())
+ return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
+ }
if (const auto *Lvalue = dyn_cast<MemberExpr>(UnaryExpr->getSubExpr()))
return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr,
Lvalue->getMemberDecl());
}
-void CheckFreeArgumentsStackArray(Sema &S, const std::string &CalleeName,
- const DeclRefExpr *Lvalue) {
- if (!Lvalue->getType()->isArrayType())
+void CheckFreeArgumentsPlus(Sema &S, const std::string &CalleeName,
+ const UnaryOperator *UnaryExpr) {
+ const auto *Lambda = dyn_cast<LambdaExpr>(
+ UnaryExpr->getSubExpr()->IgnoreImplicitAsWritten()->IgnoreParens());
+ if (!Lambda)
return;
+ S.Diag(Lambda->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << 2 /*object: lambda expression*/;
+}
+
+void CheckFreeArgumentsStackArray(Sema &S, const std::string &CalleeName,
+ const DeclRefExpr *Lvalue) {
const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl());
if (Var == nullptr)
return;
S.Diag(Lvalue->getBeginLoc(), diag::warn_free_nonheap_object)
- << CalleeName << Var;
+ << CalleeName << 0 /*object: */ << Var;
+}
+
+void CheckFreeArgumentsCast(Sema &S, const std::string &CalleeName,
+ const CastExpr *Cast) {
+ SmallString<128> SizeString;
+ llvm::raw_svector_ostream OS(SizeString);
+
+ clang::CastKind Kind = Cast->getCastKind();
+ if (Kind == clang::CK_BitCast &&
+ !Cast->getSubExpr()->getType()->isFunctionPointerType())
+ return;
+ if (Kind == clang::CK_IntegralToPointer &&
+ !isa<IntegerLiteral>(
+ Cast->getSubExpr()->IgnoreParenImpCasts()->IgnoreParens()))
+ return;
+
+ switch (Cast->getCastKind()) {
+ case clang::CK_BitCast:
+ case clang::CK_IntegralToPointer:
+ case clang::CK_FunctionToPointerDecay:
+ OS << '\'';
+ Cast->printPretty(OS, nullptr, S.getPrintingPolicy());
+ OS << '\'';
+ break;
+ default:
+ return;
+ }
+
+ S.Diag(Cast->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << 0 /*object: */ << OS.str();
}
} // namespace
/// Alerts the user that they are attempting to free a non-malloc'd object.
void Sema::CheckFreeArguments(const CallExpr *E) {
- const Expr *Arg = E->getArg(0)->IgnoreParenCasts();
const std::string CalleeName =
dyn_cast<FunctionDecl>(E->getCalleeDecl())->getQualifiedNameAsString();
- if (const auto *UnaryExpr = dyn_cast<UnaryOperator>(Arg))
- return CheckFreeArgumentsAddressof(*this, CalleeName, UnaryExpr);
+ { // Prefer something that doesn't involve a cast to make things simpler.
+ const Expr *Arg = E->getArg(0)->IgnoreParenCasts();
+ if (const auto *UnaryExpr = dyn_cast<UnaryOperator>(Arg))
+ switch (UnaryExpr->getOpcode()) {
+ case UnaryOperator::Opcode::UO_AddrOf:
+ return CheckFreeArgumentsAddressof(*this, CalleeName, UnaryExpr);
+ case UnaryOperator::Opcode::UO_Plus:
+ return CheckFreeArgumentsPlus(*this, CalleeName, UnaryExpr);
+ default:
+ break;
+ }
+
+ if (const auto *Lvalue = dyn_cast<DeclRefExpr>(Arg))
+ if (Lvalue->getType()->isArrayType())
+ return CheckFreeArgumentsStackArray(*this, CalleeName, Lvalue);
+
+ if (const auto *Label = dyn_cast<AddrLabelExpr>(Arg)) {
+ Diag(Label->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << 0 /*object: */ << Label->getLabel()->getIdentifier();
+ return;
+ }
- if (const auto *Lvalue = dyn_cast<DeclRefExpr>(Arg))
- return CheckFreeArgumentsStackArray(*this, CalleeName, Lvalue);
+ if (isa<BlockExpr>(Arg)) {
+ Diag(Arg->getBeginLoc(), diag::warn_free_nonheap_object)
+ << CalleeName << 1 /*object: block*/;
+ return;
+ }
+ }
+ // Maybe the cast was important, check after the other cases.
+ if (const auto *Cast = dyn_cast<CastExpr>(E->getArg(0)))
+ return CheckFreeArgumentsCast(*this, CalleeName, Cast);
}
void
@@ -11225,11 +11750,14 @@ static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E,
<< OtherIsBooleanDespiteType << *Result
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
} else {
- unsigned Diag = (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
- ? (HasEnumType(OriginalOther)
- ? diag::warn_unsigned_enum_always_true_comparison
- : diag::warn_unsigned_always_true_comparison)
- : diag::warn_tautological_constant_compare;
+ bool IsCharTy = OtherT.withoutLocalFastQualifiers() == S.Context.CharTy;
+ unsigned Diag =
+ (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
+ ? (HasEnumType(OriginalOther)
+ ? diag::warn_unsigned_enum_always_true_comparison
+ : IsCharTy ? diag::warn_unsigned_char_always_true_comparison
+ : diag::warn_unsigned_always_true_comparison)
+ : diag::warn_tautological_constant_compare;
S.Diag(E->getOperatorLoc(), Diag)
<< RhsConstant << OtherT << E->getOpcodeStr() << OS.str() << *Result
@@ -11484,8 +12012,8 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
if (FieldWidth == 1 && Value == 1)
return false;
- std::string PrettyValue = Value.toString(10);
- std::string PrettyTrunc = TruncatedValue.toString(10);
+ std::string PrettyValue = toString(Value, 10);
+ std::string PrettyTrunc = toString(TruncatedValue, 10);
S.Diag(InitLoc, diag::warn_impcast_bitfield_precision_constant)
<< PrettyValue << PrettyTrunc << OriginalInit->getType()
@@ -11721,7 +12249,7 @@ static std::string PrettyPrintInRange(const llvm::APSInt &Value,
llvm::APSInt ValueInRange = Value;
ValueInRange.setIsSigned(!Range.NonNegative);
ValueInRange = ValueInRange.trunc(Range.Width);
- return ValueInRange.toString(10);
+ return toString(ValueInRange, 10);
}
static bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) {
@@ -12037,7 +12565,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
adornObjCBoolConversionDiagWithTernaryFixit(
S, E,
S.Diag(CC, diag::warn_impcast_constant_value_to_objc_bool)
- << Result.Val.getInt().toString(10));
+ << toString(Result.Val.getInt(), 10));
}
return;
}
@@ -12052,6 +12580,13 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
// Strip vector types.
if (isa<VectorType>(Source)) {
+ if (Target->isVLSTBuiltinType() &&
+ (S.Context.areCompatibleSveTypes(QualType(Target, 0),
+ QualType(Source, 0)) ||
+ S.Context.areLaxCompatibleSveTypes(QualType(Target, 0),
+ QualType(Source, 0))))
+ return;
+
if (!isa<VectorType>(Target)) {
if (S.SourceMgr.isInSystemMacro(CC))
return;
@@ -12212,7 +12747,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (Overflowed) {
S.DiagRuntimeBehavior(E->getExprLoc(), E,
S.PDiag(diag::warn_impcast_fixed_point_range)
- << Value.toString(/*Radix=*/10) << T
+ << toString(Value, /*Radix=*/10) << T
<< E->getSourceRange()
<< clang::SourceRange(CC));
return;
@@ -12252,7 +12787,8 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
llvm::APFloat::rmNearestTiesToEven);
if (ConversionStatus != llvm::APFloat::opOK) {
- std::string PrettySourceValue = SourceInt->toString(10);
+ SmallString<32> PrettySourceValue;
+ SourceInt->toString(PrettySourceValue, 10);
SmallString<32> PrettyTargetValue;
TargetFloatValue.toString(PrettyTargetValue, TargetPrecision);
@@ -12311,7 +12847,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
if (S.SourceMgr.isInSystemMacro(CC))
return;
- std::string PrettySourceValue = Value.toString(10);
+ std::string PrettySourceValue = toString(Value, 10);
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
S.DiagRuntimeBehavior(
@@ -12357,7 +12893,7 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
!S.SourceMgr.isInSystemMacro(CC)) {
llvm::APSInt Value = Result.Val.getInt();
if (isSameWidthConstantConversion(S, E, T, CC)) {
- std::string PrettySourceValue = Value.toString(10);
+ std::string PrettySourceValue = toString(Value, 10);
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
S.DiagRuntimeBehavior(
@@ -14043,7 +14579,8 @@ static getBaseAlignmentAndOffsetFromLValue(const Expr *E, ASTContext &Ctx) {
case Stmt::MemberExprClass: {
auto *ME = cast<MemberExpr>(E);
auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
- if (!FD || FD->getType()->isReferenceType())
+ if (!FD || FD->getType()->isReferenceType() ||
+ FD->getParent()->isInvalidDecl())
break;
Optional<std::pair<CharUnits, CharUnits>> P;
if (ME->isArrow())
@@ -14267,11 +14804,11 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const ConstantArrayType *ArrayTy =
Context.getAsConstantArrayType(BaseExpr->getType());
- if (!ArrayTy)
- return;
-
- const Type *BaseType = ArrayTy->getElementType().getTypePtr();
- if (EffectiveType->isDependentType() || BaseType->isDependentType())
+ const Type *BaseType =
+ ArrayTy == nullptr ? nullptr : ArrayTy->getElementType().getTypePtr();
+ bool IsUnboundedArray = (BaseType == nullptr);
+ if (EffectiveType->isDependentType() ||
+ (!IsUnboundedArray && BaseType->isDependentType()))
return;
Expr::EvalResult Result;
@@ -14279,8 +14816,10 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
return;
llvm::APSInt index = Result.Val.getInt();
- if (IndexNegated)
+ if (IndexNegated) {
+ index.setIsUnsigned(false);
index = -index;
+ }
const NamedDecl *ND = nullptr;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
@@ -14288,6 +14827,74 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = ME->getMemberDecl();
+ if (IsUnboundedArray) {
+ if (index.isUnsigned() || !index.isNegative()) {
+ const auto &ASTC = getASTContext();
+ unsigned AddrBits =
+ ASTC.getTargetInfo().getPointerWidth(ASTC.getTargetAddressSpace(
+ EffectiveType->getCanonicalTypeInternal()));
+ if (index.getBitWidth() < AddrBits)
+ index = index.zext(AddrBits);
+ Optional<CharUnits> ElemCharUnits =
+ ASTC.getTypeSizeInCharsIfKnown(EffectiveType);
+ // PR50741 - If EffectiveType has unknown size (e.g., if it's a void
+ // pointer) bounds-checking isn't meaningful.
+ if (!ElemCharUnits)
+ return;
+ llvm::APInt ElemBytes(index.getBitWidth(), ElemCharUnits->getQuantity());
+ // If index has more active bits than address space, we already know
+ // we have a bounds violation to warn about. Otherwise, compute
+ // address of (index + 1)th element, and warn about bounds violation
+ // only if that address exceeds address space.
+ if (index.getActiveBits() <= AddrBits) {
+ bool Overflow;
+ llvm::APInt Product(index);
+ Product += 1;
+ Product = Product.umul_ov(ElemBytes, Overflow);
+ if (!Overflow && Product.getActiveBits() <= AddrBits)
+ return;
+ }
+
+ // Need to compute max possible elements in address space, since that
+ // is included in diag message.
+ llvm::APInt MaxElems = llvm::APInt::getMaxValue(AddrBits);
+ MaxElems = MaxElems.zext(std::max(AddrBits + 1, ElemBytes.getBitWidth()));
+ MaxElems += 1;
+ ElemBytes = ElemBytes.zextOrTrunc(MaxElems.getBitWidth());
+ MaxElems = MaxElems.udiv(ElemBytes);
+
+ unsigned DiagID =
+ ASE ? diag::warn_array_index_exceeds_max_addressable_bounds
+ : diag::warn_ptr_arith_exceeds_max_addressable_bounds;
+
+ // Diag message shows element size in bits and in "bytes" (platform-
+ // dependent CharUnits)
+ DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
+ PDiag(DiagID)
+ << toString(index, 10, true) << AddrBits
+ << (unsigned)ASTC.toBits(*ElemCharUnits)
+ << toString(ElemBytes, 10, false)
+ << toString(MaxElems, 10, false)
+ << (unsigned)MaxElems.getLimitedValue(~0U)
+ << IndexExpr->getSourceRange());
+
+ if (!ND) {
+ // Try harder to find a NamedDecl to point at in the note.
+ while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
+ BaseExpr = ASE->getBase()->IgnoreParenCasts();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
+ ND = DRE->getDecl();
+ if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
+ ND = ME->getMemberDecl();
+ }
+
+ if (ND)
+ DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr,
+ PDiag(diag::note_array_declared_here) << ND);
+ }
+ return;
+ }
+
if (index.isUnsigned() || !index.isNegative()) {
// It is possible that the type of the base expression after
// IgnoreParenCasts is incomplete, even though the type of the base
@@ -14350,13 +14957,12 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
}
}
- unsigned DiagID = diag::warn_ptr_arith_exceeds_bounds;
- if (ASE)
- DiagID = diag::warn_array_index_exceeds_bounds;
+ unsigned DiagID = ASE ? diag::warn_array_index_exceeds_bounds
+ : diag::warn_ptr_arith_exceeds_bounds;
DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
- PDiag(DiagID) << index.toString(10, true)
- << size.toString(10, true)
+ PDiag(DiagID) << toString(index, 10, true)
+ << toString(size, 10, true)
<< (unsigned)size.getLimitedValue(~0U)
<< IndexExpr->getSourceRange());
} else {
@@ -14367,18 +14973,17 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
}
DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
- PDiag(DiagID) << index.toString(10, true)
+ PDiag(DiagID) << toString(index, 10, true)
<< IndexExpr->getSourceRange());
}
if (!ND) {
// Try harder to find a NamedDecl to point at in the note.
- while (const ArraySubscriptExpr *ASE =
- dyn_cast<ArraySubscriptExpr>(BaseExpr))
+ while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
BaseExpr = ASE->getBase()->IgnoreParenCasts();
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
ND = DRE->getDecl();
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr))
+ if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
ND = ME->getMemberDecl();
}