xref: /freebsd-src/contrib/llvm-project/clang/lib/Edit/Commit.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- Commit.cpp - A unit of edits ---------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "clang/Edit/Commit.h"
100b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
110b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
120b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
130b57cec5SDimitry Andric #include "clang/Edit/EditedSource.h"
140b57cec5SDimitry Andric #include "clang/Edit/FileOffset.h"
150b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
160b57cec5SDimitry Andric #include "clang/Lex/PPConditionalDirectiveRecord.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
180b57cec5SDimitry Andric #include <cassert>
190b57cec5SDimitry Andric #include <utility>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace clang;
220b57cec5SDimitry Andric using namespace edit;
230b57cec5SDimitry Andric 
getFileLocation(SourceManager & SM) const240b57cec5SDimitry Andric SourceLocation Commit::Edit::getFileLocation(SourceManager &SM) const {
250b57cec5SDimitry Andric   SourceLocation Loc = SM.getLocForStartOfFile(Offset.getFID());
260b57cec5SDimitry Andric   Loc = Loc.getLocWithOffset(Offset.getOffset());
270b57cec5SDimitry Andric   assert(Loc.isFileID());
280b57cec5SDimitry Andric   return Loc;
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
getFileRange(SourceManager & SM) const310b57cec5SDimitry Andric CharSourceRange Commit::Edit::getFileRange(SourceManager &SM) const {
320b57cec5SDimitry Andric   SourceLocation Loc = getFileLocation(SM);
330b57cec5SDimitry Andric   return CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(Length));
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
getInsertFromRange(SourceManager & SM) const360b57cec5SDimitry Andric CharSourceRange Commit::Edit::getInsertFromRange(SourceManager &SM) const {
370b57cec5SDimitry Andric   SourceLocation Loc = SM.getLocForStartOfFile(InsertFromRangeOffs.getFID());
380b57cec5SDimitry Andric   Loc = Loc.getLocWithOffset(InsertFromRangeOffs.getOffset());
390b57cec5SDimitry Andric   assert(Loc.isFileID());
400b57cec5SDimitry Andric   return CharSourceRange::getCharRange(Loc, Loc.getLocWithOffset(Length));
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
Commit(EditedSource & Editor)430b57cec5SDimitry Andric Commit::Commit(EditedSource &Editor)
440b57cec5SDimitry Andric     : SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),
450b57cec5SDimitry Andric       PPRec(Editor.getPPCondDirectiveRecord()),
460b57cec5SDimitry Andric       Editor(&Editor) {}
470b57cec5SDimitry Andric 
insert(SourceLocation loc,StringRef text,bool afterToken,bool beforePreviousInsertions)480b57cec5SDimitry Andric bool Commit::insert(SourceLocation loc, StringRef text,
490b57cec5SDimitry Andric                     bool afterToken, bool beforePreviousInsertions) {
500b57cec5SDimitry Andric   if (text.empty())
510b57cec5SDimitry Andric     return true;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   FileOffset Offs;
540b57cec5SDimitry Andric   if ((!afterToken && !canInsert(loc, Offs)) ||
550b57cec5SDimitry Andric       ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
560b57cec5SDimitry Andric     IsCommitable = false;
570b57cec5SDimitry Andric     return false;
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   addInsert(loc, Offs, text, beforePreviousInsertions);
610b57cec5SDimitry Andric   return true;
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
insertFromRange(SourceLocation loc,CharSourceRange range,bool afterToken,bool beforePreviousInsertions)640b57cec5SDimitry Andric bool Commit::insertFromRange(SourceLocation loc,
650b57cec5SDimitry Andric                              CharSourceRange range,
660b57cec5SDimitry Andric                              bool afterToken, bool beforePreviousInsertions) {
670b57cec5SDimitry Andric   FileOffset RangeOffs;
680b57cec5SDimitry Andric   unsigned RangeLen;
690b57cec5SDimitry Andric   if (!canRemoveRange(range, RangeOffs, RangeLen)) {
700b57cec5SDimitry Andric     IsCommitable = false;
710b57cec5SDimitry Andric     return false;
720b57cec5SDimitry Andric   }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   FileOffset Offs;
750b57cec5SDimitry Andric   if ((!afterToken && !canInsert(loc, Offs)) ||
760b57cec5SDimitry Andric       ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {
770b57cec5SDimitry Andric     IsCommitable = false;
780b57cec5SDimitry Andric     return false;
790b57cec5SDimitry Andric   }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   if (PPRec &&
820b57cec5SDimitry Andric       PPRec->areInDifferentConditionalDirectiveRegion(loc, range.getBegin())) {
830b57cec5SDimitry Andric     IsCommitable = false;
840b57cec5SDimitry Andric     return false;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   addInsertFromRange(loc, Offs, RangeOffs, RangeLen, beforePreviousInsertions);
880b57cec5SDimitry Andric   return true;
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
remove(CharSourceRange range)910b57cec5SDimitry Andric bool Commit::remove(CharSourceRange range) {
920b57cec5SDimitry Andric   FileOffset Offs;
930b57cec5SDimitry Andric   unsigned Len;
940b57cec5SDimitry Andric   if (!canRemoveRange(range, Offs, Len)) {
950b57cec5SDimitry Andric     IsCommitable = false;
960b57cec5SDimitry Andric     return false;
970b57cec5SDimitry Andric   }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   addRemove(range.getBegin(), Offs, Len);
1000b57cec5SDimitry Andric   return true;
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
insertWrap(StringRef before,CharSourceRange range,StringRef after)1030b57cec5SDimitry Andric bool Commit::insertWrap(StringRef before, CharSourceRange range,
1040b57cec5SDimitry Andric                         StringRef after) {
1050b57cec5SDimitry Andric   bool commitableBefore = insert(range.getBegin(), before, /*afterToken=*/false,
1060b57cec5SDimitry Andric                                  /*beforePreviousInsertions=*/true);
1070b57cec5SDimitry Andric   bool commitableAfter;
1080b57cec5SDimitry Andric   if (range.isTokenRange())
1090b57cec5SDimitry Andric     commitableAfter = insertAfterToken(range.getEnd(), after);
1100b57cec5SDimitry Andric   else
1110b57cec5SDimitry Andric     commitableAfter = insert(range.getEnd(), after);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   return commitableBefore && commitableAfter;
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
replace(CharSourceRange range,StringRef text)1160b57cec5SDimitry Andric bool Commit::replace(CharSourceRange range, StringRef text) {
1170b57cec5SDimitry Andric   if (text.empty())
1180b57cec5SDimitry Andric     return remove(range);
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   FileOffset Offs;
1210b57cec5SDimitry Andric   unsigned Len;
1220b57cec5SDimitry Andric   if (!canInsert(range.getBegin(), Offs) || !canRemoveRange(range, Offs, Len)) {
1230b57cec5SDimitry Andric     IsCommitable = false;
1240b57cec5SDimitry Andric     return false;
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   addRemove(range.getBegin(), Offs, Len);
1280b57cec5SDimitry Andric   addInsert(range.getBegin(), Offs, text, false);
1290b57cec5SDimitry Andric   return true;
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
replaceWithInner(CharSourceRange range,CharSourceRange replacementRange)1320b57cec5SDimitry Andric bool Commit::replaceWithInner(CharSourceRange range,
1330b57cec5SDimitry Andric                               CharSourceRange replacementRange) {
1340b57cec5SDimitry Andric   FileOffset OuterBegin;
1350b57cec5SDimitry Andric   unsigned OuterLen;
1360b57cec5SDimitry Andric   if (!canRemoveRange(range, OuterBegin, OuterLen)) {
1370b57cec5SDimitry Andric     IsCommitable = false;
1380b57cec5SDimitry Andric     return false;
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   FileOffset InnerBegin;
1420b57cec5SDimitry Andric   unsigned InnerLen;
1430b57cec5SDimitry Andric   if (!canRemoveRange(replacementRange, InnerBegin, InnerLen)) {
1440b57cec5SDimitry Andric     IsCommitable = false;
1450b57cec5SDimitry Andric     return false;
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   FileOffset OuterEnd = OuterBegin.getWithOffset(OuterLen);
1490b57cec5SDimitry Andric   FileOffset InnerEnd = InnerBegin.getWithOffset(InnerLen);
1500b57cec5SDimitry Andric   if (OuterBegin.getFID() != InnerBegin.getFID() ||
1510b57cec5SDimitry Andric       InnerBegin < OuterBegin ||
1520b57cec5SDimitry Andric       InnerBegin > OuterEnd ||
1530b57cec5SDimitry Andric       InnerEnd > OuterEnd) {
1540b57cec5SDimitry Andric     IsCommitable = false;
1550b57cec5SDimitry Andric     return false;
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   addRemove(range.getBegin(),
1590b57cec5SDimitry Andric             OuterBegin, InnerBegin.getOffset() - OuterBegin.getOffset());
1600b57cec5SDimitry Andric   addRemove(replacementRange.getEnd(),
1610b57cec5SDimitry Andric             InnerEnd, OuterEnd.getOffset() - InnerEnd.getOffset());
1620b57cec5SDimitry Andric   return true;
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
replaceText(SourceLocation loc,StringRef text,StringRef replacementText)1650b57cec5SDimitry Andric bool Commit::replaceText(SourceLocation loc, StringRef text,
1660b57cec5SDimitry Andric                          StringRef replacementText) {
1670b57cec5SDimitry Andric   if (text.empty() || replacementText.empty())
1680b57cec5SDimitry Andric     return true;
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   FileOffset Offs;
1710b57cec5SDimitry Andric   unsigned Len;
1720b57cec5SDimitry Andric   if (!canReplaceText(loc, replacementText, Offs, Len)) {
1730b57cec5SDimitry Andric     IsCommitable = false;
1740b57cec5SDimitry Andric     return false;
1750b57cec5SDimitry Andric   }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   addRemove(loc, Offs, Len);
1780b57cec5SDimitry Andric   addInsert(loc, Offs, text, false);
1790b57cec5SDimitry Andric   return true;
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
addInsert(SourceLocation OrigLoc,FileOffset Offs,StringRef text,bool beforePreviousInsertions)1820b57cec5SDimitry Andric void Commit::addInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text,
1830b57cec5SDimitry Andric                        bool beforePreviousInsertions) {
1840b57cec5SDimitry Andric   if (text.empty())
1850b57cec5SDimitry Andric     return;
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   Edit data;
1880b57cec5SDimitry Andric   data.Kind = Act_Insert;
1890b57cec5SDimitry Andric   data.OrigLoc = OrigLoc;
1900b57cec5SDimitry Andric   data.Offset = Offs;
1910b57cec5SDimitry Andric   data.Text = text.copy(StrAlloc);
1920b57cec5SDimitry Andric   data.BeforePrev = beforePreviousInsertions;
1930b57cec5SDimitry Andric   CachedEdits.push_back(data);
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
addInsertFromRange(SourceLocation OrigLoc,FileOffset Offs,FileOffset RangeOffs,unsigned RangeLen,bool beforePreviousInsertions)1960b57cec5SDimitry Andric void Commit::addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs,
1970b57cec5SDimitry Andric                                 FileOffset RangeOffs, unsigned RangeLen,
1980b57cec5SDimitry Andric                                 bool beforePreviousInsertions) {
1990b57cec5SDimitry Andric   if (RangeLen == 0)
2000b57cec5SDimitry Andric     return;
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   Edit data;
2030b57cec5SDimitry Andric   data.Kind = Act_InsertFromRange;
2040b57cec5SDimitry Andric   data.OrigLoc = OrigLoc;
2050b57cec5SDimitry Andric   data.Offset = Offs;
2060b57cec5SDimitry Andric   data.InsertFromRangeOffs = RangeOffs;
2070b57cec5SDimitry Andric   data.Length = RangeLen;
2080b57cec5SDimitry Andric   data.BeforePrev = beforePreviousInsertions;
2090b57cec5SDimitry Andric   CachedEdits.push_back(data);
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric 
addRemove(SourceLocation OrigLoc,FileOffset Offs,unsigned Len)2120b57cec5SDimitry Andric void Commit::addRemove(SourceLocation OrigLoc,
2130b57cec5SDimitry Andric                        FileOffset Offs, unsigned Len) {
2140b57cec5SDimitry Andric   if (Len == 0)
2150b57cec5SDimitry Andric     return;
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric   Edit data;
2180b57cec5SDimitry Andric   data.Kind = Act_Remove;
2190b57cec5SDimitry Andric   data.OrigLoc = OrigLoc;
2200b57cec5SDimitry Andric   data.Offset = Offs;
2210b57cec5SDimitry Andric   data.Length = Len;
2220b57cec5SDimitry Andric   CachedEdits.push_back(data);
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
canInsert(SourceLocation loc,FileOffset & offs)2250b57cec5SDimitry Andric bool Commit::canInsert(SourceLocation loc, FileOffset &offs) {
2260b57cec5SDimitry Andric   if (loc.isInvalid())
2270b57cec5SDimitry Andric     return false;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   if (loc.isMacroID())
2300b57cec5SDimitry Andric     isAtStartOfMacroExpansion(loc, &loc);
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   const SourceManager &SM = SourceMgr;
2330b57cec5SDimitry Andric   loc = SM.getTopMacroCallerLoc(loc);
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   if (loc.isMacroID())
2360b57cec5SDimitry Andric     if (!isAtStartOfMacroExpansion(loc, &loc))
2370b57cec5SDimitry Andric       return false;
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   if (SM.isInSystemHeader(loc))
2400b57cec5SDimitry Andric     return false;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
2430b57cec5SDimitry Andric   if (locInfo.first.isInvalid())
2440b57cec5SDimitry Andric     return false;
2450b57cec5SDimitry Andric   offs = FileOffset(locInfo.first, locInfo.second);
2460b57cec5SDimitry Andric   return canInsertInOffset(loc, offs);
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
canInsertAfterToken(SourceLocation loc,FileOffset & offs,SourceLocation & AfterLoc)2490b57cec5SDimitry Andric bool Commit::canInsertAfterToken(SourceLocation loc, FileOffset &offs,
2500b57cec5SDimitry Andric                                  SourceLocation &AfterLoc) {
2510b57cec5SDimitry Andric   if (loc.isInvalid())
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric     return false;
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   SourceLocation spellLoc = SourceMgr.getSpellingLoc(loc);
2560b57cec5SDimitry Andric   unsigned tokLen = Lexer::MeasureTokenLength(spellLoc, SourceMgr, LangOpts);
2570b57cec5SDimitry Andric   AfterLoc = loc.getLocWithOffset(tokLen);
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   if (loc.isMacroID())
2600b57cec5SDimitry Andric     isAtEndOfMacroExpansion(loc, &loc);
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   const SourceManager &SM = SourceMgr;
2630b57cec5SDimitry Andric   loc = SM.getTopMacroCallerLoc(loc);
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   if (loc.isMacroID())
2660b57cec5SDimitry Andric     if (!isAtEndOfMacroExpansion(loc, &loc))
2670b57cec5SDimitry Andric       return false;
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   if (SM.isInSystemHeader(loc))
2700b57cec5SDimitry Andric     return false;
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   loc = Lexer::getLocForEndOfToken(loc, 0, SourceMgr, LangOpts);
2730b57cec5SDimitry Andric   if (loc.isInvalid())
2740b57cec5SDimitry Andric     return false;
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
2770b57cec5SDimitry Andric   if (locInfo.first.isInvalid())
2780b57cec5SDimitry Andric     return false;
2790b57cec5SDimitry Andric   offs = FileOffset(locInfo.first, locInfo.second);
2800b57cec5SDimitry Andric   return canInsertInOffset(loc, offs);
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric 
canInsertInOffset(SourceLocation OrigLoc,FileOffset Offs)2830b57cec5SDimitry Andric bool Commit::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {
2840b57cec5SDimitry Andric   for (const auto &act : CachedEdits)
2850b57cec5SDimitry Andric     if (act.Kind == Act_Remove) {
2860b57cec5SDimitry Andric       if (act.Offset.getFID() == Offs.getFID() &&
2870b57cec5SDimitry Andric           Offs > act.Offset && Offs < act.Offset.getWithOffset(act.Length))
2880b57cec5SDimitry Andric         return false; // position has been removed.
2890b57cec5SDimitry Andric     }
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   if (!Editor)
2920b57cec5SDimitry Andric     return true;
2930b57cec5SDimitry Andric   return Editor->canInsertInOffset(OrigLoc, Offs);
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
canRemoveRange(CharSourceRange range,FileOffset & Offs,unsigned & Len)2960b57cec5SDimitry Andric bool Commit::canRemoveRange(CharSourceRange range,
2970b57cec5SDimitry Andric                             FileOffset &Offs, unsigned &Len) {
2980b57cec5SDimitry Andric   const SourceManager &SM = SourceMgr;
2990b57cec5SDimitry Andric   range = Lexer::makeFileCharRange(range, SM, LangOpts);
3000b57cec5SDimitry Andric   if (range.isInvalid())
3010b57cec5SDimitry Andric     return false;
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric   if (range.getBegin().isMacroID() || range.getEnd().isMacroID())
3040b57cec5SDimitry Andric     return false;
3050b57cec5SDimitry Andric   if (SM.isInSystemHeader(range.getBegin()) ||
3060b57cec5SDimitry Andric       SM.isInSystemHeader(range.getEnd()))
3070b57cec5SDimitry Andric     return false;
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   if (PPRec && PPRec->rangeIntersectsConditionalDirective(range.getAsRange()))
3100b57cec5SDimitry Andric     return false;
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(range.getBegin());
3130b57cec5SDimitry Andric   std::pair<FileID, unsigned> endInfo = SM.getDecomposedLoc(range.getEnd());
3140b57cec5SDimitry Andric   if (beginInfo.first != endInfo.first ||
3150b57cec5SDimitry Andric       beginInfo.second > endInfo.second)
3160b57cec5SDimitry Andric     return false;
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   Offs = FileOffset(beginInfo.first, beginInfo.second);
3190b57cec5SDimitry Andric   Len = endInfo.second - beginInfo.second;
3200b57cec5SDimitry Andric   return true;
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
canReplaceText(SourceLocation loc,StringRef text,FileOffset & Offs,unsigned & Len)3230b57cec5SDimitry Andric bool Commit::canReplaceText(SourceLocation loc, StringRef text,
3240b57cec5SDimitry Andric                             FileOffset &Offs, unsigned &Len) {
3250b57cec5SDimitry Andric   assert(!text.empty());
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   if (!canInsert(loc, Offs))
3280b57cec5SDimitry Andric     return false;
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   // Try to load the file buffer.
3310b57cec5SDimitry Andric   bool invalidTemp = false;
3320b57cec5SDimitry Andric   StringRef file = SourceMgr.getBufferData(Offs.getFID(), &invalidTemp);
3330b57cec5SDimitry Andric   if (invalidTemp)
3340b57cec5SDimitry Andric     return false;
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   Len = text.size();
337*5f757f3fSDimitry Andric   return file.substr(Offs.getOffset()).starts_with(text);
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric 
isAtStartOfMacroExpansion(SourceLocation loc,SourceLocation * MacroBegin) const3400b57cec5SDimitry Andric bool Commit::isAtStartOfMacroExpansion(SourceLocation loc,
3410b57cec5SDimitry Andric                                        SourceLocation *MacroBegin) const {
3420b57cec5SDimitry Andric   return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts, MacroBegin);
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric 
isAtEndOfMacroExpansion(SourceLocation loc,SourceLocation * MacroEnd) const3450b57cec5SDimitry Andric bool Commit::isAtEndOfMacroExpansion(SourceLocation loc,
3460b57cec5SDimitry Andric                                      SourceLocation *MacroEnd) const {
3470b57cec5SDimitry Andric   return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd);
3480b57cec5SDimitry Andric }
349