Skip to content

Commit af8b797

Browse files
committed
[clang] Cut off IncludeLoc walk on TU boundary, return early
1 parent 8f035aa commit af8b797

File tree

2 files changed

+90
-49
lines changed

2 files changed

+90
-49
lines changed

clang/include/clang/Basic/SourceManager.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,10 @@ class SourceManager : public RefCountedBase<SourceManager> {
701701
/// use (-ID - 2).
702702
SmallVector<SrcMgr::SLocEntry, 0> LoadedSLocEntryTable;
703703

704+
/// For each allocation in LoadedSLocEntryTable, we keep the new size. This
705+
/// can be used to determine whether two FileIDs come from the same AST file.
706+
SmallVector<size_t, 0> LoadedSLocEntryTableSegments;
707+
704708
/// The starting offset of the next local SLocEntry.
705709
///
706710
/// This is LocalSLocEntryTable.back().Offset + the size of that entry.
@@ -1649,6 +1653,11 @@ class SourceManager : public RefCountedBase<SourceManager> {
16491653
isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs,
16501654
std::pair<FileID, unsigned> &ROffs) const;
16511655

1656+
/// Determines whether the two decomposed source location is in the same TU.
1657+
bool isInTheSameTranslationUnitImpl(
1658+
const std::pair<FileID, unsigned> &LOffs,
1659+
const std::pair<FileID, unsigned> &ROffs) const;
1660+
16521661
/// Determines the order of 2 source locations in the "source location
16531662
/// address space".
16541663
bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const {

clang/lib/Basic/SourceManager.cpp

Lines changed: 81 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -458,11 +458,14 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
458458
CurrentLoadedOffset - TotalSize < NextLocalOffset) {
459459
return std::make_pair(0, 0);
460460
}
461-
LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries);
462-
SLocEntryLoaded.resize(LoadedSLocEntryTable.size());
461+
462+
unsigned NewTableSize = LoadedSLocEntryTable.size() + NumSLocEntries;
463+
LoadedSLocEntryTableSegments.push_back(NewTableSize);
464+
LoadedSLocEntryTable.resize(NewTableSize);
465+
SLocEntryLoaded.resize(NewTableSize);
466+
463467
CurrentLoadedOffset -= TotalSize;
464-
int ID = LoadedSLocEntryTable.size();
465-
return std::make_pair(-ID - 1, CurrentLoadedOffset);
468+
return std::make_pair(-NewTableSize - 1, CurrentLoadedOffset);
466469
}
467470

468471
/// As part of recovering from missing or changed content, produce a
@@ -1976,14 +1979,36 @@ SourceManager::getDecomposedIncludedLoc(FileID FID) const {
19761979
return DecompLoc;
19771980
}
19781981

