summaryrefslogtreecommitdiff
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.cpp850
1 files changed, 599 insertions, 251 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index de75c10417e7..6ffd2096cbc5 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -408,6 +408,64 @@ static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) {
namespace {
+class ScanfDiagnosticFormatHandler
+ : public analyze_format_string::FormatStringHandler {
+ // Accepts the argument index (relative to the first destination index) of the
+ // argument whose size we want.
+ using ComputeSizeFunction =
+ llvm::function_ref<Optional<llvm::APSInt>(unsigned)>;
+
+ // Accepts the argument index (relative to the first destination index), the
+ // destination size, and the source size).
+ using DiagnoseFunction =
+ llvm::function_ref<void(unsigned, unsigned, unsigned)>;
+
+ ComputeSizeFunction ComputeSizeArgument;
+ DiagnoseFunction Diagnose;
+
+public:
+ ScanfDiagnosticFormatHandler(ComputeSizeFunction ComputeSizeArgument,
+ DiagnoseFunction Diagnose)
+ : ComputeSizeArgument(ComputeSizeArgument), Diagnose(Diagnose) {}
+
+ bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
+ const char *StartSpecifier,
+ unsigned specifierLen) override {
+ if (!FS.consumesDataArgument())
+ return true;
+
+ unsigned NulByte = 0;
+ switch ((FS.getConversionSpecifier().getKind())) {
+ default:
+ return true;
+ case analyze_format_string::ConversionSpecifier::sArg:
+ case analyze_format_string::ConversionSpecifier::ScanListArg:
+ NulByte = 1;
+ break;
+ case analyze_format_string::ConversionSpecifier::cArg:
+ break;
+ }
+
+ auto OptionalFW = FS.getFieldWidth();
+ if (OptionalFW.getHowSpecified() !=
+ analyze_format_string::OptionalAmount::HowSpecified::Constant)
+ return true;
+
+ unsigned SourceSize = OptionalFW.getConstantAmount() + NulByte;
+
+ auto DestSizeAPS = ComputeSizeArgument(FS.getArgIndex());
+ if (!DestSizeAPS)
+ return true;
+
+ unsigned DestSize = DestSizeAPS->getZExtValue();
+
+ if (DestSize < SourceSize)
+ Diagnose(FS.getArgIndex(), DestSize, SourceSize);
+
+ return true;
+ }
+};
+
class EstimateSizeFormatHandler
: public analyze_format_string::FormatStringHandler {
size_t Size;
@@ -588,14 +646,8 @@ private:
} // namespace
-/// Check a call to BuiltinID for buffer overflows. If BuiltinID is a
-/// __builtin_*_chk function, then use the object size argument specified in the
-/// source. Otherwise, infer the object size using __builtin_object_size.
void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
CallExpr *TheCall) {
- // FIXME: There are some more useful checks we could be doing here:
- // - Evaluate strlen of strcpy arguments, use as object size.
-
if (TheCall->isValueDependent() || TheCall->isTypeDependent() ||
isConstantEvaluated())
return;
@@ -607,13 +659,138 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
const TargetInfo &TI = getASTContext().getTargetInfo();
unsigned SizeTypeWidth = TI.getTypeWidth(TI.getSizeType());
+ auto ComputeExplicitObjectSizeArgument =
+ [&](unsigned Index) -> Optional<llvm::APSInt> {
+ Expr::EvalResult Result;
+ Expr *SizeArg = TheCall->getArg(Index);
+ if (!SizeArg->EvaluateAsInt(Result, getASTContext()))
+ return llvm::None;
+ return Result.Val.getInt();
+ };
+
+ auto ComputeSizeArgument = [&](unsigned Index) -> Optional<llvm::APSInt> {
+ // If the parameter has a pass_object_size attribute, then we should use its
+ // (potentially) more strict checking mode. Otherwise, conservatively assume
+ // type 0.
+ int BOSType = 0;
+ // This check can fail for variadic functions.
+ if (Index < FD->getNumParams()) {
+ if (const auto *POS =
+ FD->getParamDecl(Index)->getAttr<PassObjectSizeAttr>())
+ BOSType = POS->getType();
+ }
+
+ const Expr *ObjArg = TheCall->getArg(Index);
+ uint64_t Result;
+ if (!ObjArg->tryEvaluateObjectSize(Result, getASTContext(), BOSType))
+ return llvm::None;
+
+ // Get the object size in the target's size_t width.
+ return llvm::APSInt::getUnsigned(Result).extOrTrunc(SizeTypeWidth);
+ };
+
+ auto ComputeStrLenArgument = [&](unsigned Index) -> Optional<llvm::APSInt> {
+ Expr *ObjArg = TheCall->getArg(Index);
+ uint64_t Result;
+ if (!ObjArg->tryEvaluateStrLen(Result, getASTContext()))
+ return llvm::None;
+ // Add 1 for null byte.
+ return llvm::APSInt::getUnsigned(Result + 1).extOrTrunc(SizeTypeWidth);
+ };
+
+ Optional<llvm::APSInt> SourceSize;
+ Optional<llvm::APSInt> DestinationSize;
unsigned DiagID = 0;
bool IsChkVariant = false;
- Optional<llvm::APSInt> UsedSize;
- unsigned SizeIndex, ObjectIndex;
+
+ auto GetFunctionName = [&]() {
+ StringRef FunctionName = getASTContext().BuiltinInfo.getName(BuiltinID);
+ // Skim off the details of whichever builtin was called to produce a better
+ // diagnostic, as it's unlikely that the user wrote the __builtin
+ // explicitly.
+ if (IsChkVariant) {
+ FunctionName = FunctionName.drop_front(std::strlen("__builtin___"));
+ FunctionName = FunctionName.drop_back(std::strlen("_chk"));
+ } else if (FunctionName.startswith("__builtin_")) {
+ FunctionName = FunctionName.drop_front(std::strlen("__builtin_"));
+ }
+ return FunctionName;
+ };
+
switch (BuiltinID) {
default:
return;
+ case Builtin::BI__builtin_strcpy:
+ case Builtin::BIstrcpy: {
+ DiagID = diag::warn_fortify_strlen_overflow;
+ SourceSize = ComputeStrLenArgument(1);
+ DestinationSize = ComputeSizeArgument(0);
+ break;
+ }
+
+ case Builtin::BI__builtin___strcpy_chk: {
+ DiagID = diag::warn_fortify_strlen_overflow;
+ SourceSize = ComputeStrLenArgument(1);
+ DestinationSize = ComputeExplicitObjectSizeArgument(2);
+ IsChkVariant = true;
+ break;
+ }
+
+ case Builtin::BIscanf:
+ case Builtin::BIfscanf:
+ case Builtin::BIsscanf: {
+ unsigned FormatIndex = 1;
+ unsigned DataIndex = 2;
+ if (BuiltinID == Builtin::BIscanf) {
+ FormatIndex = 0;
+ DataIndex = 1;
+ }
+
+ const auto *FormatExpr =
+ TheCall->getArg(FormatIndex)->IgnoreParenImpCasts();
+
+ const auto *Format = dyn_cast<StringLiteral>(FormatExpr);
+ if (!Format)
+ return;
+
+ if (!Format->isAscii() && !Format->isUTF8())
+ return;
+
+ auto Diagnose = [&](unsigned ArgIndex, unsigned DestSize,
+ unsigned SourceSize) {
+ DiagID = diag::warn_fortify_scanf_overflow;
+ unsigned Index = ArgIndex + DataIndex;
+ StringRef FunctionName = GetFunctionName();
+ DiagRuntimeBehavior(TheCall->getArg(Index)->getBeginLoc(), TheCall,
+ PDiag(DiagID) << FunctionName << (Index + 1)
+ << DestSize << SourceSize);
+ };
+
+ StringRef FormatStrRef = Format->getString();
+ auto ShiftedComputeSizeArgument = [&](unsigned Index) {
+ return ComputeSizeArgument(Index + DataIndex);
+ };
+ ScanfDiagnosticFormatHandler H(ShiftedComputeSizeArgument, Diagnose);
+ const char *FormatBytes = FormatStrRef.data();
+ const ConstantArrayType *T =
+ Context.getAsConstantArrayType(Format->getType());
+ assert(T && "String literal not of constant array type!");
+ size_t TypeSize = T->getSize().getZExtValue();
+
+ // In case there's a null byte somewhere.
+ size_t StrLen =
+ std::min(std::max(TypeSize, size_t(1)) - 1, FormatStrRef.find(0));
+
+ analyze_format_string::ParseScanfString(H, FormatBytes,
+ FormatBytes + StrLen, getLangOpts(),
+ Context.getTargetInfo());
+
+ // Unlike the other cases, in this one we have already issued the diagnostic
+ // here, so no need to continue (because unlike the other cases, here the
+ // diagnostic refers to the argument number).
+ return;
+ }
+
case Builtin::BIsprintf:
case Builtin::BI__builtin___sprintf_chk: {
size_t FormatIndex = BuiltinID == Builtin::BIsprintf ? 1 : 3;
@@ -639,14 +816,13 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
H, FormatBytes, FormatBytes + StrLen, getLangOpts(),
Context.getTargetInfo(), false)) {
DiagID = diag::warn_fortify_source_format_overflow;
- UsedSize = llvm::APSInt::getUnsigned(H.getSizeLowerBound())
- .extOrTrunc(SizeTypeWidth);
+ SourceSize = llvm::APSInt::getUnsigned(H.getSizeLowerBound())
+ .extOrTrunc(SizeTypeWidth);
if (BuiltinID == Builtin::BI__builtin___sprintf_chk) {
+ DestinationSize = ComputeExplicitObjectSizeArgument(2);
IsChkVariant = true;
- ObjectIndex = 2;
} else {
- IsChkVariant = false;
- ObjectIndex = 0;
+ DestinationSize = ComputeSizeArgument(0);
}
break;
}
@@ -664,18 +840,19 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
case Builtin::BI__builtin___memccpy_chk:
case Builtin::BI__builtin___mempcpy_chk: {
DiagID = diag::warn_builtin_chk_overflow;
+ SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 2);
+ DestinationSize =
+ ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
IsChkVariant = true;
- SizeIndex = TheCall->getNumArgs() - 2;
- ObjectIndex = TheCall->getNumArgs() - 1;
break;
}
case Builtin::BI__builtin___snprintf_chk:
case Builtin::BI__builtin___vsnprintf_chk: {
DiagID = diag::warn_builtin_chk_overflow;
+ SourceSize = ComputeExplicitObjectSizeArgument(1);
+ DestinationSize = ComputeExplicitObjectSizeArgument(3);
IsChkVariant = true;
- SizeIndex = 1;
- ObjectIndex = 3;
break;
}
@@ -691,8 +868,8 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
// size larger than the destination buffer though; this is a runtime abort
// in _FORTIFY_SOURCE mode, and is quite suspicious otherwise.
DiagID = diag::warn_fortify_source_size_mismatch;
- SizeIndex = TheCall->getNumArgs() - 1;
- ObjectIndex = 0;
+ SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
+ DestinationSize = ComputeSizeArgument(0);
break;
}
@@ -705,8 +882,8 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
case Builtin::BImempcpy:
case Builtin::BI__builtin_mempcpy: {
DiagID = diag::warn_fortify_source_overflow;
- SizeIndex = TheCall->getNumArgs() - 1;
- ObjectIndex = 0;
+ SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
+ DestinationSize = ComputeSizeArgument(0);
break;
}
case Builtin::BIsnprintf:
@@ -714,66 +891,25 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
case Builtin::BIvsnprintf:
case Builtin::BI__builtin_vsnprintf: {
DiagID = diag::warn_fortify_source_size_mismatch;
- SizeIndex = 1;
- ObjectIndex = 0;
+ SourceSize = ComputeExplicitObjectSizeArgument(1);
+ DestinationSize = ComputeSizeArgument(0);
break;
}
}
- llvm::APSInt ObjectSize;
- // For __builtin___*_chk, the object size is explicitly provided by the caller
- // (usually using __builtin_object_size). Use that value to check this call.
- if (IsChkVariant) {
- Expr::EvalResult Result;
- Expr *SizeArg = TheCall->getArg(ObjectIndex);
- if (!SizeArg->EvaluateAsInt(Result, getASTContext()))
- return;
- ObjectSize = Result.Val.getInt();
-
- // Otherwise, try to evaluate an imaginary call to __builtin_object_size.
- } else {
- // If the parameter has a pass_object_size attribute, then we should use its
- // (potentially) more strict checking mode. Otherwise, conservatively assume
- // type 0.
- int BOSType = 0;
- if (const auto *POS =
- FD->getParamDecl(ObjectIndex)->getAttr<PassObjectSizeAttr>())
- BOSType = POS->getType();
-
- Expr *ObjArg = TheCall->getArg(ObjectIndex);
- uint64_t Result;
- if (!ObjArg->tryEvaluateObjectSize(Result, getASTContext(), BOSType))
- return;
- // Get the object size in the target's size_t width.
- ObjectSize = llvm::APSInt::getUnsigned(Result).extOrTrunc(SizeTypeWidth);
- }
-
- // Evaluate the number of bytes of the object that this call will use.
- if (!UsedSize) {
- Expr::EvalResult Result;
- Expr *UsedSizeArg = TheCall->getArg(SizeIndex);
- if (!UsedSizeArg->EvaluateAsInt(Result, getASTContext()))
- return;
- UsedSize = Result.Val.getInt().extOrTrunc(SizeTypeWidth);
- }
-
- if (UsedSize.getValue().ule(ObjectSize))
+ if (!SourceSize || !DestinationSize ||
+ SourceSize.getValue().ule(DestinationSize.getValue()))
return;
- StringRef FunctionName = getASTContext().BuiltinInfo.getName(BuiltinID);
- // Skim off the details of whichever builtin was called to produce a better
- // diagnostic, as it's unlikley that the user wrote the __builtin explicitly.
- if (IsChkVariant) {
- FunctionName = FunctionName.drop_front(std::strlen("__builtin___"));
- FunctionName = FunctionName.drop_back(std::strlen("_chk"));
- } else if (FunctionName.startswith("__builtin_")) {
- FunctionName = FunctionName.drop_front(std::strlen("__builtin_"));
- }
+ StringRef FunctionName = GetFunctionName();
+ SmallString<16> DestinationStr;
+ SmallString<16> SourceStr;
+ DestinationSize->toString(DestinationStr, /*Radix=*/10);
+ SourceSize->toString(SourceStr, /*Radix=*/10);
DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
PDiag(DiagID)
- << FunctionName << toString(ObjectSize, /*Radix=*/10)
- << toString(UsedSize.getValue(), /*Radix=*/10));
+ << FunctionName << DestinationStr << SourceStr);
}
static bool SemaBuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall,
@@ -1715,7 +1851,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
// value so we bail out.
if (SizeOp->isValueDependent())
break;
- if (!SizeOp->EvaluateKnownConstInt(Context).isNullValue()) {
+ if (!SizeOp->EvaluateKnownConstInt(Context).isZero()) {
CheckNonNullArgument(*this, TheCall->getArg(0), TheCall->getExprLoc());
CheckNonNullArgument(*this, TheCall->getArg(1), TheCall->getExprLoc());
}
@@ -1962,6 +2098,20 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
break;
}
+ case Builtin::BI__builtin_elementwise_abs:
+ if (SemaBuiltinElementwiseMathOneArg(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_elementwise_min:
+ case Builtin::BI__builtin_elementwise_max:
+ if (SemaBuiltinElementwiseMath(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_reduce_max:
+ case Builtin::BI__builtin_reduce_min:
+ if (SemaBuiltinReduceMath(TheCall))
+ return ExprError();
+ break;
case Builtin::BI__builtin_matrix_transpose:
return SemaBuiltinMatrixTranspose(TheCall, TheCallResult);
@@ -2591,8 +2741,8 @@ static bool isValidBPFPreserveFieldInfoArg(Expr *Arg) {
// to BPF backend to check whether the access is a
// field access or not.
return (Arg->IgnoreParens()->getObjectKind() == OK_BitField ||
- dyn_cast<MemberExpr>(Arg->IgnoreParens()) ||
- dyn_cast<ArraySubscriptExpr>(Arg->IgnoreParens()));
+ isa<MemberExpr>(Arg->IgnoreParens()) ||
+ isa<ArraySubscriptExpr>(Arg->IgnoreParens()));
}
static bool isEltOfVectorTy(ASTContext &Context, CallExpr *Call, Sema &S,
@@ -2616,8 +2766,8 @@ static bool isValidBPFPreserveTypeInfoArg(Expr *Arg) {
// 1. __builtin_preserve_type_info(*(<type> *)0, flag);
// 2. <type> var;
// __builtin_preserve_type_info(var, flag);
- if (!dyn_cast<DeclRefExpr>(Arg->IgnoreParens()) &&
- !dyn_cast<UnaryOperator>(Arg->IgnoreParens()))
+ if (!isa<DeclRefExpr>(Arg->IgnoreParens()) &&
+ !isa<UnaryOperator>(Arg->IgnoreParens()))
return false;
// Typedef type.
@@ -2674,12 +2824,7 @@ static bool isValidBPFPreserveEnumValueArg(Expr *Arg) {
return false;
// The enum value must be supported.
- for (auto *EDI : ET->getDecl()->enumerators()) {
- if (EDI == Enumerator)
- return true;
- }
-
- return false;
+ return llvm::is_contained(ET->getDecl()->enumerators(), Enumerator);
}
bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID,
@@ -2974,8 +3119,8 @@ bool Sema::CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall) {
unsigned M = 1 << A.Align;
Min *= M;
Max *= M;
- Error |= SemaBuiltinConstantArgRange(TheCall, A.OpNum, Min, Max) |
- SemaBuiltinConstantArgMultiple(TheCall, A.OpNum, M);
+ Error |= SemaBuiltinConstantArgRange(TheCall, A.OpNum, Min, Max);
+ Error |= SemaBuiltinConstantArgMultiple(TheCall, A.OpNum, M);
}
}
return Error;
@@ -3280,6 +3425,14 @@ static bool isPPC_64Builtin(unsigned BuiltinID) {
case PPC::BI__builtin_ppc_store8r:
case PPC::BI__builtin_ppc_insert_exp:
case PPC::BI__builtin_ppc_extract_sig:
+ case PPC::BI__builtin_ppc_addex:
+ case PPC::BI__builtin_darn:
+ case PPC::BI__builtin_darn_raw:
+ case PPC::BI__builtin_ppc_compare_and_swaplp:
+ case PPC::BI__builtin_ppc_fetch_and_addlp:
+ case PPC::BI__builtin_ppc_fetch_and_andlp:
+ case PPC::BI__builtin_ppc_fetch_and_orlp:
+ case PPC::BI__builtin_ppc_fetch_and_swaplp:
return true;
}
return false;
@@ -3351,6 +3504,18 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case PPC::BI__builtin_tabortdci:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31) ||
SemaBuiltinConstantArgRange(TheCall, 2, 0, 31);
+ // According to GCC 'Basic PowerPC Built-in Functions Available on ISA 2.05',
+ // __builtin_(un)pack_longdouble are available only if long double uses IBM
+ // extended double representation.
+ case PPC::BI__builtin_unpack_longdouble:
+ if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 1))
+ return true;
+ LLVM_FALLTHROUGH;
+ case PPC::BI__builtin_pack_longdouble:
+ if (&TI.getLongDoubleFormat() != &llvm::APFloat::PPCDoubleDouble())
+ return Diag(TheCall->getBeginLoc(), diag::err_ppc_builtin_requires_abi)
+ << "ibmlongdouble";
+ return false;
case PPC::BI__builtin_altivec_dst:
case PPC::BI__builtin_altivec_dstt:
case PPC::BI__builtin_altivec_dstst:
@@ -3410,8 +3575,7 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
// 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);
+ return SemaValueIsRunOfOnes(TheCall, 2);
case PPC::BI__builtin_ppc_rlwimi:
case PPC::BI__builtin_ppc_rldimi:
return SemaBuiltinConstantArg(TheCall, 2, Result) ||
@@ -3421,6 +3585,19 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
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_addex: {
+ if (SemaFeatureCheck(*this, TheCall, "isa-v30-instructions",
+ diag::err_ppc_builtin_only_on_arch, "9") ||
+ SemaBuiltinConstantArgRange(TheCall, 2, 0, 3))
+ return true;
+ // Output warning for reserved values 1 to 3.
+ int ArgValue =
+ TheCall->getArg(2)->getIntegerConstantExpr(Context)->getSExtValue();
+ if (ArgValue != 0)
+ Diag(TheCall->getBeginLoc(), diag::warn_argument_undefined_behaviour)
+ << ArgValue;
+ return false;
+ }
case PPC::BI__builtin_ppc_mtfsb0:
case PPC::BI__builtin_ppc_mtfsb1:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31);
@@ -3445,9 +3622,50 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
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);
+ case PPC::BI__builtin_altivec_vcntmbb:
+ case PPC::BI__builtin_altivec_vcntmbh:
+ case PPC::BI__builtin_altivec_vcntmbw:
+ case PPC::BI__builtin_altivec_vcntmbd:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
+ case PPC::BI__builtin_darn:
+ case PPC::BI__builtin_darn_raw:
+ case PPC::BI__builtin_darn_32:
+ return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions",
+ diag::err_ppc_builtin_only_on_arch, "9");
+ case PPC::BI__builtin_vsx_xxgenpcvbm:
+ case PPC::BI__builtin_vsx_xxgenpcvhm:
+ case PPC::BI__builtin_vsx_xxgenpcvwm:
+ case PPC::BI__builtin_vsx_xxgenpcvdm:
+ return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3);
+ case PPC::BI__builtin_ppc_compare_exp_uo:
+ case PPC::BI__builtin_ppc_compare_exp_lt:
+ case PPC::BI__builtin_ppc_compare_exp_gt:
+ case PPC::BI__builtin_ppc_compare_exp_eq:
+ return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions",
+ diag::err_ppc_builtin_only_on_arch, "9") ||
+ SemaFeatureCheck(*this, TheCall, "vsx",
+ diag::err_ppc_builtin_requires_vsx);
+ case PPC::BI__builtin_ppc_test_data_class: {
+ // Check if the first argument of the __builtin_ppc_test_data_class call is
+ // valid. The argument must be either a 'float' or a 'double'.
+ QualType ArgType = TheCall->getArg(0)->getType();
+ if (ArgType != QualType(Context.FloatTy) &&
+ ArgType != QualType(Context.DoubleTy))
+ return Diag(TheCall->getBeginLoc(),
+ diag::err_ppc_invalid_test_data_class_type);
+ return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions",
+ diag::err_ppc_builtin_only_on_arch, "9") ||
+ SemaFeatureCheck(*this, TheCall, "vsx",
+ diag::err_ppc_builtin_requires_vsx) ||
+ SemaBuiltinConstantArgRange(TheCall, 1, 0, 127);
+ }
+ case PPC::BI__builtin_ppc_load8r:
+ case PPC::BI__builtin_ppc_store8r:
+ return SemaFeatureCheck(*this, TheCall, "isa-v206-instructions",
+ diag::err_ppc_builtin_only_on_arch, "7");
+#define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \
+ case PPC::BI__builtin_##Name: \
+ return SemaBuiltinPPCMMACall(TheCall, BuiltinID, Types);
#include "clang/Basic/BuiltinsPPC.def"
}
return SemaBuiltinConstantArgRange(TheCall, i, l, u);
@@ -3499,7 +3717,7 @@ bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
<< ArgExpr->getType();
auto Ord = ArgResult.Val.getInt().getZExtValue();
- // Check valididty of memory ordering as per C11 / C++11's memody model.
+ // Check validity of memory ordering as per C11 / C++11's memody model.
// Only fence needs check. Atomic dec/inc allow all memory orders.
if (!llvm::isValidAtomicOrderingCABI(Ord))
return Diag(ArgExpr->getBeginLoc(),
@@ -3586,138 +3804,12 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI,
return true;
switch (BuiltinID) {
- case RISCV::BI__builtin_rvv_vsetvli:
+ case RISCVVector::BI__builtin_rvv_vsetvli:
return SemaBuiltinConstantArgRange(TheCall, 1, 0, 3) ||
CheckRISCVLMUL(TheCall, 2);
- case RISCV::BI__builtin_rvv_vsetvlimax:
+ case RISCVVector::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;
@@ -3850,14 +3942,22 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vcvttss2si64:
case X86::BI__builtin_ia32_vcvttss2usi32:
case X86::BI__builtin_ia32_vcvttss2usi64:
+ case X86::BI__builtin_ia32_vcvttsh2si32:
+ case X86::BI__builtin_ia32_vcvttsh2si64:
+ case X86::BI__builtin_ia32_vcvttsh2usi32:
+ case X86::BI__builtin_ia32_vcvttsh2usi64:
ArgNum = 1;
break;
case X86::BI__builtin_ia32_maxpd512:
case X86::BI__builtin_ia32_maxps512:
case X86::BI__builtin_ia32_minpd512:
case X86::BI__builtin_ia32_minps512:
+ case X86::BI__builtin_ia32_maxph512:
+ case X86::BI__builtin_ia32_minph512:
ArgNum = 2;
break;
+ case X86::BI__builtin_ia32_vcvtph2pd512_mask:
+ case X86::BI__builtin_ia32_vcvtph2psx512_mask:
case X86::BI__builtin_ia32_cvtps2pd512_mask:
case X86::BI__builtin_ia32_cvttpd2dq512_mask:
case X86::BI__builtin_ia32_cvttpd2qq512_mask:
@@ -3867,16 +3967,24 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cvttps2qq512_mask:
case X86::BI__builtin_ia32_cvttps2udq512_mask:
case X86::BI__builtin_ia32_cvttps2uqq512_mask:
+ case X86::BI__builtin_ia32_vcvttph2w512_mask:
+ case X86::BI__builtin_ia32_vcvttph2uw512_mask:
+ case X86::BI__builtin_ia32_vcvttph2dq512_mask:
+ case X86::BI__builtin_ia32_vcvttph2udq512_mask:
+ case X86::BI__builtin_ia32_vcvttph2qq512_mask:
+ case X86::BI__builtin_ia32_vcvttph2uqq512_mask:
case X86::BI__builtin_ia32_exp2pd_mask:
case X86::BI__builtin_ia32_exp2ps_mask:
case X86::BI__builtin_ia32_getexppd512_mask:
case X86::BI__builtin_ia32_getexpps512_mask:
+ case X86::BI__builtin_ia32_getexpph512_mask:
case X86::BI__builtin_ia32_rcp28pd_mask:
case X86::BI__builtin_ia32_rcp28ps_mask:
case X86::BI__builtin_ia32_rsqrt28pd_mask:
case X86::BI__builtin_ia32_rsqrt28ps_mask:
case X86::BI__builtin_ia32_vcomisd:
case X86::BI__builtin_ia32_vcomiss:
+ case X86::BI__builtin_ia32_vcomish:
case X86::BI__builtin_ia32_vcvtph2ps512_mask:
ArgNum = 3;
break;
@@ -3884,21 +3992,30 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cmpps512_mask:
case X86::BI__builtin_ia32_cmpsd_mask:
case X86::BI__builtin_ia32_cmpss_mask:
+ case X86::BI__builtin_ia32_cmpsh_mask:
+ case X86::BI__builtin_ia32_vcvtsh2sd_round_mask:
+ case X86::BI__builtin_ia32_vcvtsh2ss_round_mask:
case X86::BI__builtin_ia32_cvtss2sd_round_mask:
case X86::BI__builtin_ia32_getexpsd128_round_mask:
case X86::BI__builtin_ia32_getexpss128_round_mask:
+ case X86::BI__builtin_ia32_getexpsh128_round_mask:
case X86::BI__builtin_ia32_getmantpd512_mask:
case X86::BI__builtin_ia32_getmantps512_mask:
+ case X86::BI__builtin_ia32_getmantph512_mask:
case X86::BI__builtin_ia32_maxsd_round_mask:
case X86::BI__builtin_ia32_maxss_round_mask:
+ case X86::BI__builtin_ia32_maxsh_round_mask:
case X86::BI__builtin_ia32_minsd_round_mask:
case X86::BI__builtin_ia32_minss_round_mask:
+ case X86::BI__builtin_ia32_minsh_round_mask:
case X86::BI__builtin_ia32_rcp28sd_round_mask:
case X86::BI__builtin_ia32_rcp28ss_round_mask:
case X86::BI__builtin_ia32_reducepd512_mask:
case X86::BI__builtin_ia32_reduceps512_mask:
+ case X86::BI__builtin_ia32_reduceph512_mask:
case X86::BI__builtin_ia32_rndscalepd_mask:
case X86::BI__builtin_ia32_rndscaleps_mask:
+ case X86::BI__builtin_ia32_rndscaleph_mask:
case X86::BI__builtin_ia32_rsqrt28sd_round_mask:
case X86::BI__builtin_ia32_rsqrt28ss_round_mask:
ArgNum = 4;
@@ -3913,14 +4030,17 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_fixupimmss_maskz:
case X86::BI__builtin_ia32_getmantsd_round_mask:
case X86::BI__builtin_ia32_getmantss_round_mask:
+ case X86::BI__builtin_ia32_getmantsh_round_mask:
case X86::BI__builtin_ia32_rangepd512_mask:
case X86::BI__builtin_ia32_rangeps512_mask:
case X86::BI__builtin_ia32_rangesd128_round_mask:
case X86::BI__builtin_ia32_rangess128_round_mask:
case X86::BI__builtin_ia32_reducesd_mask:
case X86::BI__builtin_ia32_reducess_mask:
+ case X86::BI__builtin_ia32_reducesh_mask:
case X86::BI__builtin_ia32_rndscalesd_round_mask:
case X86::BI__builtin_ia32_rndscaless_round_mask:
+ case X86::BI__builtin_ia32_rndscalesh_round_mask:
ArgNum = 5;
break;
case X86::BI__builtin_ia32_vcvtsd2si64:
@@ -3931,11 +4051,20 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vcvtss2si64:
case X86::BI__builtin_ia32_vcvtss2usi32:
case X86::BI__builtin_ia32_vcvtss2usi64:
+ case X86::BI__builtin_ia32_vcvtsh2si32:
+ case X86::BI__builtin_ia32_vcvtsh2si64:
+ case X86::BI__builtin_ia32_vcvtsh2usi32:
+ case X86::BI__builtin_ia32_vcvtsh2usi64:
case X86::BI__builtin_ia32_sqrtpd512:
case X86::BI__builtin_ia32_sqrtps512:
+ case X86::BI__builtin_ia32_sqrtph512:
ArgNum = 1;
HasRC = true;
break;
+ case X86::BI__builtin_ia32_addph512:
+ case X86::BI__builtin_ia32_divph512:
+ case X86::BI__builtin_ia32_mulph512:
+ case X86::BI__builtin_ia32_subph512:
case X86::BI__builtin_ia32_addpd512:
case X86::BI__builtin_ia32_addps512:
case X86::BI__builtin_ia32_divpd512:
@@ -3950,11 +4079,17 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cvtusi2sd64:
case X86::BI__builtin_ia32_cvtusi2ss32:
case X86::BI__builtin_ia32_cvtusi2ss64:
+ case X86::BI__builtin_ia32_vcvtusi2sh:
+ case X86::BI__builtin_ia32_vcvtusi642sh:
+ case X86::BI__builtin_ia32_vcvtsi2sh:
+ case X86::BI__builtin_ia32_vcvtsi642sh:
ArgNum = 2;
HasRC = true;
break;
case X86::BI__builtin_ia32_cvtdq2ps512_mask:
case X86::BI__builtin_ia32_cvtudq2ps512_mask:
+ case X86::BI__builtin_ia32_vcvtpd2ph512_mask:
+ case X86::BI__builtin_ia32_vcvtps2phx512_mask:
case X86::BI__builtin_ia32_cvtpd2ps512_mask:
case X86::BI__builtin_ia32_cvtpd2dq512_mask:
case X86::BI__builtin_ia32_cvtpd2qq512_mask:
@@ -3968,30 +4103,54 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_cvtqq2ps512_mask:
case X86::BI__builtin_ia32_cvtuqq2pd512_mask:
case X86::BI__builtin_ia32_cvtuqq2ps512_mask:
+ case X86::BI__builtin_ia32_vcvtdq2ph512_mask:
+ case X86::BI__builtin_ia32_vcvtudq2ph512_mask:
+ case X86::BI__builtin_ia32_vcvtw2ph512_mask:
+ case X86::BI__builtin_ia32_vcvtuw2ph512_mask:
+ case X86::BI__builtin_ia32_vcvtph2w512_mask:
+ case X86::BI__builtin_ia32_vcvtph2uw512_mask:
+ case X86::BI__builtin_ia32_vcvtph2dq512_mask:
+ case X86::BI__builtin_ia32_vcvtph2udq512_mask:
+ case X86::BI__builtin_ia32_vcvtph2qq512_mask:
+ case X86::BI__builtin_ia32_vcvtph2uqq512_mask:
+ case X86::BI__builtin_ia32_vcvtqq2ph512_mask:
+ case X86::BI__builtin_ia32_vcvtuqq2ph512_mask:
ArgNum = 3;
HasRC = true;
break;
+ case X86::BI__builtin_ia32_addsh_round_mask:
case X86::BI__builtin_ia32_addss_round_mask:
case X86::BI__builtin_ia32_addsd_round_mask:
+ case X86::BI__builtin_ia32_divsh_round_mask:
case X86::BI__builtin_ia32_divss_round_mask:
case X86::BI__builtin_ia32_divsd_round_mask:
+ case X86::BI__builtin_ia32_mulsh_round_mask:
case X86::BI__builtin_ia32_mulss_round_mask:
case X86::BI__builtin_ia32_mulsd_round_mask:
+ case X86::BI__builtin_ia32_subsh_round_mask:
case X86::BI__builtin_ia32_subss_round_mask:
case X86::BI__builtin_ia32_subsd_round_mask:
+ case X86::BI__builtin_ia32_scalefph512_mask:
case X86::BI__builtin_ia32_scalefpd512_mask:
case X86::BI__builtin_ia32_scalefps512_mask:
case X86::BI__builtin_ia32_scalefsd_round_mask:
case X86::BI__builtin_ia32_scalefss_round_mask:
+ case X86::BI__builtin_ia32_scalefsh_round_mask:
case X86::BI__builtin_ia32_cvtsd2ss_round_mask:
+ case X86::BI__builtin_ia32_vcvtss2sh_round_mask:
+ case X86::BI__builtin_ia32_vcvtsd2sh_round_mask:
case X86::BI__builtin_ia32_sqrtsd_round_mask:
case X86::BI__builtin_ia32_sqrtss_round_mask:
+ case X86::BI__builtin_ia32_sqrtsh_round_mask:
case X86::BI__builtin_ia32_vfmaddsd3_mask:
case X86::BI__builtin_ia32_vfmaddsd3_maskz:
case X86::BI__builtin_ia32_vfmaddsd3_mask3:
case X86::BI__builtin_ia32_vfmaddss3_mask:
case X86::BI__builtin_ia32_vfmaddss3_maskz:
case X86::BI__builtin_ia32_vfmaddss3_mask3:
+ case X86::BI__builtin_ia32_vfmaddsh3_mask:
+ case X86::BI__builtin_ia32_vfmaddsh3_maskz:
+ case X86::BI__builtin_ia32_vfmaddsh3_mask3:
case X86::BI__builtin_ia32_vfmaddpd512_mask:
case X86::BI__builtin_ia32_vfmaddpd512_maskz:
case X86::BI__builtin_ia32_vfmaddpd512_mask3:
@@ -4000,6 +4159,10 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vfmaddps512_maskz:
case X86::BI__builtin_ia32_vfmaddps512_mask3:
case X86::BI__builtin_ia32_vfmsubps512_mask3:
+ case X86::BI__builtin_ia32_vfmaddph512_mask:
+ case X86::BI__builtin_ia32_vfmaddph512_maskz:
+ case X86::BI__builtin_ia32_vfmaddph512_mask3:
+ case X86::BI__builtin_ia32_vfmsubph512_mask3:
case X86::BI__builtin_ia32_vfmaddsubpd512_mask:
case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
@@ -4008,6 +4171,26 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
case X86::BI__builtin_ia32_vfmaddsubps512_maskz:
case X86::BI__builtin_ia32_vfmaddsubps512_mask3:
case X86::BI__builtin_ia32_vfmsubaddps512_mask3:
+ case X86::BI__builtin_ia32_vfmaddsubph512_mask:
+ case X86::BI__builtin_ia32_vfmaddsubph512_maskz:
+ case X86::BI__builtin_ia32_vfmaddsubph512_mask3:
+ case X86::BI__builtin_ia32_vfmsubaddph512_mask3:
+ case X86::BI__builtin_ia32_vfmaddcsh_mask:
+ case X86::BI__builtin_ia32_vfmaddcsh_round_mask:
+ case X86::BI__builtin_ia32_vfmaddcsh_round_mask3:
+ case X86::BI__builtin_ia32_vfmaddcph512_mask:
+ case X86::BI__builtin_ia32_vfmaddcph512_maskz:
+ case X86::BI__builtin_ia32_vfmaddcph512_mask3:
+ case X86::BI__builtin_ia32_vfcmaddcsh_mask:
+ case X86::BI__builtin_ia32_vfcmaddcsh_round_mask:
+ case X86::BI__builtin_ia32_vfcmaddcsh_round_mask3:
+ case X86::BI__builtin_ia32_vfcmaddcph512_mask:
+ case X86::BI__builtin_ia32_vfcmaddcph512_maskz:
+ case X86::BI__builtin_ia32_vfcmaddcph512_mask3:
+ case X86::BI__builtin_ia32_vfmulcsh_mask:
+ case X86::BI__builtin_ia32_vfmulcph512_mask:
+ case X86::BI__builtin_ia32_vfcmulcsh_mask:
+ case X86::BI__builtin_ia32_vfcmulcph512_mask:
ArgNum = 4;
HasRC = true;
break;
@@ -4359,6 +4542,9 @@ bool Sema::CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case X86::BI__builtin_ia32_getmantps256_mask:
case X86::BI__builtin_ia32_getmantpd512_mask:
case X86::BI__builtin_ia32_getmantps512_mask:
+ case X86::BI__builtin_ia32_getmantph128_mask:
+ case X86::BI__builtin_ia32_getmantph256_mask:
+ case X86::BI__builtin_ia32_getmantph512_mask:
case X86::BI__builtin_ia32_vec_ext_v16qi:
case X86::BI__builtin_ia32_vec_ext_v16hi:
i = 1; l = 0; u = 15;
@@ -4377,6 +4563,7 @@ bool Sema::CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case X86::BI__builtin_ia32_rangeps512_mask:
case X86::BI__builtin_ia32_getmantsd_round_mask:
case X86::BI__builtin_ia32_getmantss_round_mask:
+ case X86::BI__builtin_ia32_getmantsh_round_mask:
case X86::BI__builtin_ia32_vec_set_v16qi:
case X86::BI__builtin_ia32_vec_set_v16hi:
i = 2; l = 0; u = 15;
@@ -4429,12 +4616,16 @@ bool Sema::CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case X86::BI__builtin_ia32_rndscalepd_256_mask:
case X86::BI__builtin_ia32_rndscaleps_mask:
case X86::BI__builtin_ia32_rndscalepd_mask:
+ case X86::BI__builtin_ia32_rndscaleph_mask:
case X86::BI__builtin_ia32_reducepd128_mask:
case X86::BI__builtin_ia32_reducepd256_mask:
case X86::BI__builtin_ia32_reducepd512_mask:
case X86::BI__builtin_ia32_reduceps128_mask:
case X86::BI__builtin_ia32_reduceps256_mask:
case X86::BI__builtin_ia32_reduceps512_mask:
+ case X86::BI__builtin_ia32_reduceph128_mask:
+ case X86::BI__builtin_ia32_reduceph256_mask:
+ case X86::BI__builtin_ia32_reduceph512_mask:
case X86::BI__builtin_ia32_prold512:
case X86::BI__builtin_ia32_prolq512:
case X86::BI__builtin_ia32_prold128:
@@ -4453,8 +4644,12 @@ bool Sema::CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case X86::BI__builtin_ia32_fpclassps256_mask:
case X86::BI__builtin_ia32_fpclassps512_mask:
case X86::BI__builtin_ia32_fpclasspd512_mask:
+ case X86::BI__builtin_ia32_fpclassph128_mask:
+ case X86::BI__builtin_ia32_fpclassph256_mask:
+ case X86::BI__builtin_ia32_fpclassph512_mask:
case X86::BI__builtin_ia32_fpclasssd_mask:
case X86::BI__builtin_ia32_fpclassss_mask:
+ case X86::BI__builtin_ia32_fpclasssh_mask:
case X86::BI__builtin_ia32_pslldqi128_byteshift:
case X86::BI__builtin_ia32_pslldqi256_byteshift:
case X86::BI__builtin_ia32_pslldqi512_byteshift:
@@ -4565,6 +4760,8 @@ bool Sema::CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case X86::BI__builtin_ia32_reducess_mask:
case X86::BI__builtin_ia32_rndscalesd_round_mask:
case X86::BI__builtin_ia32_rndscaless_round_mask:
+ case X86::BI__builtin_ia32_rndscalesh_round_mask:
+ case X86::BI__builtin_ia32_reducesh_mask:
i = 4; l = 0; u = 255;
break;
}
@@ -4829,7 +5026,7 @@ void Sema::CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
if (ArgAlign < ParamAlign)
Diag(Loc, diag::warn_param_mismatched_alignment)
<< (int)ArgAlign.getQuantity() << (int)ParamAlign.getQuantity()
- << ParamName << FDecl;
+ << ParamName << (FDecl != nullptr) << FDecl;
}
/// Handles the checks for format strings, non-POD arguments to vararg
@@ -5229,6 +5426,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
case AtomicExpr::AO__c11_atomic_fetch_and:
case AtomicExpr::AO__c11_atomic_fetch_or:
case AtomicExpr::AO__c11_atomic_fetch_xor:
+ case AtomicExpr::AO__c11_atomic_fetch_nand:
case AtomicExpr::AO__opencl_atomic_fetch_and:
case AtomicExpr::AO__opencl_atomic_fetch_or:
case AtomicExpr::AO__opencl_atomic_fetch_xor:
@@ -6286,6 +6484,21 @@ bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
}
bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
+ auto IsSuitablyTypedFormatArgument = [this](const Expr *Arg) -> bool {
+ const LangOptions &LO = getLangOpts();
+
+ if (LO.CPlusPlus)
+ return Arg->getType()
+ .getCanonicalType()
+ .getTypePtr()
+ ->getPointeeType()
+ .withoutLocalFastQualifiers() == Context.CharTy;
+
+ // In C, allow aliasing through `char *`, this is required for AArch64 at
+ // least.
+ return true;
+ };
+
// void __va_start(va_list *ap, const char *named_addr, size_t slot_size,
// const char *named_addr);
@@ -6314,8 +6527,7 @@ bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
const QualType &ConstCharPtrTy =
Context.getPointerType(Context.CharTy.withConst());
- if (!Arg1Ty->isPointerType() ||
- Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy)
+ if (!Arg1Ty->isPointerType() || !IsSuitablyTypedFormatArgument(Arg1))
Diag(Arg1->getBeginLoc(), diag::err_typecheck_convert_incompatible)
<< Arg1->getType() << ConstCharPtrTy << 1 /* different class */
<< 0 /* qualifier difference */
@@ -6586,7 +6798,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
<< TheCall->getArg(i)->getSourceRange());
// Allow -1 which will be translated to undef in the IR.
- if (Result->isSigned() && Result->isAllOnesValue())
+ if (Result->isSigned() && Result->isAllOnes())
continue;
if (Result->getActiveBits() > 64 ||
@@ -7286,11 +7498,35 @@ bool Sema::SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
/// Emit an error and return true on failure; return false on success.
/// TypeStr is a string containing the type descriptor of the value returned by
/// the builtin and the descriptors of the expected type of the arguments.
-bool Sema::SemaBuiltinPPCMMACall(CallExpr *TheCall, const char *TypeStr) {
+bool Sema::SemaBuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
+ const char *TypeStr) {
assert((TypeStr[0] != '\0') &&
"Invalid types in PPC MMA builtin declaration");
+ switch (BuiltinID) {
+ default:
+ // This function is called in CheckPPCBuiltinFunctionCall where the
+ // BuiltinID is guaranteed to be an MMA or pair vector memop builtin, here
+ // we are isolating the pair vector memop builtins that can be used with mma
+ // off so the default case is every builtin that requires mma and paired
+ // vector memops.
+ if (SemaFeatureCheck(*this, TheCall, "paired-vector-memops",
+ diag::err_ppc_builtin_only_on_arch, "10") ||
+ SemaFeatureCheck(*this, TheCall, "mma",
+ diag::err_ppc_builtin_only_on_arch, "10"))
+ return true;
+ break;
+ case PPC::BI__builtin_vsx_lxvp:
+ case PPC::BI__builtin_vsx_stxvp:
+ case PPC::BI__builtin_vsx_assemble_pair:
+ case PPC::BI__builtin_vsx_disassemble_pair:
+ if (SemaFeatureCheck(*this, TheCall, "paired-vector-memops",
+ diag::err_ppc_builtin_only_on_arch, "10"))
+ return true;
+ break;
+ }
+
unsigned Mask = 0;
unsigned ArgNum = 0;
@@ -7308,13 +7544,23 @@ bool Sema::SemaBuiltinPPCMMACall(CallExpr *TheCall, const char *TypeStr) {
}
Expr *Arg = TheCall->getArg(ArgNum);
- QualType ArgType = Arg->getType();
+ QualType PassedType = Arg->getType();
+ QualType StrippedRVType = PassedType.getCanonicalType();
- if ((ExpectedType->isVoidPointerType() && !ArgType->isPointerType()) ||
- (!ExpectedType->isVoidPointerType() &&
- ArgType.getCanonicalType() != ExpectedType))
- return Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible)
- << ArgType << ExpectedType << 1 << 0 << 0;
+ // Strip Restrict/Volatile qualifiers.
+ if (StrippedRVType.isRestrictQualified() ||
+ StrippedRVType.isVolatileQualified())
+ StrippedRVType = StrippedRVType.getCanonicalType().getUnqualifiedType();
+
+ // The only case where the argument type and expected type are allowed to
+ // mismatch is if the argument type is a non-void pointer (or array) and
+ // expected type is a void pointer.
+ if (StrippedRVType != ExpectedType)
+ if (!(ExpectedType->isVoidPointerType() &&
+ (StrippedRVType->isPointerType() || StrippedRVType->isArrayType())))
+ return Diag(Arg->getBeginLoc(),
+ diag::err_typecheck_convert_incompatible)
+ << PassedType << ExpectedType << 1 << 0 << 0;
// If the value of the Mask is not 0, we have a constraint in the size of
// the integer argument so here we ensure the argument is a constant that
@@ -7678,11 +7924,11 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
// }
if (HasVAListArg) {
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(VD)) {
- if (const NamedDecl *ND = dyn_cast<NamedDecl>(PV->getDeclContext())) {
+ if (const Decl *D = dyn_cast<Decl>(PV->getDeclContext())) {
int PVIndex = PV->getFunctionScopeIndex() + 1;
- for (const auto *PVFormat : ND->specific_attrs<FormatAttr>()) {
+ for (const auto *PVFormat : D->specific_attrs<FormatAttr>()) {
// adjust for implicit parameter
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D))
if (MD->isInstance())
++PVIndex;
// We also check if the formats are compatible.
@@ -9545,8 +9791,7 @@ static void CheckFormatString(Sema &S, const FormatStringLiteral *FExpr,
// Emit a warning if the string literal is truncated and does not contain an
// embedded null character.
- if (TypeSize <= StrRef.size() &&
- StrRef.substr(0, TypeSize).find('\0') == StringRef::npos) {
+ if (TypeSize <= StrRef.size() && !StrRef.substr(0, TypeSize).contains('\0')) {
CheckFormatHandler::EmitFormatDiagnostic(
S, inFunctionCall, Args[format_idx],
S.PDiag(diag::warn_printf_format_string_not_null_terminated),
@@ -11138,7 +11383,7 @@ static QualType GetExprType(const Expr *E) {
///
/// \param MaxWidth The width to which the value will be truncated.
/// \param Approximate If \c true, return a likely range for the result: in
-/// particular, assume that aritmetic on narrower types doesn't leave
+/// particular, assume that arithmetic on narrower types doesn't leave
/// those types. If \c false, return a range including all possible
/// result values.
static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
@@ -13059,6 +13304,20 @@ static void AnalyzeImplicitConversions(
<< OrigE->getSourceRange() << T->isBooleanType()
<< FixItHint::CreateReplacement(UO->getBeginLoc(), "!");
+ if (const auto *BO = dyn_cast<BinaryOperator>(SourceExpr))
+ if ((BO->getOpcode() == BO_And || BO->getOpcode() == BO_Or) &&
+ BO->getLHS()->isKnownToHaveBooleanValue() &&
+ BO->getRHS()->isKnownToHaveBooleanValue() &&
+ BO->getLHS()->HasSideEffects(S.Context) &&
+ BO->getRHS()->HasSideEffects(S.Context)) {
+ S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
+ << (BO->getOpcode() == BO_And ? "&" : "|") << OrigE->getSourceRange()
+ << FixItHint::CreateReplacement(
+ BO->getOperatorLoc(),
+ (BO->getOpcode() == BO_And ? "&&" : "||"));
+ S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
+ }
+
// For conditional operators, we analyze the arguments as if they
// were being fed directly into the output.
if (auto *CO = dyn_cast<AbstractConditionalOperator>(SourceExpr)) {
@@ -15999,7 +16258,7 @@ static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
///
/// \param MagicValue Type tag magic value.
///
-/// \param isConstantEvaluated wether the evalaution should be performed in
+/// \param isConstantEvaluated whether the evalaution should be performed in
/// constant context.
static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx,
@@ -16079,7 +16338,7 @@ static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx,
///
/// \param TypeInfo Information about the corresponding C type.
///
-/// \param isConstantEvaluated wether the evalaution should be performed in
+/// \param isConstantEvaluated whether the evalaution should be performed in
/// constant context.
///
/// \returns true if the corresponding C type was found.
@@ -16352,10 +16611,8 @@ void Sema::RefersToMemberWithReducedAlignment(
// Synthesize offset of the whole access.
CharUnits Offset;
- for (auto I = ReverseMemberChain.rbegin(); I != ReverseMemberChain.rend();
- I++) {
- Offset += Context.toCharUnitsFromBits(Context.getFieldOffset(*I));
- }
+ for (const FieldDecl *FD : llvm::reverse(ReverseMemberChain))
+ Offset += Context.toCharUnitsFromBits(Context.getFieldOffset(FD));
// Compute the CompleteObjectAlignment as the alignment of the whole chain.
CharUnits CompleteObjectAlignment = Context.getTypeAlignInChars(
@@ -16408,6 +16665,94 @@ void Sema::CheckAddressOfPackedMember(Expr *rhs) {
_2, _3, _4));
}
+// Check if \p Ty is a valid type for the elementwise math builtins. If it is
+// not a valid type, emit an error message and return true. Otherwise return
+// false.
+static bool checkMathBuiltinElementType(Sema &S, SourceLocation Loc,
+ QualType Ty) {
+ if (!Ty->getAs<VectorType>() && !ConstantMatrixType::isValidElementType(Ty)) {
+ S.Diag(Loc, diag::err_builtin_invalid_arg_type)
+ << 1 << /* vector, integer or float ty*/ 0 << Ty;
+ return true;
+ }
+ return false;
+}
+
+bool Sema::SemaBuiltinElementwiseMathOneArg(CallExpr *TheCall) {
+ if (checkArgCount(*this, TheCall, 1))
+ return true;
+
+ ExprResult A = UsualUnaryConversions(TheCall->getArg(0));
+ SourceLocation ArgLoc = TheCall->getArg(0)->getBeginLoc();
+ if (A.isInvalid())
+ return true;
+
+ TheCall->setArg(0, A.get());
+ QualType TyA = A.get()->getType();
+ if (checkMathBuiltinElementType(*this, ArgLoc, TyA))
+ return true;
+
+ QualType EltTy = TyA;
+ if (auto *VecTy = EltTy->getAs<VectorType>())
+ EltTy = VecTy->getElementType();
+ if (EltTy->isUnsignedIntegerType())
+ return Diag(ArgLoc, diag::err_builtin_invalid_arg_type)
+ << 1 << /*signed integer or float ty*/ 3 << TyA;
+
+ TheCall->setType(TyA);
+ return false;
+}
+
+bool Sema::SemaBuiltinElementwiseMath(CallExpr *TheCall) {
+ if (checkArgCount(*this, TheCall, 2))
+ return true;
+
+ ExprResult A = TheCall->getArg(0);
+ ExprResult B = TheCall->getArg(1);
+ // Do standard promotions between the two arguments, returning their common
+ // type.
+ QualType Res =
+ UsualArithmeticConversions(A, B, TheCall->getExprLoc(), ACK_Comparison);
+ if (A.isInvalid() || B.isInvalid())
+ return true;
+
+ QualType TyA = A.get()->getType();
+ QualType TyB = B.get()->getType();
+
+ if (Res.isNull() || TyA.getCanonicalType() != TyB.getCanonicalType())
+ return Diag(A.get()->getBeginLoc(),
+ diag::err_typecheck_call_different_arg_types)
+ << TyA << TyB;
+
+ if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc(), TyA))
+ return true;
+
+ TheCall->setArg(0, A.get());
+ TheCall->setArg(1, B.get());
+ TheCall->setType(Res);
+ return false;
+}
+
+bool Sema::SemaBuiltinReduceMath(CallExpr *TheCall) {
+ if (checkArgCount(*this, TheCall, 1))
+ return true;
+
+ ExprResult A = UsualUnaryConversions(TheCall->getArg(0));
+ if (A.isInvalid())
+ return true;
+
+ TheCall->setArg(0, A.get());
+ const VectorType *TyA = A.get()->getType()->getAs<VectorType>();
+ if (!TyA) {
+ SourceLocation ArgLoc = TheCall->getArg(0)->getBeginLoc();
+ return Diag(ArgLoc, diag::err_builtin_invalid_arg_type)
+ << 1 << /* vector ty*/ 4 << A.get()->getType();
+ }
+
+ TheCall->setType(TyA->getElementType());
+ return false;
+}
+
ExprResult Sema::SemaBuiltinMatrixTranspose(CallExpr *TheCall,
ExprResult CallResult) {
if (checkArgCount(*this, TheCall, 1))
@@ -16420,7 +16765,8 @@ ExprResult Sema::SemaBuiltinMatrixTranspose(CallExpr *TheCall,
auto *MType = Matrix->getType()->getAs<ConstantMatrixType>();
if (!MType) {
- Diag(Matrix->getBeginLoc(), diag::err_builtin_matrix_arg);
+ Diag(Matrix->getBeginLoc(), diag::err_builtin_invalid_arg_type)
+ << 1 << /* matrix ty*/ 1 << Matrix->getType();
return ExprError();
}
@@ -16491,15 +16837,16 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
auto *PtrTy = PtrExpr->getType()->getAs<PointerType>();
QualType ElementTy;
if (!PtrTy) {
- Diag(PtrExpr->getBeginLoc(), diag::err_builtin_matrix_pointer_arg)
- << PtrArgIdx + 1;
+ Diag(PtrExpr->getBeginLoc(), diag::err_builtin_invalid_arg_type)
+ << PtrArgIdx + 1 << /*pointer to element ty*/ 2 << PtrExpr->getType();
ArgError = true;
} else {
ElementTy = PtrTy->getPointeeType().getUnqualifiedType();
if (!ConstantMatrixType::isValidElementType(ElementTy)) {
- Diag(PtrExpr->getBeginLoc(), diag::err_builtin_matrix_pointer_arg)
- << PtrArgIdx + 1;
+ Diag(PtrExpr->getBeginLoc(), diag::err_builtin_invalid_arg_type)
+ << PtrArgIdx + 1 << /* pointer to element ty*/ 2
+ << PtrExpr->getType();
ArgError = true;
}
}
@@ -16536,7 +16883,7 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
return CallResult;
}
- // Check row and column dimenions.
+ // Check row and column dimensions.
llvm::Optional<unsigned> MaybeRows;
if (RowsExpr)
MaybeRows = getAndVerifyMatrixDimension(RowsExpr, "row", *this);
@@ -16598,7 +16945,8 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
auto *MatrixTy = MatrixExpr->getType()->getAs<ConstantMatrixType>();
if (!MatrixTy) {
- Diag(MatrixExpr->getBeginLoc(), diag::err_builtin_matrix_arg) << 0;
+ Diag(MatrixExpr->getBeginLoc(), diag::err_builtin_invalid_arg_type)
+ << 1 << /*matrix ty */ 1 << MatrixExpr->getType();
ArgError = true;
}
@@ -16617,8 +16965,8 @@ ExprResult Sema::SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
// Check pointer argument.
auto *PtrTy = PtrExpr->getType()->getAs<PointerType>();
if (!PtrTy) {
- Diag(PtrExpr->getBeginLoc(), diag::err_builtin_matrix_pointer_arg)
- << PtrArgIdx + 1;
+ Diag(PtrExpr->getBeginLoc(), diag::err_builtin_invalid_arg_type)
+ << PtrArgIdx + 1 << /*pointer to element ty*/ 2 << PtrExpr->getType();
ArgError = true;
} else {
QualType ElementTy = PtrTy->getPointeeType();