diff options
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 1625 |
1 files changed, 809 insertions, 816 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index e18dd056e90..5530bd8fe76 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -772,409 +772,406 @@ 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:
- 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();
+ // 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(); } // Ensure that the second argument is of type 'FunctionType' @@ -4395,419 +4392,415 @@ 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, 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)
+/// 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) if (SemaBuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3)) return true; |