clang 20.0.0git
SourceLocation.h
Go to the documentation of this file.
1//===- SourceLocation.h - Compact identifier for Source Files ---*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// Defines the clang::SourceLocation class and associated facilities.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H
15#define LLVM_CLANG_BASIC_SOURCELOCATION_H
16
18#include "clang/Basic/LLVM.h"
19#include "llvm/ADT/StringRef.h"
20#include <cassert>
21#include <cstdint>
22#include <string>
23#include <utility>
24
25namespace llvm {
26
27class FoldingSetNodeID;
28template <typename T, typename Enable> struct FoldingSetTrait;
29
30} // namespace llvm
31
32namespace clang {
33
34class SourceManager;
35
36/// An opaque identifier used by SourceManager which refers to a
37/// source file (MemoryBuffer) along with its \#include path and \#line data.
38///
39class FileID {
40 /// A mostly-opaque identifier, where 0 is "invalid", >0 is
41 /// this module, and <-1 is something loaded from another module.
42 int ID = 0;
43
44public:
45 bool isValid() const { return ID != 0; }
46 bool isInvalid() const { return ID == 0; }
47
48 bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
49 bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
50 bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
51 bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
52 bool operator>(const FileID &RHS) const { return RHS < *this; }
53 bool operator>=(const FileID &RHS) const { return RHS <= *this; }
54
55 static FileID getSentinel() { return get(-1); }
56 unsigned getHashValue() const { return static_cast<unsigned>(ID); }
57
58private:
59 friend class ASTWriter;
60 friend class ASTReader;
61 friend class SourceManager;
63
64 static FileID get(int V) {
65 FileID F;
66 F.ID = V;
67 return F;
68 }
69
70 int getOpaqueValue() const { return ID; }
71};
72
73/// Encodes a location in the source. The SourceManager can decode this
74/// to get at the full include stack, line and column information.
75///
76/// Technically, a source location is simply an offset into the manager's view
77/// of the input source, which is all input buffers (including macro
78/// expansions) concatenated in an effectively arbitrary order. The manager
79/// actually maintains two blocks of input buffers. One, starting at offset
80/// 0 and growing upwards, contains all buffers from this module. The other,
81/// starting at the highest possible offset and growing downwards, contains
82/// buffers of loaded modules.
83///
84/// In addition, one bit of SourceLocation is used for quick access to the
85/// information whether the location is in a file or a macro expansion.
86///
87/// It is important that this type remains small. It is currently 32 bits wide.
89 friend class ASTReader;
90 friend class ASTWriter;
91 friend class SourceManager;
92 friend struct llvm::FoldingSetTrait<SourceLocation, void>;
94
95public:
96 using UIntTy = uint32_t;
97 using IntTy = int32_t;
98
99private:
100 UIntTy ID = 0;
101
102 enum : UIntTy { MacroIDBit = 1ULL << (8 * sizeof(UIntTy) - 1) };
103
104public:
105 bool isFileID() const { return (ID & MacroIDBit) == 0; }
106 bool isMacroID() const { return (ID & MacroIDBit) != 0; }
107
108 /// Return true if this is a valid SourceLocation object.
109 ///
110 /// Invalid SourceLocations are often used when events have no corresponding
111 /// location in the source (e.g. a diagnostic is required for a command line
112 /// option).
113 bool isValid() const { return ID != 0; }
114 bool isInvalid() const { return ID == 0; }
115
116private:
117 /// Return the offset into the manager's global input view.
118 UIntTy getOffset() const { return ID & ~MacroIDBit; }
119
120 static SourceLocation getFileLoc(UIntTy ID) {
121 assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
122 SourceLocation L;
123 L.ID = ID;
124 return L;
125 }
126
127 static SourceLocation getMacroLoc(UIntTy ID) {
128 assert((ID & MacroIDBit) == 0 && "Ran out of source locations!");
129 SourceLocation L;
130 L.ID = MacroIDBit | ID;
131 return L;
132 }
133
134public:
135 /// Return a source location with the specified offset from this
136 /// SourceLocation.
138 assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow");
140 L.ID = ID+Offset;
141 return L;
142 }
143
144 /// When a SourceLocation itself cannot be used, this returns
145 /// an (opaque) 32-bit integer encoding for it.
146 ///
147 /// This should only be passed to SourceLocation::getFromRawEncoding, it
148 /// should not be inspected directly.
149 UIntTy getRawEncoding() const { return ID; }
150
151 /// Turn a raw encoding of a SourceLocation object into
152 /// a real SourceLocation.
153 ///
154 /// \see getRawEncoding.
157 X.ID = Encoding;
158 return X;
159 }
160
161 /// When a SourceLocation itself cannot be used, this returns
162 /// an (opaque) pointer encoding for it.
163 ///
164 /// This should only be passed to SourceLocation::getFromPtrEncoding, it
165 /// should not be inspected directly.
166 void* getPtrEncoding() const {
167 // Double cast to avoid a warning "cast to pointer from integer of different
168 // size".
169 return (void*)(uintptr_t)getRawEncoding();
170 }
171
172 /// Turn a pointer encoding of a SourceLocation object back
173 /// into a real SourceLocation.
174 static SourceLocation getFromPtrEncoding(const void *Encoding) {
176 }
177
179 return Start.isValid() && Start.isFileID() && End.isValid() &&
180 End.isFileID();
181 }
182
183 unsigned getHashValue() const;
184 void print(raw_ostream &OS, const SourceManager &SM) const;
185 std::string printToString(const SourceManager &SM) const;
186 void dump(const SourceManager &SM) const;
187};
188
189inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
190 return LHS.getRawEncoding() == RHS.getRawEncoding();
191}
192
193inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
194 return !(LHS == RHS);
195}
196
197// Ordering is meaningful only if LHS and RHS have the same FileID!
198// Otherwise use SourceManager::isBeforeInTranslationUnit().
199inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
200 return LHS.getRawEncoding() < RHS.getRawEncoding();
201}
202inline bool operator>(const SourceLocation &LHS, const SourceLocation &RHS) {
203 return LHS.getRawEncoding() > RHS.getRawEncoding();
204}
205inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) {
206 return LHS.getRawEncoding() <= RHS.getRawEncoding();
207}
208inline bool operator>=(const SourceLocation &LHS, const SourceLocation &RHS) {
209 return LHS.getRawEncoding() >= RHS.getRawEncoding();
210}
211
212/// A trivial tuple used to represent a source range.
216
217public:
218 SourceRange() = default;
219 SourceRange(SourceLocation loc) : B(loc), E(loc) {}
220 SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
221
222 SourceLocation getBegin() const { return B; }
223 SourceLocation getEnd() const { return E; }
224
225 void setBegin(SourceLocation b) { B = b; }
226 void setEnd(SourceLocation e) { E = e; }
227
228 bool isValid() const { return B.isValid() && E.isValid(); }
229 bool isInvalid() const { return !isValid(); }
230
231 bool operator==(const SourceRange &X) const {
232 return B == X.B && E == X.E;
233 }
234
235 bool operator!=(const SourceRange &X) const {
236 return B != X.B || E != X.E;
237 }
238
239 // Returns true iff other is wholly contained within this range.
240 bool fullyContains(const SourceRange &other) const {
241 return B <= other.B && E >= other.E;
242 }
243
244 void print(raw_ostream &OS, const SourceManager &SM) const;
245 std::string printToString(const SourceManager &SM) const;
246 void dump(const SourceManager &SM) const;
247};
248
249/// Represents a character-granular source range.
250///
251/// The underlying SourceRange can either specify the starting/ending character
252/// of the range, or it can specify the start of the range and the start of the
253/// last token of the range (a "token range"). In the token range case, the
254/// size of the last token must be measured to determine the actual end of the
255/// range.
257 SourceRange Range;
258 bool IsTokenRange = false;
259
260public:
261 CharSourceRange() = default;
262 CharSourceRange(SourceRange R, bool ITR) : Range(R), IsTokenRange(ITR) {}
263
265 return CharSourceRange(R, true);
266 }
267
269 return CharSourceRange(R, false);
270 }
271
273 return getTokenRange(SourceRange(B, E));
274 }
275
277 return getCharRange(SourceRange(B, E));
278 }
279
280 /// Return true if the end of this range specifies the start of
281 /// the last token. Return false if the end of this range specifies the last
282 /// character in the range.
283 bool isTokenRange() const { return IsTokenRange; }
284 bool isCharRange() const { return !IsTokenRange; }
285
286 SourceLocation getBegin() const { return Range.getBegin(); }
287 SourceLocation getEnd() const { return Range.getEnd(); }
288 SourceRange getAsRange() const { return Range; }
289
290 void setBegin(SourceLocation b) { Range.setBegin(b); }
291 void setEnd(SourceLocation e) { Range.setEnd(e); }
292 void setTokenRange(bool TR) { IsTokenRange = TR; }
293
294 bool isValid() const { return Range.isValid(); }
295 bool isInvalid() const { return !isValid(); }
296};
297
298/// Represents an unpacked "presumed" location which can be presented
299/// to the user.
300///
301/// A 'presumed' location can be modified by \#line and GNU line marker
302/// directives and is always the expansion point of a normal location.
303///
304/// You can get a PresumedLoc from a SourceLocation with SourceManager.
306 const char *Filename = nullptr;
307 FileID ID;
308 unsigned Line, Col;
309 SourceLocation IncludeLoc;
310
311public:
312 PresumedLoc() = default;
313 PresumedLoc(const char *FN, FileID FID, unsigned Ln, unsigned Co,
315 : Filename(FN), ID(FID), Line(Ln), Col(Co), IncludeLoc(IL) {}
316
317 /// Return true if this object is invalid or uninitialized.
318 ///
319 /// This occurs when created with invalid source locations or when walking
320 /// off the top of a \#include stack.
321 bool isInvalid() const { return Filename == nullptr; }
322 bool isValid() const { return Filename != nullptr; }
323
324 /// Return the presumed filename of this location.
325 ///
326 /// This can be affected by \#line etc.
327 const char *getFilename() const {
328 assert(isValid());
329 return Filename;
330 }
331
333 assert(isValid());
334 return ID;
335 }
336
337 /// Return the presumed line number of this location.
338 ///
339 /// This can be affected by \#line etc.
340 unsigned getLine() const {
341 assert(isValid());
342 return Line;
343 }
344
345 /// Return the presumed column number of this location.
346 ///
347 /// This cannot be affected by \#line, but is packaged here for convenience.
348 unsigned getColumn() const {
349 assert(isValid());
350 return Col;
351 }
352
353 /// Return the presumed include location of this location.
354 ///
355 /// This can be affected by GNU linemarker directives.
357 assert(isValid());
358 return IncludeLoc;
359 }
360};
361
362/// A SourceLocation and its associated SourceManager.
363///
364/// This is useful for argument passing to functions that expect both objects.
365///
366/// This class does not guarantee the presence of either the SourceManager or
367/// a valid SourceLocation. Clients should use `isValid()` and `hasManager()`
368/// before calling the member functions.
370 const SourceManager *SrcMgr = nullptr;
371
372public:
373 /// Creates a FullSourceLoc where isValid() returns \c false.
374 FullSourceLoc() = default;
375
377 : SourceLocation(Loc), SrcMgr(&SM) {}
378
379 /// Checks whether the SourceManager is present.
380 bool hasManager() const { return SrcMgr != nullptr; }
381
382 /// \pre hasManager()
383 const SourceManager &getManager() const {
384 assert(SrcMgr && "SourceManager is NULL.");
385 return *SrcMgr;
386 }
387
388 FileID getFileID() const;
389
393 PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const;
394 bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const;
396 std::pair<FullSourceLoc, StringRef> getModuleImportLoc() const;
397 unsigned getFileOffset() const;
398
399 unsigned getExpansionLineNumber(bool *Invalid = nullptr) const;
400 unsigned getExpansionColumnNumber(bool *Invalid = nullptr) const;
401
402 /// Decompose the underlying \c SourceLocation into a raw (FileID + Offset)
403 /// pair, after walking through all expansion records.
404 ///
405 /// \see SourceManager::getDecomposedExpansionLoc
406 std::pair<FileID, unsigned> getDecomposedExpansionLoc() const;
407
408 unsigned getSpellingLineNumber(bool *Invalid = nullptr) const;
409 unsigned getSpellingColumnNumber(bool *Invalid = nullptr) const;
410
411 const char *getCharacterData(bool *Invalid = nullptr) const;
412
413 unsigned getLineNumber(bool *Invalid = nullptr) const;
414 unsigned getColumnNumber(bool *Invalid = nullptr) const;
415
416 const FileEntry *getFileEntry() const;
418
419 /// Return a StringRef to the source buffer data for the
420 /// specified FileID.
421 StringRef getBufferData(bool *Invalid = nullptr) const;
422
423 /// Decompose the specified location into a raw FileID + Offset pair.
424 ///
425 /// The first element is the FileID, the second is the offset from the
426 /// start of the buffer of the location.
427 std::pair<FileID, unsigned> getDecomposedLoc() const;
428
429 bool isInSystemHeader() const;
430
431 /// Determines the order of 2 source locations in the translation unit.
432 ///
433 /// \returns true if this source location comes before 'Loc', false otherwise.
435
436 /// Determines the order of 2 source locations in the translation unit.
437 ///
438 /// \returns true if this source location comes before 'Loc', false otherwise.
439 bool