[cfe-commits] r74014 - in /cfe/trunk: include/clang/Basic/SourceManager.h lib/Basic/SourceManager.cpp
Argiris Kirtzidis
akyrtzi at gmail.com
Tue Jun 23 15:01:48 PDT 2009
Author: akirtzidis
Date: Tue Jun 23 17:01:48 2009
New Revision: 74014
URL: http://llvm.org/viewvc/llvm-project?rev=74014&view=rev
Log:
Introduce SourceManager::ísBeforeInTranslationUnit() which can compare 2 source locations and determine which one comes before the other, relative to the translation unit.
Modified:
cfe/trunk/include/clang/Basic/SourceManager.h
cfe/trunk/lib/Basic/SourceManager.cpp
Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=74014&r1=74013&r2=74014&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Tue Jun 23 17:01:48 2009
@@ -326,6 +326,11 @@
// Statistics for -print-stats.
mutable unsigned NumLinearScans, NumBinaryProbes;
+ // Cache results for the isBeforeInTranslationUnit method.
+ mutable FileID LastLFIDForBeforeTUCheck;
+ mutable FileID LastRFIDForBeforeTUCheck;
+ mutable bool LastResForBeforeTUCheck;
+
// SourceManager doesn't support copy construction.
explicit SourceManager(const SourceManager&);
void operator=(const SourceManager&);
@@ -637,6 +642,11 @@
SourceLocation getLocation(const FileEntry *SourceFile,
unsigned Line, unsigned Col) 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;
+
// Iterators over FileInfos.
typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>
::const_iterator fileinfo_iterator;
Modified: cfe/trunk/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=74014&r1=74013&r2=74014&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/SourceManager.cpp (original)
+++ cfe/trunk/lib/Basic/SourceManager.cpp Tue Jun 23 17:01:48 2009
@@ -957,6 +957,106 @@
getFileLocWithOffset(FilePos + Col - 1);
}
+/// \brief Determines the order of 2 source locations in the translation unit.
+///
+/// \returns true if LHS source location comes before RHS, false otherwise.
+bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
+ SourceLocation RHS) const {
+ assert(LHS.isValid() && RHS.isValid() && "Passed invalid source location!");
+ if (LHS == RHS)
+ return false;
+
+ std::pair<FileID, unsigned> LOffs = getDecomposedLoc(LHS);
+ std::pair<FileID, unsigned> ROffs = getDecomposedLoc(RHS);
+
+ // If the source locations are in the same file, just compare offsets.
+ if (LOffs.first == ROffs.first)
+ return LOffs.second < ROffs.second;
+
+ // If we are comparing a source location with multiple locations in the same
+ // file, we get a big win by caching the result.
+
+ if (LastLFIDForBeforeTUCheck == LOffs.first &&
+ LastRFIDForBeforeTUCheck == ROffs.first)
+ return LastResForBeforeTUCheck;
+
+ LastLFIDForBeforeTUCheck = LOffs.first;
+ LastRFIDForBeforeTUCheck = ROffs.first;
+
+ // "Traverse" the include/instantiation stacks of both locations and try to
+ // find a common "ancestor".
+ //
+ // First we traverse the stack of the right location and check each level
+ // against the level of the left location, while collecting all levels in a
+ // "stack map".
+
+ std::map<FileID, unsigned> ROffsMap;
+ ROffsMap[ROffs.first] = ROffs.second;
+
+ while (1) {
+ SourceLocation UpperLoc;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(ROffs.first);
+ if (Entry.isInstantiation())
+ UpperLoc = Entry.getInstantiation().getInstantiationLocStart();
+ else
+ UpperLoc = Entry.getFile().getIncludeLoc();
+
+ if (UpperLoc.isInvalid())
+ break; // We reached the top.
+
+ ROffs = getDecomposedLoc(UpperLoc);
+
+ if (LOffs.first == ROffs.first)
+ return LastResForBeforeTUCheck = LOffs.second < ROffs.second;
+
+ ROffsMap[ROffs.first] = ROffs.second;
+ }
+
+ // We didn't find a common ancestor. Now traverse the stack of the left
+ // location, checking against the stack map of the right location.
+
+ while (1) {
+ SourceLocation UpperLoc;
+ const SrcMgr::SLocEntry &Entry = getSLocEntry(LOffs.first);
+ if (Entry.isInstantiation())
+ UpperLoc = Entry.getInstantiation().getInstantiationLocStart();
+ else
+ UpperLoc = Entry.getFile().getIncludeLoc();
+
+ if (UpperLoc.isInvalid())
+ break; // We reached the top.
+
+ LOffs = getDecomposedLoc(UpperLoc);
+
+ std::map<FileID, unsigned>::iterator I = ROffsMap.find(LOffs.first);
+ if (I != ROffsMap.end())
+ return LastResForBeforeTUCheck = LOffs.second < I->second;
+ }
+
+ // No common ancestor.
+ // Now we are getting into murky waters. Most probably this is because one
+ // location is in the predefines buffer.
+
+ const FileEntry *LEntry =
+ getSLocEntry(LOffs.first).getFile().getContentCache()->Entry;
+ const FileEntry *REntry =
+ getSLocEntry(ROffs.first).getFile().getContentCache()->Entry;
+
+ // If the locations are in two memory buffers we give up, we can't answer
+ // which one should be considered first.
+ // FIXME: Should there be a way to "include" memory buffers in the translation
+ // unit ?
+ assert((LEntry != 0 || REntry != 0) && "Locations in memory buffers.");
+
+ // Consider the memory buffer as coming before the file in the translation
+ // unit.
+ if (LEntry == 0)
+ return LastResForBeforeTUCheck = true;
+ else {
+ assert(REntry == 0 && "Locations in not #included files ?");
+ return LastResForBeforeTUCheck = false;
+ }
+}
/// PrintStats - Print statistics to stderr.
///
More information about the cfe-commits
mailing list