@@ -461,8 +461,9 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
461
461
LoadedSLocEntryTable.resize (LoadedSLocEntryTable.size () + NumSLocEntries);
462
462
SLocEntryLoaded.resize (LoadedSLocEntryTable.size ());
463
463
CurrentLoadedOffset -= TotalSize;
464
- int ID = LoadedSLocEntryTable.size ();
465
- return std::make_pair (-ID - 1 , CurrentLoadedOffset);
464
+ int BaseID = -int (LoadedSLocEntryTable.size ()) - 1 ;
465
+ LoadedSLocEntryAllocBegin.push_back (FileID::get (BaseID));
466
+ return std::make_pair (BaseID, CurrentLoadedOffset);
466
467
}
467
468
468
469
// / As part of recovering from missing or changed content, produce a
@@ -1976,14 +1977,38 @@ SourceManager::getDecomposedIncludedLoc(FileID FID) const {
1976
1977
return DecompLoc;
1977
1978
}
1978
1979
1980
+ bool SourceManager::isInTheSameTranslationUnitImpl (
1981
+ const std::pair<FileID, unsigned > &LOffs,
1982
+ const std::pair<FileID, unsigned > &ROffs) const {
1983
+ // If one is local while the other is loaded.
1984
+ if (isLoadedFileID (LOffs.first ) != isLoadedFileID (ROffs.first ))
1985
+ return false ;
1986
+
1987
+ if (isLoadedFileID (LOffs.first ) && isLoadedFileID (ROffs.first )) {
1988
+ auto FindSLocEntryAlloc = [this ](FileID FID) {
1989
+ // Loaded FileIDs are negative, we store the lowest FileID from each
1990
+ // allocation, later allocations have lower FileIDs.
1991
+ return llvm::lower_bound (LoadedSLocEntryAllocBegin, FID, std::greater{});
1992
+ };
1993
+
1994
+ // If both are loaded from different AST files.
1995
+ if (FindSLocEntryAlloc (LOffs.first ) != FindSLocEntryAlloc (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 );
@@ -2100,53 +2098,88 @@ std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
2100
2098
2101
2099
// A location within a FileID on the path up from LOffs to the main file.
2102
2100
struct Entry {
2103
- unsigned Offset;
2104
- FileID ParentFID ; // Used for breaking ties.
2101
+ std::pair<FileID, unsigned > DecomposedLoc; // FileID redundant, but clearer.
2102
+ FileID ChildFID ; // Used for breaking ties. Invalid for the initial loc .
2105
2103
};
2106
2104
llvm::SmallDenseMap<FileID, Entry, 16 > LChain;
2107
2105
2108
- FileID Parent ;
2106
+ FileID LChild ;
2109
2107
do {
2110
- LChain.try_emplace (LOffs.first , Entry{LOffs. second , Parent });
2108
+ LChain.try_emplace (LOffs.first , Entry{LOffs, LChild });
2111
2109
// We catch the case where LOffs is in a file included by ROffs and
2112
2110
// quit early. The other way round unfortunately remains suboptimal.
2113
2111
if (LOffs.first == ROffs.first )
2114
2112
break ;
2115
- Parent = LOffs.first ;
2116
- } while (!MoveUpIncludeHierarchy (LOffs, *this ));
2113
+ LChild = LOffs.first ;
2114
+ } while (!MoveUpTranslationUnitIncludeHierarchy (LOffs, *this ));
2117
2115
2118
- Parent = FileID () ;
2116
+ FileID RChild ;
2119
2117
do {
2120
- auto I = LChain.find (ROffs.first );
2121
- if (I != LChain.end ()) {
2118
+ auto LIt = LChain.find (ROffs.first );
2119
+ if (LIt != LChain.end ()) {
2122
2120
// Compare the locations within the common file and cache them.
2123
- LOffs. first = I-> first ;
2124
- LOffs. second = I ->second .Offset ;
2125
- // The relative order of LParent and RParent is a tiebreaker when
2121
+ LOffs = LIt-> second . DecomposedLoc ;
2122
+ LChild = LIt ->second .ChildFID ;
2123
+ // The relative order of LChild and RChild is a tiebreaker when
2126
2124
// - locs expand to the same location (occurs in macro arg expansion)
2127
2125
// - one loc is a parent of the other (we consider the parent as "first")
2128
- // For the parent to be first, the invalid file ID must compare smaller.
2126
+ // For the parent entry to be first, its invalid child file ID must
2127
+ // compare smaller to the valid child file ID of the other entry.
2129
2128
// However loaded FileIDs are <0, so we perform *unsigned* comparison!
2130
2129
// This changes the relative order of local vs loaded FileIDs, but it
2131
2130
// doesn't matter as these are never mixed in macro expansion.
2132
- unsigned LParent = I-> second . ParentFID .ID ;
2133
- unsigned RParent = Parent .ID ;
2131
+ unsigned LChildID = LChild .ID ;
2132
+ unsigned RChildID = RChild .ID ;
2134
2133
assert (((LOffs.second != ROffs.second ) ||
2135
- (LParent == 0 || RParent == 0 ) ||
2136
- isInSameSLocAddrSpace (getComposedLoc (I-> second . ParentFID , 0 ),
2137
- getComposedLoc (Parent , 0 ), nullptr )) &&
2134
+ (LChildID == 0 || RChildID == 0 ) ||
2135
+ isInSameSLocAddrSpace (getComposedLoc (LChild , 0 ),
2136
+ getComposedLoc (RChild , 0 ), nullptr )) &&
2138
2137
" Mixed local/loaded FileIDs with same include location?" );
2139
2138
IsBeforeInTUCache.setCommonLoc (LOffs.first , LOffs.second , ROffs.second ,
2140
- LParent < RParent );
2139
+ LChildID < RChildID );
2141
2140
return std::make_pair (
2142
2141
true , IsBeforeInTUCache.getCachedResult (LOffs.second , ROffs.second ));
2143
2142
}
2144
- Parent = ROffs.first ;
2145
- } while (!MoveUpIncludeHierarchy (ROffs, *this ));
2143
+ RChild = ROffs.first ;
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 ();
2151
+
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
+ }
2146
2181
2147
- // If we found no match, we're not in the same TU.
2148
- // We don't cache this, but it is rare.
2149
- return std::make_pair (false , false );
2182
+ llvm_unreachable (" Unsortable locations found" );
2150
2183
}
2151
2184
2152
2185
void SourceManager::PrintStats () const {
0 commit comments