This file is indexed.

/usr/include/clang/Basic/SourceManager.h is in libclang-dev 3.0-6ubuntu3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
//===--- SourceManager.h - Track and cache source files ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the SourceManager interface.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SOURCEMANAGER_H
#define LLVM_CLANG_SOURCEMANAGER_H

#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/MemoryBuffer.h"
#include <map>
#include <vector>
#include <cassert>

namespace clang {

class DiagnosticsEngine;
class SourceManager;
class FileManager;
class FileEntry;
class LineTableInfo;
class LangOptions;
class ASTWriter;
class ASTReader;

/// There are three different types of locations in a file: a spelling
/// location, an expansion location, and a presumed location.
///
/// Given an example of:
/// #define min(x, y) x < y ? x : y
///
/// and then later on a use of min:
/// #line 17
/// return min(a, b);
///
/// The expansion location is the line in the source code where the macro
/// was expanded (the return statement), the spelling location is the
/// location in the source where the macro was originally defined,
/// and the presumed location is where the line directive states that
/// the line is 17, or any other line.

/// SrcMgr - Public enums and private classes that are part of the
/// SourceManager implementation.
///
namespace SrcMgr {
  /// CharacteristicKind - This is used to represent whether a file or directory
  /// holds normal user code, system code, or system code which is implicitly
  /// 'extern "C"' in C++ mode.  Entire directories can be tagged with this
  /// (this is maintained by DirectoryLookup and friends) as can specific
  /// FileInfos when a #pragma system_header is seen or various other cases.
  ///
  enum CharacteristicKind {
    C_User, C_System, C_ExternCSystem
  };

  /// ContentCache - One instance of this struct is kept for every file
  /// loaded or used.  This object owns the MemoryBuffer object.
  class ContentCache {
    enum CCFlags {
      /// \brief Whether the buffer is invalid.
      InvalidFlag = 0x01,
      /// \brief Whether the buffer should not be freed on destruction.
      DoNotFreeFlag = 0x02
    };

    /// Buffer - The actual buffer containing the characters from the input
    /// file.  This is owned by the ContentCache object.
    /// The bits indicate indicates whether the buffer is invalid.
    mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;

  public:
    /// Reference to the file entry representing this ContentCache.
    /// This reference does not own the FileEntry object.
    /// It is possible for this to be NULL if
    /// the ContentCache encapsulates an imaginary text buffer.
    const FileEntry *OrigEntry;

    /// \brief References the file which the contents were actually loaded from.
    /// Can be different from 'Entry' if we overridden the contents of one file
    /// with the contents of another file.
    const FileEntry *ContentsEntry;

    /// SourceLineCache - A bump pointer allocated array of offsets for each
    /// source line.  This is lazily computed.  This is owned by the
    /// SourceManager BumpPointerAllocator object.
    unsigned *SourceLineCache;

    /// NumLines - The number of lines in this ContentCache.  This is only valid
    /// if SourceLineCache is non-null.
    unsigned NumLines;

    /// getBuffer - Returns the memory buffer for the associated content.
    ///
    /// \param Diag Object through which diagnostics will be emitted if the
    /// buffer cannot be retrieved.
    ///
    /// \param Loc If specified, is the location that invalid file diagnostics
    ///     will be emitted at.
    ///
    /// \param Invalid If non-NULL, will be set \c true if an error occurred.
    const llvm::MemoryBuffer *getBuffer(DiagnosticsEngine &Diag,
                                        const SourceManager &SM,
                                        SourceLocation Loc = SourceLocation(),
                                        bool *Invalid = 0) const;

    /// getSize - Returns the size of the content encapsulated by this
    ///  ContentCache. This can be the size of the source file or the size of an
    ///  arbitrary scratch buffer.  If the ContentCache encapsulates a source
    ///  file this size is retrieved from the file's FileEntry.
    unsigned getSize() const;

    /// getSizeBytesMapped - Returns the number of bytes actually mapped for
    /// this ContentCache. This can be 0 if the MemBuffer was not actually
    /// expanded.
    unsigned getSizeBytesMapped() const;

    /// Returns the kind of memory used to back the memory buffer for
    /// this content cache.  This is used for performance analysis.
    llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const;

    void setBuffer(const llvm::MemoryBuffer *B) {
      assert(!Buffer.getPointer() && "MemoryBuffer already set.");
      Buffer.setPointer(B);
      Buffer.setInt(false);
    }

    /// \brief Get the underlying buffer, returning NULL if the buffer is not
    /// yet available.
    const llvm::MemoryBuffer *getRawBuffer() const {
      return Buffer.getPointer();
    }

    /// \brief Replace the existing buffer (which will be deleted)
    /// with the given buffer.
    void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false);

    /// \brief Determine whether the buffer itself is invalid.
    bool isBufferInvalid() const {
      return Buffer.getInt() & InvalidFlag;
    }

    /// \brief Determine whether the buffer should be freed.
    bool shouldFreeBuffer() const {
      return (Buffer.getInt() & DoNotFreeFlag) == 0;
    }

    ContentCache(const FileEntry *Ent = 0)
      : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent),
        SourceLineCache(0), NumLines(0) {}

