mirror of
https://github.com/intel/llvm.git
synced 2026-01-30 22:53:05 +08:00
Factor out a functionality from isBeforeInTranslationUnit
The first user of this API will be the cross translation unit functionality of the Static Analyzer which will be committed in a follow-up patch. Differential Revision: https://reviews.llvm.org/D34506 llvm-svn: 306648
This commit is contained in:
@@ -1489,6 +1489,17 @@ public:
|
||||
/// \returns true if LHS source location comes before RHS, false otherwise.
|
||||
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const;
|
||||
|
||||
/// \brief Determines whether the two decomposed source location is in the
|
||||
/// same translation unit. As a byproduct, it also calculates the order
|
||||
/// of the source locations in case they are in the same TU.
|
||||
///
|
||||
/// \returns Pair of bools the first component is true if the two locations
|
||||
/// are in the same TU. The second bool is true if the first is true
|
||||
/// and \p LOffs is before \p ROffs.
|
||||
std::pair<bool, bool>
|
||||
isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs,
|
||||
std::pair<FileID, unsigned> &ROffs) const;
|
||||
|
||||
/// \brief Determines the order of 2 source locations in the "source location
|
||||
/// address space".
|
||||
bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {
|
||||
|
||||
@@ -2018,56 +2018,13 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
|
||||
if (LOffs.first.isInvalid() || ROffs.first.isInvalid())
|
||||
return LOffs.first.isInvalid() && !ROffs.first.isInvalid();
|
||||
|
||||
// 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.
|
||||
InBeforeInTUCacheEntry &IsBeforeInTUCache =
|
||||
getInBeforeInTUCache(LOffs.first, ROffs.first);
|
||||
|
||||
// If we are comparing a source location with multiple locations in the same
|
||||
// file, we get a big win by caching the result.
|
||||
if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first))
|
||||
return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
|
||||
|
||||
// Okay, we missed in the cache, start updating the cache for this query.
|
||||
IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first,
|
||||
/*isLFIDBeforeRFID=*/LOffs.first.ID < ROffs.first.ID);
|
||||
|
||||
// We need to find the common ancestor. The only way of doing this is to
|
||||
// build the complete include chain for one and then walking up the chain
|
||||
// of the other looking for a match.
|
||||
// We use a map from FileID to Offset to store the chain. Easier than writing
|
||||
// a custom set hash info that only depends on the first part of a pair.
|
||||
typedef llvm::SmallDenseMap<FileID, unsigned, 16> LocSet;
|
||||
LocSet LChain;
|
||||
do {
|
||||
LChain.insert(LOffs);
|
||||
// We catch the case where LOffs is in a file included by ROffs and
|
||||
// quit early. The other way round unfortunately remains suboptimal.
|
||||
} while (LOffs.first != ROffs.first && !MoveUpIncludeHierarchy(LOffs, *this));
|
||||
LocSet::iterator I;
|
||||
while((I = LChain.find(ROffs.first)) == LChain.end()) {
|
||||
if (MoveUpIncludeHierarchy(ROffs, *this))
|
||||
break; // Met at topmost file.
|
||||
}
|
||||
if (I != LChain.end())
|
||||
LOffs = *I;
|
||||
|
||||
// If we exited because we found a nearest common ancestor, compare the
|
||||
// locations within the common file and cache them.
|
||||
if (LOffs.first == ROffs.first) {
|
||||
IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
|
||||
return IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second);
|
||||
}
|
||||
std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
|
||||
if (InSameTU.first)
|
||||
return InSameTU.second;
|
||||
|
||||
// If we arrived here, the location is either in a built-ins buffer or
|
||||
// associated with global inline asm. PR5662 and PR22576 are examples.
|
||||
|
||||
// Clear the lookup cache, it depends on a common location.
|
||||
IsBeforeInTUCache.clear();
|
||||
StringRef LB = getBuffer(LOffs.first)->getBufferIdentifier();
|
||||
StringRef RB = getBuffer(ROffs.first)->getBufferIdentifier();
|
||||
bool LIsBuiltins = LB == "<built-in>";
|
||||
@@ -2100,6 +2057,60 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
|
||||
llvm_unreachable("Unsortable locations found");
|
||||
}
|
||||
|
||||
std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
|
||||
std::pair<FileID, unsigned> &LOffs,
|
||||
std::pair<FileID, unsigned> &ROffs) const {
|
||||
// If the source locations are in the same file, just compare offsets.
|
||||
if (LOffs.first == ROffs.first)
|
||||
return std::make_pair(true, 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.
|
||||
InBeforeInTUCacheEntry &IsBeforeInTUCache =
|
||||
getInBeforeInTUCache(LOffs.first, ROffs.first);
|
||||
|
||||
// If we are comparing a source location with multiple locations in the same
|
||||
// file, we get a big win by caching the result.
|
||||
if (IsBeforeInTUCache.isCacheValid(LOffs.first, ROffs.first))
|
||||
return std::make_pair(
|
||||
true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
|
||||
|
||||
// Okay, we missed in the cache, start updating the cache for this query.
|
||||
IsBeforeInTUCache.setQueryFIDs(LOffs.first, ROffs.first,
|
||||
/*isLFIDBeforeRFID=*/LOffs.first.ID < ROffs.first.ID);
|
||||
|
||||
// We need to find the common ancestor. The only way of doing this is to
|
||||
// build the complete include chain for one and then walking up the chain
|
||||
// of the other looking for a match.
|
||||
// We use a map from FileID to Offset to store the chain. Easier than writing
|
||||
// a custom set hash info that only depends on the first part of a pair.
|
||||
typedef llvm::SmallDenseMap<FileID, unsigned, 16> LocSet;
|
||||
LocSet LChain;
|
||||
do {
|
||||
LChain.insert(LOffs);
|
||||
// We catch the case where LOffs is in a file included by ROffs and
|
||||
// quit early. The other way round unfortunately remains suboptimal.
|
||||
} while (LOffs.first != ROffs.first && !MoveUpIncludeHierarchy(LOffs, *this));
|
||||
LocSet::iterator I;
|
||||
while((I = LChain.find(ROffs.first)) == LChain.end()) {
|
||||
if (MoveUpIncludeHierarchy(ROffs, *this))
|
||||
break; // Met at topmost file.
|
||||
}
|
||||
if (I != LChain.end())
|
||||
LOffs = *I;
|
||||
|
||||
// If we exited because we found a nearest common ancestor, compare the
|
||||
// locations within the common file and cache them.
|
||||
if (LOffs.first == ROffs.first) {
|
||||
IsBeforeInTUCache.setCommonLoc(LOffs.first, LOffs.second, ROffs.second);
|
||||
return std::make_pair(
|
||||
true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
|
||||
}
|
||||
// Clear the lookup cache, it depends on a common location.
|
||||
IsBeforeInTUCache.clear();
|
||||
return std::make_pair(false, false);
|
||||
}
|
||||
|
||||
void SourceManager::PrintStats() const {
|
||||
llvm::errs() << "\n*** Source Manager Stats:\n";
|
||||
llvm::errs() << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
|
||||
|
||||
Reference in New Issue
Block a user