@@ -458,11 +458,14 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
458
458
CurrentLoadedOffset - TotalSize < NextLocalOffset) {
459
459
return std::make_pair (0 , 0 );
460
460
}
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
+
463
467
CurrentLoadedOffset -= TotalSize;
464
- int ID = LoadedSLocEntryTable.size ();
465
- return std::make_pair (-ID - 1 , CurrentLoadedOffset);
468
+ return std::make_pair (-NewTableSize - 1 , CurrentLoadedOffset);
466
469
}
467
470
468
471
// / As part of recovering from missing or changed content, produce a
@@ -1976,14 +1979,36 @@ SourceManager::getDecomposedIncludedLoc(FileID FID) const {
1976
1979
return DecompLoc;
1977
1980
}
1978
1981
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
+
1979
2002
// / 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) {
1985
2009
std::pair<FileID, unsigned > UpperLoc = SM.getDecomposedIncludedLoc (Loc.first );
1986
- if (UpperLoc.first .isInvalid ())
2010
+ if (UpperLoc.first .isInvalid () ||
2011
+ !SM.isInTheSameTranslationUnitImpl (UpperLoc, Loc))
1987
2012
return true ; // We reached the top.
1988
2013
1989
2014
Loc = UpperLoc;
@@ -2039,45 +2064,18 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
2039
2064
std::pair<bool , bool > InSameTU = isInTheSameTranslationUnit (LOffs, ROffs);
2040
2065
if (InSameTU.first )
2041
2066
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 ;
2076
2070
}
2077
2071
2078
2072
std::pair<bool , bool > SourceManager::isInTheSameTranslationUnit (
2079
2073
std::pair<FileID, unsigned > &LOffs,
2080
2074
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
+
2081
2079
// If the source locations are in the same file, just compare offsets.
2082
2080
if (LOffs.first == ROffs.first )
2083
2081
return std::make_pair (true , LOffs.second < ROffs.second );
@@ -2113,7 +2111,7 @@ std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
2113
2111
if (LOffs.first == ROffs.first )
2114
2112
break ;
2115
2113
LChild = LOffs.first ;
2116
- } while (!MoveUpIncludeHierarchy (LOffs, *this ));
2114
+ } while (!MoveUpTranslationUnitIncludeHierarchy (LOffs, *this ));
2117
2115
2118
2116
FileID RChild;
2119
2117
do {
@@ -2143,11 +2141,45 @@ std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
2143
2141
true , IsBeforeInTUCache.getCachedResult (LOffs.second , ROffs.second ));
2144
2142
}
2145
2143
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 ();
2147
2151
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" );
2151
2183
}
2152
2184
2153
2185
void SourceManager::PrintStats () const {
0 commit comments