    ContentCache(const FileEntry *Ent, const FileEntry *contentEnt)
      : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt),
        SourceLineCache(0), NumLines(0) {}

    ~ContentCache();

    /// The copy ctor does not allow copies where source object has either
    ///  a non-NULL Buffer or SourceLineCache.  Ownership of allocated memory
    ///  is not transferred, so this is a logical error.
    ContentCache(const ContentCache &RHS)
      : Buffer(0, false), SourceLineCache(0)
    {
      OrigEntry = RHS.OrigEntry;
      ContentsEntry = RHS.ContentsEntry;

      assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 &&
              "Passed ContentCache object cannot own a buffer.");

      NumLines = RHS.NumLines;
    }

  private:
    // Disable assignments.
    ContentCache &operator=(const ContentCache& RHS);
  };

  /// FileInfo - Information about a FileID, basically just the logical file
  /// that it represents and include stack information.
  ///
  /// Each FileInfo has include stack information, indicating where it came
  /// from. This information encodes the #include chain that a token was
  /// expanded from. The main include file has an invalid IncludeLoc.
  ///
  /// FileInfos contain a "ContentCache *", with the contents of the file.
  ///
  class FileInfo {
    /// IncludeLoc - The location of the #include that brought in this file.
    /// This is an invalid SLOC for the main file (top of the #include chain).
    unsigned IncludeLoc;  // Really a SourceLocation

    /// \brief Number of FileIDs (files and macros) that were created during
    /// preprocessing of this #include, including this SLocEntry.
    /// Zero means the preprocessor didn't provide such info for this SLocEntry.
    unsigned NumCreatedFIDs;

    /// Data - This contains the ContentCache* and the bits indicating the
    /// characteristic of the file and whether it has #line info, all bitmangled
    /// together.
    uintptr_t Data;

    friend class clang::SourceManager;
    friend class clang::ASTWriter;
    friend class clang::ASTReader;
  public:
    /// get - Return a FileInfo object.
    static FileInfo get(SourceLocation IL, const ContentCache *Con,
                        CharacteristicKind FileCharacter) {
      FileInfo X;
      X.IncludeLoc = IL.getRawEncoding();
      X.NumCreatedFIDs = 0;
      X.Data = (uintptr_t)Con;
      assert((X.Data & 7) == 0 &&"ContentCache pointer insufficiently aligned");
      assert((unsigned)FileCharacter < 4 && "invalid file character");
      X.Data |= (unsigned)FileCharacter;
      return X;
    }

    SourceLocation getIncludeLoc() const {
      return SourceLocation::getFromRawEncoding(IncludeLoc);
    }
    const ContentCache* getContentCache() const {
      return reinterpret_cast<const ContentCache*>(Data & ~7UL);
    }

    /// getCharacteristic - Return whether this is a system header or not.
    CharacteristicKind getFileCharacteristic() const {
      return (CharacteristicKind)(Data & 3);
    }

    /// hasLineDirectives - Return true if this FileID has #line directives in
    /// it.
    bool hasLineDirectives() const { return (Data & 4) != 0; }

    /// setHasLineDirectives - Set the flag that indicates that this FileID has
    /// line table entries associated with it.
    void setHasLineDirectives() {
      Data |= 4;
    }
  };

  /// ExpansionInfo - Each ExpansionInfo encodes the expansion location - where
  /// the token was ultimately expanded, and the SpellingLoc - where the actual
  /// character data for the token came from.
  class ExpansionInfo {
    // Really these are all SourceLocations.

    /// SpellingLoc - Where the spelling for the token can be found.
    unsigned SpellingLoc;

    /// ExpansionLocStart/ExpansionLocEnd - In a macro expansion, these
    /// indicate the start and end of the expansion. In object-like macros,
    /// these will be the same. In a function-like macro expansion, the start
    /// will be the identifier and the end will be the ')'. Finally, in
    /// macro-argument instantitions, the end will be 'SourceLocation()', an
    /// invalid location.
    unsigned ExpansionLocStart, ExpansionLocEnd;

  public:
    SourceLocation getSpellingLoc() const {
      return SourceLocation::getFromRawEncoding(SpellingLoc);
    }
    SourceLocation getExpansionLocStart() const {
      return SourceLocation::getFromRawEncoding(ExpansionLocStart);
    }
    SourceLocation getExpansionLocEnd() const {
      SourceLocation EndLoc =
        SourceLocation::getFromRawEncoding(ExpansionLocEnd);
      return EndLoc.isInvalid() ? getExpansionLocStart() : EndLoc;
    }

    std::pair<SourceLocation,SourceLocation> getExpansionLocRange() const {
      return std::make_pair(getExpansionLocStart(), getExpansionLocEnd());
    }

    bool isMacroArgExpansion() const {
      // Note that this needs to return false for default constructed objects.
      return getExpansionLocStart().isValid() &&
        SourceLocation::getFromRawEncoding(ExpansionLocEnd).isInvalid();
    }

    /// create - Return a ExpansionInfo for an expansion. Start and End specify
    /// the expansion range (where the macro is expanded), and SpellingLoc
    /// specifies the spelling location (where the characters from the token
    /// come from). All three can refer to normal File SLocs or expansion
    /// locations.
    static ExpansionInfo create(SourceLocation SpellingLoc,
                                SourceLocation Start, SourceLocation End) {
      ExpansionInfo X;
      X.SpellingLoc = SpellingLoc.getRawEncoding();
      X.ExpansionLocStart = Start.getRawEncoding();
      X.ExpansionLocEnd = End.getRawEncoding();
      return X;
    }

    /// createForMacroArg - Return a special ExpansionInfo for the expansion of
    /// a macro argument into a function-like macro's body. ExpansionLoc
    /// specifies the expansion location (where the macro is expanded). This
    /// doesn't need to be a range because a macro is always expanded at
    /// a macro parameter reference, and macro parameters are always exactly
    /// one token. SpellingLoc specifies the spelling location (where the
    /// characters from the token come from). ExpansionLoc and SpellingLoc can
    /// both refer to normal File SLocs or expansion locations.
    ///
    /// Given the code:
    /// \code
    ///   #define F(x) f(x)
    ///   F(42);
    /// \endcode
    ///
    /// When expanding '\c F(42)', the '\c x' would call this with an
    /// SpellingLoc pointing at '\c 42' anad an ExpansionLoc pointing at its
    /// location in the definition of '\c F'.
    static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc,
                                           SourceLocation ExpansionLoc) {
      // We store an intentionally invalid source location for the end of the
      // expansion range to mark that this is a macro argument ion rather than
      // a normal one.
      return create(SpellingLoc, ExpansionLoc, SourceLocation());
    }
  };

  /// SLocEntry - This is a discriminated union of FileInfo and
  /// ExpansionInfo.  SourceManager keeps an array of these objects, and
  /// they are uniquely identified by the FileID datatype.
  class SLocEntry {
    unsigned Offset;   // low bit is set for expansion info.
    union {
      FileInfo File;
      ExpansionInfo Expansion;
    };
  public:
    unsigned getOffset() const { return Offset >> 1; }

    bool isExpansion() const { return Offset & 1; }
    bool isFile() const { return !isExpansion(); }

    const FileInfo &getFile() const {
      assert(isFile() && "Not a file SLocEntry!");
      return File;
    }

    const ExpansionInfo &getExpansion() const {
      assert(isExpansion() && "Not a macro expansion SLocEntry!");
      return Expansion;
    }

    static SLocEntry get(unsigned Offset, const FileInfo &FI) {
      SLocEntry E;
      E.Offset = Offset << 1;
      E.File = FI;
      return E;
    }

    static SLocEntry get(unsigned Offset, const ExpansionInfo &Expansion) {
      SLocEntry E;
      E.Offset = (Offset << 1) | 1;
      E.Expansion = Expansion;
      return E;
    }
  };
}  // end SrcMgr namespace.

