Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -366,9 +366,33 @@ Non-comprehensive list of changes in this release
correct method to check for these features is to test for the ``__PTRAUTH__``
macro.

- 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.

New Compiler Flags
------------------
- 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``).


- New option ``-Wundef-true`` added and enabled by default to warn when `true` is used in the C preprocessor without being defined before C23.

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/AllDiagnosticKinds.inc
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#include "clang/Basic/DiagnosticRefactoringKinds.inc"
#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
#include "clang/Basic/DiagnosticTrapKinds.inc"
#include "clang/Basic/DiagnosticCASKinds.inc"

// clang-format on
11 changes: 6 additions & 5 deletions clang/include/clang/Basic/AllDiagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,21 @@
#include "clang/Basic/DiagnosticInstallAPI.h"
#include "clang/Basic/DiagnosticLex.h"
#include "clang/Basic/DiagnosticParse.h"
#include "clang/Basic/DiagnosticRefactoring.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/DiagnosticSerialization.h"
#include "clang/Basic/DiagnosticRefactoring.h"
#include "clang/Basic/DiagnosticTrap.h"

namespace clang {
template <size_t SizeOfStr, typename FieldType>
class StringSizerHelper {
template <size_t SizeOfStr, typename FieldType> class StringSizerHelper {
static_assert(SizeOfStr <= FieldType(~0U), "Field too small!");

public:
enum { Size = SizeOfStr };
};
} // end namespace clang

#define STR_SIZE(str, fieldTy) clang::StringSizerHelper<sizeof(str)-1, \
fieldTy>::Size
#define STR_SIZE(str, fieldTy) \
clang::StringSizerHelper<sizeof(str) - 1, fieldTy>::Size

#endif
1 change: 1 addition & 0 deletions clang/include/clang/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,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
1 change: 1 addition & 0 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,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.
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 @@ -178,6 +178,16 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// The callback for mc result.
std::optional<llvm::MCTargetOptions::ResultCallBackTy> MCCallBack;

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 @@ -1269,10 +1270,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 @@ -236,3 +238,4 @@ include "DiagnosticParseKinds.td"
include "DiagnosticRefactoringKinds.td"
include "DiagnosticSemaKinds.td"
include "DiagnosticSerializationKinds.td"
include "DiagnosticTrapKinds.td"
160 changes: 85 additions & 75 deletions clang/include/clang/Basic/DiagnosticIDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,78 +23,82 @@
#include <vector>

namespace clang {
class DiagnosticsEngine;
class DiagnosticBuilder;
class LangOptions;
class SourceLocation;

// Import the diagnostic enums themselves.
namespace diag {
enum class Group;

// Size of each of the diagnostic categories.
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 400,
DIAG_SIZE_FRONTEND = 200,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 500,
DIAG_SIZE_PARSE = 800,
DIAG_SIZE_AST = 300,
DIAG_SIZE_COMMENT = 100,
DIAG_SIZE_CROSSTU = 100,
DIAG_SIZE_SEMA = 5000,
DIAG_SIZE_ANALYSIS = 100,
DIAG_SIZE_REFACTORING = 1000,
DIAG_SIZE_INSTALLAPI = 100,
DIAG_SIZE_CAS = 100,
};
// Start position for diagnostics.
enum {
DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + static_cast<int>(DIAG_SIZE_COMMON),
DIAG_START_FRONTEND = DIAG_START_DRIVER + static_cast<int>(DIAG_SIZE_DRIVER),
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + static_cast<int>(DIAG_SIZE_FRONTEND),
DIAG_START_LEX = DIAG_START_SERIALIZATION + static_cast<int>(DIAG_SIZE_SERIALIZATION),
DIAG_START_PARSE = DIAG_START_LEX + static_cast<int>(DIAG_SIZE_LEX),
DIAG_START_AST = DIAG_START_PARSE + static_cast<int>(DIAG_SIZE_PARSE),
DIAG_START_COMMENT = DIAG_START_AST + static_cast<int>(DIAG_SIZE_AST),
DIAG_START_CROSSTU = DIAG_START_COMMENT + static_cast<int>(DIAG_SIZE_COMMENT),
DIAG_START_SEMA = DIAG_START_CROSSTU + static_cast<int>(DIAG_SIZE_CROSSTU),
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_START_CAS = DIAG_START_INSTALLAPI + static_cast<int>(DIAG_START_INSTALLAPI),
DIAG_UPPER_LIMIT = DIAG_START_CAS + static_cast<int>(DIAG_SIZE_CAS)
};

class CustomDiagInfo;

/// All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;

/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either Ignore (nothing), Remark (emit a remark), Warning
/// (emit a warning) or Error (emit as an error). It allows clients to
/// map ERRORs to Error or Fatal (stop emitting diagnostics after this one).
enum class Severity : uint8_t {
// NOTE: 0 means "uncomputed".
Ignored = 1, ///< Do not present this diagnostic, ignore it.
Remark = 2, ///< Present this diagnostic as a remark.
Warning = 3, ///< Present this diagnostic as a warning.
Error = 4, ///< Present this diagnostic as an error.
Fatal = 5 ///< Present this diagnostic as a fatal error.
};

/// Flavors of diagnostics we can emit. Used to filter for a particular
/// kind of diagnostic (for instance, for -W/-R flags).
enum class Flavor {
WarningOrError, ///< A diagnostic that indicates a problem or potential
///< problem. Can be made fatal by -Werror.
Remark ///< A diagnostic that indicates normal progress through
///< compilation.
};
} // end namespace diag
class DiagnosticsEngine;
class DiagnosticBuilder;
class LangOptions;
class SourceLocation;

// Import the diagnostic enums themselves.
namespace diag {
enum class Group;

// Size of each of the diagnostic categories.
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 400,
DIAG_SIZE_FRONTEND = 200,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 500,
DIAG_SIZE_PARSE = 800,
DIAG_SIZE_AST = 300,
DIAG_SIZE_COMMENT = 100,
DIAG_SIZE_CROSSTU = 100,
DIAG_SIZE_SEMA = 5000,
DIAG_SIZE_ANALYSIS = 100,
DIAG_SIZE_REFACTORING = 1000,
DIAG_SIZE_INSTALLAPI = 100,
DIAG_SIZE_TRAP = 100,
DIAG_SIZE_CAS = 100,
};
// Start position for diagnostics.
// clang-format off
enum {
DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + static_cast<int>(DIAG_SIZE_COMMON),
DIAG_START_FRONTEND = DIAG_START_DRIVER + static_cast<int>(DIAG_SIZE_DRIVER),
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + static_cast<int>(DIAG_SIZE_FRONTEND),
DIAG_START_LEX = DIAG_START_SERIALIZATION + static_cast<int>(DIAG_SIZE_SERIALIZATION),
DIAG_START_PARSE = DIAG_START_LEX + static_cast<int>(DIAG_SIZE_LEX),
DIAG_START_AST = DIAG_START_PARSE + static_cast<int>(DIAG_SIZE_PARSE),
DIAG_START_COMMENT = DIAG_START_AST + static_cast<int>(DIAG_SIZE_AST),
DIAG_START_CROSSTU = DIAG_START_COMMENT + static_cast<int>(DIAG_SIZE_COMMENT),
DIAG_START_SEMA = DIAG_START_CROSSTU + static_cast<int>(DIAG_SIZE_CROSSTU),
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_START_TRAP = DIAG_START_INSTALLAPI + static_cast<int>(DIAG_SIZE_INSTALLAPI),
DIAG_START_CAS = DIAG_START_TRAP + static_cast<int>(DIAG_SIZE_TRAP),
DIAG_UPPER_LIMIT = DIAG_START_CAS + static_cast<int>(DIAG_SIZE_CAS)
};
// clang-format on

class CustomDiagInfo;

/// All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;

/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either Ignore (nothing), Remark (emit a remark), Warning
/// (emit a warning) or Error (emit as an error). It allows clients to
/// map ERRORs to Error or Fatal (stop emitting diagnostics after this one).
enum class Severity : uint8_t {
// NOTE: 0 means "uncomputed".
Ignored = 1, ///< Do not present this diagnostic, ignore it.
Remark = 2, ///< Present this diagnostic as a remark.
Warning = 3, ///< Present this diagnostic as a warning.
Error = 4, ///< Present this diagnostic as an error.
Fatal = 5 ///< Present this diagnostic as a fatal error.
};

/// Flavors of diagnostics we can emit. Used to filter for a particular
/// kind of diagnostic (for instance, for -W/-R flags).
enum class Flavor {
WarningOrError, ///< A diagnostic that indicates a problem or potential
///< problem. Can be made fatal by -Werror.
Remark ///< A diagnostic that indicates normal progress through
///< compilation.
};
} // end namespace diag
} // end namespace clang

// This has to be included *after* the DIAG_START_ enums above are defined.
Expand Down Expand Up @@ -175,7 +179,8 @@ class DiagnosticMapping {

/// Used for handling and querying diagnostic IDs.
///
/// Can be used and shared by multiple Diagnostics for multiple translation units.
/// Can be used and shared by multiple Diagnostics for multiple translation
/// units.
class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
public:
/// The level of the diagnostic, after it has been through mapping.
Expand All @@ -188,7 +193,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 @@ -358,6 +364,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 Expand Up @@ -496,6 +506,6 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
friend class DiagnosticsEngine;
};

} // end namespace clang
} // end namespace clang

#endif
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">;

}
}
Loading