@@ -460,8 +460,9 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries,
460460 LoadedSLocEntryTable.resize (LoadedSLocEntryTable.size () + NumSLocEntries);
461461 SLocEntryLoaded.resize (LoadedSLocEntryTable.size ());
462462 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);
465466}
466467
467468// / As part of recovering from missing or changed content, produce a
@@ -1964,14 +1965,38 @@ SourceManager::getDecomposedIncludedLoc(FileID FID) const {
19641965 return DecompLoc;
19651966}
19661967
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+
19671990// / 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) {
19731997 std::pair<FileID, unsigned > UpperLoc = SM.getDecomposedIncludedLoc (Loc.first );
1974- if (UpperLoc.first .isInvalid ())
1998+ if (UpperLoc.first .isInvalid () ||
1999+ !SM.isInTheSameTranslationUnitImpl (UpperLoc, Loc))
19752000 return true ; // We reached the top.
19762001
19772002 Loc = UpperLoc;
@@ -2027,45 +2052,18 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
20272052 std::pair<bool , bool > InSameTU = isInTheSameTranslationUnit (LOffs, ROffs);
20282053 if (InSameTU.first )
20292054 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 ;
20642058}
20652059
20662060std::pair<bool , bool > SourceManager::isInTheSameTranslationUnit (
20672061 std::pair<FileID, unsigned > &LOffs,
20682062 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+
20692067 // If the source locations are in the same file, just compare offsets.
20702068 if (LOffs.first == ROffs.first )
20712069 return std::make_pair (true , LOffs.second < ROffs.second );
@@ -2088,53 +2086,88 @@ std::pair<bool, bool> SourceManager::isInTheSameTranslationUnit(
20882086
20892087 // A location within a FileID on the path up from LOffs to the main file.
20902088 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 .
20932091 };
20942092 llvm::SmallDenseMap<FileID, Entry, 16 > LChain;
20952093
2096- FileID Parent ;
2094+ FileID LChild ;
20972095 do {
2098- LChain.try_emplace (LOffs.first , Entry{LOffs. second , Parent });
2096+ LChain.try_emplace (LOffs.first , Entry{LOffs, LChild });
20992097 // We catch the case where LOffs is in a file included by ROffs and
21002098 // quit early. The other way round unfortunately remains suboptimal.
21012099 if (LOffs.first == ROffs.first )
21022100 break ;
2103- Parent = LOffs.first ;
2104- } while (!MoveUpIncludeHierarchy (LOffs, *this ));
2101+ LChild = LOffs.first ;
2102+ } while (!MoveUpTranslationUnitIncludeHierarchy (LOffs, *this ));
21052103
2106- Parent = FileID () ;
2104+ FileID RChild ;
21072105 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 ()) {
21102108 // 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
21142112 // - locs expand to the same location (occurs in macro arg expansion)
21152113 // - 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.
21172116 // However loaded FileIDs are <0, so we perform *unsigned* comparison!
21182117 // This changes the relative order of local vs loaded FileIDs, but it
21192118 // 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 ;
21222121 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 )) &&
21262125 " Mixed local/loaded FileIDs with same include location?" );
21272126 IsBeforeInTUCache.setCommonLoc (LOffs.first , LOffs.second , ROffs.second ,
2128- LParent < RParent );
2127+ LChildID < RChildID );
21292128 return std::make_pair (
21302129 true , IsBeforeInTUCache.getCachedResult (LOffs.second , ROffs.second ));
21312130 }
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+ }
21342169
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" );
21382171}
21392172
21402173void SourceManager::PrintStats () const {
0 commit comments