/// \brief External source of source location entries.
class ExternalSLocEntrySource {
public:
  virtual ~ExternalSLocEntrySource();

  /// \brief Read the source location entry with index ID, which will always be
  /// less than -1.
  ///
  /// \returns true if an error occurred that prevented the source-location
  /// entry from being loaded.
  virtual bool ReadSLocEntry(int ID) = 0;
};


/// IsBeforeInTranslationUnitCache - This class holds the cache used by
/// isBeforeInTranslationUnit.  The cache structure is complex enough to be
/// worth breaking out of SourceManager.
class IsBeforeInTranslationUnitCache {
  /// L/R QueryFID - These are the FID's of the cached query.  If these match up
  /// with a subsequent query, the result can be reused.
  FileID LQueryFID, RQueryFID;

  /// \brief True if LQueryFID was created before RQueryFID. This is used
  /// to compare macro expansion locations.
  bool IsLQFIDBeforeRQFID;

  /// CommonFID - This is the file found in common between the two #include
  /// traces.  It is the nearest common ancestor of the #include tree.
  FileID CommonFID;

  /// L/R CommonOffset - This is the offset of the previous query in CommonFID.
  /// Usually, this represents the location of the #include for QueryFID, but if
  /// LQueryFID is a parent of RQueryFID (or vise versa) then these can be a
  /// random token in the parent.
  unsigned LCommonOffset, RCommonOffset;
public:

  /// isCacheValid - Return true if the currently cached values match up with
  /// the specified LHS/RHS query.  If not, we can't use the cache.
  bool isCacheValid(FileID LHS, FileID RHS) const {
    return LQueryFID == LHS && RQueryFID == RHS;
  }

  /// getCachedResult - If the cache is valid, compute the result given the
  /// specified offsets in the LHS/RHS FID's.
  bool getCachedResult(unsigned LOffset, unsigned ROffset) const {
    // If one of the query files is the common file, use the offset.  Otherwise,
    // use the #include loc in the common file.
    if (LQueryFID != CommonFID) LOffset = LCommonOffset;
    if (RQueryFID != CommonFID) ROffset = RCommonOffset;

    // It is common for multiple macro expansions to be "included" from the same
    // location (expansion location), in which case use the order of the FileIDs
    // to determine which came first. This will also take care the case where
    // one of the locations points at the inclusion/expansion point of the other
    // in which case its FileID will come before the other.
    if (LOffset == ROffset &&
        (LQueryFID != CommonFID || RQueryFID != CommonFID))
      return IsLQFIDBeforeRQFID;

    return LOffset < ROffset;
  }

  // Set up a new query.
  void setQueryFIDs(FileID LHS, FileID RHS, bool isLFIDBeforeRFID) {
    assert(LHS != RHS);
    LQueryFID = LHS;
    RQueryFID = RHS;
    IsLQFIDBeforeRQFID = isLFIDBeforeRFID;
  }

  void clear() {
    LQueryFID = RQueryFID = FileID();
    IsLQFIDBeforeRQFID = false;
  }

  void setCommonLoc(FileID commonFID, unsigned lCommonOffset,
                    unsigned rCommonOffset) {
    CommonFID = commonFID;
    LCommonOffset = lCommonOffset;
    RCommonOffset = rCommonOffset;
  }

};

/// \brief This class handles loading and caching of source files into memory.
///
/// This object owns the MemoryBuffer objects for all of the loaded
/// files and assigns unique FileID's for each unique #include chain.
///
/// The SourceManager can be queried for information about SourceLocation
/// objects, turning them into either spelling or expansion locations. Spelling
/// locations represent where the bytes corresponding to a token came from and
/// expansion locations represent where the location is in the user's view. In
/// the case of a macro expansion, for example, the spelling location indicates
/// where the expanded token came from and the expansion location specifies
/// where it was expanded.
class SourceManager : public llvm::RefCountedBase<SourceManager> {
  /// \brief DiagnosticsEngine object.
  DiagnosticsEngine &Diag;

  FileManager &FileMgr;

  mutable llvm::BumpPtrAllocator ContentCacheAlloc;

  /// FileInfos - Memoized information about all of the files tracked by this
  /// SourceManager.  This set allows us to merge ContentCache entries based
  /// on their FileEntry*.  All ContentCache objects will thus have unique,
  /// non-null, FileEntry pointers.
  llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos;

  /// \brief True if the ContentCache for files that are overriden by other
  /// files, should report the original file name. Defaults to true.
  bool OverridenFilesKeepOriginalName;

  /// \brief Files that have been overriden with the contents from another file.
  llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles;

  /// MemBufferInfos - Information about various memory buffers that we have
  /// read in.  All FileEntry* within the stored ContentCache objects are NULL,
  /// as they do not refer to a file.
  std::vector<SrcMgr::ContentCache*> MemBufferInfos;

  /// \brief The table of SLocEntries that are local to this module.
  ///
  /// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid
  /// expansion.
  std::vector<SrcMgr::SLocEntry> LocalSLocEntryTable;

  /// \brief The table of SLocEntries that are loaded from other modules.
  ///
  /// Negative FileIDs are indexes into this table. To get from ID to an index,
  /// use (-ID - 2).
  std::vector<SrcMgr::SLocEntry> LoadedSLocEntryTable;

  /// \brief The starting offset of the next local SLocEntry.
  ///
  /// This is LocalSLocEntryTable.back().Offset + the size of that entry.
  unsigned NextLocalOffset;

  /// \brief The starting offset of the latest batch of loaded SLocEntries.
  ///
  /// This is LoadedSLocEntryTable.back().Offset, except that that entry might
  /// not have been loaded, so that value would be unknown.
  unsigned CurrentLoadedOffset;

  /// \brief The highest possible offset is 2^31-1, so CurrentLoadedOffset
  /// starts at 2^31.
  static const unsigned MaxLoadedOffset = 1U << 31U;

  /// \brief A bitmap that indicates whether the entries of LoadedSLocEntryTable
  /// have already been loaded from the external source.
  ///
  /// Same indexing as LoadedSLocEntryTable.
  std::vector<bool> SLocEntryLoaded;

  /// \brief An external source for source location entries.
  ExternalSLocEntrySource *ExternalSLocEntries;

  /// LastFileIDLookup - This is a one-entry cache to speed up getFileID.
  /// LastFileIDLookup records the last FileID looked up or created, because it
  /// is very common to look up many tokens from the same file.
  mutable FileID LastFileIDLookup;

  /// LineTable - This holds information for #line directives.  It is referenced
  /// by indices from SLocEntryTable.
  LineTableInfo *LineTable;

  /// LastLineNo - These ivars serve as a cache used in the getLineNumber
  /// method which is used to speedup getLineNumber calls to nearby locations.
  mutable FileID LastLineNoFileIDQuery;
  mutable SrcMgr::ContentCache *LastLineNoContentCache;
  mutable unsigned LastLineNoFilePos;
  mutable unsigned LastLineNoResult;

  /// MainFileID - The file ID for the main source file of the translation unit.
  FileID MainFileID;

  /// \brief The file ID for the precompiled preamble there is one.
  FileID PreambleFileID;

  // Statistics for -print-stats.
  mutable unsigned NumLinearScans, NumBinaryProbes;

  // Cache results for the isBeforeInTranslationUnit method.
  mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache;

  // Cache for the "fake" buffer used for error-recovery purposes.
  mutable llvm::MemoryBuffer *FakeBufferForRecovery;

  /// \brief Lazily computed map of macro argument chunks to their expanded
  /// source location.
  typedef std::map<unsigned, SourceLocation> MacroArgsMap;

  mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap; 

