@@ -460,8 +460,9 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
460
460
LoadedSLocEntryTable.resize (LoadedSLocEntryTable.size () + NumSLocEntries);
461
461
SLocEntryLoaded.resize (LoadedSLocEntryTable.size ());
462
462
CurrentLoadedOffset -= TotalSize;
463
- int ID = LoadedSLocEntryTable.size ();
464
- return std::make_pair (-ID - 1 , CurrentLoadedOffset);
463
+ int BaseID = -int (LoadedSLocEntryTable.size ()) - 1 ;
464
+ LoadedSLocEntryAllocBegin.push_back (FileID::get (BaseID));
465
+ return std::make_pair (BaseID, CurrentLoadedOffset);
465
466
}
466
467
467
468
// / As part of recovering from missing or changed content, produce a
@@ -1964,14 +1965,38 @@ SourceManager::getDecomposedIncludedLoc(FileID FID) const {
1964
1965
return DecompLoc;
1965
1966
}
1966
1967
1968
+ bool SourceManager::isInTheSameTranslationUnitImpl (
1969
+ const std::pair<FileID, unsigned > &LOffs,
1970
+ const std::pair<FileID, unsigned > &ROffs) const {
1971
+ // If one is local while the other is loaded.
1972
+ if (isLoadedFileID (LOffs.first ) != isLoadedFileID (ROffs.first ))
1973
+ return false ;
1974
+
1975
+ if (isLoadedFileID (LOffs.first ) && isLoadedFileID (ROffs.first )) {
1976
+ auto FindSLocEntryAlloc = [this ](FileID FID) {
1977
+ // Loaded FileIDs are negative, we store the lowest FileID from each
1978
+ // allocation, later allocations have lower FileIDs.
1979
+ return llvm::lower_bound (LoadedSLocEntryAllocBegin, FID, std::greater{});
1980
+ };
1981
+
1982
+ // If both are loaded from different AST files.
1983
+ if (FindSLocEntryAlloc (LOffs.first ) != FindSLocEntryAlloc (ROffs.first ))
1984
+ return false ;
1985
+ }
1986
+
1987
+ return true ;
1988
+ }
1989
+
1967
1990
// / Given a decomposed source location, move it up the include/expansion stack
1968
- // / to the parent source location. If this is possible, return the decomposed
1969
- // / version of the parent in Loc and return false. If Loc is the top-level
1970
- // / entry, return true and don't modify it.
1971
- static bool MoveUpIncludeHierarchy (std::pair<FileID, unsigned > &Loc,
1972
- const SourceManager &SM) {
1991
+ // / to the parent source location within the same translation unit. If this is
1992
+ // / possible, return the decomposed version of the parent in Loc and return
1993
+ // / false. If Loc is a top-level entry, return true and don't modify it.
1994
+ static bool
1995
+ MoveUpTranslationUnitIncludeHierarchy (std::pair<FileID, unsigned > &Loc,
1996
+ const SourceManager &SM) {
1973
1997
std::pair<FileID, unsigned > UpperLoc = SM.getDecomposedIncludedLoc (Loc.first );
1974
- if (UpperLoc.first .isInvalid ())
1998
+ if (UpperLoc.first .isInvalid () ||
1999
+ !SM.isInTheSameTranslationUnitImpl (UpperLoc, Loc))
1975
2000
return true ; // We reached the top.
1976
2001
1977
2002
Loc = UpperLoc;
@@ -2027,45 +2052,18 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
2027
2052
std::pair<bool , bool > InSameTU = isInTheSameTranslationUnit (LOffs, ROffs);
2028
2053
if (InSameTU.first )
2029
2054
return InSameTU.second ;
2030
-
2031
- // If we arrived here, the location is either in a built-ins buffer or
2032
- // associated with global inline asm. PR5662 and PR22576 are examples.
2033
-
2034
- StringRef LB = getBufferOrFake (LOffs.first ).getBufferIdentifier ();
2035
- StringRef RB = getBufferOrFake (ROffs.first ).getBufferIdentifier ();
2036
- bool LIsBuiltins = LB == " <built-in>" ;
2037
- bool RIsBuiltins = RB == " <built-in>" ;
2038
- // Sort built-in before non-built-in.
2039
- if (LIsBuiltins || RIsBuiltins) {
2040
- if (LIsBuiltins != RIsBuiltins)
2041
- return LIsBuiltins;
2042
- // Both are in built-in buffers, but from different files. We just claim that
2043
- // lower IDs come first.
2044
- return LOffs.first < ROffs.first ;
2045
- }
2046
- bool LIsAsm = LB == " <inline asm>" ;
2047
- bool RIsAsm = RB == " <inline asm>" ;
2048
- // Sort assembler after built-ins, but before the rest.
2049
- if (LIsAsm || RIsAsm) {
2050
- if (LIsAsm != RIsAsm)
2051
- return RIsAsm;
2052
- assert (LOffs.first == ROffs.first );
2053
- return false ;
2054
- }
2055
- bool LIsScratch = LB == " <scratch space>" ;
2056
- bool RIsScratch = RB == " <scratch space>" ;
2057
- // Sort scratch after inline asm, but before the rest.
2058
- if (LIsScratch || RIsScratch) {
2059
- if (LIsScratch != RIsScratch)
2060
- return LIsScratch;
2061
- return LOffs.second < ROffs.second ;
2062
- }
2063
- llvm_unreachable (" Unsortable locations found" );
2055
+ // TODO: This should be unreachable, but some clients are calling this
2056
+ // function before making sure LHS and RHS are in the same TU.
2057
+ return LOffs.first < ROffs.first ;
2064
2058
}
2065
2059
2066
2060
std::pair<bool , bool > SourceManager::isInTheSameTranslationUnit (
2067
2061
std::pair<FileID, unsigned > &LOffs,
2068
2062
std::pair<FileID, unsigned > &ROffs) const {
2063
+ // If the source locations are not in the same TU, return early.
2064
+ if (!isInTheSameTranslationUnitImpl (LOffs, ROffs))
2065
+ return std::make_pair (false , false );
2066
+
2069
2067
// If the source locations are in the same file, just compare offsets.
2070
2068
if (LOffs.first == ROffs.first )
2071
2069
return std::make_pair (true , LOffs.second < ROffs.second );
@@ -2088,53 +2086,88 @@ std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
2088
2086
2089
2087
// A location within a FileID on the path up from LOffs to the main file.
2090
2088
struct Entry {
2091
- unsigned Offset;
2092
- FileID ParentFID ; // Used for breaking ties.
2089
+ std::pair<FileID, unsigned > DecomposedLoc; // FileID redundant, but clearer.
2090
+ FileID ChildFID ; // Used for breaking ties. Invalid for the initial loc .
2093
2091
};
2094
2092
llvm::SmallDenseMap<FileID, Entry, 16 > LChain;
2095
2093
2096
- FileID Parent ;
2094
+ FileID LChild ;
2097
2095
do {
2098
- LChain.try_emplace (LOffs.first , Entry{LOffs. second , Parent });
2096
+ LChain.try_emplace (LOffs.first , Entry{LOffs, LChild });
2099
2097
// We catch the case where LOffs is in a file included by ROffs and
2100
2098
// quit early. The other way round unfortunately remains suboptimal.
2101
2099
if (LOffs.first == ROffs.first )
2102
2100
break ;
2103
- Parent = LOffs.first ;
2104
- } while (!MoveUpIncludeHierarchy (LOffs, *this ));
2101
+ LChild = LOffs.first ;
2102
+ } while (!MoveUpTranslationUnitIncludeHierarchy (LOffs, *this ));
2105
2103
2106
- Parent = FileID () ;
2104
+ FileID RChild ;
2107
2105
do {
2108
- auto I = LChain.find (ROffs.first );
2109
- if (I != LChain.end ()) {
2106
+ auto LIt = LChain.find (ROffs.first );
2107
+ if (LIt != LChain.end ()) {
2110
2108
// Compare the locations within the common file and cache them.
2111
- LOffs. first = I-> first ;
2112
- LOffs. second = I ->second .Offset ;
2113
- // The relative order of LParent and RParent is a tiebreaker when
2109
+ LOffs = LIt-> second . DecomposedLoc ;
2110
+ LChild = LIt ->second .ChildFID ;
2111
+ // The relative order of LChild and RChild is a tiebreaker when
2114
2112
// - locs expand to the same location (occurs in macro arg expansion)
2115
2113
// - one loc is a parent of the other (we consider the parent as "first")
2116
- // For the parent to be first, the invalid file ID must compare smaller.
2114
+ // For the parent entry to be first, its invalid child file ID must
2115
+ // compare smaller to the valid child file ID of the other entry.
2117
2116
// However loaded FileIDs are <0, so we perform *unsigned* comparison!
2118
2117
// This changes the relative order of local vs loaded FileIDs, but it
2119
2118
// doesn't matter as these are never mixed in macro expansion.
2120
- unsigned LParent = I-> second . ParentFID .ID ;
2121
- unsigned RParent = Parent .ID ;
2119
+ unsigned LChildID = LChild .ID ;
2120
+ unsigned RChildID = RChild .ID ;
2122
2121
assert (((LOffs.second != ROffs.second ) ||
2123
- (LParent == 0 || RParent == 0 ) ||
2124
- isInSameSLocAddrSpace (getComposedLoc (I-> second . ParentFID , 0 ),
2125
- getComposedLoc (Parent , 0 ), nullptr )) &&
2122
+ (LChildID == 0 || RChildID == 0 ) ||
2123
+ isInSameSLocAddrSpace (getComposedLoc (LChild , 0 ),
2124
+ getComposedLoc (RChild , 0 ), nullptr )) &&
2126
2125
" Mixed local/loaded FileIDs with same include location?" );
2127
2126
IsBeforeInTUCache.setCommonLoc (LOffs.first , LOffs.second , ROffs.second ,
2128
- LParent < RParent );
2127
+ LChildID < RChildID );
2129
2128
return std::make_pair (
2130
2129
true , IsBeforeInTUCache.getCachedResult (LOffs.second , ROffs.second ));
2131
2130
}
2132
- Parent = ROffs.first ;
2133
- } while (!MoveUpIncludeHierarchy (ROffs, *this ));
2131
+ RChild = ROffs.first ;
2132
+ } while (!MoveUpTranslationUnitIncludeHierarchy (ROffs, *this ));
2133
+
2134
+ // If we found no match, the location is either in a built-ins buffer or
2135
+ // associated with global inline asm. PR5662 and PR22576 are examples.
2136
+
2137
+ StringRef LB = getBufferOrFake (LOffs.first ).getBufferIdentifier ();
2138
+ StringRef RB = getBufferOrFake (ROffs.first ).getBufferIdentifier ();
2139
+
2140
+ bool LIsBuiltins = LB == " <built-in>" ;
2141
+ bool RIsBuiltins = RB == " <built-in>" ;
2142
+ // Sort built-in before non-built-in.
2143
+ if (LIsBuiltins || RIsBuiltins) {
2144
+ if (LIsBuiltins != RIsBuiltins)
2145
+ return std::make_pair (true , LIsBuiltins);
2146
+ // Both are in built-in buffers, but from different files. We just claim
2147
+ // that lower IDs come first.
2148
+ return std::make_pair (true , LOffs.first < ROffs.first );
2149
+ }
2150
+
2151
+ bool LIsAsm = LB == " <inline asm>" ;
2152
+ bool RIsAsm = RB == " <inline asm>" ;
2153
+ // Sort assembler after built-ins, but before the rest.
2154
+ if (LIsAsm || RIsAsm) {
2155
+ if (LIsAsm != RIsAsm)
2156
+ return std::make_pair (true , RIsAsm);
2157
+ assert (LOffs.first == ROffs.first );
2158
+ return std::make_pair (true , false );
2159
+ }
2160
+
2161
+ bool LIsScratch = LB == " <scratch space>" ;
2162
+ bool RIsScratch = RB == " <scratch space>" ;
2163
+ // Sort scratch after inline asm, but before the rest.
2164
+ if (LIsScratch || RIsScratch) {
2165
+ if (LIsScratch != RIsScratch)
2166
+ return std::make_pair (true , LIsScratch);
2167
+ return std::make_pair (true , LOffs.second < ROffs.second );
2168
+ }
2134
2169
2135
- // If we found no match, we're not in the same TU.
2136
- // We don't cache this, but it is rare.
2137
- return std::make_pair (false , false );
2170
+ llvm_unreachable (" Unsortable locations found" );
2138
2171
}
2139
2172
2140
2173
void SourceManager::PrintStats () const {
0 commit comments