================ @@ -1534,6 +1536,103 @@ inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { return Report(SourceLocation(), DiagID); } +//===----------------------------------------------------------------------===// +// RuntimeTrapDiagnosticBuilder and helper classes +//===----------------------------------------------------------------------===// + +/// Helper class for \class RuntimeTrapDiagnosticBuilder. This class stores the +/// "trap reason" built by \class RuntimeTrapDiagnosticBuilder. This consists of +/// a trap message and trap category. +/// +/// It is intended that this object be allocated on the stack. +class TrapReason { +public: + TrapReason() {} + /// \return The trap message. Note the lifetime of the underlying storage for + /// the returned StringRef lives in this class which means the returned + /// StringRef should not be used after this class is destroyed. + StringRef getMessage() const { return Message; } + + /// \return the trap category (e.g. "Undefined Behavior Sanitizer") + StringRef getCategory() const { return Category; } + + bool isEmpty() const { return Message.size() == 0 && Category.size() == 0; } + + /// \return a pointer to this object if it contains a non-empty trap reason, + /// otherwise return `nullptr`. This is a convenient helper for passing + /// TrapReason objects to function calls that have a `TrapReason*` parameter. + TrapReason *getPtr() { + if (isEmpty()) + return nullptr; + return this; + } + +private: + llvm::SmallString<64> Message; + // The Category doesn't need its own storage because the StringRef points + // to a global constant string. + StringRef Category; + + // Only this class can set the private fields. + friend class RuntimeTrapDiagnosticBuilder; +}; + +/// Class to make it convenient to initialize TrapReason objects which can be +/// used to attach the "trap reason" to trap instructions. +/// +/// Although this class inherits from \class DiagnosticBuilder it has slightly +/// different semantics. +/// +/// * This class should only be used with trap diagnostics (declared in +/// `DiagnosticTrapKinds.td`). +/// * The `RuntimeTrapDiagnosticBuilder` does not emit diagnostics to the normal +/// diagnostics consumers on destruction like normal Diagnostic builders. +/// Instead on destruction it assigns to the TrapReason object passed in to +/// the constructor. +/// +/// Given that this class inherits from `DiagnosticBuilder` it inherits all of +/// its abilities to format diagnostic messages and consume various types in +/// class (e.g. Type, Exprs, etc.). This makes it particularly suited to +/// printing types and expressions from the AST while codegen-ing runtime +/// checks. +/// +/// +/// Example use via the `CodeGenModule::RuntimeDiag` helper. +/// +/// \code +/// { +/// TrapReason TR; +/// CGM.RuntimeDiag(diag::trap_diagnostic, TR) << 0 << SomeExpr << SomeType; +/// consume(TR.getPtr()); +/// } +/// \endcode +/// +/// +class RuntimeTrapDiagnosticBuilder : public DiagnosticBuilder { ---------------- delcypher wrote:
I figured it out. I forgot that when I moved the class I also moved it into a different namespace so I forgot to update the forward declaration in `Diagnostic.h` to be in the correct namespace. So doing this "works": ``` index af26a04d9488..b957ca331781 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -60,6 +60,9 @@ class Preprocessor; class SourceManager; class StoredDiagnostic; +namespace CodeGen { + class TrapReasonBuilder; +} // namespace CodeGen namespace tok { enum TokenKind : unsigned short; @@ -1234,6 +1237,7 @@ class DiagnosticBuilder : public StreamingDiagnostic { friend class DiagnosticsEngine; friend class PartialDiagnostic; friend class Diagnostic; + friend class CodeGen::TrapReasonBuilder; mutable DiagnosticsEngine *DiagObj = nullptr; @@ -1260,13 +1264,14 @@ class DiagnosticBuilder : public StreamingDiagnostic { DiagnosticBuilder() = default; -protected: + DiagnosticBuilder(DiagnosticsEngine *DiagObj, SourceLocation DiagLoc, unsigned DiagID); DiagnosticsEngine *getDiagnosticsEngine() const { return DiagObj; } unsigned getDiagID() const { return DiagID; } +protected: /// Clear out the current diagnostic. void Clear() const { DiagObj = nullptr; ``` I think it's very ugly though to have the `CodeGen` namespace mentioned in the `Diagnostic.h` so I'd much rather not rely on using `friend class` and instead just rely on using the new `protected` accessor methods I added. https://github.com/llvm/llvm-project/pull/154618 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits