Author: Anthony Tran Date: 2025-07-26T08:50:25-07:00 New Revision: 29992cfd628ed5b968ccb73b17ed0521382ba317
URL: https://github.com/llvm/llvm-project/commit/29992cfd628ed5b968ccb73b17ed0521382ba317 DIFF: https://github.com/llvm/llvm-project/commit/29992cfd628ed5b968ccb73b17ed0521382ba317.diff LOG: [Clang][CodeGen] Emit “trap reasons” on UBSan traps (#145967) This patch adds a human readable trap category and message to UBSan traps. The category and message are encoded in a fake frame in the debug info where the function is a fake inline function where the name encodes the trap category and message. This is the same mechanism used by Clang’s `__builtin_verbose_trap()`. This change allows consumers of binaries built with trapping UBSan to more easily identify the reason for trapping. In particular LLDB already has a frame recognizer that recognizes the fake function names emitted in debug info by this patch. A patch testing this behavior in LLDB will be added in a separately. The human readable trap messages are based on the messages currently emitted by the userspace runtime for UBSan in compiler-rt. Note the wording is not identical because the userspace UBSan runtime has access to dynamic information that is not available during Clang’s codegen. Test cases for each UBSan trap kind are included. This complements the [`-fsanitize-annotate-debug-info` feature](https://github.com/llvm/llvm-project/pull/141997). While `-fsanitize-annotate-debug-info` attempts to annotate all UBSan-added instructions, this feature (`-fsanitize-debug-trap-reasons`) only annotates the final trap instruction using SanitizerHandler information. This work is part of a GSoc 2025 project. Added: clang/test/CodeGen/ubsan-trap-reason-add-overflow.c clang/test/CodeGen/ubsan-trap-reason-alignment-assumption.c clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c clang/test/CodeGen/ubsan-trap-reason-cfi-check-fail.c clang/test/CodeGen/ubsan-trap-reason-crash.cpp clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c clang/test/CodeGen/ubsan-trap-reason-dynamic-type-cache-miss.cpp clang/test/CodeGen/ubsan-trap-reason-flag.c clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c clang/test/CodeGen/ubsan-trap-reason-invalid-objc-cast.m clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c clang/test/CodeGen/ubsan-trap-reason-nullability-return.c clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c clang/test/CodeGen/ubsan-trap-reason-type-mismatch.c clang/test/CodeGen/ubsan-trap-reason-vla-bound-not-positive.c Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Driver/Options.td clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/SanitizerHandler.h clang/lib/Driver/SanitizerArgs.cpp clang/test/CodeGen/bounds-checking-debuginfo.c clang/test/CodeGen/cfi-icall-generalize-debuginfo.c clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c clang/test/CodeGen/ubsan-trap-debugloc.c Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ec51ffddce1af..95a0bbf734056 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -89,9 +89,18 @@ Non-comprehensive list of changes in this release ------------------------------------------------- - Added ``__builtin_elementwise_minnumnum`` and ``__builtin_elementwise_maxnumnum``. +- Trapping UBSan (e.g. ``-fsanitize-trap=undefined``) now emits a string describing the reason for + trapping into the generated debug info. This feature allows debuggers (e.g. LLDB) to display + the reason for trapping if the trap is reached. The string is currently encoded in the debug + info as an artificial frame that claims to be inlined at the trap location. The function used + for the artificial frame is an artificial function whose name encodes the reason for trapping. + The encoding used is currently the same as ``__builtin_verbose_trap`` but might change in the future. + This feature is enabled by default but can be disabled by compiling with + ``-fno-sanitize-annotate-debug-info-traps``. New Compiler Flags ------------------ +- New option ``-fno-sanitize-annotate-debug-info-traps`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``). Deprecated Compiler Flags ------------------------- diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index e137738102544..423b696785500 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -307,6 +307,7 @@ CODEGENOPT(SanitizeBinaryMetadataAtomics, 1, 0, Benign) ///< Emit PCs for atomic CODEGENOPT(SanitizeBinaryMetadataUAR, 1, 0, Benign) ///< Emit PCs for start of functions ///< that are subject for use-after-return checking. CODEGENOPT(SanitizeStats , 1, 0, Benign) ///< Collect statistics for sanitizers. +CODEGENOPT(SanitizeDebugTrapReasons, 1, 1 , Benign) ///< Enable UBSan trapping messages CODEGENOPT(SimplifyLibCalls , 1, 1, Benign) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0, Benign) ///< -soft-float. CODEGENOPT(SpeculativeLoadHardening, 1, 0, Benign) ///< Enable speculative load hardening. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 916400efdb449..e2ab046b26ae6 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2597,6 +2597,16 @@ def fsanitize_undefined_trap_on_error def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">, Group<f_clang_Group>, Alias<fno_sanitize_trap_EQ>, AliasArgs<["undefined"]>; +defm sanitize_debug_trap_reasons + : BoolFOption< + "sanitize-debug-trap-reasons", + CodeGenOpts<"SanitizeDebugTrapReasons">, DefaultTrue, + PosFlag<SetTrue, [], [ClangOption, CC1Option], + "Annotate trap blocks in debug info with UBSan trap reasons">, + NegFlag<SetFalse, [], [ClangOption, CC1Option], + "Do not annotate trap blocks in debug info with UBSan trap " + "reasons">>; + defm sanitize_minimal_runtime : BoolOption<"f", "sanitize-minimal-runtime", CodeGenOpts<"SanitizeMinimalRuntime">, DefaultFalse, PosFlag<SetTrue>, diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index a371b6755f74d..77fc3a2aee94f 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -6435,7 +6435,7 @@ CodeGenFunction::LexicalScope::~LexicalScope() { static std::string SanitizerHandlerToCheckLabel(SanitizerHandler Handler) { std::string Label; switch (Handler) { -#define SANITIZER_CHECK(Enum, Name, Version) \ +#define SANITIZER_CHECK(Enum, Name, Version, Msg) \ case Enum: \ Label = "__ubsan_check_" #Name; \ break; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 85c768807572f..90aed796cf5ab 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -85,6 +85,16 @@ enum VariableTypeDescriptorKind : uint16_t { // Miscellaneous Helper Methods //===--------------------------------------------------------------------===// +static llvm::StringRef GetUBSanTrapForHandler(SanitizerHandler ID) { + switch (ID) { +#define SANITIZER_CHECK(Enum, Name, Version, Msg) \ + case SanitizerHandler::Enum: \ + return Msg; + LIST_SANITIZER_CHECKS +#undef SANITIZER_CHECK + } +} + /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. RawAddress @@ -3649,7 +3659,7 @@ struct SanitizerHandlerInfo { } const SanitizerHandlerInfo SanitizerHandlers[] = { -#define SANITIZER_CHECK(Enum, Name, Version) {#Name, Version}, +#define SANITIZER_CHECK(Enum, Name, Version, Msg) {#Name, Version}, LIST_SANITIZER_CHECKS #undef SANITIZER_CHECK }; @@ -3954,6 +3964,8 @@ void CodeGenFunction::EmitCfiCheckFail() { StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI, Args, SourceLocation()); + ApplyDebugLocation ADL = ApplyDebugLocation::CreateArtificial(*this); + // This function is not affected by NoSanitizeList. This function does // not have a source location, but "src:*" would still apply. Revert any // changes to SanOpts made in StartFunction. @@ -4051,6 +4063,15 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; + llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation(); + llvm::StringRef TrapMessage = GetUBSanTrapForHandler(CheckHandlerID); + + if (getDebugInfo() && !TrapMessage.empty() && + CGM.getCodeGenOpts().SanitizeDebugTrapReasons && TrapLocation) { + TrapLocation = getDebugInfo()->CreateTrapFailureMessageFor( + TrapLocation, "Undefined Behavior Sanitizer", TrapMessage); + } + NoMerge = NoMerge || !CGM.getCodeGenOpts().OptimizationLevel || (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>()); @@ -4059,8 +4080,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, auto Call = TrapBB->begin(); assert(isa<llvm::CallInst>(Call) && "Expected call in trap BB"); - Call->applyMergedLocation(Call->getDebugLoc(), - Builder.getCurrentDebugLocation()); + Call->applyMergedLocation(Call->getDebugLoc(), TrapLocation); + Builder.CreateCondBr(Checked, Cont, TrapBB, MDHelper.createLikelyBranchWeights()); } else { @@ -4069,6 +4090,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, MDHelper.createLikelyBranchWeights()); EmitBlock(TrapBB); + ApplyDebugLocation applyTrapDI(*this, TrapLocation); + llvm::CallInst *TrapCall = Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::ubsantrap), llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID)); diff --git a/clang/lib/CodeGen/SanitizerHandler.h b/clang/lib/CodeGen/SanitizerHandler.h index bb42e3947cf14..a66e7ab354eb2 100644 --- a/clang/lib/CodeGen/SanitizerHandler.h +++ b/clang/lib/CodeGen/SanitizerHandler.h @@ -14,35 +14,69 @@ #define LLVM_CLANG_LIB_CODEGEN_SANITIZER_HANDLER_H #define LIST_SANITIZER_CHECKS \ - SANITIZER_CHECK(AddOverflow, add_overflow, 0) \ - SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0) \ - SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0) \ - SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0) \ - SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0) \ - SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0) \ - SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0) \ - SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0) \ - SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \ - SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0) \ - SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \ - SANITIZER_CHECK(MissingReturn, missing_return, 0) \ - SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \ - SANITIZER_CHECK(NegateOverflow, negate_overflow, 0) \ - SANITIZER_CHECK(NullabilityArg, nullability_arg, 0) \ - SANITIZER_CHECK(NullabilityReturn, nullability_return, 1) \ - SANITIZER_CHECK(NonnullArg, nonnull_arg, 0) \ - SANITIZER_CHECK(NonnullReturn, nonnull_return, 1) \ - SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0) \ - SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0) \ - SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0) \ - SANITIZER_CHECK(SubOverflow, sub_overflow, 0) \ - SANITIZER_CHECK(TypeMismatch, type_mismatch, 1) \ - SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0) \ - SANITIZER_CHECK(VLABoundNotPositive, vla_bound_not_positive, 0) \ - SANITIZER_CHECK(BoundsSafety, bounds_safety, 0) + SANITIZER_CHECK(AddOverflow, add_overflow, 0, "Integer addition overflowed") \ + SANITIZER_CHECK(BuiltinUnreachable, builtin_unreachable, 0, \ + "_builtin_unreachable(), execution reached an unreachable " \ + "program point") \ + SANITIZER_CHECK(CFICheckFail, cfi_check_fail, 0, \ + "Control flow integrity check failed") \ + SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0, \ + "Integer divide or remainder overflowed") \ + SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0, \ + "Dynamic type cache miss, member call made on an object " \ + "whose dynamic type diff ers from the expected type") \ + SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0, \ + "Floating-point to integer conversion overflowed") \ + SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0, \ + "Function called with mismatched signature") \ + SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0, \ + "Implicit integer conversion overflowed or lost data") \ + SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0, \ + "Invalid use of builtin function") \ + SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0, \ + "Invalid Objective-C cast") \ + SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0, \ + "Loaded an invalid or uninitialized value for the type") \ + SANITIZER_CHECK(MissingReturn, missing_return, 0, \ + "Execution reached the end of a value-returning function " \ + "without returning a value") \ + SANITIZER_CHECK(MulOverflow, mul_overflow, 0, \ + "Integer multiplication overflowed") \ + SANITIZER_CHECK(NegateOverflow, negate_overflow, 0, \ + "Integer negation overflowed") \ + SANITIZER_CHECK( \ + NullabilityArg, nullability_arg, 0, \ + "Passing null as an argument which is annotated with _Nonnull") \ + SANITIZER_CHECK(NullabilityReturn, nullability_return, 1, \ + "Returning null from a function with a return type " \ + "annotated with _Nonnull") \ + SANITIZER_CHECK(NonnullArg, nonnull_arg, 0, \ + "Passing null pointer as an argument which is declared to " \ + "never be null") \ + SANITIZER_CHECK(NonnullReturn, nonnull_return, 1, \ + "Returning null pointer from a function which is declared " \ + "to never return null") \ + SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0, "Array index out of bounds") \ + SANITIZER_CHECK(PointerOverflow, pointer_overflow, 0, \ + "Pointer arithmetic overflowed bounds") \ + SANITIZER_CHECK(ShiftOutOfBounds, shift_out_of_bounds, 0, \ + "Shift exponent is too large for the type") \ + SANITIZER_CHECK(SubOverflow, sub_overflow, 0, \ + "Integer subtraction overflowed") \ + SANITIZER_CHECK(TypeMismatch, type_mismatch, 1, \ + "Type mismatch in operation") \ + SANITIZER_CHECK(AlignmentAssumption, alignment_assumption, 0, \ + "Alignment assumption violated") \ + SANITIZER_CHECK( \ + VLABoundNotPositive, vla_bound_not_positive, 0, \ + "Variable length array bound evaluates to non-positive value") \ + SANITIZER_CHECK(BoundsSafety, bounds_safety, 0, \ + "") // BoundsSafety Msg is empty because it is not considered + // part of UBSan; therefore, no trap reason is emitted for + // this case. enum SanitizerHandler { -#define SANITIZER_CHECK(Enum, Name, Version) Enum, +#define SANITIZER_CHECK(Enum, Name, Version, Msg) Enum, LIST_SANITIZER_CHECKS #undef SANITIZER_CHECK }; diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 21e4cff6309c3..98793a5bb9979 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -1382,6 +1382,12 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, CmdArgs.push_back(Args.MakeArgString("-fsanitize-annotate-debug-info=" + toString(AnnotateDebugInfo))); + if (const Arg *A = + Args.getLastArg(options::OPT_fsanitize_debug_trap_reasons, + options::OPT_fno_sanitize_debug_trap_reasons)) { + CmdArgs.push_back(Args.MakeArgString(A->getAsString(Args))); + } + addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-ignorelist=", UserIgnorelistFiles); addSpecialCaseListOpt(Args, CmdArgs, diff --git a/clang/test/CodeGen/bounds-checking-debuginfo.c b/clang/test/CodeGen/bounds-checking-debuginfo.c index 74c06665dfe02..bd7aedd7ac2c1 100644 --- a/clang/test/CodeGen/bounds-checking-debuginfo.c +++ b/clang/test/CodeGen/bounds-checking-debuginfo.c @@ -25,13 +25,13 @@ void d(double*); // CHECK-TRAP-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 10, !dbg [[DBG23]], !nosanitize [[META10]] // CHECK-TRAP-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG23]], !prof [[PROF27:![0-9]+]], !nosanitize [[META10]] // CHECK-TRAP: [[TRAP]]: -// CHECK-TRAP-NEXT: call void @llvm.ubsantrap(i8 18) #[[ATTR3:[0-9]+]], !dbg [[DBG23]], !nosanitize [[META10]] -// CHECK-TRAP-NEXT: unreachable, !dbg [[DBG23]], !nosanitize [[META10]] +// CHECK-TRAP-NEXT: call void @llvm.ubsantrap(i8 18) #[[ATTR3:[0-9]+]], !dbg [[DBGTRAP:![0-9]+]], !nosanitize [[META10]] +// CHECK-TRAP-NEXT: unreachable, !dbg [[DBGTRAP]], !nosanitize [[META10]] // CHECK-TRAP: [[CONT]]: // CHECK-TRAP-NEXT: [[IDXPROM:%.*]] = sext i32 [[CALL]] to i64, !dbg [[DBG26:![0-9]+]] // CHECK-TRAP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x double], ptr [[A]], i64 0, i64 [[IDXPROM]], !dbg [[DBG26]] // CHECK-TRAP-NEXT: [[TMP2:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !dbg [[DBG26]] -// CHECK-TRAP-NEXT: ret double [[TMP2]], !dbg [[DBG28:![0-9]+]] +// CHECK-TRAP-NEXT: ret double [[TMP2]], !dbg [[DBG30:![0-9]+]] // // CHECK-NOTRAP-LABEL: define dso_local double @f1( // CHECK-NOTRAP-SAME: i32 noundef [[B:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG4:![0-9]+]] { @@ -93,7 +93,9 @@ double f1(int b, int i) { // CHECK-TRAP: [[META25]] = !DISubroutineType(types: null) // CHECK-TRAP: [[DBG26]] = !DILocation(line: 66, column: 10, scope: [[DBG4]]) // CHECK-TRAP: [[PROF27]] = !{!"branch_weights", i32 1048575, i32 1} -// CHECK-TRAP: [[DBG28]] = !DILocation(line: 66, column: 3, scope: [[DBG4]]) +// CHECK-TRAP: [[DBGTRAP]] = !DILocation(line: 0, scope: [[TRAPMSG:![0-9]+]], inlinedAt: [[DBG23]]) +// CHECK-TRAP: [[TRAPMSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Array index out of bounds", scope: [[META5]], file: [[META5]], type: [[META25]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]]) +// CHECK-TRAP: [[DBG30]] = !DILocation(line: 66, column: 3, scope: [[DBG4]]) //. // CHECK-NOTRAP: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) // CHECK-NOTRAP: [[META1]] = !DIFile(filename: "<stdin>", directory: {{.*}}) diff --git a/clang/test/CodeGen/cfi-icall-generalize-debuginfo.c b/clang/test/CodeGen/cfi-icall-generalize-debuginfo.c index 304b60539c3d1..0ffc2b9e415d4 100644 --- a/clang/test/CodeGen/cfi-icall-generalize-debuginfo.c +++ b/clang/test/CodeGen/cfi-icall-generalize-debuginfo.c @@ -30,11 +30,11 @@ int** f(const char *a, const char **b) { // UNGENERALIZED-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FP]], metadata !"_ZTSFPPiPKcPS2_E"), !dbg [[DBG34:![0-9]+]], !nosanitize [[META38:![0-9]+]] // UNGENERALIZED-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG34]], !prof [[PROF39:![0-9]+]], !nosanitize [[META38]] // UNGENERALIZED: [[TRAP]]: -// UNGENERALIZED-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4:[0-9]+]], !dbg [[DBG34]], !nosanitize [[META38]] -// UNGENERALIZED-NEXT: unreachable, !dbg [[DBG34]], !nosanitize [[META38]] +// UNGENERALIZED-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4:[0-9]+]], !dbg [[DBGTRAP:![0-9]+]], !nosanitize [[META38]] +// UNGENERALIZED-NEXT: unreachable, !dbg [[DBGTRAP]], !nosanitize [[META38]] // UNGENERALIZED: [[CONT]]: // UNGENERALIZED-NEXT: [[CALL:%.*]] = tail call ptr [[FP]](ptr noundef null, ptr noundef null) #[[ATTR5:[0-9]+]], !dbg [[DBG37:![0-9]+]] -// UNGENERALIZED-NEXT: ret void, !dbg [[DBG40:![0-9]+]] +// UNGENERALIZED-NEXT: ret void, !dbg [[DBG42:![0-9]+]] // // GENERALIZED-LABEL: define dso_local void @g( // GENERALIZED-SAME: ptr noundef [[FP:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] !dbg [[DBG25:![0-9]+]] !type [[META31:![0-9]+]] !type [[META32:![0-9]+]] { @@ -43,11 +43,11 @@ int** f(const char *a, const char **b) { // GENERALIZED-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FP]], metadata !"_ZTSFPvPKvS_E.generalized"), !dbg [[DBG34:![0-9]+]], !nosanitize [[META38:![0-9]+]] // GENERALIZED-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG34]], !prof [[PROF39:![0-9]+]], !nosanitize [[META38]] // GENERALIZED: [[TRAP]]: -// GENERALIZED-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4:[0-9]+]], !dbg [[DBG34]], !nosanitize [[META38]] -// GENERALIZED-NEXT: unreachable, !dbg [[DBG34]], !nosanitize [[META38]] +// GENERALIZED-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR4:[0-9]+]], !dbg [[DBGTRAP:![0-9]+]], !nosanitize [[META38]] +// GENERALIZED-NEXT: unreachable, !dbg [[DBGTRAP]], !nosanitize [[META38]] // GENERALIZED: [[CONT]]: // GENERALIZED-NEXT: [[CALL:%.*]] = tail call ptr [[FP]](ptr noundef null, ptr noundef null) #[[ATTR5:[0-9]+]], !dbg [[DBG37:![0-9]+]] -// GENERALIZED-NEXT: ret void, !dbg [[DBG40:![0-9]+]] +// GENERALIZED-NEXT: ret void, !dbg [[DBG42:![0-9]+]] // void g(int** (*fp)(const char *, const char **)) { fp(0, 0); @@ -90,7 +90,9 @@ void g(int** (*fp)(const char *, const char **)) { // UNGENERALIZED: [[DBG37]] = !DILocation(line: 53, column: 3, scope: [[DBG25]]) // UNGENERALIZED: [[META38]] = !{} // UNGENERALIZED: [[PROF39]] = !{!"branch_weights", i32 1048575, i32 1} -// UNGENERALIZED: [[DBG40]] = !DILocation(line: 54, column: 1, scope: [[DBG25]]) +// UNGENERALIZED: [[DBGTRAP]] = !DILocation(line: 0, scope: [[TRAPMSG:![0-9]+]], inlinedAt: [[DBG34]]) +// UNGENERALIZED: [[TRAPMSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Control flow integrity check failed", scope: [[META11]], file: [[META11]], type: [[META36]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]]) +// UNGENERALIZED: [[DBG42]] = !DILocation(line: 54, column: 1, scope: [[DBG25]]) //. // GENERALIZED: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: [[META2:![0-9]+]], splitDebugInlining: false, nameTableKind: None) // GENERALIZED: [[META1]] = !DIFile(filename: "{{.*}}<stdin>", directory: {{.*}}) @@ -128,5 +130,7 @@ void g(int** (*fp)(const char *, const char **)) { // GENERALIZED: [[DBG37]] = !DILocation(line: 53, column: 3, scope: [[DBG25]]) // GENERALIZED: [[META38]] = !{} // GENERALIZED: [[PROF39]] = !{!"branch_weights", i32 1048575, i32 1} -// GENERALIZED: [[DBG40]] = !DILocation(line: 54, column: 1, scope: [[DBG25]]) +// GENERALIZED: [[DBGTRAP]] = !DILocation(line: 0, scope: [[TRAPMSG:![0-9]+]], inlinedAt: [[DBG34]]) +// GENERALIZED: [[TRAPMSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Control flow integrity check failed", scope: [[META11]], file: [[META11]], type: [[META36]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]]) +// GENERALIZED: [[DBG42]] = !DILocation(line: 54, column: 1, scope: [[DBG25]]) //. diff --git a/clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c b/clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c index a2f6ee0c6805c..258c3bfbc9f55 100644 --- a/clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c +++ b/clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c @@ -15,50 +15,50 @@ // CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32E.normalized"), !dbg [[DBG21:![0-9]+]], !nosanitize [[META25:![0-9]+]] // CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG21]], !prof [[PROF26:![0-9]+]], !nosanitize [[META25]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3:[0-9]+]], !dbg [[DBG21]], !nosanitize [[META25]] -// CHECK-NEXT: unreachable, !dbg [[DBG21]], !nosanitize [[META25]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3:[0-9]+]], !dbg [[DBGTRAP:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: unreachable, !dbg [[DBGTRAP]], !nosanitize [[META25]] // CHECK: [[CONT]]: // CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG]]) #[[ATTR4:[0-9]+]], !dbg [[DBG24:![0-9]+]] -// CHECK-NEXT: ret void, !dbg [[DBG27:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG29:![0-9]+]] // void foo(void (*fn)(int), int arg) { fn(arg); } // CHECK-LABEL: define dso_local void @bar( -// CHECK-SAME: ptr noundef [[FN:%.*]], i32 noundef [[ARG1:%.*]], i32 noundef [[ARG2:%.*]]) local_unnamed_addr #[[ATTR0]] !dbg [[DBG28:![0-9]+]] !type [[META38:![0-9]+]] !type [[META39:![0-9]+]] { +// CHECK-SAME: ptr noundef [[FN:%.*]], i32 noundef [[ARG1:%.*]], i32 noundef [[ARG2:%.*]]) local_unnamed_addr #[[ATTR0]] !dbg [[DBG30:![0-9]+]] !type [[META40:![0-9]+]] !type [[META41:![0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: #dbg_value(ptr [[FN]], [[META35:![0-9]+]], !DIExpression(), [[META40:![0-9]+]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG1]], [[META36:![0-9]+]], !DIExpression(), [[META40]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG2]], [[META37:![0-9]+]], !DIExpression(), [[META40]]) -// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32S_E.normalized"), !dbg [[DBG41:![0-9]+]], !nosanitize [[META25]] -// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG41]], !prof [[PROF26]], !nosanitize [[META25]] +// CHECK-NEXT: #dbg_value(ptr [[FN]], [[META37:![0-9]+]], !DIExpression(), [[META42:![0-9]+]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG1]], [[META38:![0-9]+]], !DIExpression(), [[META42]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG2]], [[META39:![0-9]+]], !DIExpression(), [[META42]]) +// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32S_E.normalized"), !dbg [[DBG43:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG43]], !prof [[PROF26]], !nosanitize [[META25]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3]], !dbg [[DBG41]], !nosanitize [[META25]] -// CHECK-NEXT: unreachable, !dbg [[DBG41]], !nosanitize [[META25]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3]], !dbg [[DBG45:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: unreachable, !dbg [[DBG45]], !nosanitize [[META25]] // CHECK: [[CONT]]: -// CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG1]], i32 noundef [[ARG2]]) #[[ATTR4]], !dbg [[DBG42:![0-9]+]] -// CHECK-NEXT: ret void, !dbg [[DBG43:![0-9]+]] +// CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG1]], i32 noundef [[ARG2]]) #[[ATTR4]], !dbg [[DBG44:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG46:![0-9]+]] // void bar(void (*fn)(int, int), int arg1, int arg2) { fn(arg1, arg2); } // CHECK-LABEL: define dso_local void @baz( -// CHECK-SAME: ptr noundef [[FN:%.*]], i32 noundef [[ARG1:%.*]], i32 noundef [[ARG2:%.*]], i32 noundef [[ARG3:%.*]]) local_unnamed_addr #[[ATTR0]] !dbg [[DBG44:![0-9]+]] !type [[META55:![0-9]+]] !type [[META56:![0-9]+]] { +// CHECK-SAME: ptr noundef [[FN:%.*]], i32 noundef [[ARG1:%.*]], i32 noundef [[ARG2:%.*]], i32 noundef [[ARG3:%.*]]) local_unnamed_addr #[[ATTR0]] !dbg [[DBG47:![0-9]+]] !type [[META58:![0-9]+]] !type [[META59:![0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: #dbg_value(ptr [[FN]], [[META51:![0-9]+]], !DIExpression(), [[META57:![0-9]+]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG1]], [[META52:![0-9]+]], !DIExpression(), [[META57]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG2]], [[META53:![0-9]+]], !DIExpression(), [[META57]]) -// CHECK-NEXT: #dbg_value(i32 [[ARG3]], [[META54:![0-9]+]], !DIExpression(), [[META57]]) -// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32S_S_E.normalized"), !dbg [[DBG58:![0-9]+]], !nosanitize [[META25]] -// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG58]], !prof [[PROF26]], !nosanitize [[META25]] +// CHECK-NEXT: #dbg_value(ptr [[FN]], [[META54:![0-9]+]], !DIExpression(), [[META60:![0-9]+]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG1]], [[META55:![0-9]+]], !DIExpression(), [[META60]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG2]], [[META56:![0-9]+]], !DIExpression(), [[META60]]) +// CHECK-NEXT: #dbg_value(i32 [[ARG3]], [[META57:![0-9]+]], !DIExpression(), [[META60]]) +// CHECK-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[FN]], metadata !"_ZTSFvu3i32S_S_E.normalized"), !dbg [[DBG61:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: br i1 [[TMP0]], label %[[CONT:.*]], label %[[TRAP:.*]], !dbg [[DBG61]], !prof [[PROF26]], !nosanitize [[META25]] // CHECK: [[TRAP]]: -// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3]], !dbg [[DBG58]], !nosanitize [[META25]] -// CHECK-NEXT: unreachable, !dbg [[DBG58]], !nosanitize [[META25]] +// CHECK-NEXT: tail call void @llvm.ubsantrap(i8 2) #[[ATTR3]], !dbg [[DBG63:![0-9]+]], !nosanitize [[META25]] +// CHECK-NEXT: unreachable, !dbg [[DBG63]], !nosanitize [[META25]] // CHECK: [[CONT]]: -// CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG1]], i32 noundef [[ARG2]], i32 noundef [[ARG3]]) #[[ATTR4]], !dbg [[DBG59:![0-9]+]] -// CHECK-NEXT: ret void, !dbg [[DBG60:![0-9]+]] +// CHECK-NEXT: tail call void [[FN]](i32 noundef [[ARG1]], i32 noundef [[ARG2]], i32 noundef [[ARG3]]) #[[ATTR4]], !dbg [[DBG62:![0-9]+]] +// CHECK-NEXT: ret void, !dbg [[DBG64:![0-9]+]] // void baz(void (*fn)(int, int, int), int arg1, int arg2, int arg3) { fn(arg1, arg2, arg3); @@ -87,38 +87,42 @@ void baz(void (*fn)(int, int, int), int arg1, int arg2, int arg3) { // CHECK: [[DBG24]] = !DILocation(line: 25, column: 5, scope: [[DBG7]]) // CHECK: [[META25]] = !{} // CHECK: [[PROF26]] = !{!"branch_weights", i32 1048575, i32 1} -// CHECK: [[DBG27]] = !DILocation(line: 26, column: 1, scope: [[DBG7]]) -// CHECK: [[DBG28]] = distinct !DISubprogram(name: "bar", scope: [[META8]], file: [[META8]], line: 43, type: [[META29:![0-9]+]], scopeLine: 43, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META34:![0-9]+]]) -// CHECK: [[META29]] = !DISubroutineType(types: [[META30:![0-9]+]]) -// CHECK: [[META30]] = !{null, [[META31:![0-9]+]], [[META14]], [[META14]]} -// CHECK: [[META31]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META32:![0-9]+]], size: 64) -// CHECK: [[META32]] = !DISubroutineType(types: [[META33:![0-9]+]]) -// CHECK: [[META33]] = !{null, [[META14]], [[META14]]} -// CHECK: [[META34]] = !{[[META35]], [[META36]], [[META37]]} -// CHECK: [[META35]] = !DILocalVariable(name: "fn", arg: 1, scope: [[DBG28]], file: [[META8]], line: 43, type: [[META31]]) -// CHECK: [[META36]] = !DILocalVariable(name: "arg1", arg: 2, scope: [[DBG28]], file: [[META8]], line: 43, type: [[META14]]) -// CHECK: [[META37]] = !DILocalVariable(name: "arg2", arg: 3, scope: [[DBG28]], file: [[META8]], line: 43, type: [[META14]]) -// CHECK: [[META38]] = !{i64 0, !"_ZTSFvPFvu3i32S_ES_S_E.normalized"} -// CHECK: [[META39]] = !{i64 0, !"_ZTSFvPvu3i32S0_E.normalized.generalized"} -// CHECK: [[META40]] = !DILocation(line: 0, scope: [[DBG28]]) -// CHECK: [[DBG41]] = !DILocation(line: 0, scope: [[META22]], inlinedAt: [[DBG42]]) -// CHECK: [[DBG42]] = !DILocation(line: 44, column: 5, scope: [[DBG28]]) -// CHECK: [[DBG43]] = !DILocation(line: 45, column: 1, scope: [[DBG28]]) -// CHECK: [[DBG44]] = distinct !DISubprogram(name: "baz", scope: [[META8]], file: [[META8]], line: 63, type: [[META45:![0-9]+]], scopeLine: 63, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META50:![0-9]+]]) -// CHECK: [[META45]] = !DISubroutineType(types: [[META46:![0-9]+]]) -// CHECK: [[META46]] = !{null, [[META47:![0-9]+]], [[META14]], [[META14]], [[META14]]} -// CHECK: [[META47]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META48:![0-9]+]], size: 64) +// CHECK: [[DBGTRAP]] = !DILocation(line: 0, scope: [[TRAPMSG:![0-9]+]], inlinedAt: [[DBG21]]) +// CHECK: [[TRAPMSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Control flow integrity check failed", scope: [[META8]], file: [[META8]], type: [[META23]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]]) +// CHECK: [[DBG29]] = !DILocation(line: 26, column: 1, scope: [[DBG7]]) +// CHECK: [[DBG30]] = distinct !DISubprogram(name: "bar", scope: [[META8]], file: [[META8]], line: 43, type: [[META31:![0-9]+]], scopeLine: 43, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META36:![0-9]+]]) +// CHECK: [[META31]] = !DISubroutineType(types: [[META32:![0-9]+]]) +// CHECK: [[META32]] = !{null, [[META33:![0-9]+]], [[META14]], [[META14]]} +// CHECK: [[META33]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META34:![0-9]+]], size: 64) +// CHECK: [[META34]] = !DISubroutineType(types: [[META35:![0-9]+]]) +// CHECK: [[META35]] = !{null, [[META14]], [[META14]]} +// CHECK: [[META36]] = !{[[META37]], [[META38]], [[META39]]} +// CHECK: [[META37]] = !DILocalVariable(name: "fn", arg: 1, scope: [[DBG30]], file: [[META8]], line: 43, type: [[META33]]) +// CHECK: [[META38]] = !DILocalVariable(name: "arg1", arg: 2, scope: [[DBG30]], file: [[META8]], line: 43, type: [[META14]]) +// CHECK: [[META39]] = !DILocalVariable(name: "arg2", arg: 3, scope: [[DBG30]], file: [[META8]], line: 43, type: [[META14]]) +// CHECK: [[META40]] = !{i64 0, !"_ZTSFvPFvu3i32S_ES_S_E.normalized"} +// CHECK: [[META41]] = !{i64 0, !"_ZTSFvPvu3i32S0_E.normalized.generalized"} +// CHECK: [[META42]] = !DILocation(line: 0, scope: [[DBG30]]) +// CHECK: [[DBG43]] = !DILocation(line: 0, scope: [[META22]], inlinedAt: [[DBG44]]) +// CHECK: [[DBG44]] = !DILocation(line: 44, column: 5, scope: [[DBG30]]) +// CHECK: [[DBG45]] = !DILocation(line: 0, scope: [[TRAPMSG]], inlinedAt: [[DBG43]]) +// CHECK: [[DBG46]] = !DILocation(line: 45, column: 1, scope: [[DBG30]]) +// CHECK: [[DBG47]] = distinct !DISubprogram(name: "baz", scope: [[META8]], file: [[META8]], line: 63, type: [[META48:![0-9]+]], scopeLine: 63, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META53:![0-9]+]]) // CHECK: [[META48]] = !DISubroutineType(types: [[META49:![0-9]+]]) -// CHECK: [[META49]] = !{null, [[META14]], [[META14]], [[META14]]} -// CHECK: [[META50]] = !{[[META51]], [[META52]], [[META53]], [[META54]]} -// CHECK: [[META51]] = !DILocalVariable(name: "fn", arg: 1, scope: [[DBG44]], file: [[META8]], line: 63, type: [[META47]]) -// CHECK: [[META52]] = !DILocalVariable(name: "arg1", arg: 2, scope: [[DBG44]], file: [[META8]], line: 63, type: [[META14]]) -// CHECK: [[META53]] = !DILocalVariable(name: "arg2", arg: 3, scope: [[DBG44]], file: [[META8]], line: 63, type: [[META14]]) -// CHECK: [[META54]] = !DILocalVariable(name: "arg3", arg: 4, scope: [[DBG44]], file: [[META8]], line: 63, type: [[META14]]) -// CHECK: [[META55]] = !{i64 0, !"_ZTSFvPFvu3i32S_S_ES_S_S_E.normalized"} -// CHECK: [[META56]] = !{i64 0, !"_ZTSFvPvu3i32S0_S0_E.normalized.generalized"} -// CHECK: [[META57]] = !DILocation(line: 0, scope: [[DBG44]]) -// CHECK: [[DBG58]] = !DILocation(line: 0, scope: [[META22]], inlinedAt: [[DBG59]]) -// CHECK: [[DBG59]] = !DILocation(line: 64, column: 5, scope: [[DBG44]]) -// CHECK: [[DBG60]] = !DILocation(line: 65, column: 1, scope: [[DBG44]]) +// CHECK: [[META49]] = !{null, [[META50:![0-9]+]], [[META14]], [[META14]], [[META14]]} +// CHECK: [[META50]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META51:![0-9]+]], size: 64) +// CHECK: [[META51]] = !DISubroutineType(types: [[META52:![0-9]+]]) +// CHECK: [[META52]] = !{null, [[META14]], [[META14]], [[META14]]} +// CHECK: [[META53]] = !{[[META54]], [[META55]], [[META56]], [[META57]]} +// CHECK: [[META54]] = !DILocalVariable(name: "fn", arg: 1, scope: [[DBG47]], file: [[META8]], line: 63, type: [[META50]]) +// CHECK: [[META55]] = !DILocalVariable(name: "arg1", arg: 2, scope: [[DBG47]], file: [[META8]], line: 63, type: [[META14]]) +// CHECK: [[META56]] = !DILocalVariable(name: "arg2", arg: 3, scope: [[DBG47]], file: [[META8]], line: 63, type: [[META14]]) +// CHECK: [[META57]] = !DILocalVariable(name: "arg3", arg: 4, scope: [[DBG47]], file: [[META8]], line: 63, type: [[META14]]) +// CHECK: [[META58]] = !{i64 0, !"_ZTSFvPFvu3i32S_S_ES_S_S_E.normalized"} +// CHECK: [[META59]] = !{i64 0, !"_ZTSFvPvu3i32S0_S0_E.normalized.generalized"} +// CHECK: [[META60]] = !DILocation(line: 0, scope: [[DBG47]]) +// CHECK: [[DBG61]] = !DILocation(line: 0, scope: [[META22]], inlinedAt: [[DBG62]]) +// CHECK: [[DBG62]] = !DILocation(line: 64, column: 5, scope: [[DBG47]]) +// CHECK: [[DBG63]] = !DILocation(line: 0, scope: [[TRAPMSG]], inlinedAt: [[DBG61]]) +// CHECK: [[DBG64]] = !DILocation(line: 65, column: 1, scope: [[DBG47]]) //. diff --git a/clang/test/CodeGen/ubsan-trap-debugloc.c b/clang/test/CodeGen/ubsan-trap-debugloc.c index 87cbfadec7d30..2f5258a6f4ce2 100644 --- a/clang/test/CodeGen/ubsan-trap-debugloc.c +++ b/clang/test/CodeGen/ubsan-trap-debugloc.c @@ -20,5 +20,8 @@ void bar(volatile int a) __attribute__((optnone)) { // CHECK: [[LOC]] = !DILocation(line: 0 // With optimisations disabled the traps are not merged and retain accurate debug locations -// CHECK: [[LOC2]] = !DILocation(line: 15, column: 9 -// CHECK: [[LOC3]] = !DILocation(line: 16, column: 9 + // CHECK-DAG: [[SRC2:![0-9]+]] = !DILocation(line: 15, column: 9, + // CHECK-DAG: [[SRC3:![0-9]+]] = !DILocation(line: 16, column: 9, + // CHECK-DAG: [[LOC2]] = !DILocation(line: 0, scope: [[SCOPE2:![0-9]+]], inlinedAt: [[SRC2]]) + // CHECK-DAG: [[LOC3]] = !DILocation(line: 0, scope: [[SCOPE3:![0-9]+]], inlinedAt: [[SRC3]]) + diff --git a/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c new file mode 100644 index 0000000000000..225778d68833d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int add_overflow(int a, int b) { return a + b; } + +// CHECK-LABEL: @add_overflow +// CHECK: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer addition overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-alignment-assumption.c b/clang/test/CodeGen/ubsan-trap-reason-alignment-assumption.c new file mode 100644 index 0000000000000..3247ceb4d4a74 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-alignment-assumption.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - | FileCheck %s + +#include <stdint.h> +int32_t *get_int(void) __attribute__((assume_aligned(16))); + +void retrieve_int(void) { + int *i = get_int(); + *i = 7; +} + +// CHECK-LABEL: @retrieve_int +// CHECK: call void @llvm.ubsantrap(i8 23) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Alignment assumption violated" diff --git a/clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c b/clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c new file mode 100644 index 0000000000000..97bd6905bc327 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=unreachable -fsanitize-trap=unreachable -emit-llvm %s -o - | FileCheck %s + +int call_builtin_unreachable(void) { __builtin_unreachable(); } + +// CHECK-LABEL: @call_builtin_unreachable +// CHECK: call void @llvm.ubsantrap(i8 1) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$_builtin_unreachable(), execution reached an unreachable program point" diff --git a/clang/test/CodeGen/ubsan-trap-reason-cfi-check-fail.c b/clang/test/CodeGen/ubsan-trap-reason-cfi-check-fail.c new file mode 100644 index 0000000000000..9304f51046c0d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-cfi-check-fail.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -emit-llvm %s -o - | FileCheck %s + +typedef int (*fp_t)(int); + +int good(int x) { return x + 1; } + +int bad(void) { return 0; } + +int cfi_trigger(int a) { + fp_t p = good; + int r1 = p(a); + + p = (fp_t)(void *)bad; + int r2 = p(a); + + return r1 + r2; +} + +// CHECK-LABEL: @good +// CHECK-LABEL: @bad +// CHECK-LABEL: @cfi_trigger +// CHECK: call void @llvm.ubsantrap(i8 2) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Control flow integrity check failed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-crash.cpp b/clang/test/CodeGen/ubsan-trap-reason-crash.cpp new file mode 100644 index 0000000000000..6add9bf2b6b34 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-crash.cpp @@ -0,0 +1,20 @@ +// FIXME: We should emit a trap message for this case too. +// But sometimes Clang will emit a ubsan trap into the prologue of a function, +// at which point the debug-info locations haven't been set up yet and +// can't hook up our artificial inline frame. [Issue #150707] + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=null -fsanitize-trap=null -emit-llvm %s -o - | FileCheck %s + +struct Foo { + void target() {} +} f; + +void caller() { + f.target(); +} + + +// CHECK-LABEL: @_Z6callerv +// CHECK: call void @llvm.ubsantrap(i8 22){{.*}}!nosanitize +// CHECK-NOT: __clang_trap_msg diff --git a/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c new file mode 100644 index 0000000000000..d0b21dd173894 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int div_rem_overflow(int a, int b) { return a / b; } + +// CHECK-LABEL: @div_rem_overflow +// CHECK: call void @llvm.ubsantrap(i8 3) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer divide or remainder overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-dynamic-type-cache-miss.cpp b/clang/test/CodeGen/ubsan-trap-reason-dynamic-type-cache-miss.cpp new file mode 100644 index 0000000000000..f89fbdcf1002f --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-dynamic-type-cache-miss.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=vptr -fsanitize-trap=vptr -emit-llvm %s -o - | FileCheck %s + +struct A { + virtual void foo(); +}; +struct B { + virtual void bar(); +}; + +void A::foo() {} +void B::bar() {} + +int dynamic_type_cache_miss() { + B b; + A &a = reinterpret_cast<A &>(b); + a.foo(); + return 0; +} + +// CHECK-LABEL: @_ZN1A3fooEv +// CHECK-LABEL: @_ZN1B3barEv +// CHECK-LABEL: @_Z23dynamic_type_cache_missv +// CHECK: call void @llvm.ubsantrap(i8 4) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Dynamic type cache miss, member call made on an object whose dynamic type diff ers from the expected type" diff --git a/clang/test/CodeGen/ubsan-trap-reason-flag.c b/clang/test/CodeGen/ubsan-trap-reason-flag.c new file mode 100644 index 0000000000000..5cc16d154bf68 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-flag.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=ANNOTATE + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow \ +// RUN: -fsanitize-debug-trap-reasons -emit-llvm %s -o - | FileCheck %s --check-prefix=ANNOTATE + +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow \ +// RUN: -fno-sanitize-debug-trap-reasons -emit-llvm %s -o - | FileCheck %s --check-prefix=NO-ANNOTATE + +int add_overflow(int a, int b) { return a + b; } + +// ANNOTATE-LABEL: @add_overflow +// ANNOTATE: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] +// ANNOTATE: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// ANNOTATE: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer addition overflowed" + +// NO-ANNOTATE-LABEL: @add_overflow +// NO-ANNOTATE: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] +// NO-ANNOTATE-NOT: __clang_trap_msg diff --git a/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c new file mode 100644 index 0000000000000..079a191e05d4b --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=float-cast-overflow -fsanitize-trap=float-cast-overflow -emit-llvm %s -o - | FileCheck %s + +int float_cast_overflow(float x) { return (int)x; } + +// CHECK-LABEL: @float_cast_overflow +// CHECK: call void @llvm.ubsantrap(i8 5) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Floating-point to integer conversion overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c b/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c new file mode 100644 index 0000000000000..1727f9c092a4c --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=function -fsanitize-trap=function -emit-llvm %s -o - | FileCheck %s + +void target(void) {} + +int function_type_mismatch(void) { + int (*fp_int)(int); + + fp_int = (int (*)(int))(void *)target; + + return fp_int(42); +} + +// CHECK-LABEL: @target +// CHECK-LABEL: @function_type_mismatch +// CHECK: call void @llvm.ubsantrap(i8 6) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Function called with mismatched signature" diff --git a/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c b/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c new file mode 100644 index 0000000000000..43c091d51a5c2 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=implicit-unsigned-integer-truncation -fsanitize-trap=implicit-unsigned-integer-truncation -emit-llvm %s -o - | FileCheck %s + +unsigned long long big; + +unsigned implicit_conversion(void) { return big; } + +// CHECK-LABEL: @implicit_conversion +// CHECK: call void @llvm.ubsantrap(i8 7) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Implicit integer conversion overflowed or lost data" diff --git a/clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c b/clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c new file mode 100644 index 0000000000000..56cf6744277df --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=builtin -fsanitize-trap=builtin -emit-llvm %s -o - | FileCheck %s + +unsigned invalid_builtin(unsigned x) { return __builtin_clz(x); } + +// CHECK-LABEL: @invalid_builtin +// CHECK: call void @llvm.ubsantrap(i8 8) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Invalid use of builtin function" diff --git a/clang/test/CodeGen/ubsan-trap-reason-invalid-objc-cast.m b/clang/test/CodeGen/ubsan-trap-reason-invalid-objc-cast.m new file mode 100644 index 0000000000000..ed2d5ffe1600c --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-invalid-objc-cast.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=objc-cast -fsanitize-trap=objc-cast -emit-llvm %s -o - | FileCheck %s + +@interface NSFastEnumerationState +@end + +#define NSUInteger unsigned int + +@interface NSArray ++(NSArray*) arrayWithObjects: (id) first, ...; +- (NSUInteger) countByEnumeratingWithState:(NSFastEnumerationState *) state + objects:(id[]) buffer + count:(NSUInteger) len; +-(unsigned) count; +@end +@interface NSString +-(const char*) cString; +@end + +void receive_NSString(NSString*); + +void t0(void) { + NSArray *array = [NSArray arrayWithObjects: @"0", @"1", (void*)0]; + for (NSString *i in array) { + receive_NSString(i); + } +} + +// CHECK-LABEL: @t0 +// CHECK: call void @llvm.ubsantrap(i8 9) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Invalid Objective-C cast" diff --git a/clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c b/clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c new file mode 100644 index 0000000000000..4aad8325c5119 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=bool -fsanitize-trap=bool -emit-llvm %s -o - | FileCheck %s + +#include <stdbool.h> + +unsigned char bad_byte; + +bool load_invalid_value(void) { return *((bool *)&bad_byte); } + +// CHECK-LABEL: @load_invalid_value +// CHECK: call void @llvm.ubsantrap(i8 10) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Loaded an invalid or uninitialized value for the type" diff --git a/clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp b/clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp new file mode 100644 index 0000000000000..2818d9d202720 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=return -fsanitize-trap=return -emit-llvm %s -o - | FileCheck %s + +int missing_return(int x) { + if (x > 0) + return x; +} + +// CHECK-LABEL: @_Z14missing_return +// CHECK: call void @llvm.ubsantrap(i8 11) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Execution reached the end of a value-returning function without returning a value" diff --git a/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c new file mode 100644 index 0000000000000..cf9a0b4e7439c --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int mul_overflow(int a, int b) { return a * b; } + +// CHECK-LABEL: @mul_overflow +// CHECK: call void @llvm.ubsantrap(i8 12) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer multiplication overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c new file mode 100644 index 0000000000000..55346794b2928 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int negate_overflow() { + int x; + return -x; +} + +// CHECK-LABEL: @negate_overflow +// CHECK: call void @llvm.ubsantrap(i8 13) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer negation overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c b/clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c new file mode 100644 index 0000000000000..1f0f450d86180 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=nonnull-attribute -fsanitize-trap=nonnull-attribute -emit-llvm %s -o - | FileCheck %s + +__attribute__((nonnull)) void nonnull_arg(int *p) { (void)p; } + +void trigger_nonnull_arg() { nonnull_arg(0); } + +// CHECK-LABEL: @nonnull_arg +// CHECK-LABEL: @trigger_nonnull_arg +// CHECK: call void @llvm.ubsantrap(i8 16) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Passing null pointer as an argument which is declared to never be null" diff --git a/clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c b/clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c new file mode 100644 index 0000000000000..1197b4dbafea5 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=returns-nonnull-attribute -fsanitize-trap=returns-nonnull-attribute -emit-llvm %s -o - | FileCheck %s + +__attribute__((returns_nonnull)) int *must_return_nonnull(int bad) { + if (bad) + return 0; + static int x = 1; + return &x; +} + +// CHECK-LABEL: @must_return_nonnull +// CHECK: call void @llvm.ubsantrap(i8 17) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Returning null pointer from a function which is declared to never return null" diff --git a/clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c b/clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c new file mode 100644 index 0000000000000..2bc71dec67c93 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=nullability-arg -fsanitize-trap=nullability-arg -emit-llvm %s -o - | FileCheck %s + +#include <stddef.h> + +int nullability_arg(int *_Nonnull p) { return *p; } + +int trigger_nullability_arg(void) { return nullability_arg(NULL); } + +// CHECK-LABEL: @nullability_arg +// CHECK-LABEL: @trigger_nullability_arg +// CHECK: call void @llvm.ubsantrap(i8 14) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Passing null as an argument which is annotated with _Nonnull" diff --git a/clang/test/CodeGen/ubsan-trap-reason-nullability-return.c b/clang/test/CodeGen/ubsan-trap-reason-nullability-return.c new file mode 100644 index 0000000000000..3d64c5a71a9e7 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-nullability-return.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=nullability-return -fsanitize-trap=nullability-return -emit-llvm %s -o - | FileCheck %s + +#include <stdbool.h> +#include <stddef.h> + +int *_Nonnull nullability_return(bool fail) { + if (fail) + return NULL; + + static int x = 0; + return &x; +} + +// CHECK-LABEL: @nullability_return +// CHECK: call void @llvm.ubsantrap(i8 15) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Returning null from a function with a return type annotated with _Nonnull" diff --git a/clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c b/clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c new file mode 100644 index 0000000000000..979886da6d25b --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=array-bounds -fsanitize-trap=array-bounds -emit-llvm %s -o - | FileCheck %s + +int out_of_bounds() { + int a[1] = {0}; + return a[1]; +} + +// CHECK-LABEL: @out_of_bounds +// CHECK: call void @llvm.ubsantrap(i8 18) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Array index out of bounds" diff --git a/clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c new file mode 100644 index 0000000000000..41cb4873a423c --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - | FileCheck %s + +#include <stddef.h> +#include <stdint.h> + +int *pointer_overflow(void) { + int buf[4]; + volatile size_t n = (SIZE_MAX / sizeof(int)) - 1; + return buf + n; +} + +// CHECK-LABEL: @pointer_overflow +// CHECK: call void @llvm.ubsantrap(i8 19) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Pointer arithmetic overflowed bounds" diff --git a/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c b/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c new file mode 100644 index 0000000000000..1a7465d93aef5 --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=shift-base -fsanitize-trap=shift-base -emit-llvm %s -o - | FileCheck %s + +int shift_out_of_bounds(void) { + int sh = 32; + return 1 << sh; +} + +// CHECK-LABEL: @shift_out_of_bounds +// CHECK: call void @llvm.ubsantrap(i8 20) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Shift exponent is too large for the type" diff --git a/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c new file mode 100644 index 0000000000000..62aa7fc953dad --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-sub-overflow.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -emit-llvm %s -o - | FileCheck %s + +int sub_overflow(int a, int b) { return a - b; } + +// CHECK-LABEL: @sub_overflow +// CHECK: call void @llvm.ubsantrap(i8 21) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Integer subtraction overflowed" diff --git a/clang/test/CodeGen/ubsan-trap-reason-type-mismatch.c b/clang/test/CodeGen/ubsan-trap-reason-type-mismatch.c new file mode 100644 index 0000000000000..802ec91b53a0d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-type-mismatch.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=alignment -fsanitize-trap=alignment -emit-llvm %s -o - | FileCheck %s + +int type_mismatch(int *p) { return *p; } + +// CHECK-LABEL: @type_mismatch +// CHECK: call void @llvm.ubsantrap(i8 22) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Type mismatch in operation" diff --git a/clang/test/CodeGen/ubsan-trap-reason-vla-bound-not-positive.c b/clang/test/CodeGen/ubsan-trap-reason-vla-bound-not-positive.c new file mode 100644 index 0000000000000..ad9c408b5e14d --- /dev/null +++ b/clang/test/CodeGen/ubsan-trap-reason-vla-bound-not-positive.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple arm64-apple-macosx14.0.0 -O0 -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fsanitize=vla-bound -fsanitize-trap=vla-bound -emit-llvm %s -o - | FileCheck %s + +int n = 0; + +int vla_bound_not_positive(void) { + int a[n]; + return sizeof a; +} + +// CHECK-LABEL: @vla_bound_not_positive +// CHECK: call void @llvm.ubsantrap(i8 24) {{.*}}!dbg [[LOC:![0-9]+]] +// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) +// CHECK: [[MSG]] = distinct !DISubprogram(name: "__clang_trap_msg$Undefined Behavior Sanitizer$Variable length array bound evaluates to non-positive value" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits