Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5044fa0
[UBSan][BoundsSafety] Implement support for more expressive "trap rea…
delcypher Aug 19, 2025
edafb6c
Add `[[nodiscard]]` to `RuntimeTrapDiagnosticBuilder`
delcypher Aug 21, 2025
9c7cf18
Remove unnecessary incldue
delcypher Aug 21, 2025
9fcb7a7
Use modern header block for `DiagnosticTrap.h` and add a little bit of
delcypher Aug 21, 2025
e2449b7
Fix some formatting
delcypher Aug 21, 2025
3aed658
Use %enum_select
delcypher Aug 21, 2025
eff527d
Use llvm::SmallString instead of llvm::SmallVector
delcypher Aug 21, 2025
7e0cde9
Move `RuntimeTrapDiagnosticBuilder` to a safer API where the storage and
delcypher Aug 22, 2025
ac683d7
Fix `tools/clang/test/Misc/warning-flags.c` by teaching `diagtool` to
delcypher Aug 22, 2025
6aa8296
Update clang/include/clang/Basic/Diagnostic.td
delcypher Aug 25, 2025
5d819f2
Update clang/include/clang/Basic/DiagnosticTrap.h
delcypher Aug 25, 2025
c54409f
Update clang/lib/CodeGen/CGExprScalar.cpp
delcypher Aug 25, 2025
ad5cd32
Rename classes and move into CodeGen
delcypher Aug 25, 2025
4d7acf8
Small clean ups
delcypher Aug 25, 2025
abfade4
Drop top-level comment in header
delcypher Aug 25, 2025
fc6b7cd
Add missing include to unbreak the build
delcypher Aug 25, 2025
3a8b319
Add missing `isEmpty()` test to fix tests
delcypher Aug 26, 2025
8973973
Fix inconsistent ordering
delcypher Aug 26, 2025
4e3200f
Update clang/include/clang/Basic/Diagnostic.td
delcypher Aug 26, 2025
e5859be
Update clang/lib/CodeGen/TrapReasonBuilder.h
delcypher Aug 26, 2025
58a897c
Update clang/lib/CodeGen/TrapReasonBuilder.h
delcypher Aug 26, 2025
6c78086
Fix out-of-date comment
delcypher Aug 26, 2025
bc4842f
Make `-fsanitize-debug-trap-reasons=` a parameterized flag that takes
delcypher Aug 26, 2025
85c4e42
Fix formatting
delcypher Aug 26, 2025
783eca9
Fix typos in some test comments
delcypher Aug 26, 2025
cd62acd
Address some feedback for the release notes and also explain about
delcypher Aug 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,27 @@ 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``.
- Trapping UBSan (e.g. ``-fsanitize=undefined -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-debug-trap-reasons``. The feature has a ``basic`` and
``detailed`` mode (the default). The ``basic`` mode emits a hard-coded string
per trap kind (e.g. ``Integer addition overflowed``) and the ``detailed`` mode
emits a more descriptive string describing each individual trap (e.g. ``signed
integer addition overflow in 'a + b'``). The ``detailed`` mode produces larger
debug info than ``basic`` but is more helpful for debugging. The
``-fsanitize-debug-trap-reasons=`` flag can be used to switch between the
different modes or disable the feature entirely. Note due to trap merging in
optimized builds (i.e. in each function all traps of the same kind get merged
into the same trap instruction) the trap reasons might be removed. To prevent
this build without optimizations (i.e. use `-O0` or use the `optnone` function
attribute) or use the `fno-sanitize-merge=` flag in optimized builds.

- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` functions for integer types can
now be used in constant expressions.
Expand Down Expand Up @@ -185,7 +198,9 @@ Non-comprehensive list of changes in this release

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``).
- New option ``-fno-sanitize-debug-trap-reasons`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
- New option ``-fsanitize-debug-trap-reasons=`` added to control emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).


Lanai Support
^^^^^^^^^^^^^^
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/AllDiagnosticKinds.inc
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#include "clang/Basic/DiagnosticRefactoringKinds.inc"
#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
#include "clang/Basic/DiagnosticTrapKinds.inc"
// clang-format on
1 change: 1 addition & 0 deletions clang/include/clang/Basic/AllDiagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "clang/Basic/DiagnosticRefactoring.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/DiagnosticSerialization.h"
#include "clang/Basic/DiagnosticTrap.h"

namespace clang {
template <size_t SizeOfStr, typename FieldType> class StringSizerHelper {
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ clang_diag_gen(Parse)
clang_diag_gen(Refactoring)
clang_diag_gen(Sema)
clang_diag_gen(Serialization)
clang_diag_gen(Trap)
clang_tablegen(DiagnosticGroups.inc -gen-clang-diag-groups
SOURCE Diagnostic.td
TARGET ClangDiagnosticGroups)
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +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
ENUM_CODEGENOPT(SanitizeDebugTrapReasons, SanitizeDebugTrapReasonKind, 2, SanitizeDebugTrapReasonKind::Detailed, Benign) ///< Control how "trap reasons" are emitted in debug info
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.
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,16 @@ class CodeGenOptions : public CodeGenOptionsBase {
Forced,
};

enum SanitizeDebugTrapReasonKind {
None, ///< Trap Messages are omitted. This offers the smallest debug info
///< size but at the cost of making traps hard to debug.
Basic, ///< Trap Message is fixed per SanitizerKind. Produces smaller debug
///< info than `Detailed` but is not as helpful for debugging.
Detailed, ///< Trap Message includes more context (e.g. the expression being
///< overflowed). This is more helpful for debugging but produces
///< larger debug info than `Basic`.
};

/// The code model to use (-mcmodel).
std::string CodeModel;

Expand Down
6 changes: 5 additions & 1 deletion clang/include/clang/Basic/Diagnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
Expand Down Expand Up @@ -1259,10 +1260,13 @@ class DiagnosticBuilder : public StreamingDiagnostic {

DiagnosticBuilder() = default;

protected:
DiagnosticBuilder(DiagnosticsEngine *DiagObj, SourceLocation DiagLoc,
unsigned DiagID);

protected:
DiagnosticsEngine *getDiagnosticsEngine() const { return DiagObj; }
unsigned getDiagID() const { return DiagID; }

/// Clear out the current diagnostic.
void Clear() const {
DiagObj = nullptr;
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/Diagnostic.td
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def CLASS_REMARK : DiagClass;
def CLASS_WARNING : DiagClass;
def CLASS_EXTENSION : DiagClass;
def CLASS_ERROR : DiagClass;
def CLASS_TRAP : DiagClass;

// Responses to a diagnostic in a SFINAE context.
class SFINAEResponse;
Expand Down Expand Up @@ -144,7 +145,8 @@ class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Ignored>;
class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Warning>;
// Notes can provide supplementary information on errors, warnings, and remarks.
class Note<string str> : Diagnostic<str, CLASS_NOTE, SEV_Fatal/*ignored*/>;

// Trap messages attached to traps in debug info.
class Trap<string str> : Diagnostic<str, CLASS_TRAP, SEV_Fatal/*ignored*/>;

class DefaultIgnore { Severity DefaultSeverity = SEV_Ignored; }
class DefaultWarn { Severity DefaultSeverity = SEV_Warning; }
Expand Down Expand Up @@ -235,3 +237,4 @@ include "DiagnosticParseKinds.td"
include "DiagnosticRefactoringKinds.td"
include "DiagnosticSemaKinds.td"
include "DiagnosticSerializationKinds.td"
include "DiagnosticTrapKinds.td"
11 changes: 9 additions & 2 deletions clang/include/clang/Basic/DiagnosticIDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ enum {
DIAG_SIZE_ANALYSIS = 100,
DIAG_SIZE_REFACTORING = 1000,
DIAG_SIZE_INSTALLAPI = 100,
DIAG_SIZE_TRAP = 100,
};
// Start position for diagnostics.
// clang-format off
Expand All @@ -64,7 +65,8 @@ enum {
DIAG_START_ANALYSIS = DIAG_START_SEMA + static_cast<int>(DIAG_SIZE_SEMA),
DIAG_START_REFACTORING = DIAG_START_ANALYSIS + static_cast<int>(DIAG_SIZE_ANALYSIS),
DIAG_START_INSTALLAPI = DIAG_START_REFACTORING + static_cast<int>(DIAG_SIZE_REFACTORING),
DIAG_UPPER_LIMIT = DIAG_START_INSTALLAPI + static_cast<int>(DIAG_SIZE_INSTALLAPI)
DIAG_START_TRAP = DIAG_START_INSTALLAPI + static_cast<int>(DIAG_SIZE_INSTALLAPI),
DIAG_UPPER_LIMIT = DIAG_START_TRAP + static_cast<int>(DIAG_SIZE_TRAP)
};
// clang-format on

Expand Down Expand Up @@ -189,7 +191,8 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
CLASS_REMARK = 0x02,
CLASS_WARNING = 0x03,
CLASS_EXTENSION = 0x04,
CLASS_ERROR = 0x05
CLASS_ERROR = 0x05,
CLASS_TRAP = 0x06
};

static bool IsCustomDiag(diag::kind Diag) {
Expand Down Expand Up @@ -363,6 +366,10 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
///
bool isExtensionDiag(unsigned DiagID, bool &EnabledByDefault) const;

bool isTrapDiag(unsigned DiagID) const {
return getDiagClass(DiagID) == CLASS_TRAP;
}

/// Given a group ID, returns the flag that toggles the group.
/// For example, for Group::DeprecatedDeclarations, returns
/// "deprecated-declarations".
Expand Down
14 changes: 14 additions & 0 deletions clang/include/clang/Basic/DiagnosticTrap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_DIAGNOSTICTRAP_H
#define LLVM_CLANG_BASIC_DIAGNOSTICTRAP_H

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticTrapInterface.inc"

#endif
30 changes: 30 additions & 0 deletions clang/include/clang/Basic/DiagnosticTrapKinds.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//==--- DiagnosticTrapKinds.td ------------------------ -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Trap Diagnostics
//
// These are diagnostics that are emitted into `TrapReason` objects using the
// `TrapReasonBuilder` class. These `TrapReason` objects are then encoded into
// debug info during codegen, rather than to the traditional diagnostic
// consumers like the terminal. Their primary purpose is to make debugging traps
// (e.g. `-fsanitize-trap=undefined`) easier by attaching a trap category and
// message to the trap instruction that tools like a debugger can show.
//
//===----------------------------------------------------------------------===//
let Component = "Trap" in {
let CategoryName = "Undefined Behavior Sanitizer" in {

def trap_ubsan_arith_overflow : Trap<
"%select{unsigned|signed}0 integer "
"%enum_select<UBSanArithKind>{"
"%Add{addition}|"
"%Sub{subtraction}|"
"%Mul{multiplication}"
"}1 overflow in %2">;

}
}
31 changes: 21 additions & 10 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2612,16 +2612,27 @@ 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">>;

def fsanitize_debug_trap_reasons_EQ
: Joined<["-"], "fsanitize-debug-trap-reasons=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Set how trap reasons are emitted. "
"`none` - Not emitted. This gives the smallest debug info; "
"`basic` - Emit a fixed trap message per check type. This increases the "
"debug info size but not as much as `detailed`; "
"`detailed` - Emit a more detailed trap message. This increases the "
"debug info size the most. Default is `detailed`.">,
Values<"none,basic,detailed">,
NormalizedValuesScope<"CodeGenOptions::SanitizeDebugTrapReasonKind">,
NormalizedValues<["None", "Basic", "Detailed"]>,
MarshallingInfoEnum<CodeGenOpts<"SanitizeDebugTrapReasons">, "Detailed">;
def fsanitize_debug_trap_reasons
: Flag<["-"], "fsanitize-debug-trap-reasons">, Group<f_clang_Group>,
Alias<fsanitize_debug_trap_reasons_EQ>, AliasArgs<["detailed"]>,
HelpText<"Alias for -fsanitize-debug-trap-reasons=detailed">;
def fno_sanitize_debug_trap_reasons
: Flag<["-"], "fno-sanitize-debug-trap-reasons">, Group<f_clang_Group>,
Alias<fsanitize_debug_trap_reasons_EQ>, AliasArgs<["none"]>,
HelpText<"Alias for -fsanitize-debug-trap-reasons=none">;
defm sanitize_minimal_runtime : BoolOption<"f", "sanitize-minimal-runtime",
CodeGenOpts<"SanitizeMinimalRuntime">, DefaultFalse,
PosFlag<SetTrue>,
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,8 @@ void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {

void DiagnosticsEngine::Report(Level DiagLevel, const Diagnostic &Info) {
assert(DiagLevel != Ignored && "Cannot emit ignored diagnostics!");
assert(!getDiagnosticIDs()->isTrapDiag(Info.getID()) &&
"Trap diagnostics should not be consumed by the DiagnosticsEngine");
Client->HandleDiagnostic(DiagLevel, Info);
if (Client->IncludeInDiagnosticCounts()) {
if (DiagLevel == Warning)
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/DiagnosticIDs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ enum DiagnosticClass {
CLASS_WARNING = DiagnosticIDs::CLASS_WARNING,
CLASS_EXTENSION = DiagnosticIDs::CLASS_EXTENSION,
CLASS_ERROR = DiagnosticIDs::CLASS_ERROR,
CLASS_TRAP = DiagnosticIDs::CLASS_TRAP,
};

struct StaticDiagInfoRec {
Expand Down Expand Up @@ -139,6 +140,7 @@ VALIDATE_DIAG_SIZE(SEMA)
VALIDATE_DIAG_SIZE(ANALYSIS)
VALIDATE_DIAG_SIZE(REFACTORING)
VALIDATE_DIAG_SIZE(INSTALLAPI)
VALIDATE_DIAG_SIZE(TRAP)
#undef VALIDATE_DIAG_SIZE
#undef STRINGIFY_NAME

Expand Down Expand Up @@ -171,6 +173,7 @@ const StaticDiagInfoRec StaticDiagInfo[] = {
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#include "clang/Basic/DiagnosticRefactoringKinds.inc"
#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
#include "clang/Basic/DiagnosticTrapKinds.inc"
// clang-format on
#undef DIAG
};
Expand Down Expand Up @@ -214,6 +217,7 @@ CATEGORY(SEMA, CROSSTU)
CATEGORY(ANALYSIS, SEMA)
CATEGORY(REFACTORING, ANALYSIS)
CATEGORY(INSTALLAPI, REFACTORING)
CATEGORY(TRAP, INSTALLAPI)
#undef CATEGORY

// Avoid out of bounds reads.
Expand Down
25 changes: 19 additions & 6 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3782,7 +3782,7 @@ static void emitCheckHandlerCall(CodeGenFunction &CGF,
void CodeGenFunction::EmitCheck(
ArrayRef<std::pair<llvm::Value *, SanitizerKind::SanitizerOrdinal>> Checked,
SanitizerHandler CheckHandler, ArrayRef<llvm::Constant *> StaticArgs,
ArrayRef<llvm::Value *> DynamicArgs) {
ArrayRef<llvm::Value *> DynamicArgs, const TrapReason *TR) {
assert(IsSanitizerScope);
assert(Checked.size() > 0);
assert(CheckHandler >= 0 &&
Expand Down Expand Up @@ -3821,7 +3821,7 @@ void CodeGenFunction::EmitCheck(
}

if (TrapCond)
EmitTrapCheck(TrapCond, CheckHandler, NoMerge);
EmitTrapCheck(TrapCond, CheckHandler, NoMerge, TR);
if (!FatalCond && !RecoverableCond)
return;

Expand Down Expand Up @@ -4133,7 +4133,7 @@ void CodeGenFunction::EmitUnreachable(SourceLocation Loc) {

void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
SanitizerHandler CheckHandlerID,
bool NoMerge) {
bool NoMerge, const TrapReason *TR) {
llvm::BasicBlock *Cont = createBasicBlock("cont");

// If we're optimizing, collapse all calls to trap down to just one per
Expand All @@ -4144,12 +4144,25 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID];

llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation();
llvm::StringRef TrapMessage = GetUBSanTrapForHandler(CheckHandlerID);
llvm::StringRef TrapMessage;
llvm::StringRef TrapCategory;
auto DebugTrapReasonKind = CGM.getCodeGenOpts().getSanitizeDebugTrapReasons();
if (TR && !TR->isEmpty() &&
DebugTrapReasonKind ==
CodeGenOptions::SanitizeDebugTrapReasonKind::Detailed) {
TrapMessage = TR->getMessage();
TrapCategory = TR->getCategory();
} else {
TrapMessage = GetUBSanTrapForHandler(CheckHandlerID);
TrapCategory = "Undefined Behavior Sanitizer";
}

if (getDebugInfo() && !TrapMessage.empty() &&
CGM.getCodeGenOpts().SanitizeDebugTrapReasons && TrapLocation) {
DebugTrapReasonKind !=
CodeGenOptions::SanitizeDebugTrapReasonKind::None &&
TrapLocation) {
TrapLocation = getDebugInfo()->CreateTrapFailureMessageFor(
TrapLocation, "Undefined Behavior Sanitizer", TrapMessage);
TrapLocation, TrapCategory, TrapMessage);
}

NoMerge = NoMerge || !CGM.getCodeGenOpts().OptimizationLevel ||
Expand Down
Loading