diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2018-06-19 14:36:04 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2018-06-19 14:36:04 +0000 |
commit | 9360cb0745b3488e5123bda56557a5b1ce11bf7f (patch) | |
tree | 166a7fc4be68d616a966f04e1d329559fd0992f1 /clang/lib/Sema/SemaChecking.cpp | |
parent | 8779968805593a066a0fcbaee2ffbaadaed33ccf (diff) | |
download | bcm5719-llvm-9360cb0745b3488e5123bda56557a5b1ce11bf7f.tar.gz bcm5719-llvm-9360cb0745b3488e5123bda56557a5b1ce11bf7f.zip |
Implement semantic checking for __builtin_signbit.
r242675 changed the signature for the signbit builtin but did not introduce proper semantic checking to ensure the arguments are as-expected. This patch groups the signbit builtin along with the other fp classification builtins. Fixes PR28172.
llvm-svn: 335048
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 1625 |
1 files changed, 816 insertions, 809 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 5530bd8fe76..e18dd056e90 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -772,406 +772,409 @@ static bool SemaBuiltinReserveRWPipe(Sema &S, CallExpr *Call) { } // Since return type of reserve_read/write_pipe built-in function is - // reserve_id_t, which is not defined in the builtin def file , we used int - // as return type and need to override the return type of these functions. - Call->setType(S.Context.OCLReserveIDTy); - - return false; -} - -// Performs a semantic analysis on {work_group_/sub_group_ -// /_}commit_{read/write}_pipe -// \param S Reference to the semantic analyzer. -// \param Call The call to the builtin function to be analyzed. -// \return True if a semantic error was found, false otherwise. -static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 2)) - return true; - - if (checkOpenCLPipeArg(S, Call)) - return true; - - // Check reserve_id_t. - if (!Call->getArg(1)->getType()->isReserveIDT()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg) - << Call->getDirectCallee() << S.Context.OCLReserveIDTy - << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange(); - return true; - } - - return false; -} - -// Performs a semantic analysis on the call to built-in Pipe -// Query Functions. -// \param S Reference to the semantic analyzer. -// \param Call The call to the builtin function to be analyzed. -// \return True if a semantic error was found, false otherwise. -static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) { - if (checkArgCount(S, Call, 1)) - return true; - - if (!Call->getArg(0)->getType()->isPipeType()) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg) - << Call->getDirectCallee() << Call->getArg(0)->getSourceRange(); - return true; - } - - return false; -} - -// OpenCL v2.0 s6.13.9 - Address space qualifier functions. -// Performs semantic analysis for the to_global/local/private call. -// \param S Reference to the semantic analyzer. -// \param BuiltinID ID of the builtin function. -// \param Call A pointer to the builtin call. -// \return True if a semantic error has been found, false otherwise. -static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, - CallExpr *Call) { - if (Call->getNumArgs() != 1) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num) - << Call->getDirectCallee() << Call->getSourceRange(); - return true; - } - - auto RT = Call->getArg(0)->getType(); - if (!RT->isPointerType() || RT->getPointeeType() - .getAddressSpace() == LangAS::opencl_constant) { - S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg) - << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange(); - return true; - } - - RT = RT->getPointeeType(); - auto Qual = RT.getQualifiers(); - switch (BuiltinID) { - case Builtin::BIto_global: - Qual.setAddressSpace(LangAS::opencl_global); - break; - case Builtin::BIto_local: - Qual.setAddressSpace(LangAS::opencl_local); - break; - case Builtin::BIto_private: - Qual.setAddressSpace(LangAS::opencl_private); - break; - default: - llvm_unreachable("Invalid builtin function"); - } - Call->setType(S.Context.getPointerType(S.Context.getQualifiedType( - RT.getUnqualifiedType(), Qual))); - - return false; -} - -// Emit an error and return true if the current architecture is not in the list -// of supported architectures. -static bool -CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall, - ArrayRef<llvm::Triple::ArchType> SupportedArchs) { - llvm::Triple::ArchType CurArch = - S.getASTContext().getTargetInfo().getTriple().getArch(); - if (llvm::is_contained(SupportedArchs, CurArch)) - return false; - S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported) - << TheCall->getSourceRange(); - return true; -} - -ExprResult -Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, - CallExpr *TheCall) { - ExprResult TheCallResult(TheCall); - - // Find out if any arguments are required to be integer constant expressions. - unsigned ICEArguments = 0; - ASTContext::GetBuiltinTypeError Error; - Context.GetBuiltinType(BuiltinID, Error, &ICEArguments); - if (Error != ASTContext::GE_None) - ICEArguments = 0; // Don't diagnose previously diagnosed errors. - - // If any arguments are required to be ICE's, check and diagnose. - for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) { - // Skip arguments not required to be ICE's. - if ((ICEArguments & (1 << ArgNo)) == 0) continue; - - llvm::APSInt Result; - if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) - return true; - ICEArguments &= ~(1 << ArgNo); - } - - switch (BuiltinID) { - case Builtin::BI__builtin___CFStringMakeConstantString: - assert(TheCall->getNumArgs() == 1 && - "Wrong # arguments to builtin CFStringMakeConstantString"); - if (CheckObjCString(TheCall->getArg(0))) - return ExprError(); - break; - case Builtin::BI__builtin_ms_va_start: - case Builtin::BI__builtin_stdarg_start: - case Builtin::BI__builtin_va_start: - if (SemaBuiltinVAStart(BuiltinID, TheCall)) - return ExprError(); - break; - case Builtin::BI__va_start: { - switch (Context.getTargetInfo().getTriple().getArch()) { - case llvm::Triple::arm: - case llvm::Triple::thumb: - if (SemaBuiltinVAStartARMMicrosoft(TheCall)) - return ExprError(); - break; - default: - if (SemaBuiltinVAStart(BuiltinID, TheCall)) - return ExprError(); - break; - } - break; - } - - // The acquire, release, and no fence variants are ARM and AArch64 only. - case Builtin::BI_interlockedbittestandset_acq: - case Builtin::BI_interlockedbittestandset_rel: - case Builtin::BI_interlockedbittestandset_nf: - case Builtin::BI_interlockedbittestandreset_acq: - case Builtin::BI_interlockedbittestandreset_rel: - case Builtin::BI_interlockedbittestandreset_nf: - if (CheckBuiltinTargetSupport( - *this, BuiltinID, TheCall, - {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64})) - return ExprError(); - break; - - // The 64-bit bittest variants are x64, ARM, and AArch64 only. - case Builtin::BI_bittest64: - case Builtin::BI_bittestandcomplement64: - case Builtin::BI_bittestandreset64: - case Builtin::BI_bittestandset64: - case Builtin::BI_interlockedbittestandreset64: - case Builtin::BI_interlockedbittestandset64: - if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall, - {llvm::Triple::x86_64, llvm::Triple::arm, - llvm::Triple::thumb, llvm::Triple::aarch64})) - return ExprError(); - break; - - case Builtin::BI__builtin_isgreater: - case Builtin::BI__builtin_isgreaterequal: - case Builtin::BI__builtin_isless: - case Builtin::BI__builtin_islessequal: - case Builtin::BI__builtin_islessgreater: - case Builtin::BI__builtin_isunordered: - if (SemaBuiltinUnorderedCompare(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_fpclassify: - if (SemaBuiltinFPClassification(TheCall, 6)) - return ExprError(); - break; - case Builtin::BI__builtin_isfinite: - case Builtin::BI__builtin_isinf: - case Builtin::BI__builtin_isinf_sign: - case Builtin::BI__builtin_isnan: - case Builtin::BI__builtin_isnormal: - if (SemaBuiltinFPClassification(TheCall, 1)) - return ExprError(); - break; - case Builtin::BI__builtin_shufflevector: - return SemaBuiltinShuffleVector(TheCall); - // TheCall will be freed by the smart pointer here, but that's fine, since - // SemaBuiltinShuffleVector guts it, but then doesn't release it. - case Builtin::BI__builtin_prefetch: - if (SemaBuiltinPrefetch(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_alloca_with_align: - if (SemaBuiltinAllocaWithAlign(TheCall)) - return ExprError(); - break; - case Builtin::BI__assume: - case Builtin::BI__builtin_assume: - if (SemaBuiltinAssume(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_assume_aligned: - if (SemaBuiltinAssumeAligned(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_object_size: - if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3)) - return ExprError(); - break; - case Builtin::BI__builtin_longjmp: - if (SemaBuiltinLongjmp(TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_setjmp: - if (SemaBuiltinSetjmp(TheCall)) - return ExprError(); - break; - case Builtin::BI_setjmp: - case Builtin::BI_setjmpex: - if (checkArgCount(*this, TheCall, 1)) - return true; - break; - case Builtin::BI__builtin_classify_type: - if (checkArgCount(*this, TheCall, 1)) return true; - TheCall->setType(Context.IntTy); - break; - case Builtin::BI__builtin_constant_p: - if (checkArgCount(*this, TheCall, 1)) return true; - TheCall->setType(Context.IntTy); - break; - case Builtin::BI__sync_fetch_and_add: - case Builtin::BI__sync_fetch_and_add_1: - case Builtin::BI__sync_fetch_and_add_2: - case Builtin::BI__sync_fetch_and_add_4: - case Builtin::BI__sync_fetch_and_add_8: - case Builtin::BI__sync_fetch_and_add_16: - case Builtin::BI__sync_fetch_and_sub: - case Builtin::BI__sync_fetch_and_sub_1: - case Builtin::BI__sync_fetch_and_sub_2: - case Builtin::BI__sync_fetch_and_sub_4: - case Builtin::BI__sync_fetch_and_sub_8: - case Builtin::BI__sync_fetch_and_sub_16: - case Builtin::BI__sync_fetch_and_or: - case Builtin::BI__sync_fetch_and_or_1: - case Builtin::BI__sync_fetch_and_or_2: - case Builtin::BI__sync_fetch_and_or_4: - case Builtin::BI__sync_fetch_and_or_8: - case Builtin::BI__sync_fetch_and_or_16: - case Builtin::BI__sync_fetch_and_and: - case Builtin::BI__sync_fetch_and_and_1: - case Builtin::BI__sync_fetch_and_and_2: - case Builtin::BI__sync_fetch_and_and_4: - case Builtin::BI__sync_fetch_and_and_8: - case Builtin::BI__sync_fetch_and_and_16: - case Builtin::BI__sync_fetch_and_xor: - case Builtin::BI__sync_fetch_and_xor_1: - case Builtin::BI__sync_fetch_and_xor_2: - case Builtin::BI__sync_fetch_and_xor_4: - case Builtin::BI__sync_fetch_and_xor_8: - case Builtin::BI__sync_fetch_and_xor_16: - case Builtin::BI__sync_fetch_and_nand: - case Builtin::BI__sync_fetch_and_nand_1: - case Builtin::BI__sync_fetch_and_nand_2: - case Builtin::BI__sync_fetch_and_nand_4: - case Builtin::BI__sync_fetch_and_nand_8: - case Builtin::BI__sync_fetch_and_nand_16: - case Builtin::BI__sync_add_and_fetch: - case Builtin::BI__sync_add_and_fetch_1: - case Builtin::BI__sync_add_and_fetch_2: - case Builtin::BI__sync_add_and_fetch_4: - case Builtin::BI__sync_add_and_fetch_8: - case Builtin::BI__sync_add_and_fetch_16: - case Builtin::BI__sync_sub_and_fetch: - case Builtin::BI__sync_sub_and_fetch_1: - case Builtin::BI__sync_sub_and_fetch_2: - case Builtin::BI__sync_sub_and_fetch_4: - case Builtin::BI__sync_sub_and_fetch_8: - case Builtin::BI__sync_sub_and_fetch_16: - case Builtin::BI__sync_and_and_fetch: - case Builtin::BI__sync_and_and_fetch_1: - case Builtin::BI__sync_and_and_fetch_2: - case Builtin::BI__sync_and_and_fetch_4: - case Builtin::BI__sync_and_and_fetch_8: - case Builtin::BI__sync_and_and_fetch_16: - case Builtin::BI__sync_or_and_fetch: - case Builtin::BI__sync_or_and_fetch_1: - case Builtin::BI__sync_or_and_fetch_2: - case Builtin::BI__sync_or_and_fetch_4: - case Builtin::BI__sync_or_and_fetch_8: - case Builtin::BI__sync_or_and_fetch_16: - case Builtin::BI__sync_xor_and_fetch: - case Builtin::BI__sync_xor_and_fetch_1: - case Builtin::BI__sync_xor_and_fetch_2: - case Builtin::BI__sync_xor_and_fetch_4: - case Builtin::BI__sync_xor_and_fetch_8: - case Builtin::BI__sync_xor_and_fetch_16: - case Builtin::BI__sync_nand_and_fetch: - case Builtin::BI__sync_nand_and_fetch_1: - case Builtin::BI__sync_nand_and_fetch_2: - case Builtin::BI__sync_nand_and_fetch_4: - case Builtin::BI__sync_nand_and_fetch_8: - case Builtin::BI__sync_nand_and_fetch_16: - case Builtin::BI__sync_val_compare_and_swap: - case Builtin::BI__sync_val_compare_and_swap_1: - case Builtin::BI__sync_val_compare_and_swap_2: - case Builtin::BI__sync_val_compare_and_swap_4: - case Builtin::BI__sync_val_compare_and_swap_8: - case Builtin::BI__sync_val_compare_and_swap_16: - case Builtin::BI__sync_bool_compare_and_swap: - case Builtin::BI__sync_bool_compare_and_swap_1: - case Builtin::BI__sync_bool_compare_and_swap_2: - case Builtin::BI__sync_bool_compare_and_swap_4: - case Builtin::BI__sync_bool_compare_and_swap_8: - case Builtin::BI__sync_bool_compare_and_swap_16: - case Builtin::BI__sync_lock_test_and_set: - case Builtin::BI__sync_lock_test_and_set_1: - case Builtin::BI__sync_lock_test_and_set_2: - case Builtin::BI__sync_lock_test_and_set_4: - case Builtin::BI__sync_lock_test_and_set_8: - case Builtin::BI__sync_lock_test_and_set_16: - case Builtin::BI__sync_lock_release: - case Builtin::BI__sync_lock_release_1: - case Builtin::BI__sync_lock_release_2: - case Builtin::BI__sync_lock_release_4: - case Builtin::BI__sync_lock_release_8: - case Builtin::BI__sync_lock_release_16: - case Builtin::BI__sync_swap: - case Builtin::BI__sync_swap_1: - case Builtin::BI__sync_swap_2: - case Builtin::BI__sync_swap_4: - case Builtin::BI__sync_swap_8: - case Builtin::BI__sync_swap_16: - return SemaBuiltinAtomicOverloaded(TheCallResult); - case Builtin::BI__builtin_nontemporal_load: - case Builtin::BI__builtin_nontemporal_store: - return SemaBuiltinNontemporalOverloaded(TheCallResult); -#define BUILTIN(ID, TYPE, ATTRS) -#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ - case Builtin::BI##ID: \ - return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID); -#include "clang/Basic/Builtins.def" - case Builtin::BI__annotation: - if (SemaBuiltinMSVCAnnotation(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_annotation: - if (SemaBuiltinAnnotation(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_addressof: - if (SemaBuiltinAddressof(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_add_overflow: - case Builtin::BI__builtin_sub_overflow: - case Builtin::BI__builtin_mul_overflow: - if (SemaBuiltinOverflow(*this, TheCall)) - return ExprError(); - break; - case Builtin::BI__builtin_operator_new: - case Builtin::BI__builtin_operator_delete: { - bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete; - ExprResult Res = - SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete); - if (Res.isInvalid()) - CorrectDelayedTyposInExpr(TheCallResult.get()); - return Res; - } - case Builtin::BI__builtin_dump_struct: { - // We first want to ensure we are called with 2 arguments - if (checkArgCount(*this, TheCall, 2)) - return ExprError(); - // Ensure that the first argument is of type 'struct XX *' - const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts(); - const QualType PtrArgType = PtrArg->getType(); - if (!PtrArgType->isPointerType() || - !PtrArgType->getPointeeType()->isRecordType()) { - Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible) - << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType - << "structure pointer"; - return ExprError(); + // reserve_id_t, which is not defined in the builtin def file , we used int
+ // as return type and need to override the return type of these functions.
+ Call->setType(S.Context.OCLReserveIDTy);
+
+ return false;
+}
+
+// Performs a semantic analysis on {work_group_/sub_group_
+// /_}commit_{read/write}_pipe
+// \param S Reference to the semantic analyzer.
+// \param Call The call to the builtin function to be analyzed.
+// \return True if a semantic error was found, false otherwise.
+static bool SemaBuiltinCommitRWPipe(Sema &S, CallExpr *Call) {
+ if (checkArgCount(S, Call, 2))
+ return true;
+
+ if (checkOpenCLPipeArg(S, Call))
+ return true;
+
+ // Check reserve_id_t.
+ if (!Call->getArg(1)->getType()->isReserveIDT()) {
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_invalid_arg)
+ << Call->getDirectCallee() << S.Context.OCLReserveIDTy
+ << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
+ return true;
+ }
+
+ return false;
+}
+
+// Performs a semantic analysis on the call to built-in Pipe
+// Query Functions.
+// \param S Reference to the semantic analyzer.
+// \param Call The call to the builtin function to be analyzed.
+// \return True if a semantic error was found, false otherwise.
+static bool SemaBuiltinPipePackets(Sema &S, CallExpr *Call) {
+ if (checkArgCount(S, Call, 1))
+ return true;
+
+ if (!Call->getArg(0)->getType()->isPipeType()) {
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_pipe_first_arg)
+ << Call->getDirectCallee() << Call->getArg(0)->getSourceRange();
+ return true;
+ }
+
+ return false;
+}
+
+// OpenCL v2.0 s6.13.9 - Address space qualifier functions.
+// Performs semantic analysis for the to_global/local/private call.
+// \param S Reference to the semantic analyzer.
+// \param BuiltinID ID of the builtin function.
+// \param Call A pointer to the builtin call.
+// \return True if a semantic error has been found, false otherwise.
+static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID,
+ CallExpr *Call) {
+ if (Call->getNumArgs() != 1) {
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_arg_num)
+ << Call->getDirectCallee() << Call->getSourceRange();
+ return true;
+ }
+
+ auto RT = Call->getArg(0)->getType();
+ if (!RT->isPointerType() || RT->getPointeeType()
+ .getAddressSpace() == LangAS::opencl_constant) {
+ S.Diag(Call->getLocStart(), diag::err_opencl_builtin_to_addr_invalid_arg)
+ << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange();
+ return true;
+ }
+
+ RT = RT->getPointeeType();
+ auto Qual = RT.getQualifiers();
+ switch (BuiltinID) {
+ case Builtin::BIto_global:
+ Qual.setAddressSpace(LangAS::opencl_global);
+ break;
+ case Builtin::BIto_local:
+ Qual.setAddressSpace(LangAS::opencl_local);
+ break;
+ case Builtin::BIto_private:
+ Qual.setAddressSpace(LangAS::opencl_private);
+ break;
+ default:
+ llvm_unreachable("Invalid builtin function");
+ }
+ Call->setType(S.Context.getPointerType(S.Context.getQualifiedType(
+ RT.getUnqualifiedType(), Qual)));
+
+ return false;
+}
+
+// Emit an error and return true if the current architecture is not in the list
+// of supported architectures.
+static bool
+CheckBuiltinTargetSupport(Sema &S, unsigned BuiltinID, CallExpr *TheCall,
+ ArrayRef<llvm::Triple::ArchType> SupportedArchs) {
+ llvm::Triple::ArchType CurArch =
+ S.getASTContext().getTargetInfo().getTriple().getArch();
+ if (llvm::is_contained(SupportedArchs, CurArch))
+ return false;
+ S.Diag(TheCall->getLocStart(), diag::err_builtin_target_unsupported)
+ << TheCall->getSourceRange();
+ return true;
+}
+
+ExprResult
+Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
+ CallExpr *TheCall) {
+ ExprResult TheCallResult(TheCall);
+
+ // Find out if any arguments are required to be integer constant expressions.
+ unsigned ICEArguments = 0;
+ ASTContext::GetBuiltinTypeError Error;
+ Context.GetBuiltinType(BuiltinID, Error, &ICEArguments);
+ if (Error != ASTContext::GE_None)
+ ICEArguments = 0; // Don't diagnose previously diagnosed errors.
+
+ // If any arguments are required to be ICE's, check and diagnose.
+ for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) {
+ // Skip arguments not required to be ICE's.
+ if ((ICEArguments & (1 << ArgNo)) == 0) continue;
+
+ llvm::APSInt Result;
+ if (SemaBuiltinConstantArg(TheCall, ArgNo, Result))
+ return true;
+ ICEArguments &= ~(1 << ArgNo);
+ }
+
+ switch (BuiltinID) {
+ case Builtin::BI__builtin___CFStringMakeConstantString:
+ assert(TheCall->getNumArgs() == 1 &&
+ "Wrong # arguments to builtin CFStringMakeConstantString");
+ if (CheckObjCString(TheCall->getArg(0)))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_ms_va_start:
+ case Builtin::BI__builtin_stdarg_start:
+ case Builtin::BI__builtin_va_start:
+ if (SemaBuiltinVAStart(BuiltinID, TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__va_start: {
+ switch (Context.getTargetInfo().getTriple().getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ if (SemaBuiltinVAStartARMMicrosoft(TheCall))
+ return ExprError();
+ break;
+ default:
+ if (SemaBuiltinVAStart(BuiltinID, TheCall))
+ return ExprError();
+ break;
+ }
+ break;
+ }
+
+ // The acquire, release, and no fence variants are ARM and AArch64 only.
+ case Builtin::BI_interlockedbittestandset_acq:
+ case Builtin::BI_interlockedbittestandset_rel:
+ case Builtin::BI_interlockedbittestandset_nf:
+ case Builtin::BI_interlockedbittestandreset_acq:
+ case Builtin::BI_interlockedbittestandreset_rel:
+ case Builtin::BI_interlockedbittestandreset_nf:
+ if (CheckBuiltinTargetSupport(
+ *this, BuiltinID, TheCall,
+ {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64}))
+ return ExprError();
+ break;
+
+ // The 64-bit bittest variants are x64, ARM, and AArch64 only.
+ case Builtin::BI_bittest64:
+ case Builtin::BI_bittestandcomplement64:
+ case Builtin::BI_bittestandreset64:
+ case Builtin::BI_bittestandset64:
+ case Builtin::BI_interlockedbittestandreset64:
+ case Builtin::BI_interlockedbittestandset64:
+ if (CheckBuiltinTargetSupport(*this, BuiltinID, TheCall,
+ {llvm::Triple::x86_64, llvm::Triple::arm,
+ llvm::Triple::thumb, llvm::Triple::aarch64}))
+ return ExprError();
+ break;
+
+ case Builtin::BI__builtin_isgreater:
+ case Builtin::BI__builtin_isgreaterequal:
+ case Builtin::BI__builtin_isless:
+ case Builtin::BI__builtin_islessequal:
+ case Builtin::BI__builtin_islessgreater:
+ case Builtin::BI__builtin_isunordered:
+ if (SemaBuiltinUnorderedCompare(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_fpclassify:
+ if (SemaBuiltinFPClassification(TheCall, 6))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_isfinite:
+ case Builtin::BI__builtin_isinf:
+ case Builtin::BI__builtin_isinf_sign:
+ case Builtin::BI__builtin_isnan:
+ case Builtin::BI__builtin_isnormal:
+ case Builtin::BI__builtin_signbit:
+ case Builtin::BI__builtin_signbitf:
+ case Builtin::BI__builtin_signbitl:
+ if (SemaBuiltinFPClassification(TheCall, 1))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_shufflevector:
+ return SemaBuiltinShuffleVector(TheCall);
+ // TheCall will be freed by the smart pointer here, but that's fine, since
+ // SemaBuiltinShuffleVector guts it, but then doesn't release it.
+ case Builtin::BI__builtin_prefetch:
+ if (SemaBuiltinPrefetch(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_alloca_with_align:
+ if (SemaBuiltinAllocaWithAlign(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__assume:
+ case Builtin::BI__builtin_assume:
+ if (SemaBuiltinAssume(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_assume_aligned:
+ if (SemaBuiltinAssumeAligned(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_object_size:
+ if (SemaBuiltinConstantArgRange(TheCall, 1, 0, 3))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_longjmp:
+ if (SemaBuiltinLongjmp(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_setjmp:
+ if (SemaBuiltinSetjmp(TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI_setjmp:
+ case Builtin::BI_setjmpex:
+ if (checkArgCount(*this, TheCall, 1))
+ return true;
+ break;
+ case Builtin::BI__builtin_classify_type:
+ if (checkArgCount(*this, TheCall, 1)) return true;
+ TheCall->setType(Context.IntTy);
+ break;
+ case Builtin::BI__builtin_constant_p:
+ if (checkArgCount(*this, TheCall, 1)) return true;
+ TheCall->setType(Context.IntTy);
+ break;
+ case Builtin::BI__sync_fetch_and_add:
+ case Builtin::BI__sync_fetch_and_add_1:
+ case Builtin::BI__sync_fetch_and_add_2:
+ case Builtin::BI__sync_fetch_and_add_4:
+ case Builtin::BI__sync_fetch_and_add_8:
+ case Builtin::BI__sync_fetch_and_add_16:
+ case Builtin::BI__sync_fetch_and_sub:
+ case Builtin::BI__sync_fetch_and_sub_1:
+ case Builtin::BI__sync_fetch_and_sub_2:
+ case Builtin::BI__sync_fetch_and_sub_4:
+ case Builtin::BI__sync_fetch_and_sub_8:
+ case Builtin::BI__sync_fetch_and_sub_16:
+ case Builtin::BI__sync_fetch_and_or:
+ case Builtin::BI__sync_fetch_and_or_1:
+ case Builtin::BI__sync_fetch_and_or_2:
+ case Builtin::BI__sync_fetch_and_or_4:
+ case Builtin::BI__sync_fetch_and_or_8:
+ case Builtin::BI__sync_fetch_and_or_16:
+ case Builtin::BI__sync_fetch_and_and:
+ case Builtin::BI__sync_fetch_and_and_1:
+ case Builtin::BI__sync_fetch_and_and_2:
+ case Builtin::BI__sync_fetch_and_and_4:
+ case Builtin::BI__sync_fetch_and_and_8:
+ case Builtin::BI__sync_fetch_and_and_16:
+ case Builtin::BI__sync_fetch_and_xor:
+ case Builtin::BI__sync_fetch_and_xor_1:
+ case Builtin::BI__sync_fetch_and_xor_2:
+ case Builtin::BI__sync_fetch_and_xor_4:
+ case Builtin::BI__sync_fetch_and_xor_8:
+ case Builtin::BI__sync_fetch_and_xor_16:
+ case Builtin::BI__sync_fetch_and_nand:
+ case Builtin::BI__sync_fetch_and_nand_1:
+ case Builtin::BI__sync_fetch_and_nand_2:
+ case Builtin::BI__sync_fetch_and_nand_4:
+ case Builtin::BI__sync_fetch_and_nand_8:
+ case Builtin::BI__sync_fetch_and_nand_16:
+ case Builtin::BI__sync_add_and_fetch:
+ case Builtin::BI__sync_add_and_fetch_1:
+ case Builtin::BI__sync_add_and_fetch_2:
+ case Builtin::BI__sync_add_and_fetch_4:
+ case Builtin::BI__sync_add_and_fetch_8:
+ case Builtin::BI__sync_add_and_fetch_16:
+ case Builtin::BI__sync_sub_and_fetch:
+ case Builtin::BI__sync_sub_and_fetch_1:
+ case Builtin::BI__sync_sub_and_fetch_2:
+ case Builtin::BI__sync_sub_and_fetch_4:
+ case Builtin::BI__sync_sub_and_fetch_8:
+ case Builtin::BI__sync_sub_and_fetch_16:
+ case Builtin::BI__sync_and_and_fetch:
+ case Builtin::BI__sync_and_and_fetch_1:
+ case Builtin::BI__sync_and_and_fetch_2:
+ case Builtin::BI__sync_and_and_fetch_4:
+ case Builtin::BI__sync_and_and_fetch_8:
+ case Builtin::BI__sync_and_and_fetch_16:
+ case Builtin::BI__sync_or_and_fetch:
+ case Builtin::BI__sync_or_and_fetch_1:
+ case Builtin::BI__sync_or_and_fetch_2:
+ case Builtin::BI__sync_or_and_fetch_4:
+ case Builtin::BI__sync_or_and_fetch_8:
+ case Builtin::BI__sync_or_and_fetch_16:
+ case Builtin::BI__sync_xor_and_fetch:
+ case Builtin::BI__sync_xor_and_fetch_1:
+ case Builtin::BI__sync_xor_and_fetch_2:
+ case Builtin::BI__sync_xor_and_fetch_4:
+ case Builtin::BI__sync_xor_and_fetch_8:
+ case Builtin::BI__sync_xor_and_fetch_16:
+ case Builtin::BI__sync_nand_and_fetch:
+ case Builtin::BI__sync_nand_and_fetch_1:
+ case Builtin::BI__sync_nand_and_fetch_2:
+ case Builtin::BI__sync_nand_and_fetch_4:
+ case Builtin::BI__sync_nand_and_fetch_8:
+ case Builtin::BI__sync_nand_and_fetch_16:
+ case Builtin::BI__sync_val_compare_and_swap:
+ case Builtin::BI__sync_val_compare_and_swap_1:
+ case Builtin::BI__sync_val_compare_and_swap_2:
+ case Builtin::BI__sync_val_compare_and_swap_4:
+ case Builtin::BI__sync_val_compare_and_swap_8:
+ case Builtin::BI__sync_val_compare_and_swap_16:
+ case Builtin::BI__sync_bool_compare_and_swap:
+ case Builtin::BI__sync_bool_compare_and_swap_1:
+ case Builtin::BI__sync_bool_compare_and_swap_2:
+ case Builtin::BI__sync_bool_compare_and_swap_4:
+ case Builtin::BI__sync_bool_compare_and_swap_8:
+ case Builtin::BI__sync_bool_compare_and_swap_16:
+ case Builtin::BI__sync_lock_test_and_set:
+ case Builtin::BI__sync_lock_test_and_set_1:
+ case Builtin::BI__sync_lock_test_and_set_2:
+ case Builtin::BI__sync_lock_test_and_set_4:
+ case Builtin::BI__sync_lock_test_and_set_8:
+ case Builtin::BI__sync_lock_test_and_set_16:
+ case Builtin::BI__sync_lock_release:
+ case Builtin::BI__sync_lock_release_1:
+ case Builtin::BI__sync_lock_release_2:
+ case Builtin::BI__sync_lock_release_4:
+ case Builtin::BI__sync_lock_release_8:
+ case Builtin::BI__sync_lock_release_16:
+ case Builtin::BI__sync_swap:
+ case Builtin::BI__sync_swap_1:
+ case Builtin::BI__sync_swap_2:
+ case Builtin::BI__sync_swap_4:
+ case Builtin::BI__sync_swap_8:
+ case Builtin::BI__sync_swap_16:
+ return SemaBuiltinAtomicOverloaded(TheCallResult);
+ case Builtin::BI__builtin_nontemporal_load:
+ case Builtin::BI__builtin_nontemporal_store:
+ return SemaBuiltinNontemporalOverloaded(TheCallResult);
+#define BUILTIN(ID, TYPE, ATTRS)
+#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \
+ case Builtin::BI##ID: \
+ return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID);
+#include "clang/Basic/Builtins.def"
+ case Builtin::BI__annotation:
+ if (SemaBuiltinMSVCAnnotation(*this, TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_annotation:
+ if (SemaBuiltinAnnotation(*this, TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_addressof:
+ if (SemaBuiltinAddressof(*this, TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_add_overflow:
+ case Builtin::BI__builtin_sub_overflow:
+ case Builtin::BI__builtin_mul_overflow:
+ if (SemaBuiltinOverflow(*this, TheCall))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_operator_new:
+ case Builtin::BI__builtin_operator_delete: {
+ bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete;
+ ExprResult Res =
+ SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete);
+ if (Res.isInvalid())
+ CorrectDelayedTyposInExpr(TheCallResult.get());
+ return Res;
+ }
+ case Builtin::BI__builtin_dump_struct: {
+ // We first want to ensure we are called with 2 arguments
+ if (checkArgCount(*this, TheCall, 2))
+ return ExprError();
+ // Ensure that the first argument is of type 'struct XX *'
+ const Expr *PtrArg = TheCall->getArg(0)->IgnoreParenImpCasts();
+ const QualType PtrArgType = PtrArg->getType();
+ if (!PtrArgType->isPointerType() ||
+ !PtrArgType->getPointeeType()->isRecordType()) {
+ Diag(PtrArg->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << PtrArgType << "structure pointer" << 1 << 0 << 3 << 1 << PtrArgType
+ << "structure pointer";
+ return ExprError();
} // Ensure that the second argument is of type 'FunctionType' @@ -4392,415 +4395,419 @@ static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn, return false; } -/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' -/// for validity. Emit an error and return true on failure; return false -/// on success. -bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { - Expr *Fn = TheCall->getCallee(); - - if (checkVAStartABI(*this, BuiltinID, Fn)) - return true; - - if (TheCall->getNumArgs() > 2) { - Diag(TheCall->getArg(2)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << Fn->getSourceRange() - << SourceRange(TheCall->getArg(2)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); - return true; - } - - if (TheCall->getNumArgs() < 2) { - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs(); - } - - // Type-check the first argument normally. - if (checkBuiltinArgument(*this, TheCall, 0)) - return true; - - // Check that the current function is variadic, and get its last parameter. - ParmVarDecl *LastParam; - if (checkVAStartIsInVariadicFunction(*this, Fn, &LastParam)) - return true; - - // Verify that the second argument to the builtin is the last argument of the - // current function or method. - bool SecondArgIsLastNamedArgument = false; - const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts(); - - // These are valid if SecondArgIsLastNamedArgument is false after the next - // block. - QualType Type; - SourceLocation ParamLoc; - bool IsCRegister = false; - - if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) { - if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) { - SecondArgIsLastNamedArgument = PV == LastParam; - - Type = PV->getType(); - ParamLoc = PV->getLocation(); - IsCRegister = - PV->getStorageClass() == SC_Register && !getLangOpts().CPlusPlus; - } - } - - if (!SecondArgIsLastNamedArgument) - Diag(TheCall->getArg(1)->getLocStart(), - diag::warn_second_arg_of_va_start_not_last_named_param); - else if (IsCRegister || Type->isReferenceType() || - Type->isSpecificBuiltinType(BuiltinType::Float) || [=] { - // Promotable integers are UB, but enumerations need a bit of - // extra checking to see what their promotable type actually is. - if (!Type->isPromotableIntegerType()) - return false; - if (!Type->isEnumeralType()) - return true; - const EnumDecl *ED = Type->getAs<EnumType>()->getDecl(); - return !(ED && - Context.typesAreCompatible(ED->getPromotionType(), Type)); - }()) { - unsigned Reason = 0; - if (Type->isReferenceType()) Reason = 1; - else if (IsCRegister) Reason = 2; - Diag(Arg->getLocStart(), diag::warn_va_start_type_is_undefined) << Reason; - Diag(ParamLoc, diag::note_parameter_type) << Type; - } - - TheCall->setType(Context.VoidTy); - return false; -} - -bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) { - // void __va_start(va_list *ap, const char *named_addr, size_t slot_size, - // const char *named_addr); - - Expr *Func = Call->getCallee(); - - if (Call->getNumArgs() < 3) - return Diag(Call->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 3 << Call->getNumArgs(); - - // Type-check the first argument normally. - if (checkBuiltinArgument(*this, Call, 0)) - return true; - - // Check that the current function is variadic. - if (checkVAStartIsInVariadicFunction(*this, Func)) - return true; - - // __va_start on Windows does not validate the parameter qualifiers - - const Expr *Arg1 = Call->getArg(1)->IgnoreParens(); - const Type *Arg1Ty = Arg1->getType().getCanonicalType().getTypePtr(); - - const Expr *Arg2 = Call->getArg(2)->IgnoreParens(); - const Type *Arg2Ty = Arg2->getType().getCanonicalType().getTypePtr(); - - const QualType &ConstCharPtrTy = - Context.getPointerType(Context.CharTy.withConst()); - if (!Arg1Ty->isPointerType() || - Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy) - Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible) - << Arg1->getType() << ConstCharPtrTy - << 1 /* different class */ - << 0 /* qualifier difference */ - << 3 /* parameter mismatch */ - << 2 << Arg1->getType() << ConstCharPtrTy; - - const QualType SizeTy = Context.getSizeType(); - if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy) - Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible) - << Arg2->getType() << SizeTy - << 1 /* different class */ - << 0 /* qualifier difference */ - << 3 /* parameter mismatch */ - << 3 << Arg2->getType() << SizeTy; - - return false; -} - -/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and -/// friends. This is declared to take (...), so we have to check everything. -bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 2) - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << 2 << TheCall->getNumArgs()/*function call*/; - if (TheCall->getNumArgs() > 2) - return Diag(TheCall->getArg(2)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(2)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); - - ExprResult OrigArg0 = TheCall->getArg(0); - ExprResult OrigArg1 = TheCall->getArg(1); - - // Do standard promotions between the two arguments, returning their common - // type. - QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); - if (OrigArg0.isInvalid() || OrigArg1.isInvalid()) - return true; - - // Make sure any conversions are pushed back into the call; this is - // type safe since unordered compare builtins are declared as "_Bool - // foo(...)". - TheCall->setArg(0, OrigArg0.get()); - TheCall->setArg(1, OrigArg1.get()); - - if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent()) - return false; - - // If the common type isn't a real floating type, then the arguments were - // invalid for this operation. - if (Res.isNull() || !Res->isRealFloatingType()) - return Diag(OrigArg0.get()->getLocStart(), - diag::err_typecheck_call_invalid_ordered_compare) - << OrigArg0.get()->getType() << OrigArg1.get()->getType() - << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); - - return false; -} - -/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like -/// __builtin_isnan and friends. This is declared to take (...), so we have -/// to check everything. We expect the last argument to be a floating point -/// value. -bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { - if (TheCall->getNumArgs() < NumArgs) - return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) - << 0 << NumArgs << TheCall->getNumArgs()/*function call*/; - if (TheCall->getNumArgs() > NumArgs) - return Diag(TheCall->getArg(NumArgs)->getLocStart(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() - << SourceRange(TheCall->getArg(NumArgs)->getLocStart(), - (*(TheCall->arg_end()-1))->getLocEnd()); - - Expr *OrigArg = TheCall->getArg(NumArgs-1); - - if (OrigArg->isTypeDependent()) - return false; - - // This operation requires a non-_Complex floating-point number. - if (!OrigArg->getType()->isRealFloatingType()) - return Diag(OrigArg->getLocStart(), - diag::err_typecheck_call_invalid_unary_fp) - << OrigArg->getType() << OrigArg->getSourceRange(); - - // If this is an implicit conversion from float -> float or double, remove it. - if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) { - // Only remove standard FloatCasts, leaving other casts inplace - if (Cast->getCastKind() == CK_FloatingCast) { - Expr *CastArg = Cast->getSubExpr(); - if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { - assert((Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || - Cast->getType()->isSpecificBuiltinType(BuiltinType::Float)) && - "promotion from float to either float or double is the only expected cast here"); - Cast->setSubExpr(nullptr); - TheCall->setArg(NumArgs-1, CastArg); - } - } - } - - return false; -} - -// Customized Sema Checking for VSX builtins that have the following signature: -// vector [...] builtinName(vector [...], vector [...], const int); -// Which takes the same type of vectors (any legal vector type) for the first -// two arguments and takes compile time constant for the third argument. -// Example builtins are : -// vector double vec_xxpermdi(vector double, vector double, int); -// vector short vec_xxsldwi(vector short, vector short, int); -bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { - unsigned ExpectedNumArgs = 3; - if (TheCall->getNumArgs() < ExpectedNumArgs) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() - << TheCall->getSourceRange(); - - if (TheCall->getNumArgs() > ExpectedNumArgs) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs() - << TheCall->getSourceRange(); - - // Check the third argument is a compile time constant - llvm::APSInt Value; - if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context)) - return Diag(TheCall->getLocStart(), - diag::err_vsx_builtin_nonconstant_argument) - << 3 /* argument index */ << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(2)->getLocStart(), - TheCall->getArg(2)->getLocEnd()); - - QualType Arg1Ty = TheCall->getArg(0)->getType(); - QualType Arg2Ty = TheCall->getArg(1)->getType(); - - // Check the type of argument 1 and argument 2 are vectors. - SourceLocation BuiltinLoc = TheCall->getLocStart(); - if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) || - (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) { - return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - } - - // Check the first two arguments are the same type. - if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) { - return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd()); - } - - // When default clang type checking is turned off and the customized type - // checking is used, the returning type of the function must be explicitly - // set. Otherwise it is _Bool by default. - TheCall->setType(Arg1Ty); - - return false; -} - -/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. -// This is declared to take (...), so we have to check everything. -ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 2) - return ExprError(Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() - << TheCall->getSourceRange()); - - // Determine which of the following types of shufflevector we're checking: - // 1) unary, vector mask: (lhs, mask) - // 2) binary, scalar mask: (lhs, rhs, index, ..., index) - QualType resType = TheCall->getArg(0)->getType(); - unsigned numElements = 0; - - if (!TheCall->getArg(0)->isTypeDependent() && - !TheCall->getArg(1)->isTypeDependent()) { - QualType LHSType = TheCall->getArg(0)->getType(); - QualType RHSType = TheCall->getArg(1)->getType(); - - if (!LHSType->isVectorType() || !RHSType->isVectorType()) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_non_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); - - numElements = LHSType->getAs<VectorType>()->getNumElements(); - unsigned numResElements = TheCall->getNumArgs() - 2; - - // Check to see if we have a call with 2 vector arguments, the unary shuffle - // with mask. If so, verify that RHS is an integer vector type with the - // same number of elts as lhs. - if (TheCall->getNumArgs() == 2) { - if (!RHSType->hasIntegerRepresentation() || - RHSType->getAs<VectorType>()->getNumElements() != numElements) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_incompatible_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(1)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); - } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { - return ExprError(Diag(TheCall->getLocStart(), - diag::err_vec_builtin_incompatible_vector) - << TheCall->getDirectCallee() - << SourceRange(TheCall->getArg(0)->getLocStart(), - TheCall->getArg(1)->getLocEnd())); - } else if (numElements != numResElements) { - QualType eltType = LHSType->getAs<VectorType>()->getElementType(); - resType = Context.getVectorType(eltType, numResElements, - VectorType::GenericVector); - } - } - - for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { - if (TheCall->getArg(i)->isTypeDependent() || - TheCall->getArg(i)->isValueDependent()) - continue; - - llvm::APSInt Result(32); - if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_shufflevector_nonconstant_argument) - << TheCall->getArg(i)->getSourceRange()); - - // Allow -1 which will be translated to undef in the IR. - if (Result.isSigned() && Result.isAllOnesValue()) - continue; - - if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) - return ExprError(Diag(TheCall->getLocStart(), - diag::err_shufflevector_argument_too_large) - << TheCall->getArg(i)->getSourceRange()); - } - - SmallVector<Expr*, 32> exprs; - - for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { - exprs.push_back(TheCall->getArg(i)); - TheCall->setArg(i, nullptr); - } - - return new (Context) ShuffleVectorExpr(Context, exprs, resType, - TheCall->getCallee()->getLocStart(), - TheCall->getRParenLoc()); -} - -/// SemaConvertVectorExpr - Handle __builtin_convertvector -ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, - SourceLocation BuiltinLoc, - SourceLocation RParenLoc) { - ExprValueKind VK = VK_RValue; - ExprObjectKind OK = OK_Ordinary; - QualType DstTy = TInfo->getType(); - QualType SrcTy = E->getType(); - - if (!SrcTy->isVectorType() && !SrcTy->isDependentType()) - return ExprError(Diag(BuiltinLoc, - diag::err_convertvector_non_vector) - << E->getSourceRange()); - if (!DstTy->isVectorType() && !DstTy->isDependentType()) - return ExprError(Diag(BuiltinLoc, - diag::err_convertvector_non_vector_type)); - - if (!SrcTy->isDependentType() && !DstTy->isDependentType()) { - unsigned SrcElts = SrcTy->getAs<VectorType>()->getNumElements(); - unsigned DstElts = DstTy->getAs<VectorType>()->getNumElements(); - if (SrcElts != DstElts) - return ExprError(Diag(BuiltinLoc, - diag::err_convertvector_incompatible_vector) - << E->getSourceRange()); - } - - return new (Context) - ConvertVectorExpr(E, TInfo, DstTy, VK, OK, BuiltinLoc, RParenLoc); -} - -/// SemaBuiltinPrefetch - Handle __builtin_prefetch. -// This is declared to take (const void*, ...) and can take two -// optional constant int args. -bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { - unsigned NumArgs = TheCall->getNumArgs(); - - if (NumArgs > 3) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args_at_most) - << 0 /*function call*/ << 3 << NumArgs - << TheCall->getSourceRange(); - - // Argument 0 is checked for us and the remaining arguments must be - // constant integers. - for (unsigned i = 1; i != NumArgs; ++i) +/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start'
+/// for validity. Emit an error and return true on failure; return false
+/// on success.
+bool Sema::SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
+ Expr *Fn = TheCall->getCallee();
+
+ if (checkVAStartABI(*this, BuiltinID, Fn))
+ return true;
+
+ if (TheCall->getNumArgs() > 2) {
+ Diag(TheCall->getArg(2)->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+ << Fn->getSourceRange()
+ << SourceRange(TheCall->getArg(2)->getLocStart(),
+ (*(TheCall->arg_end()-1))->getLocEnd());
+ return true;
+ }
+
+ if (TheCall->getNumArgs() < 2) {
+ return Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_few_args_at_least)
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs();
+ }
+
+ // Type-check the first argument normally.
+ if (checkBuiltinArgument(*this, TheCall, 0))
+ return true;
+
+ // Check that the current function is variadic, and get its last parameter.
+ ParmVarDecl *LastParam;
+ if (checkVAStartIsInVariadicFunction(*this, Fn, &LastParam))
+ return true;
+
+ // Verify that the second argument to the builtin is the last argument of the
+ // current function or method.
+ bool SecondArgIsLastNamedArgument = false;
+ const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
+
+ // These are valid if SecondArgIsLastNamedArgument is false after the next
+ // block.
+ QualType Type;
+ SourceLocation ParamLoc;
+ bool IsCRegister = false;
+
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
+ if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
+ SecondArgIsLastNamedArgument = PV == LastParam;
+
+ Type = PV->getType();
+ ParamLoc = PV->getLocation();
+ IsCRegister =
+ PV->getStorageClass() == SC_Register && !getLangOpts().CPlusPlus;
+ }
+ }
+
+ if (!SecondArgIsLastNamedArgument)
+ Diag(TheCall->getArg(1)->getLocStart(),
+ diag::warn_second_arg_of_va_start_not_last_named_param);
+ else if (IsCRegister || Type->isReferenceType() ||
+ Type->isSpecificBuiltinType(BuiltinType::Float) || [=] {
+ // Promotable integers are UB, but enumerations need a bit of
+ // extra checking to see what their promotable type actually is.
+ if (!Type->isPromotableIntegerType())
+ return false;
+ if (!Type->isEnumeralType())
+ return true;
+ const EnumDecl *ED = Type->getAs<EnumType>()->getDecl();
+ return !(ED &&
+ Context.typesAreCompatible(ED->getPromotionType(), Type));
+ }()) {
+ unsigned Reason = 0;
+ if (Type->isReferenceType()) Reason = 1;
+ else if (IsCRegister) Reason = 2;
+ Diag(Arg->getLocStart(), diag::warn_va_start_type_is_undefined) << Reason;
+ Diag(ParamLoc, diag::note_parameter_type) << Type;
+ }
+
+ TheCall->setType(Context.VoidTy);
+ return false;
+}
+
+bool Sema::SemaBuiltinVAStartARMMicrosoft(CallExpr *Call) {
+ // void __va_start(va_list *ap, const char *named_addr, size_t slot_size,
+ // const char *named_addr);
+
+ Expr *Func = Call->getCallee();
+
+ if (Call->getNumArgs() < 3)
+ return Diag(Call->getLocEnd(),
+ diag::err_typecheck_call_too_few_args_at_least)
+ << 0 /*function call*/ << 3 << Call->getNumArgs();
+
+ // Type-check the first argument normally.
+ if (checkBuiltinArgument(*this, Call, 0))
+ return true;
+
+ // Check that the current function is variadic.
+ if (checkVAStartIsInVariadicFunction(*this, Func))
+ return true;
+
+ // __va_start on Windows does not validate the parameter qualifiers
+
+ const Expr *Arg1 = Call->getArg(1)->IgnoreParens();
+ const Type *Arg1Ty = Arg1->getType().getCanonicalType().getTypePtr();
+
+ const Expr *Arg2 = Call->getArg(2)->IgnoreParens();
+ const Type *Arg2Ty = Arg2->getType().getCanonicalType().getTypePtr();
+
+ const QualType &ConstCharPtrTy =
+ Context.getPointerType(Context.CharTy.withConst());
+ if (!Arg1Ty->isPointerType() ||
+ Arg1Ty->getPointeeType().withoutLocalFastQualifiers() != Context.CharTy)
+ Diag(Arg1->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << Arg1->getType() << ConstCharPtrTy
+ << 1 /* different class */
+ << 0 /* qualifier difference */
+ << 3 /* parameter mismatch */
+ << 2 << Arg1->getType() << ConstCharPtrTy;
+
+ const QualType SizeTy = Context.getSizeType();
+ if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy)
+ Diag(Arg2->getLocStart(), diag::err_typecheck_convert_incompatible)
+ << Arg2->getType() << SizeTy
+ << 1 /* different class */
+ << 0 /* qualifier difference */
+ << 3 /* parameter mismatch */
+ << 3 << Arg2->getType() << SizeTy;
+
+ return false;
+}
+
+/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and
+/// friends. This is declared to take (...), so we have to check everything.
+bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) {
+ if (TheCall->getNumArgs() < 2)
+ return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+ << 0 << 2 << TheCall->getNumArgs()/*function call*/;
+ if (TheCall->getNumArgs() > 2)
+ return Diag(TheCall->getArg(2)->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+ << SourceRange(TheCall->getArg(2)->getLocStart(),
+ (*(TheCall->arg_end()-1))->getLocEnd());
+
+ ExprResult OrigArg0 = TheCall->getArg(0);
+ ExprResult OrigArg1 = TheCall->getArg(1);
+
+ // Do standard promotions between the two arguments, returning their common
+ // type.
+ QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false);
+ if (OrigArg0.isInvalid() || OrigArg1.isInvalid())
+ return true;
+
+ // Make sure any conversions are pushed back into the call; this is
+ // type safe since unordered compare builtins are declared as "_Bool
+ // foo(...)".
+ TheCall->setArg(0, OrigArg0.get());
+ TheCall->setArg(1, OrigArg1.get());
+
+ if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent())
+ return false;
+
+ // If the common type isn't a real floating type, then the arguments were
+ // invalid for this operation.
+ if (Res.isNull() || !Res->isRealFloatingType())
+ return Diag(OrigArg0.get()->getLocStart(),
+ diag::err_typecheck_call_invalid_ordered_compare)
+ << OrigArg0.get()->getType() << OrigArg1.get()->getType()
+ << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd());
+
+ return false;
+}
+
+/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like
+/// __builtin_isnan and friends. This is declared to take (...), so we have
+/// to check everything. We expect the last argument to be a floating point
+/// value.
+bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
+ if (TheCall->getNumArgs() < NumArgs)
+ return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+ << 0 << NumArgs << TheCall->getNumArgs()/*function call*/;
+ if (TheCall->getNumArgs() > NumArgs)
+ return Diag(TheCall->getArg(NumArgs)->getLocStart(),
+ diag::err_typecheck_call_too_many_args)
+ << 0 /*function call*/ << NumArgs << TheCall->getNumArgs()
+ << SourceRange(TheCall->getArg(NumArgs)->getLocStart(),
+ (*(TheCall->arg_end()-1))->getLocEnd());
+
+ Expr *OrigArg = TheCall->getArg(NumArgs-1);
+
+ if (OrigArg->isTypeDependent())
+ return false;
+
+ // This operation requires a non-_Complex floating-point number.
+ if (!OrigArg->getType()->isRealFloatingType())
+ return Diag(OrigArg->getLocStart(),
+ diag::err_typecheck_call_invalid_unary_fp)
+ << OrigArg->getType() << OrigArg->getSourceRange();
+
+ // If this is an implicit conversion from float -> float, double, or
+ // long double, remove it.
+ if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) {
+ // Only remove standard FloatCasts, leaving other casts inplace
+ if (Cast->getCastKind() == CK_FloatingCast) {
+ Expr *CastArg = Cast->getSubExpr();
+ if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) {
+ assert(
+ (Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) ||
+ Cast->getType()->isSpecificBuiltinType(BuiltinType::Float) ||
+ Cast->getType()->isSpecificBuiltinType(BuiltinType::LongDouble)) &&
+ "promotion from float to either float, double, or long double is "
+ "the only expected cast here");
+ Cast->setSubExpr(nullptr);
+ TheCall->setArg(NumArgs-1, CastArg);
+ }
+ }
+ }
+
+ return false;
+}
+
+// Customized Sema Checking for VSX builtins that have the following signature:
+// vector [...] builtinName(vector [...], vector [...], const int);
+// Which takes the same type of vectors (any legal vector type) for the first
+// two arguments and takes compile time constant for the third argument.
+// Example builtins are :
+// vector double vec_xxpermdi(vector double, vector double, int);
+// vector short vec_xxsldwi(vector short, vector short, int);
+bool Sema::SemaBuiltinVSX(CallExpr *TheCall) {
+ unsigned ExpectedNumArgs = 3;
+ if (TheCall->getNumArgs() < ExpectedNumArgs)
+ return Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_few_args_at_least)
+ << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs()
+ << TheCall->getSourceRange();
+
+ if (TheCall->getNumArgs() > ExpectedNumArgs)
+ return Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_many_args_at_most)
+ << 0 /*function call*/ << ExpectedNumArgs << TheCall->getNumArgs()
+ << TheCall->getSourceRange();
+
+ // Check the third argument is a compile time constant
+ llvm::APSInt Value;
+ if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context))
+ return Diag(TheCall->getLocStart(),
+ diag::err_vsx_builtin_nonconstant_argument)
+ << 3 /* argument index */ << TheCall->getDirectCallee()
+ << SourceRange(TheCall->getArg(2)->getLocStart(),
+ TheCall->getArg(2)->getLocEnd());
+
+ QualType Arg1Ty = TheCall->getArg(0)->getType();
+ QualType Arg2Ty = TheCall->getArg(1)->getType();
+
+ // Check the type of argument 1 and argument 2 are vectors.
+ SourceLocation BuiltinLoc = TheCall->getLocStart();
+ if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||
+ (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {
+ return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
+ << TheCall->getDirectCallee()
+ << SourceRange(TheCall->getArg(0)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd());
+ }
+
+ // Check the first two arguments are the same type.
+ if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) {
+ return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
+ << TheCall->getDirectCallee()
+ << SourceRange(TheCall->getArg(0)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd());
+ }
+
+ // When default clang type checking is turned off and the customized type
+ // checking is used, the returning type of the function must be explicitly
+ // set. Otherwise it is _Bool by default.
+ TheCall->setType(Arg1Ty);
+
+ return false;
+}
+
+/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector.
+// This is declared to take (...), so we have to check everything.
+ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
+ if (TheCall->getNumArgs() < 2)
+ return ExprError(Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_few_args_at_least)
+ << 0 /*function call*/ << 2 << TheCall->getNumArgs()
+ << TheCall->getSourceRange());
+
+ // Determine which of the following types of shufflevector we're checking:
+ // 1) unary, vector mask: (lhs, mask)
+ // 2) binary, scalar mask: (lhs, rhs, index, ..., index)
+ QualType resType = TheCall->getArg(0)->getType();
+ unsigned numElements = 0;
+
+ if (!TheCall->getArg(0)->isTypeDependent() &&
+ !TheCall->getArg(1)->isTypeDependent()) {
+ QualType LHSType = TheCall->getArg(0)->getType();
+ QualType RHSType = TheCall->getArg(1)->getType();
+
+ if (!LHSType->isVectorType() || !RHSType->isVectorType())
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_vec_builtin_non_vector)
+ << TheCall->getDirectCallee()
+ << SourceRange(TheCall->getArg(0)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd()));
+
+ numElements = LHSType->getAs<VectorType>()->getNumElements();
+ unsigned numResElements = TheCall->getNumArgs() - 2;
+
+ // Check to see if we have a call with 2 vector arguments, the unary shuffle
+ // with mask. If so, verify that RHS is an integer vector type with the
+ // same number of elts as lhs.
+ if (TheCall->getNumArgs() == 2) {
+ if (!RHSType->hasIntegerRepresentation() ||
+ RHSType->getAs<VectorType>()->getNumElements() != numElements)
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_vec_builtin_incompatible_vector)
+ << TheCall->getDirectCallee()
+ << SourceRange(TheCall->getArg(1)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd()));
+ } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_vec_builtin_incompatible_vector)
+ << TheCall->getDirectCallee()
+ << SourceRange(TheCall->getArg(0)->getLocStart(),
+ TheCall->getArg(1)->getLocEnd()));
+ } else if (numElements != numResElements) {
+ QualType eltType = LHSType->getAs<VectorType>()->getElementType();
+ resType = Context.getVectorType(eltType, numResElements,
+ VectorType::GenericVector);
+ }
+ }
+
+ for (unsigned i = 2; i < TheCall->getNumArgs(); i++) {
+ if (TheCall->getArg(i)->isTypeDependent() ||
+ TheCall->getArg(i)->isValueDependent())
+ continue;
+
+ llvm::APSInt Result(32);
+ if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context))
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_shufflevector_nonconstant_argument)
+ << TheCall->getArg(i)->getSourceRange());
+
+ // Allow -1 which will be translated to undef in the IR.
+ if (Result.isSigned() && Result.isAllOnesValue())
+ continue;
+
+ if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2)
+ return ExprError(Diag(TheCall->getLocStart(),
+ diag::err_shufflevector_argument_too_large)
+ << TheCall->getArg(i)->getSourceRange());
+ }
+
+ SmallVector<Expr*, 32> exprs;
+
+ for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
+ exprs.push_back(TheCall->getArg(i));
+ TheCall->setArg(i, nullptr);
+ }
+
+ return new (Context) ShuffleVectorExpr(Context, exprs, resType,
+ TheCall->getCallee()->getLocStart(),
+ TheCall->getRParenLoc());
+}
+
+/// SemaConvertVectorExpr - Handle __builtin_convertvector
+ExprResult Sema::SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc) {
+ ExprValueKind VK = VK_RValue;
+ ExprObjectKind OK = OK_Ordinary;
+ QualType DstTy = TInfo->getType();
+ QualType SrcTy = E->getType();
+
+ if (!SrcTy->isVectorType() && !SrcTy->isDependentType())
+ return ExprError(Diag(BuiltinLoc,
+ diag::err_convertvector_non_vector)
+ << E->getSourceRange());
+ if (!DstTy->isVectorType() && !DstTy->isDependentType())
+ return ExprError(Diag(BuiltinLoc,
+ diag::err_convertvector_non_vector_type));
+
+ if (!SrcTy->isDependentType() && !DstTy->isDependentType()) {
+ unsigned SrcElts = SrcTy->getAs<VectorType>()->getNumElements();
+ unsigned DstElts = DstTy->getAs<VectorType>()->getNumElements();
+ if (SrcElts != DstElts)
+ return ExprError(Diag(BuiltinLoc,
+ diag::err_convertvector_incompatible_vector)
+ << E->getSourceRange());
+ }
+
+ return new (Context)
+ ConvertVectorExpr(E, TInfo, DstTy, VK, OK, BuiltinLoc, RParenLoc);
+}
+
+/// SemaBuiltinPrefetch - Handle __builtin_prefetch.
+// This is declared to take (const void*, ...) and can take two
+// optional constant int args.
+bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
+ unsigned NumArgs = TheCall->getNumArgs();
+
+ if (NumArgs > 3)
+ return Diag(TheCall->getLocEnd(),
+ diag::err_typecheck_call_too_many_args_at_most)
+ << 0 /*function call*/ << 3 << NumArgs
+ << TheCall->getSourceRange();
+
+ // Argument 0 is checked for us and the remaining arguments must be
+ // constant integers.
+ for (unsigned i = 1; i != NumArgs; ++i)
if (SemaBuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3)) return true; |