From: Adrian Prantl Date: Wed, 28 Nov 2018 21:44:06 +0000 (+0000) Subject: Ensure sanitizer check function calls have a !dbg location X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=db9f93e7f33d4f8bfd5f60930cf14cbd467378fc;p=clang Ensure sanitizer check function calls have a !dbg location Function calls without a !dbg location inside a function that has a DISubprogram make it impossible to construct inline information and are rejected by the verifier. This patch ensures that sanitizer check function calls have a !dbg location, by carrying forward the location of the preceding instruction or by inserting an artificial location if necessary. This fixes a crash when compiling the attached testcase with -Os. rdar://problem/45311226 Differential Revision: https://reviews.llvm.org/D53459 Note: This reapllies r344915, modified to reuse the IRBuilder's DebugLoc if one exists instead of picking the one from CGDebugInfo since the latter may get reset when emitting thunks such as block helpers in the middle of emitting another function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@347810 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index f4b0f8fb67..17a75c0bb1 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -2879,6 +2879,11 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF, CheckRecoverableKind RecoverKind, bool IsFatal, llvm::BasicBlock *ContBB) { assert(IsFatal || RecoverKind != CheckRecoverableKind::Unrecoverable); + Optional DL; + if (!CGF.Builder.getCurrentDebugLocation()) { + // Ensure that the call has at least an artificial debug location. + DL.emplace(CGF, SourceLocation()); + } bool NeedsAbortSuffix = IsFatal && RecoverKind != CheckRecoverableKind::Unrecoverable; bool MinimalRuntime = CGF.CGM.getCodeGenOpts().SanitizeMinimalRuntime; diff --git a/test/CodeGenCXX/ubsan-check-debuglocs.cpp b/test/CodeGenCXX/ubsan-check-debuglocs.cpp new file mode 100644 index 0000000000..96a697aca5 --- /dev/null +++ b/test/CodeGenCXX/ubsan-check-debuglocs.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited \ +// RUN: -fsanitize=null %s -o - | FileCheck %s + +// Check that santizer check calls have a !dbg location. +// CHECK: define {{.*}}acquire{{.*}} !dbg +// CHECK-NOT: define +// CHECK: call void {{.*}}@__ubsan_handle_type_mismatch_v1 +// CHECK-SAME: !dbg + +struct SourceLocation { + SourceLocation acquire() {}; +}; +extern "C" void __ubsan_handle_type_mismatch_v1(SourceLocation *Loc); +static void handleTypeMismatchImpl(SourceLocation *Loc) { Loc->acquire(); } +void __ubsan_handle_type_mismatch_v1(SourceLocation *Loc) { + handleTypeMismatchImpl(Loc); +} diff --git a/test/CodeGenObjC/ubsan-check-debuglocs.m b/test/CodeGenObjC/ubsan-check-debuglocs.m new file mode 100644 index 0000000000..d85c8e83e1 --- /dev/null +++ b/test/CodeGenObjC/ubsan-check-debuglocs.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -emit-llvm -fblocks -debug-info-kind=limited \ +// RUN: -fsanitize=nullability-return %s -o - | FileCheck %s + +// Check that santizer check calls have a !dbg location. +// CHECK: call void {{.*}}@__ubsan_handle_nullability_return_v1_abort +// CHECK-SAME: !dbg + +@protocol NSObject +@end + +@interface NSObject {} +@end + +#pragma clang assume_nonnull begin +@interface NSString : NSObject ++ (instancetype)stringWithFormat:(NSString *)format, ...; +@end + +@interface NSIndexPath : NSObject {} +@end +#pragma clang assume_nonnull end + +@interface B : NSObject +@end +id foo(NSIndexPath *indexPath) { + return [B withBlock:^{ + return [NSString stringWithFormat:@"%ld", + (long)[indexPath indexAtPosition:1]]; + }]; +}