diff options
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 850 |
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(); |
