-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang][NFC] Move more things out of SemaChecking.cpp
#96641
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-hlsl Author: Vlad Serebrennikov (Endilll) ChangesThis patch moves some functions out of This patch continues the effort of splitting Patch is 111.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/96641.diff 9 Files Affected:
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2e7af0f691cbb..bbbaf245eb63a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2114,8 +2114,6 @@ class Sema final : public SemaBase {
bool FormatStringHasSArg(const StringLiteral *FExpr);
- static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
-
void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
BinaryOperatorKind Opcode);
@@ -2228,8 +2226,6 @@ class Sema final : public SemaBase {
bool BuiltinVectorMath(CallExpr *TheCall, QualType &Res);
bool BuiltinVectorToScalarMath(CallExpr *TheCall);
- bool CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-
void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
const Expr *ThisArg, ArrayRef<const Expr *> Args,
bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
@@ -2259,6 +2255,14 @@ class Sema final : public SemaBase {
bool ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
+ void CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC,
+ bool *ICContext = nullptr,
+ bool IsListInit = false);
+
+ bool BuiltinElementwiseTernaryMath(CallExpr *TheCall,
+ bool CheckForFloatArgs = true);
+ bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);
+
private:
void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
const ArraySubscriptExpr *ASE = nullptr,
@@ -2306,9 +2310,6 @@ class Sema final : public SemaBase {
AtomicExpr::AtomicOp Op);
bool BuiltinElementwiseMath(CallExpr *TheCall);
- bool BuiltinElementwiseTernaryMath(CallExpr *TheCall,
- bool CheckForFloatArgs = true);
- bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);
bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall);
bool BuiltinNonDeterministicValue(CallExpr *TheCall);
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 0e41a72e444ef..4d6958a1be3e5 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -58,6 +58,8 @@ class SemaHLSL : public SemaBase {
void handleShaderAttr(Decl *D, const ParsedAttr &AL);
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
+
+ bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
};
} // namespace clang
diff --git a/clang/include/clang/Sema/SemaObjC.h b/clang/include/clang/Sema/SemaObjC.h
index bb8887691ce5d..07c3c1a06be16 100644
--- a/clang/include/clang/Sema/SemaObjC.h
+++ b/clang/include/clang/Sema/SemaObjC.h
@@ -158,6 +158,27 @@ class SemaObjC : public SemaBase {
IdentifierInfo *getNSErrorIdent();
+ bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
+
+ /// Diagnose use of %s directive in an NSString which is being passed
+ /// as formatting string to formatting method.
+ void DiagnoseCStringFormatDirectiveInCFAPI(const NamedDecl *FDecl,
+ Expr **Args, unsigned NumArgs);
+
+ bool isSignedCharBool(QualType Ty);
+
+ void adornBoolConversionDiagWithTernaryFixit(
+ Expr *SourceExpr, const Sema::SemaDiagnosticBuilder &Builder);
+
+ /// Check an Objective-C dictionary literal being converted to the given
+ /// target type.
+ void checkDictionaryLiteral(QualType TargetType,
+ ObjCDictionaryLiteral *DictionaryLiteral);
+
+ /// Check an Objective-C array literal being converted to the given
+ /// target type.
+ void checkArrayLiteral(QualType TargetType, ObjCArrayLiteral *ArrayLiteral);
+
private:
IdentifierInfo *Ident_NSError = nullptr;
diff --git a/clang/include/clang/Sema/SemaOpenCL.h b/clang/include/clang/Sema/SemaOpenCL.h
index 0d80c4b4c0b56..7d6b4b0dec09c 100644
--- a/clang/include/clang/Sema/SemaOpenCL.h
+++ b/clang/include/clang/Sema/SemaOpenCL.h
@@ -28,6 +28,78 @@ class SemaOpenCL : public SemaBase {
// Handles intel_reqd_sub_group_size.
void handleSubGroupSize(Decl *D, const ParsedAttr &AL);
+
+ // Performs semantic analysis for the read/write_pipe call.
+ // \param S Reference to the semantic analyzer.
+ // \param Call A pointer to the builtin call.
+ // \return True if a semantic error has been found, false otherwise.
+ bool checkBuiltinRWPipe(CallExpr *Call);
+
+ // Performs a semantic analysis on the {work_group_/sub_group_
+ // /_}reserve_{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.
+ bool checkBuiltinReserveRWPipe(CallExpr *Call);
+
+ bool checkSubgroupExt(CallExpr *Call);
+
+ // 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.
+ bool checkBuiltinCommitRWPipe(CallExpr *Call);
+
+ // 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.
+ bool checkBuiltinPipePackets(CallExpr *Call);
+
+ // 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.
+ bool checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call);
+
+ /// OpenCL C v2.0, s6.13.17 - Enqueue kernel function contains four different
+ /// overload formats specified in Table 6.13.17.1.
+ /// int enqueue_kernel(queue_t queue,
+ /// kernel_enqueue_flags_t flags,
+ /// const ndrange_t ndrange,
+ /// void (^block)(void))
+ /// int enqueue_kernel(queue_t queue,
+ /// kernel_enqueue_flags_t flags,
+ /// const ndrange_t ndrange,
+ /// uint num_events_in_wait_list,
+ /// clk_event_t *event_wait_list,
+ /// clk_event_t *event_ret,
+ /// void (^block)(void))
+ /// int enqueue_kernel(queue_t queue,
+ /// kernel_enqueue_flags_t flags,
+ /// const ndrange_t ndrange,
+ /// void (^block)(local void*, ...),
+ /// uint size0, ...)
+ /// int enqueue_kernel(queue_t queue,
+ /// kernel_enqueue_flags_t flags,
+ /// const ndrange_t ndrange,
+ /// uint num_events_in_wait_list,
+ /// clk_event_t *event_wait_list,
+ /// clk_event_t *event_ret,
+ /// void (^block)(local void*, ...),
+ /// uint size0, ...)
+ bool checkBuiltinEnqueueKernel(CallExpr *TheCall);
+
+ /// OpenCL C v2.0, s6.13.17.6 - Check the argument to the
+ /// get_kernel_work_group_size
+ /// and get_kernel_preferred_work_group_size_multiple builtin functions.
+ bool checkBuiltinKernelWorkGroupSize(CallExpr *TheCall);
+
+ bool checkBuiltinNDRangeAndBlock(CallExpr *TheCall);
};
} // namespace clang
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 87988519e7691..099439491205c 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -64,12 +64,14 @@
#include "clang/Sema/SemaAMDGPU.h"
#include "clang/Sema/SemaARM.h"
#include "clang/Sema/SemaBPF.h"
+#include "clang/Sema/SemaHLSL.h"
#include "clang/Sema/SemaHexagon.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/SemaLoongArch.h"
#include "clang/Sema/SemaMIPS.h"
#include "clang/Sema/SemaNVPTX.h"
#include "clang/Sema/SemaObjC.h"
+#include "clang/Sema/SemaOpenCL.h"
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSystemZ.h"
@@ -1459,528 +1461,6 @@ static bool BuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall,
return false;
}
-static inline bool isBlockPointer(Expr *Arg) {
- return Arg->getType()->isBlockPointerType();
-}
-
-/// OpenCL C v2.0, s6.13.17.2 - Checks that the block parameters are all local
-/// void*, which is a requirement of device side enqueue.
-static bool checkOpenCLBlockArgs(Sema &S, Expr *BlockArg) {
- const BlockPointerType *BPT =
- cast<BlockPointerType>(BlockArg->getType().getCanonicalType());
- ArrayRef<QualType> Params =
- BPT->getPointeeType()->castAs<FunctionProtoType>()->getParamTypes();
- unsigned ArgCounter = 0;
- bool IllegalParams = false;
- // Iterate through the block parameters until either one is found that is not
- // a local void*, or the block is valid.
- for (ArrayRef<QualType>::iterator I = Params.begin(), E = Params.end();
- I != E; ++I, ++ArgCounter) {
- if (!(*I)->isPointerType() || !(*I)->getPointeeType()->isVoidType() ||
- (*I)->getPointeeType().getQualifiers().getAddressSpace() !=
- LangAS::opencl_local) {
- // Get the location of the error. If a block literal has been passed
- // (BlockExpr) then we can point straight to the offending argument,
- // else we just point to the variable reference.
- SourceLocation ErrorLoc;
- if (isa<BlockExpr>(BlockArg)) {
- BlockDecl *BD = cast<BlockExpr>(BlockArg)->getBlockDecl();
- ErrorLoc = BD->getParamDecl(ArgCounter)->getBeginLoc();
- } else if (isa<DeclRefExpr>(BlockArg)) {
- ErrorLoc = cast<DeclRefExpr>(BlockArg)->getBeginLoc();
- }
- S.Diag(ErrorLoc,
- diag::err_opencl_enqueue_kernel_blocks_non_local_void_args);
- IllegalParams = true;
- }
- }
-
- return IllegalParams;
-}
-
-static bool checkOpenCLSubgroupExt(Sema &S, CallExpr *Call) {
- // OpenCL device can support extension but not the feature as extension
- // requires subgroup independent forward progress, but subgroup independent
- // forward progress is optional in OpenCL C 3.0 __opencl_c_subgroups feature.
- if (!S.getOpenCLOptions().isSupported("cl_khr_subgroups", S.getLangOpts()) &&
- !S.getOpenCLOptions().isSupported("__opencl_c_subgroups",
- S.getLangOpts())) {
- S.Diag(Call->getBeginLoc(), diag::err_opencl_requires_extension)
- << 1 << Call->getDirectCallee()
- << "cl_khr_subgroups or __opencl_c_subgroups";
- return true;
- }
- return false;
-}
-
-static bool OpenCLBuiltinNDRangeAndBlock(Sema &S, CallExpr *TheCall) {
- if (S.checkArgCount(TheCall, 2))
- return true;
-
- if (checkOpenCLSubgroupExt(S, TheCall))
- return true;
-
- // First argument is an ndrange_t type.
- Expr *NDRangeArg = TheCall->getArg(0);
- if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
- S.Diag(NDRangeArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee() << "'ndrange_t'";
- return true;
- }
-
- Expr *BlockArg = TheCall->getArg(1);
- if (!isBlockPointer(BlockArg)) {
- S.Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee() << "block";
- return true;
- }
- return checkOpenCLBlockArgs(S, BlockArg);
-}
-
-/// OpenCL C v2.0, s6.13.17.6 - Check the argument to the
-/// get_kernel_work_group_size
-/// and get_kernel_preferred_work_group_size_multiple builtin functions.
-static bool OpenCLBuiltinKernelWorkGroupSize(Sema &S, CallExpr *TheCall) {
- if (S.checkArgCount(TheCall, 1))
- return true;
-
- Expr *BlockArg = TheCall->getArg(0);
- if (!isBlockPointer(BlockArg)) {
- S.Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee() << "block";
- return true;
- }
- return checkOpenCLBlockArgs(S, BlockArg);
-}
-
-/// Diagnose integer type and any valid implicit conversion to it.
-static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E,
- const QualType &IntType);
-
-static bool checkOpenCLEnqueueLocalSizeArgs(Sema &S, CallExpr *TheCall,
- unsigned Start, unsigned End) {
- bool IllegalParams = false;
- for (unsigned I = Start; I <= End; ++I)
- IllegalParams |= checkOpenCLEnqueueIntType(S, TheCall->getArg(I),
- S.Context.getSizeType());
- return IllegalParams;
-}
-
-/// OpenCL v2.0, s6.13.17.1 - Check that sizes are provided for all
-/// 'local void*' parameter of passed block.
-static bool checkOpenCLEnqueueVariadicArgs(Sema &S, CallExpr *TheCall,
- Expr *BlockArg,
- unsigned NumNonVarArgs) {
- const BlockPointerType *BPT =
- cast<BlockPointerType>(BlockArg->getType().getCanonicalType());
- unsigned NumBlockParams =
- BPT->getPointeeType()->castAs<FunctionProtoType>()->getNumParams();
- unsigned TotalNumArgs = TheCall->getNumArgs();
-
- // For each argument passed to the block, a corresponding uint needs to
- // be passed to describe the size of the local memory.
- if (TotalNumArgs != NumBlockParams + NumNonVarArgs) {
- S.Diag(TheCall->getBeginLoc(),
- diag::err_opencl_enqueue_kernel_local_size_args);
- return true;
- }
-
- // Check that the sizes of the local memory are specified by integers.
- return checkOpenCLEnqueueLocalSizeArgs(S, TheCall, NumNonVarArgs,
- TotalNumArgs - 1);
-}
-
-/// OpenCL C v2.0, s6.13.17 - Enqueue kernel function contains four different
-/// overload formats specified in Table 6.13.17.1.
-/// int enqueue_kernel(queue_t queue,
-/// kernel_enqueue_flags_t flags,
-/// const ndrange_t ndrange,
-/// void (^block)(void))
-/// int enqueue_kernel(queue_t queue,
-/// kernel_enqueue_flags_t flags,
-/// const ndrange_t ndrange,
-/// uint num_events_in_wait_list,
-/// clk_event_t *event_wait_list,
-/// clk_event_t *event_ret,
-/// void (^block)(void))
-/// int enqueue_kernel(queue_t queue,
-/// kernel_enqueue_flags_t flags,
-/// const ndrange_t ndrange,
-/// void (^block)(local void*, ...),
-/// uint size0, ...)
-/// int enqueue_kernel(queue_t queue,
-/// kernel_enqueue_flags_t flags,
-/// const ndrange_t ndrange,
-/// uint num_events_in_wait_list,
-/// clk_event_t *event_wait_list,
-/// clk_event_t *event_ret,
-/// void (^block)(local void*, ...),
-/// uint size0, ...)
-static bool OpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
- unsigned NumArgs = TheCall->getNumArgs();
-
- if (NumArgs < 4) {
- S.Diag(TheCall->getBeginLoc(),
- diag::err_typecheck_call_too_few_args_at_least)
- << 0 << 4 << NumArgs << /*is non object*/ 0;
- return true;
- }
-
- Expr *Arg0 = TheCall->getArg(0);
- Expr *Arg1 = TheCall->getArg(1);
- Expr *Arg2 = TheCall->getArg(2);
- Expr *Arg3 = TheCall->getArg(3);
-
- // First argument always needs to be a queue_t type.
- if (!Arg0->getType()->isQueueT()) {
- S.Diag(TheCall->getArg(0)->getBeginLoc(),
- diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee() << S.Context.OCLQueueTy;
- return true;
- }
-
- // Second argument always needs to be a kernel_enqueue_flags_t enum value.
- if (!Arg1->getType()->isIntegerType()) {
- S.Diag(TheCall->getArg(1)->getBeginLoc(),
- diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee() << "'kernel_enqueue_flags_t' (i.e. uint)";
- return true;
- }
-
- // Third argument is always an ndrange_t type.
- if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
- S.Diag(TheCall->getArg(2)->getBeginLoc(),
- diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee() << "'ndrange_t'";
- return true;
- }
-
- // With four arguments, there is only one form that the function could be
- // called in: no events and no variable arguments.
- if (NumArgs == 4) {
- // check that the last argument is the right block type.
- if (!isBlockPointer(Arg3)) {
- S.Diag(Arg3->getBeginLoc(), diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee() << "block";
- return true;
- }
- // we have a block type, check the prototype
- const BlockPointerType *BPT =
- cast<BlockPointerType>(Arg3->getType().getCanonicalType());
- if (BPT->getPointeeType()->castAs<FunctionProtoType>()->getNumParams() > 0) {
- S.Diag(Arg3->getBeginLoc(),
- diag::err_opencl_enqueue_kernel_blocks_no_args);
- return true;
- }
- return false;
- }
- // we can have block + varargs.
- if (isBlockPointer(Arg3))
- return (checkOpenCLBlockArgs(S, Arg3) ||
- checkOpenCLEnqueueVariadicArgs(S, TheCall, Arg3, 4));
- // last two cases with either exactly 7 args or 7 args and varargs.
- if (NumArgs >= 7) {
- // check common block argument.
- Expr *Arg6 = TheCall->getArg(6);
- if (!isBlockPointer(Arg6)) {
- S.Diag(Arg6->getBeginLoc(), diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee() << "block";
- return true;
- }
- if (checkOpenCLBlockArgs(S, Arg6))
- return true;
-
- // Forth argument has to be any integer type.
- if (!Arg3->getType()->isIntegerType()) {
- S.Diag(TheCall->getArg(3)->getBeginLoc(),
- diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee() << "integer";
- return true;
- }
- // check remaining common arguments.
- Expr *Arg4 = TheCall->getArg(4);
- Expr *Arg5 = TheCall->getArg(5);
-
- // Fifth argument is always passed as a pointer to clk_event_t.
- if (!Arg4->isNullPointerConstant(S.Context,
- Expr::NPC_ValueDependentIsNotNull) &&
- !Arg4->getType()->getPointeeOrArrayElementType()->isClkEventT()) {
- S.Diag(TheCall->getArg(4)->getBeginLoc(),
- diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee()
- << S.Context.getPointerType(S.Context.OCLClkEventTy);
- return true;
- }
-
- // Sixth argument is always passed as a pointer to clk_event_t.
- if (!Arg5->isNullPointerConstant(S.Context,
- Expr::NPC_ValueDependentIsNotNull) &&
- !(Arg5->getType()->isPointerType() &&
- Arg5->getType()->getPointeeType()->isClkEventT())) {
- S.Diag(TheCall->getArg(5)->getBeginLoc(),
- diag::err_opencl_builtin_expected_type)
- << TheCall->getDirectCallee()
- << S.Context.getPointerType(S.Context.OCLClkEventTy);
- return true;
- }
-
- if (NumArgs == 7)
- return false;
-
- return checkOpenCLEnqueueVariadicArgs(S, TheCall, Arg6, 7);
- }
-
- // None of the specific case has been detected, give generic error
- S.Diag(TheCall->getBeginLoc(),
- diag::err_opencl_enqueue_kernel_incorrect_args);
- return true;
-}
-
-/// Returns OpenCL access qual.
-static OpenCLAccessAttr *getOpenCLArgAccess(const Decl *D) {
- return D->getAttr<OpenCLAccessAttr>();
-}
-
-/// Returns true if pipe element type is different from the pointer.
-static bool checkOpenCLPipeArg(Sema &S, CallExpr *Call) {
- const Expr *Arg0 = Call->getArg(0);
- // First argument type should always be pipe.
- if (!Arg0->getType()->isPipeType()) {
- S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
- << Call->getDirectCallee() << Arg0->getS...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HLSL changes look good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, nice refactoring!
This patch moves some functions out of `SemaChecking.cpp`. ObjC-, HLSL-, OpenCL-related functions are affected. This patch continues the effort of splitting `Sema` into parts. Additional context can be found in llvm#84184 and llvm#92682.
This patch moves some functions out of `SemaChecking.cpp`. ObjC-, HLSL-, OpenCL-related functions are affected. This patch continues the effort of splitting `Sema` into parts. Additional context can be found in llvm#84184 and llvm#92682.
This patch moves some functions out of
SemaChecking.cpp
. ObjC-, HLSL-, OpenCL-related functions are affected.This patch continues the effort of splitting
Sema
into parts. Additional context can be found in #84184 and #92682.