  // SourceManager doesn't support copy construction.
  explicit SourceManager(const SourceManager&);
  void operator=(const SourceManager&);
public:
  SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr);
  ~SourceManager();

  void clearIDTables();

  DiagnosticsEngine &getDiagnostics() const { return Diag; }

  FileManager &getFileManager() const { return FileMgr; }

  /// \brief Set true if the SourceManager should report the original file name
  /// for contents of files that were overriden by other files.Defaults to true.
  void setOverridenFilesKeepOriginalName(bool value) {
    OverridenFilesKeepOriginalName = value;
  }

  /// createMainFileIDForMembuffer - Create the FileID for a memory buffer
  ///  that will represent the FileID for the main source.  One example
  ///  of when this would be used is when the main source is read from STDIN.
  FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
    assert(MainFileID.isInvalid() && "MainFileID already set!");
    MainFileID = createFileIDForMemBuffer(Buffer);
    return MainFileID;
  }

  //===--------------------------------------------------------------------===//
  // MainFileID creation and querying methods.
  //===--------------------------------------------------------------------===//

  /// getMainFileID - Returns the FileID of the main source file.
  FileID getMainFileID() const { return MainFileID; }

  /// createMainFileID - Create the FileID for the main source file.
  FileID createMainFileID(const FileEntry *SourceFile) {
    assert(MainFileID.isInvalid() && "MainFileID already set!");
    MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User);
    return MainFileID;
  }

  /// \brief Set the file ID for the precompiled preamble.
  void setPreambleFileID(FileID Preamble) {
    assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");
    PreambleFileID = Preamble;
  }

  /// \brief Get the file ID for the precompiled preamble if there is one.
  FileID getPreambleFileID() const { return PreambleFileID; }

  //===--------------------------------------------------------------------===//
  // Methods to create new FileID's and macro expansions.
  //===--------------------------------------------------------------------===//

  /// createFileID - Create a new FileID that represents the specified file
  /// being #included from the specified IncludePosition.  This translates NULL
  /// into standard input.
  FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
                      SrcMgr::CharacteristicKind FileCharacter,
                      int LoadedID = 0, unsigned LoadedOffset = 0) {
    const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
    assert(IR && "getOrCreateContentCache() cannot return NULL");
    return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset);
  }

  /// createFileIDForMemBuffer - Create a new FileID that represents the
  /// specified memory buffer.  This does no caching of the buffer and takes
  /// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
  FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer,
                                  int LoadedID = 0, unsigned LoadedOffset = 0) {
    return createFileID(createMemBufferContentCache(Buffer), SourceLocation(),
                        SrcMgr::C_User, LoadedID, LoadedOffset);
  }

  /// createMacroArgExpansionLoc - Return a new SourceLocation that encodes the
  /// fact that a token from SpellingLoc should actually be referenced from
  /// ExpansionLoc, and that it represents the expansion of a macro argument
  /// into the function-like macro body.
  SourceLocation createMacroArgExpansionLoc(SourceLocation Loc,
                                            SourceLocation ExpansionLoc,
                                            unsigned TokLength);

  /// createExpansionLoc - Return a new SourceLocation that encodes the fact
  /// that a token from SpellingLoc should actually be referenced from
  /// ExpansionLoc.
  SourceLocation createExpansionLoc(SourceLocation Loc,
                                    SourceLocation ExpansionLocStart,
                                    SourceLocation ExpansionLocEnd,
                                    unsigned TokLength,
                                    int LoadedID = 0,
                                    unsigned LoadedOffset = 0);

  /// \brief Retrieve the memory buffer associated with the given file.
  ///
  /// \param Invalid If non-NULL, will be set \c true if an error
  /// occurs while retrieving the memory buffer.
  const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File,
                                                   bool *Invalid = 0);

  /// \brief Override the contents of the given source file by providing an
  /// already-allocated buffer.
  ///
  /// \param SourceFile the source file whose contents will be overriden.
  ///
  /// \param Buffer the memory buffer whose contents will be used as the
  /// data in the given source file.
  ///
  /// \param DoNotFree If true, then the buffer will not be freed when the
  /// source manager is destroyed.
  void overrideFileContents(const FileEntry *SourceFile,
                            const llvm::MemoryBuffer *Buffer,
                            bool DoNotFree = false);

  /// \brief Override the the given source file with another one.
  ///
  /// \param SourceFile the source file which will be overriden.
  ///
  /// \param NewFile the file whose contents will be used as the
  /// data instead of the contents of the given source file.
  void overrideFileContents(const FileEntry *SourceFile,
                            const FileEntry *NewFile);

  //===--------------------------------------------------------------------===//
  // FileID manipulation methods.
  //===--------------------------------------------------------------------===//

  /// getBuffer - Return the buffer for the specified FileID. If there is an
  /// error opening this buffer the first time, this manufactures a temporary
  /// buffer and returns a non-empty error string.
  const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc,
                                      bool *Invalid = 0) const {
    bool MyInvalid = false;
    const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
    if (MyInvalid || !Entry.isFile()) {
      if (Invalid)
        *Invalid = true;

      return getFakeBufferForRecovery();
    }

    return Entry.getFile().getContentCache()->getBuffer(Diag, *this, Loc,
                                                        Invalid);
  }

  const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const {
    bool MyInvalid = false;
    const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
    if (MyInvalid || !Entry.isFile()) {
      if (Invalid)
        *Invalid = true;

      return getFakeBufferForRecovery();
    }

    return Entry.getFile().getContentCache()->getBuffer(Diag, *this,
                                                        SourceLocation(),
                                                        Invalid);
  }

  /// getFileEntryForID - Returns the FileEntry record for the provided FileID.
  const FileEntry *getFileEntryForID(FileID FID) const {
    bool MyInvalid = false;
    const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid);
    if (MyInvalid || !Entry.isFile())
      return 0;

    return Entry.getFile().getContentCache()->OrigEntry;
  }

  /// Returns the FileEntry record for the provided SLocEntry.
  const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const
  {
    return sloc.getFile().getContentCache()->OrigEntry;
  }

  /// getBufferData - Return a StringRef to the source buffer data for the
  /// specified FileID.
  ///
  /// \param FID The file ID whose contents will be returned.
  /// \param Invalid If non-NULL, will be set true if an error occurred.
  StringRef getBufferData(FileID FID, bool *Invalid = 0) const;

  /// \brief Get the number of FileIDs (files and macros) that were created
  /// during preprocessing of \arg FID, including it.
  unsigned getNumCreatedFIDsForFileID(FileID FID) const {
    bool Invalid = false;
    const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
    if (Invalid || !Entry.isFile())
      return 0;

    return Entry.getFile().NumCreatedFIDs;
  }

  /// \brief Set the number of FileIDs (files and macros) that were created
  /// during preprocessing of \arg FID, including it.
  void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs) const {
    bool Invalid = false;
    const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
    if (Invalid || !Entry.isFile())
      return;

    assert(Entry.getFile().NumCreatedFIDs == 0 && "Already set!");
    const_cast<SrcMgr::FileInfo &>(Entry.getFile()).NumCreatedFIDs = NumFIDs;
  }

  //===--------------------------------------------------------------------===//
  // SourceLocation manipulation methods.
  //===--------------------------------------------------------------------===//

  /// getFileID - Return the FileID for a SourceLocation.  This is a very
  /// hot method that is used for all SourceManager queries that start with a
  /// SourceLocation object.  It is responsible for finding the entry in
  /// SLocEntryTable which contains the specified location.
  ///
  FileID getFileID(SourceLocation SpellingLoc) const {
    unsigned SLocOffset = SpellingLoc.getOffset();

    // If our one-entry cache covers this offset, just return it.
    if (isOffsetInFileID(LastFileIDLookup, SLocOffset))
      return LastFileIDLookup;

    return getFileIDSlow(SLocOffset);
  }

  /// getLocForStartOfFile - Return the source location corresponding to the
  /// first byte of the specified file.
  SourceLocation getLocForStartOfFile(FileID FID) const {
    bool Invalid = false;
    const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
    if (Invalid || !Entry.isFile())
      return SourceLocation();

    unsigned FileOffset = Entry.getOffset();
    return SourceLocation::getFileLoc(FileOffset);
  }

  /// \brief Returns the include location if \arg FID is a #include'd file
  /// otherwise it returns an invalid location.
  SourceLocation getIncludeLoc(FileID FID) const {
    bool Invalid = false;
    const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid);
    if (Invalid || !Entry.isFile())
      return SourceLocation();

    return Entry.getFile().getIncludeLoc();
  }

  /// getExpansionLoc - Given a SourceLocation object, return the expansion
  /// location referenced by the ID.
  SourceLocation getExpansionLoc(SourceLocation Loc) const {
    // Handle the non-mapped case inline, defer to out of line code to handle
    // expansions.
    if (Loc.isFileID()) return Loc;
    return getExpansionLocSlowCase(Loc);
  }

  /// \brief Given \arg Loc, if it is a macro location return the expansion
  /// location or the spelling location, depending on if it comes from a
  /// macro argument or not.
  SourceLocation getFileLoc(SourceLocation Loc) const {
    if (Loc.isFileID()) return Loc;
    return getFileLocSlowCase(Loc);
  }

  /// getImmediateExpansionRange - Loc is required to be an expansion location.
  /// Return the start/end of the expansion information.
  std::pair<SourceLocation,SourceLocation>
  getImmediateExpansionRange(SourceLocation Loc) const;

  /// getExpansionRange - Given a SourceLocation object, return the range of
  /// tokens covered by the expansion the ultimate file.
  std::pair<SourceLocation,SourceLocation>
  getExpansionRange(SourceLocation Loc) const;


  /// getSpellingLoc - Given a SourceLocation object, return the spelling
  /// location referenced by the ID.  This is the place where the characters
  /// that make up the lexed token can be found.
  SourceLocation getSpellingLoc(SourceLocation Loc) const {
    // Handle the non-mapped case inline, defer to out of line code to handle
    // expansions.
    if (Loc.isFileID()) return Loc;
    return getSpellingLocSlowCase(Loc);
  }

  /// getImmediateSpellingLoc - Given a SourceLocation object, return the
  /// spelling location referenced by the ID.  This is the first level down
  /// towards the place where the characters that make up the lexed token can be
  /// found.  This should not generally be used by clients.
  SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const;

  /// getDecomposedLoc - Decompose the specified location into a raw FileID +
  /// Offset pair.  The first element is the FileID, the second is the
  /// offset from the start of the buffer of the location.
  std::pair<FileID, unsigned> getDecomposedLoc(SourceLocation Loc) const {
    FileID FID = getFileID(Loc);
    return std::make_pair(FID, Loc.getOffset()-getSLocEntry(FID).getOffset());
  }

  /// getDecomposedExpansionLoc - Decompose the specified location into a raw
  /// FileID + Offset pair. If the location is an expansion record, walk
  /// through it until we find the final location expanded.
  std::pair<FileID, unsigned>
  getDecomposedExpansionLoc(SourceLocation Loc) const {
    FileID FID = getFileID(Loc);
    const SrcMgr::SLocEntry *E = &getSLocEntry(FID);

    unsigned Offset = Loc.getOffset()-E->getOffset();
    if (Loc.isFileID())
      return std::make_pair(FID, Offset);

    return getDecomposedExpansionLocSlowCase(E);
  }

  /// getDecomposedSpellingLoc - Decompose the specified location into a raw
  /// FileID + Offset pair.  If the location is an expansion record, walk
  /// through it until we find its spelling record.
  std::pair<FileID, unsigned>
  getDecomposedSpellingLoc(SourceLocation Loc) const {
    FileID FID = getFileID(Loc);
    const SrcMgr::SLocEntry *E = &getSLocEntry(FID);

    unsigned Offset = Loc.getOffset()-E->getOffset();
    if (Loc.isFileID())
      return std::make_pair(FID, Offset);
    return getDecomposedSpellingLocSlowCase(E, Offset);
  }

  /// getFileOffset - This method returns the offset from the start
  /// of the file that the specified SourceLocation represents. This is not very
  /// meaningful for a macro ID.
  unsigned getFileOffset(SourceLocation SpellingLoc) const {
    return getDecomposedLoc(SpellingLoc).second;
  }

  /// isMacroArgExpansion - This method tests whether the given source location
  /// represents a macro argument's expansion into the function-like macro
  /// definition. Such source locations only appear inside of the expansion
  /// locations representing where a particular function-like macro was
  /// expanded.
  bool isMacroArgExpansion(SourceLocation Loc) const;

  /// \brief Returns true if \arg Loc is inside the [\arg Start, +\arg Length)
  /// chunk of the source location address space.
  /// If it's true and \arg RelativeOffset is non-null, it will be set to the
  /// relative offset of \arg Loc inside the chunk.
  bool isInSLocAddrSpace(SourceLocation Loc,
                         SourceLocation Start, unsigned Length,
                         unsigned *RelativeOffset = 0) const {
    assert(((Start.getOffset() < NextLocalOffset &&
               Start.getOffset()+Length <= NextLocalOffset) ||
            (Start.getOffset() >= CurrentLoadedOffset &&
                Start.getOffset()+Length < MaxLoadedOffset)) &&
           "Chunk is not valid SLoc address space");
    unsigned LocOffs = Loc.getOffset();
    unsigned BeginOffs = Start.getOffset();
    unsigned EndOffs = BeginOffs + Length;
    if (LocOffs >= BeginOffs && LocOffs < EndOffs) {
      if (RelativeOffset)
        *RelativeOffset = LocOffs - BeginOffs;
      return true;
    }

    return false;
  }

  /// \brief Return true if both \arg LHS and \arg RHS are in the local source
  /// location address space or the loaded one. If it's true and
  /// \arg RelativeOffset is non-null, it will be set to the offset of \arg RHS
  /// relative to \arg LHS.
  bool isInSameSLocAddrSpace(SourceLocation LHS, SourceLocation RHS,
                             int *RelativeOffset) const {
    unsigned LHSOffs = LHS.getOffset(), RHSOffs = RHS.getOffset();
    bool LHSLoaded = LHSOffs >= CurrentLoadedOffset;
    bool RHSLoaded = RHSOffs >= CurrentLoadedOffset;

    if (LHSLoaded == RHSLoaded) {
      if (RelativeOffset)
        *RelativeOffset = RHSOffs - LHSOffs;
      return true;
    }

    return false;
  }

  //===--------------------------------------------------------------------===//
  // Queries about the code at a SourceLocation.
  //===--------------------------------------------------------------------===//

  /// getCharacterData - Return a pointer to the start of the specified location
  /// in the appropriate spelling MemoryBuffer.
  ///
  /// \param Invalid If non-NULL, will be set \c true if an error occurs.
  const char *getCharacterData(SourceLocation SL, bool *Invalid = 0) const;

  /// getColumnNumber - Return the column # for the specified file position.
  /// This is significantly cheaper to compute than the line number.  This
  /// returns zero if the column number isn't known.  This may only be called
  /// on a file sloc, so you must choose a spelling or expansion location
  /// before calling this method.
  unsigned getColumnNumber(FileID FID, unsigned FilePos,
                           bool *Invalid = 0) const;
  unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;
  unsigned getExpansionColumnNumber(SourceLocation Loc,
                                    bool *Invalid = 0) const;
  unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = 0) const;


  /// getLineNumber - Given a SourceLocation, return the spelling line number
  /// for the position indicated.  This requires building and caching a table of
  /// line offsets for the MemoryBuffer, so this is not cheap: use only when
  /// about to emit a diagnostic.
  unsigned getLineNumber(FileID FID, unsigned FilePos, bool *Invalid = 0) const;
  unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
  unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = 0) const;
  unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = 0) const;

  /// Return the filename or buffer identifier of the buffer the location is in.
  /// Note that this name does not respect #line directives.  Use getPresumedLoc
  /// for normal clients.
  const char *getBufferName(SourceLocation Loc, bool *Invalid = 0) const;

  /// getFileCharacteristic - return the file characteristic of the specified
  /// source location, indicating whether this is a normal file, a system
  /// header, or an "implicit extern C" system header.
  ///
  /// This state can be modified with flags on GNU linemarker directives like:
  ///   # 4 "foo.h" 3
  /// which changes all source locations in the current file after that to be
  /// considered to be from a system header.
  SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const;

  /// getPresumedLoc - This method returns the "presumed" location of a
  /// SourceLocation specifies.  A "presumed location" can be modified by #line
  /// or GNU line marker directives.  This provides a view on the data that a
  /// user should see in diagnostics, for example.
  ///
  /// Note that a presumed location is always given as the expansion point of
  /// an expansion location, not at the spelling location.
  ///
  /// \returns The presumed location of the specified SourceLocation. If the
  /// presumed location cannot be calculate (e.g., because \p Loc is invalid
  /// or the file containing \p Loc has changed on disk), returns an invalid
  /// presumed location.
  PresumedLoc getPresumedLoc(SourceLocation Loc) const;

  /// isFromSameFile - Returns true if both SourceLocations correspond to
  ///  the same file.
  bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
    return getFileID(Loc1) == getFileID(Loc2);
  }

  /// isFromMainFile - Returns true if the file of provided SourceLocation is
  ///   the main file.
  bool isFromMainFile(SourceLocation Loc) const {
    return getFileID(Loc) == getMainFileID();
  }

  /// isInSystemHeader - Returns if a SourceLocation is in a system header.
  bool isInSystemHeader(SourceLocation Loc) const {
    return getFileCharacteristic(Loc) != SrcMgr::C_User;
  }

  /// isInExternCSystemHeader - Returns if a SourceLocation is in an "extern C"
  /// system header.
  bool isInExternCSystemHeader(SourceLocation Loc) const {
    return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
  }

  /// \brief The size of the SLocEnty that \arg FID represents.
  unsigned getFileIDSize(FileID FID) const;

  /// \brief Given a specific FileID, returns true if \arg Loc is inside that
  /// FileID chunk and sets relative offset (offset of \arg Loc from beginning
  /// of FileID) to \arg relativeOffset.
  bool isInFileID(SourceLocation Loc, FileID FID,
                  unsigned *RelativeOffset = 0) const {
    unsigned Offs = Loc.getOffset();
    if (isOffsetInFileID(FID, Offs)) {
      if (RelativeOffset)
        *RelativeOffset = Offs - getSLocEntry(FID).getOffset();
      return true;
    }

    return false;
  }

  //===--------------------------------------------------------------------===//
  // Line Table Manipulation Routines
  //===--------------------------------------------------------------------===//

  /// getLineTableFilenameID - Return the uniqued ID for the specified filename.
  ///
  unsigned getLineTableFilenameID(StringRef Str);

  /// AddLineNote - Add a line note to the line table for the FileID and offset
  /// specified by Loc.  If FilenameID is -1, it is considered to be
  /// unspecified.
  void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID);
  void AddLineNote(SourceLocation Loc, unsigned LineNo, int FilenameID,
                   bool IsFileEntry, bool IsFileExit,
                   bool IsSystemHeader, bool IsExternCHeader);

  /// \brief Determine if the source manager has a line table.
  bool hasLineTable() const { return LineTable != 0; }

  /// \brief Retrieve the stored line table.
  LineTableInfo &getLineTable();

  //===--------------------------------------------------------------------===//
  // Queries for performance analysis.
  //===--------------------------------------------------------------------===//

  /// Return the total amount of physical memory allocated by the
  /// ContentCache allocator.
  size_t getContentCacheSize() const {
    return ContentCacheAlloc.getTotalMemory();
  }

  struct MemoryBufferSizes {
    const size_t malloc_bytes;
    const size_t mmap_bytes;

    MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
      : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
  };

  /// Return the amount of memory used by memory buffers, breaking down
  /// by heap-backed versus mmap'ed memory.
  MemoryBufferSizes getMemoryBufferSizes() const;

  // Return the amount of memory used for various side tables and
  // data structures in the SourceManager.
  size_t getDataStructureSizes() const;

  //===--------------------------------------------------------------------===//
  // Other miscellaneous methods.
  //===--------------------------------------------------------------------===//

  /// \brief Get the source location for the given file:line:col triplet.
  ///
  /// If the source file is included multiple times, the source location will
  /// be based upon the first inclusion.
  SourceLocation translateFileLineCol(const FileEntry *SourceFile,
                                      unsigned Line, unsigned Col) const;

  /// \brief Get the FileID for the given file.
  ///
  /// If the source file is included multiple times, the FileID will be the
  /// first inclusion.
  FileID translateFile(const FileEntry *SourceFile) const;

  /// \brief Get the source location in \arg FID for the given line:col.
  /// Returns null location if \arg FID is not a file SLocEntry.
  SourceLocation translateLineCol(FileID FID,
                                  unsigned Line, unsigned Col) const;

  /// \brief If \arg Loc points inside a function macro argument, the returned
  /// location will be the macro location in which the argument was expanded.
  /// If a macro argument is used multiple times, the expanded location will
  /// be at the first expansion of the argument.
  /// e.g.
  ///   MY_MACRO(foo);
  ///             ^
  /// Passing a file location pointing at 'foo', will yield a macro location
  /// where 'foo' was expanded into.
  SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const;

  /// \brief Determines the order of 2 source locations in the translation unit.
  ///
  /// \returns true if LHS source location comes before RHS, false otherwise.
  bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;

  /// \brief Comparison function class.
  class LocBeforeThanCompare : public std::binary_function<SourceLocation,
                                                         SourceLocation, bool> {
    SourceManager &SM;

  public:
    explicit LocBeforeThanCompare(SourceManager &SM) : SM(SM) { }

    bool operator()(SourceLocation LHS, SourceLocation RHS) const {
      return SM.isBeforeInTranslationUnit(LHS, RHS);
    }
  };

  /// \brief Determines the order of 2 source locations in the "source location
  /// address space".
  bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {
    return isBeforeInSLocAddrSpace(LHS, RHS.getOffset());
  }

  /// \brief Determines the order of a source location and a source location
  /// offset in the "source location address space".
  ///
  /// Note that we always consider source locations loaded from
  bool isBeforeInSLocAddrSpace(SourceLocation LHS, unsigned RHS) const {
    unsigned LHSOffset = LHS.getOffset();
    bool LHSLoaded = LHSOffset >= CurrentLoadedOffset;
    bool RHSLoaded = RHS >= CurrentLoadedOffset;
    if (LHSLoaded == RHSLoaded)
      return LHSOffset < RHS;

    return LHSLoaded;
  }

  // Iterators over FileInfos.
  typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>
      ::const_iterator fileinfo_iterator;
  fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); }
  fileinfo_iterator fileinfo_end() const { return FileInfos.end(); }
  bool hasFileInfo(const FileEntry *File) const {
    return FileInfos.find(File) != FileInfos.end();
  }

  /// PrintStats - Print statistics to stderr.
  ///
  void PrintStats() const;

  /// \brief Get the number of local SLocEntries we have.
  unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); }

  /// \brief Get a local SLocEntry. This is exposed for indexing.
  const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index,
                                             bool *Invalid = 0) const {
    assert(Index < LocalSLocEntryTable.size() && "Invalid index");
    return LocalSLocEntryTable[Index];
  }

  /// \brief Get the number of loaded SLocEntries we have.
  unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();}

  /// \brief Get a loaded SLocEntry. This is exposed for indexing.
  const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, bool *Invalid=0) const {
    assert(Index < LoadedSLocEntryTable.size() && "Invalid index");
    if (!SLocEntryLoaded[Index])
      ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2));
    return LoadedSLocEntryTable[Index];
  }

  const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const {
    return getSLocEntryByID(FID.ID);
  }

  unsigned getNextLocalOffset() const { return NextLocalOffset; }

  void setExternalSLocEntrySource(ExternalSLocEntrySource *Source) {
    assert(LoadedSLocEntryTable.empty() &&
           "Invalidating existing loaded entries");
    ExternalSLocEntries = Source;
  }

  /// \brief Allocate a number of loaded SLocEntries, which will be actually
  /// loaded on demand from the external source.
  ///
  /// NumSLocEntries will be allocated, which occupy a total of TotalSize space
  /// in the global source view. The lowest ID and the base offset of the
  /// entries will be returned.
  std::pair<int, unsigned>
  AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize);

  /// \brief Returns true if \arg Loc came from a PCH/Module.
  bool isLoadedSourceLocation(SourceLocation Loc) const {
    return Loc.getOffset() >= CurrentLoadedOffset;
  }

  /// \brief Returns true if \arg Loc did not come from a PCH/Module.
  bool isLocalSourceLocation(SourceLocation Loc) const {
    return Loc.getOffset() < NextLocalOffset;
  }