1982+
bool SourceManager::isInTheSameTranslationUnitImpl(
1983+
const std::pair<FileID, unsigned> &LOffs,
1984+
const std::pair<FileID, unsigned> &ROffs) const {
1985+
// If one is local while the other is loaded.
1986+
if (isLoadedFileID(LOffs.first) != isLoadedFileID(ROffs.first))
1987+
return false;
1988+
1989+
// If both are loaded from different AST files.
1990+
if (isLoadedFileID(LOffs.first) && isLoadedFileID(ROffs.first)) {
1991+
auto FindTableSegment = [this](FileID FID) {
1992+
return llvm::upper_bound(LoadedSLocEntryTableSegments, -FID.ID - 2);
1993+
};
1994+
1995+
if (FindTableSegment(LOffs.first) != FindTableSegment(ROffs.first))
1996+
return false;
1997+
}
1998+
1999+
return true;
2000+
}
2001+
19792002
/// Given a decomposed source location, move it up the include/expansion stack
1980-
/// to the parent source location. If this is possible, return the decomposed
1981-
/// version of the parent in Loc and return false. If Loc is the top-level
1982-
/// entry, return true and don't modify it.
1983-
static bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc,
1984-
const SourceManager &SM) {
2003+
/// to the parent source location within the same translation unit. If this is
2004+
/// possible, return the decomposed version of the parent in Loc and return
2005+
/// false. If Loc is a top-level entry, return true and don't modify it.
2006+
static bool
2007+
MoveUpTranslationUnitIncludeHierarchy(std::pair<FileID, unsigned> &Loc,
2008+
const SourceManager &SM) {
19852009
std::pair<FileID, unsigned> UpperLoc = SM.getDecomposedIncludedLoc(Loc.first);
1986-
if (UpperLoc.first.isInvalid())
2010+
if (UpperLoc.first.isInvalid() ||
2011+
!SM.isInTheSameTranslationUnitImpl(UpperLoc, Loc))
19872012
return true; // We reached the top.
19882013

19892014
Loc = UpperLoc;
@@ -2039,45 +2064,18 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
20392064
std::pair<bool, bool> InSameTU = isInTheSameTranslationUnit(LOffs, ROffs);
20402065
if (InSameTU.first)
20412066
return InSameTU.second;
2042-
2043-
// If we arrived here, the location is either in a built-ins buffer or
2044-
// associated with global inline asm. PR5662 and PR22576 are examples.
2045-
2046-
StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2047-
StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
2048-
bool LIsBuiltins = LB == "<built-in>";
2049-
bool RIsBuiltins = RB == "<built-in>";
2050-
// Sort built-in before non-built-in.
2051-
if (LIsBuiltins || RIsBuiltins) {
2052-
if (LIsBuiltins != RIsBuiltins)
2053-
return LIsBuiltins;
2054-
// Both are in built-in buffers, but from different files. We just claim that
2055-
// lower IDs come first.
2056-
return LOffs.first < ROffs.first;
2057-
}
2058-
bool LIsAsm = LB == "<inline asm>";
2059-
bool RIsAsm = RB == "<inline asm>";
2060-
// Sort assembler after built-ins, but before the rest.
2061-
if (LIsAsm || RIsAsm) {
2062-
if (LIsAsm != RIsAsm)
2063-
return RIsAsm;
2064-
assert(LOffs.first == ROffs.first);
2065-
return false;
2066-
}
2067-
bool LIsScratch = LB == "<scratch space>";
2068-
bool RIsScratch = RB == "<scratch space>";
2069-
// Sort scratch after inline asm, but before the rest.
2070-
if (LIsScratch || RIsScratch) {
2071-
if (LIsScratch != RIsScratch)
2072-
return LIsScratch;
2073-
return LOffs.second < ROffs.second;
2074-
}
2075-
llvm_unreachable("Unsortable locations found");
2067+
// TODO: This should be unreachable, but some clients are calling this
2068+
// function before making sure LHS and RHS are in the same TU.
2069+
return LOffs.first < ROffs.first;
20762070
}
20772071

20782072
std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
20792073
std::pair<FileID, unsigned> &LOffs,
20802074
std::pair<FileID, unsigned> &ROffs) const {
2075+
// If the source locations are not in the same TU, return early.
2076+
if (!isInTheSameTranslationUnitImpl(LOffs, ROffs))
2077+
return std::make_pair(false, false);
2078+
20812079
// If the source locations are in the same file, just compare offsets.
20822080
if (LOffs.first == ROffs.first)
20832081
return std::make_pair(true, LOffs.second < ROffs.second);
@@ -2113,7 +2111,7 @@ std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
21132111
if (LOffs.first == ROffs.first)
21142112
break;
21152113
LChild = LOffs.first;
2116-
} while (!MoveUpIncludeHierarchy(LOffs, *this));
2114+
} while (!MoveUpTranslationUnitIncludeHierarchy(LOffs, *this));
21172115

21182116
FileID RChild;
21192117
do {
@@ -2143,11 +2141,45 @@ std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
21432141
true, IsBeforeInTUCache.getCachedResult(LOffs.second, ROffs.second));
21442142
}
21452143
RChild = ROffs.first;
2146-
} while (!MoveUpIncludeHierarchy(ROffs, *this));
2144+
} while (!MoveUpTranslationUnitIncludeHierarchy(ROffs, *this));
2145+
2146+
// If we found no match, the location is either in a built-ins buffer or
2147+
// associated with global inline asm. PR5662 and PR22576 are examples.
2148+
2149+
StringRef LB = getBufferOrFake(LOffs.first).getBufferIdentifier();
2150+
StringRef RB = getBufferOrFake(ROffs.first).getBufferIdentifier();
21472151

2148-
// If we found no match, we're not in the same TU.
2149-
// We don't cache this, but it is rare.
2150-
return std::make_pair(false, false);
2152+
bool LIsBuiltins = LB == "<built-in>";
2153+
bool RIsBuiltins = RB == "<built-in>";
2154+
// Sort built-in before non-built-in.
2155+
if (LIsBuiltins || RIsBuiltins) {
2156+
if (LIsBuiltins != RIsBuiltins)
2157+
return std::make_pair(true, LIsBuiltins);
2158+
// Both are in built-in buffers, but from different files. We just claim
2159+
// that lower IDs come first.
2160+
return std::make_pair(true, LOffs.first < ROffs.first);
2161+
}
2162+
2163+
bool LIsAsm = LB == "<inline asm>";
2164+
bool RIsAsm = RB == "<inline asm>";
2165+
// Sort assembler after built-ins, but before the rest.
2166+
if (LIsAsm || RIsAsm) {
2167+
if (LIsAsm != RIsAsm)
2168+
return std::make_pair(true, RIsAsm);
2169+
assert(LOffs.first == ROffs.first);
2170+
return std::make_pair(true, false);
2171+
}
2172+
2173+
bool LIsScratch = LB == "<scratch space>";
2174+
bool RIsScratch = RB == "<scratch space>";
2175+
// Sort scratch after inline asm, but before the rest.
2176+
if (LIsScratch || RIsScratch) {
2177+
if (LIsScratch != RIsScratch)
2178+
return std::make_pair(true, LIsScratch);
2179+
return std::make_pair(true, LOffs.second < ROffs.second);
2180+
}
2181+
2182+
llvm_unreachable("Unsortable locations found");
21512183
}
21522184

21532185
void SourceManager::PrintStats() const {

0 commit comments

Comments
 (0)