1 //===-- ubsan_diag.h --------------------------------------------*- C++ -*-===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // Diagnostics emission for Clang's undefined behavior sanitizer.
10 //===----------------------------------------------------------------------===//
14 #include "ubsan_value.h"
18 /// \brief A location within a loaded module in the program. These are used when
19 /// the location can't be resolved to a SourceLocation.
20 class ModuleLocation
{
21 const char *ModuleName
;
25 ModuleLocation() : ModuleName(0), Offset(0) {}
26 ModuleLocation(const char *ModuleName
, uptr Offset
)
27 : ModuleName(ModuleName
), Offset(Offset
) {}
28 const char *getModuleName() const { return ModuleName
; }
29 uptr
getOffset() const { return Offset
; }
32 /// A location of some data within the program's address space.
33 typedef uptr MemoryLocation
;
35 /// \brief Location at which a diagnostic can be emitted. Either a
36 /// SourceLocation, a ModuleLocation, or a MemoryLocation.
39 enum LocationKind
{ LK_Null
, LK_Source
, LK_Module
, LK_Memory
};
43 // FIXME: In C++11, wrap these in an anonymous union.
44 SourceLocation SourceLoc
;
45 ModuleLocation ModuleLoc
;
46 MemoryLocation MemoryLoc
;
49 Location() : Kind(LK_Null
) {}
50 Location(SourceLocation Loc
) :
51 Kind(LK_Source
), SourceLoc(Loc
) {}
52 Location(ModuleLocation Loc
) :
53 Kind(LK_Module
), ModuleLoc(Loc
) {}
54 Location(MemoryLocation Loc
) :
55 Kind(LK_Memory
), MemoryLoc(Loc
) {}
57 LocationKind
getKind() const { return Kind
; }
59 bool isSourceLocation() const { return Kind
== LK_Source
; }
60 bool isModuleLocation() const { return Kind
== LK_Module
; }
61 bool isMemoryLocation() const { return Kind
== LK_Memory
; }
63 SourceLocation
getSourceLocation() const {
64 CHECK(isSourceLocation());
67 ModuleLocation
getModuleLocation() const {
68 CHECK(isModuleLocation());
71 MemoryLocation
getMemoryLocation() const {
72 CHECK(isMemoryLocation());
77 /// Try to obtain a location for the caller. This might fail, and produce either
78 /// an invalid location or a module location for the caller.
79 Location
getCallerLocation(uptr CallerLoc
= GET_CALLER_PC());
81 /// A diagnostic severity level.
83 DL_Error
, ///< An error.
84 DL_Note
///< A note, attached to a prior diagnostic.
87 /// \brief Annotation for a range of locations in a diagnostic.
93 Range() : Start(), End(), Text() {}
94 Range(MemoryLocation Start
, MemoryLocation End
, const char *Text
)
95 : Start(Start
), End(End
), Text(Text
) {}
96 Location
getStart() const { return Start
; }
97 Location
getEnd() const { return End
; }
98 const char *getText() const { return Text
; }
101 /// \brief A mangled C++ name. Really just a strong typedef for 'const char*'.
105 MangledName(const char *Name
) : Name(Name
) {}
106 const char *getName() const { return Name
; }
109 /// \brief Representation of an in-flight diagnostic.
111 /// Temporary \c Diag instances are created by the handler routines to
112 /// accumulate arguments for a diagnostic. The destructor emits the diagnostic
115 /// The location at which the problem occurred.
118 /// The diagnostic level.
121 /// The message which will be emitted, with %0, %1, ... placeholders for
126 /// Kinds of arguments, corresponding to members of \c Arg's union.
128 AK_String
, ///< A string argument, displayed as-is.
129 AK_Mangled
,///< A C++ mangled name, demangled before display.
130 AK_UInt
, ///< An unsigned integer argument.
131 AK_SInt
, ///< A signed integer argument.
132 AK_Float
, ///< A floating-point argument.
133 AK_Pointer
///< A pointer argument, displayed in hexadecimal.
136 /// An individual diagnostic message argument.
139 Arg(const char *String
) : Kind(AK_String
), String(String
) {}
140 Arg(MangledName MN
) : Kind(AK_Mangled
), String(MN
.getName()) {}
141 Arg(UIntMax UInt
) : Kind(AK_UInt
), UInt(UInt
) {}
142 Arg(SIntMax SInt
) : Kind(AK_SInt
), SInt(SInt
) {}
143 Arg(FloatMax Float
) : Kind(AK_Float
), Float(Float
) {}
144 Arg(const void *Pointer
) : Kind(AK_Pointer
), Pointer(Pointer
) {}
157 static const unsigned MaxArgs
= 5;
158 static const unsigned MaxRanges
= 1;
160 /// The arguments which have been added to this diagnostic so far.
164 /// The ranges which have been added to this diagnostic so far.
165 Range Ranges
[MaxRanges
];
168 Diag
&AddArg(Arg A
) {
169 CHECK(NumArgs
!= MaxArgs
);
174 Diag
&AddRange(Range A
) {
175 CHECK(NumRanges
!= MaxRanges
);
176 Ranges
[NumRanges
++] = A
;
180 /// \c Diag objects are not copyable.
181 Diag(const Diag
&); // NOT IMPLEMENTED
182 Diag
&operator=(const Diag
&);
185 Diag(Location Loc
, DiagLevel Level
, const char *Message
)
186 : Loc(Loc
), Level(Level
), Message(Message
), NumArgs(0), NumRanges(0) {}
189 Diag
&operator<<(const char *Str
) { return AddArg(Str
); }
190 Diag
&operator<<(MangledName MN
) { return AddArg(MN
); }
191 Diag
&operator<<(unsigned long long V
) { return AddArg(UIntMax(V
)); }
192 Diag
&operator<<(const void *V
) { return AddArg(V
); }
193 Diag
&operator<<(const TypeDescriptor
&V
);
194 Diag
&operator<<(const Value
&V
);
195 Diag
&operator<<(const Range
&R
) { return AddRange(R
); }
198 } // namespace __ubsan
200 #endif // UBSAN_DIAG_H