private:
  const llvm::MemoryBuffer *getFakeBufferForRecovery() const;

  /// \brief Get the entry with the given unwrapped FileID.
  const SrcMgr::SLocEntry &getSLocEntryByID(int ID) const {
    assert(ID != -1 && "Using FileID sentinel value");
    if (ID < 0)
      return getLoadedSLocEntryByID(ID);
    return getLocalSLocEntry(static_cast<unsigned>(ID));
  }

  const SrcMgr::SLocEntry &getLoadedSLocEntryByID(int ID) const {
    return getLoadedSLocEntry(static_cast<unsigned>(-ID - 2));
  }

  /// createExpansionLoc - Implements the common elements of storing an
  /// expansion info struct into the SLocEntry table and producing a source
  /// location that refers to it.
  SourceLocation createExpansionLocImpl(const SrcMgr::ExpansionInfo &Expansion,
                                        unsigned TokLength,
                                        int LoadedID = 0,
                                        unsigned LoadedOffset = 0);

  /// isOffsetInFileID - Return true if the specified FileID contains the
  /// specified SourceLocation offset.  This is a very hot method.
  inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const {
    const SrcMgr::SLocEntry &Entry = getSLocEntry(FID);
    // If the entry is after the offset, it can't contain it.
    if (SLocOffset < Entry.getOffset()) return false;

    // If this is the very last entry then it does.
    if (FID.ID == -2)
      return true;

    // If it is the last local entry, then it does if the location is local.
    if (static_cast<unsigned>(FID.ID+1) == LocalSLocEntryTable.size()) {
      return SLocOffset < NextLocalOffset;
    }

    // Otherwise, the entry after it has to not include it. This works for both
    // local and loaded entries.
    return SLocOffset < getSLocEntry(FileID::get(FID.ID+1)).getOffset();
  }

  /// createFileID - Create a new fileID for the specified ContentCache and
  ///  include position.  This works regardless of whether the ContentCache
  ///  corresponds to a file or some other input source.
  FileID createFileID(const SrcMgr::ContentCache* File,
                      SourceLocation IncludePos,
                      SrcMgr::CharacteristicKind DirCharacter,
                      int LoadedID, unsigned LoadedOffset);

  const SrcMgr::ContentCache *
    getOrCreateContentCache(const FileEntry *SourceFile);

  /// createMemBufferContentCache - Create a new ContentCache for the specified
  ///  memory buffer.
  const SrcMgr::ContentCache*
  createMemBufferContentCache(const llvm::MemoryBuffer *Buf);

  FileID getFileIDSlow(unsigned SLocOffset) const;
  FileID getFileIDLocal(unsigned SLocOffset) const;
  FileID getFileIDLoaded(unsigned SLocOffset) const;

  SourceLocation getExpansionLocSlowCase(SourceLocation Loc) const;
  SourceLocation getSpellingLocSlowCase(SourceLocation Loc) const;
  SourceLocation getFileLocSlowCase(SourceLocation Loc) const;

  std::pair<FileID, unsigned>
  getDecomposedExpansionLocSlowCase(const SrcMgr::SLocEntry *E) const;
  std::pair<FileID, unsigned>
  getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
                                   unsigned Offset) const;
  void computeMacroArgsCache(MacroArgsMap *&MacroArgsCache, FileID FID) const;

  friend class ASTReader;
  friend class ASTWriter;
};


}  // end namespace clang

#endif