Index: lib/ubsan/ubsan_diag.h =================================================================== --- lib/ubsan/ubsan_diag.h +++ lib/ubsan/ubsan_diag.h @@ -203,6 +203,9 @@ Diag &operator<<(const Range &R) { return AddRange(R); } }; +/// Optionally constructs and reports SUMMARY line like another sanitizers. +void ReportSummary(Location Loc); + } // namespace __ubsan #endif // UBSAN_DIAG_H Index: lib/ubsan/ubsan_diag.cc =================================================================== --- lib/ubsan/ubsan_diag.cc +++ lib/ubsan/ubsan_diag.cc @@ -105,8 +105,7 @@ #endif } -static void renderLocation(Location Loc) { - InternalScopedString LocBuffer(1024); +static void renderLocation(Location Loc, InternalScopedString &LocBuffer) { switch (Loc.getKind()) { case Location::LK_Source: { SourceLocation SLoc = Loc.getSourceLocation(); @@ -128,7 +127,6 @@ LocBuffer.append(""); break; } - Printf("%s:", LocBuffer.data()); } static void renderText(const char *Message, const Diag::Arg *Args) { @@ -279,7 +277,9 @@ SpinMutexLock l(&CommonSanitizerReportMutex); Printf(Decor.Bold()); - renderLocation(Loc); + InternalScopedString LocBuffer(1024); + renderLocation(Loc, LocBuffer); + Printf("%s:", LocBuffer.data()); switch (Level) { case DL_Error: @@ -300,3 +300,13 @@ renderMemorySnippet(Decor, Loc.getMemoryLocation(), Ranges, NumRanges, Args); } + +void __ubsan::ReportSummary(Location Loc) { + InitializeSanitizerCommon(); + if (!common_flags()->print_summary) + return; + InternalScopedString SummaryBuffer(1024); + SummaryBuffer.append("runtime-error: "); + renderLocation(Loc, SummaryBuffer); + ReportErrorSummary(SummaryBuffer.data()); +} Index: lib/ubsan/ubsan_handlers.cc =================================================================== --- lib/ubsan/ubsan_handlers.cc +++ lib/ubsan/ubsan_handlers.cc @@ -50,6 +50,7 @@ << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; if (Pointer) Diag(Pointer, DL_Note, "pointer points here"); + ReportSummary(Loc); } void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data, ValueHandle Pointer) { @@ -74,6 +75,7 @@ "%1 %2 %3 cannot be represented in type %4") << (Data->Type.isSignedIntegerTy() ? "signed" : "unsigned") << Value(Data->Type, LHS) << Operator << RHS << Data->Type; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_add_overflow(OverflowData *Data, @@ -124,6 +126,7 @@ Diag(Loc, DL_Error, "negation of %0 cannot be represented in type %1") << Value(Data->Type, OldVal) << Data->Type; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data, ValueHandle OldVal) { @@ -145,6 +148,7 @@ << LHSVal << Data->Type; else Diag(Loc, DL_Error, "division by zero"); + ReportSummary(Loc); } void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data, ValueHandle LHS, @@ -174,6 +178,7 @@ Diag(Loc, DL_Error, "left shift of %0 by %1 places cannot be represented in type %2") << LHSVal << RHSVal << Data->LHSType; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_shift_out_of_bounds_abort( ShiftOutOfBoundsData *Data, @@ -192,6 +197,7 @@ Value IndexVal(Data->IndexType, Index); Diag(Loc, DL_Error, "index %0 out of bounds for type %1") << IndexVal << Data->ArrayType; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data, ValueHandle Index) { @@ -200,14 +206,23 @@ } void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) { - Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call"); + SourceLocation Loc = Data->Loc.acquire(); + if (Loc.isDisabled()) + return; + + Diag(Loc, DL_Error, "execution reached a __builtin_unreachable() call"); + ReportSummary(Loc); Die(); } void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) { - Diag(Data->Loc, DL_Error, - "execution reached the end of a value-returning function " - "without returning a value"); + SourceLocation Loc = Data->Loc.acquire(); + if (Loc.isDisabled()) + return; + + Diag(Loc, DL_Error, "execution reached the end of a value-returning function " + "without returning a value"); + ReportSummary(Loc); Die(); } @@ -220,6 +235,7 @@ Diag(Loc, DL_Error, "variable length array bound evaluates to " "non-positive value %0") << Value(Data->Type, Bound); + ReportSummary(Loc); } void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data, ValueHandle Bound) { @@ -231,16 +247,20 @@ void __ubsan::__ubsan_handle_float_cast_overflow(FloatCastOverflowData *Data, ValueHandle From) { // TODO: Add deduplication once a SourceLocation is generated for this check. - Diag(getCallerLocation(), DL_Error, + Location Loc = getCallerLocation(); + Diag(Loc, DL_Error, "value %0 is outside the range of representable values of type %2") - << Value(Data->FromType, From) << Data->FromType << Data->ToType; + << Value(Data->FromType, From) << Data->FromType << Data->ToType; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_float_cast_overflow_abort( FloatCastOverflowData *Data, ValueHandle From) { - Diag(getCallerLocation(), DL_Error, + Location Loc = getCallerLocation(); + Diag(Loc, DL_Error, "value %0 is outside the range of representable values of type %2") - << Value(Data->FromType, From) << Data->FromType << Data->ToType; + << Value(Data->FromType, From) << Data->FromType << Data->ToType; + ReportSummary(Loc); Die(); } @@ -253,6 +273,7 @@ Diag(Loc, DL_Error, "load of value %0, which is not a valid value for type %1") << Value(Data->Type, Val) << Data->Type; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data, ValueHandle Val) { @@ -271,6 +292,7 @@ "call to function %0 through pointer to incorrect function type %1") << FName << Data->Type; Diag(Loc, DL_Note, "%0 defined here") << FName; + ReportSummary(Loc); } void __ubsan::__ubsan_handle_function_type_mismatch_abort( Index: lib/ubsan/ubsan_handlers_cxx.cc =================================================================== --- lib/ubsan/ubsan_handlers_cxx.cc +++ lib/ubsan/ubsan_handlers_cxx.cc @@ -60,6 +60,7 @@ << MangledName(DTI.getSubobjectTypeName()) << Range(Pointer, Pointer + sizeof(uptr), "vptr for %2 base class of %1"); + ReportSummary(Loc); if (Abort) Die(); } Index: test/ubsan/TestCases/Integer/summary.cpp =================================================================== --- /dev/null +++ test/ubsan/TestCases/Integer/summary.cpp @@ -0,0 +1,9 @@ +// RUN: %clangxx -fsanitize=integer %s -o %t && not %t 2>&1 | FileCheck %s +// REQUIRES: ubsan-asan + +#include + +int main() { + (void)(uint64_t(10000000000000000000ull) + uint64_t(9000000000000000000ull)); + // CHECK: SUMMARY: AddressSanitizer: runtime-error: {{.*}}summary.cpp:[[@LINE-1]] +} Index: test/ubsan/lit.common.cfg =================================================================== --- test/ubsan/lit.common.cfg +++ test/ubsan/lit.common.cfg @@ -21,6 +21,7 @@ clang_ubsan_cflags = [] elif ubsan_lit_test_mode == "AddressSanitizer": config.name = 'UndefinedBehaviorSanitizer-AddressSanitizer' + config.available_features.add("ubsan-asan") clang_ubsan_cflags = ["-fsanitize=address"] else: lit_config.fatal("Unknown UBSan test mode: %r" % ubsan_lit_test_mode)