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 /// Try to obtain a location for the given function pointer. This might fail,
82 /// and produce either an invalid location or a module location for the caller.
83 /// If FName is non-null and the name of the function is known, set *FName to
84 /// the function name, otherwise *FName is unchanged.
85 Location
getFunctionLocation(uptr Loc
, const char **FName
);
87 /// A diagnostic severity level.
89 DL_Error
, ///< An error.
90 DL_Note
///< A note, attached to a prior diagnostic.
93 /// \brief Annotation for a range of locations in a diagnostic.
99 Range() : Start(), End(), Text() {}
100 Range(MemoryLocation Start
, MemoryLocation End
, const char *Text
)
101 : Start(Start
), End(End
), Text(Text
) {}
102 Location
getStart() const { return Start
; }
103 Location
getEnd() const { return End
; }
104 const char *getText() const { return Text
; }
107 /// \brief A mangled C++ name. Really just a strong typedef for 'const char*'.
111 MangledName(const char *Name
) : Name(Name
) {}
112 const char *getName() const { return Name
; }
115 /// \brief Representation of an in-flight diagnostic.
117 /// Temporary \c Diag instances are created by the handler routines to
118 /// accumulate arguments for a diagnostic. The destructor emits the diagnostic
121 /// The location at which the problem occurred.
124 /// The diagnostic level.
127 /// The message which will be emitted, with %0, %1, ... placeholders for
132 /// Kinds of arguments, corresponding to members of \c Arg's union.
134 AK_String
, ///< A string argument, displayed as-is.
135 AK_Mangled
,///< A C++ mangled name, demangled before display.
136 AK_UInt
, ///< An unsigned integer argument.
137 AK_SInt
, ///< A signed integer argument.
138 AK_Float
, ///< A floating-point argument.
139 AK_Pointer
///< A pointer argument, displayed in hexadecimal.
142 /// An individual diagnostic message argument.
145 Arg(const char *String
) : Kind(AK_String
), String(String
) {}
146 Arg(MangledName MN
) : Kind(AK_Mangled
), String(MN
.getName()) {}
147 Arg(UIntMax UInt
) : Kind(AK_UInt
), UInt(UInt
) {}
148 Arg(SIntMax SInt
) : Kind(AK_SInt
), SInt(SInt
) {}
149 Arg(FloatMax Float
) : Kind(AK_Float
), Float(Float
) {}
150 Arg(const void *Pointer
) : Kind(AK_Pointer
), Pointer(Pointer
) {}
163 static const unsigned MaxArgs
= 5;
164 static const unsigned MaxRanges
= 1;
166 /// The arguments which have been added to this diagnostic so far.
170 /// The ranges which have been added to this diagnostic so far.
171 Range Ranges
[MaxRanges
];
174 Diag
&AddArg(Arg A
) {
175 CHECK(NumArgs
!= MaxArgs
);
180 Diag
&AddRange(Range A
) {
181 CHECK(NumRanges
!= MaxRanges
);
182 Ranges
[NumRanges
++] = A
;
186 /// \c Diag objects are not copyable.
187 Diag(const Diag
&); // NOT IMPLEMENTED
188 Diag
&operator=(const Diag
&);
191 Diag(Location Loc
, DiagLevel Level
, const char *Message
)
192 : Loc(Loc
), Level(Level
), Message(Message
), NumArgs(0), NumRanges(0) {}
195 Diag
&operator<<(const char *Str
) { return AddArg(Str
); }
196 Diag
&operator<<(MangledName MN
) { return AddArg(MN
); }
197 Diag
&operator<<(unsigned long long V
) { return AddArg(UIntMax(V
)); }
198 Diag
&operator<<(const void *V
) { return AddArg(V
); }
199 Diag
&operator<<(const TypeDescriptor
&V
);
200 Diag
&operator<<(const Value
&V
);
201 Diag
&operator<<(const Range
&R
) { return AddRange(R
); }
204 } // namespace __ubsan
206 #endif // UBSAN_DIAG_H