llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: UnknownUser (Z3rox-dev) <details> <summary>Changes</summary> ## Summary Add defensive `assert` checks for all `getAs<>()` calls in `CGCUDARuntime.cpp` that were previously dereferenced without null verification. ## Details The file had **8 unchecked `getAs<>()`** calls across `emitGetParamBuf()` and `EmitCUDADeviceKernelCallExpr()`, including chained dereferences like: ```cpp E->getCallee()->getType()->getAs<PointerType>()->getPointeeType(); ``` where a null return from `getAs<PointerType>()` would cause an immediate crash with no diagnostic. ### Changes: - Added `assert()` null checks for all `getAs<PointerType>()` and `getAs<FunctionProtoType>()` results - Eliminated **3 redundant `getAs<>()` calls** by caching results in local variables (`KernelPT`, `KernelFPT`, `LaunchPT`, `LaunchFPT`) - Broke chained dereferences into separate, checked steps ### Motivation: While Sema validation currently prevents these types from being null in practice, this change: 1. Follows the established defensive coding pattern used elsewhere in CodeGen (e.g., `CGExprScalar.cpp`, `CGObjCMac.cpp`) 2. Provides executable documentation of the implicit type contract 3. Improves debuggability in assertion-enabled builds 4. Makes the code more resilient to future refactoring that might alter Sema guarantees **NFC** (no functional change in release builds — asserts are compiled out). ## Testing - `check-clang-codegen-cuda`: **75/75 passed** - `check-clang-sema-cuda`: **99/99 passed** - `clang-format`: clean --- Full diff: https://github.com/llvm/llvm-project/pull/181167.diff 1 Files Affected: - (modified) clang/lib/CodeGen/CGCUDARuntime.cpp (+20-14) ``````````diff diff --git a/clang/lib/CodeGen/CGCUDARuntime.cpp b/clang/lib/CodeGen/CGCUDARuntime.cpp index 9c831b26c3a7b..545233e4f1221 100644 --- a/clang/lib/CodeGen/CGCUDARuntime.cpp +++ b/clang/lib/CodeGen/CGCUDARuntime.cpp @@ -27,6 +27,8 @@ static llvm::Value *emitGetParamBuf(CodeGenFunction &CGF, auto *GetParamBuf = CGF.getContext().getcudaGetParameterBufferDecl(); const FunctionProtoType *GetParamBufProto = GetParamBuf->getType()->getAs<FunctionProtoType>(); + assert(GetParamBufProto && + "cudaGetParameterBuffer must have function proto type"); DeclRefExpr *DRE = DeclRefExpr::Create( CGF.getContext(), {}, {}, GetParamBuf, @@ -43,8 +45,10 @@ static llvm::Value *emitGetParamBuf(CodeGenFunction &CGF, CGF.getContext().getSizeType()); // Calculate parameter sizes. const PointerType *PT = E->getCallee()->getType()->getAs<PointerType>(); + assert(PT && "CUDA kernel callee must be a pointer type"); const FunctionProtoType *FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); + assert(FTP && "CUDA kernel callee must be a function proto type"); CharUnits Offset = CharUnits::Zero(); for (auto ArgTy : FTP->getParamTypes()) { auto TInfo = CGF.CGM.getContext().getTypeInfoInChars(ArgTy); @@ -79,14 +83,16 @@ RValue CGCUDARuntime::EmitCUDADeviceKernelCallExpr( eval.begin(CGF); CGF.EmitBlock(ConfigOKBlock); - QualType KernelCalleeFuncTy = - E->getCallee()->getType()->getAs<PointerType>()->getPointeeType(); + const auto *KernelPT = E->getCallee()->getType()->getAs<PointerType>(); + assert(KernelPT && "CUDA kernel callee must be a pointer type"); + QualType KernelCalleeFuncTy = KernelPT->getPointeeType(); CGCallee KernelCallee = CGF.EmitCallee(E->getCallee()); // Emit kernel arguments. CallArgList KernelCallArgs; - CGF.EmitCallArgs(KernelCallArgs, - KernelCalleeFuncTy->getAs<FunctionProtoType>(), - E->arguments(), E->getDirectCallee()); + const auto *KernelFPT = KernelCalleeFuncTy->getAs<FunctionProtoType>(); + assert(KernelFPT && "CUDA kernel callee must be a function proto type"); + CGF.EmitCallArgs(KernelCallArgs, KernelFPT, E->arguments(), + E->getDirectCallee()); // Copy emitted kernel arguments into that parameter buffer. RawAddress CfgBase(Config, CGM.Int8Ty, /*Alignment=*/CharUnits::fromQuantity(64)); @@ -101,22 +107,22 @@ RValue CGCUDARuntime::EmitCUDADeviceKernelCallExpr( } // Make `cudaLaunchDevice` call, i.e. E->getConfig(). const CallExpr *LaunchCall = E->getConfig(); - QualType LaunchCalleeFuncTy = LaunchCall->getCallee() - ->getType() - ->getAs<PointerType>() - ->getPointeeType(); + const auto *LaunchPT = + LaunchCall->getCallee()->getType()->getAs<PointerType>(); + assert(LaunchPT && "CUDA launch callee must be a pointer type"); + QualType LaunchCalleeFuncTy = LaunchPT->getPointeeType(); CGCallee LaunchCallee = CGF.EmitCallee(LaunchCall->getCallee()); CallArgList LaunchCallArgs; - CGF.EmitCallArgs(LaunchCallArgs, - LaunchCalleeFuncTy->getAs<FunctionProtoType>(), - LaunchCall->arguments(), LaunchCall->getDirectCallee()); + const auto *LaunchFPT = LaunchCalleeFuncTy->getAs<FunctionProtoType>(); + assert(LaunchFPT && "CUDA launch callee must be a function proto type"); + CGF.EmitCallArgs(LaunchCallArgs, LaunchFPT, LaunchCall->arguments(), + LaunchCall->getDirectCallee()); // Replace func and paramterbuffer arguments. LaunchCallArgs[0] = CallArg(RValue::get(KernelCallee.getFunctionPointer()), CGM.getContext().VoidPtrTy); LaunchCallArgs[1] = CallArg(RValue::get(Config), CGM.getContext().VoidPtrTy); const CGFunctionInfo &LaunchCallInfo = CGM.getTypes().arrangeFreeFunctionCall( - LaunchCallArgs, LaunchCalleeFuncTy->getAs<FunctionProtoType>(), - /*ChainCall=*/false); + LaunchCallArgs, LaunchFPT, /*ChainCall=*/false); CGF.EmitCall(LaunchCallInfo, LaunchCallee, ReturnValue, LaunchCallArgs, CallOrInvoke, /*IsMustTail=*/false, E->getExprLoc()); `````````` </details> https://github.com/llvm/llvm-project/pull/181167 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
