@@ -49,6 +49,8 @@ class InclusionRewriter : public PPCallbacks {
4949 std::map<unsigned , const Module *> ModuleIncludes;
5050 // / Tracks where inclusions that enter modules (in a module build) are found.
5151 std::map<unsigned , const Module *> ModuleEntryIncludes;
52+ // / Tracks where #if and #elif directives get evaluated and whether to true.
53+ std::map<unsigned , bool > IfConditions;
5254 // / Used transitively for building up the FileIncludes mapping over the
5355 // / various \c PPCallbacks callbacks.
5456 SourceLocation LastInclusionLocation;
@@ -78,6 +80,10 @@ class InclusionRewriter : public PPCallbacks {
7880 StringRef SearchPath, StringRef RelativePath,
7981 const Module *Imported,
8082 SrcMgr::CharacteristicKind FileType) override ;
83+ void If (SourceLocation Loc, SourceRange ConditionRange,
84+ ConditionValueKind ConditionValue) override ;
85+ void Elif (SourceLocation Loc, SourceRange ConditionRange,
86+ ConditionValueKind ConditionValue, SourceLocation IfLoc) override ;
8187 void WriteLineInfo (StringRef Filename, int Line,
8288 SrcMgr::CharacteristicKind FileType,
8389 StringRef Extra = StringRef());
@@ -89,12 +95,10 @@ class InclusionRewriter : public PPCallbacks {
8995 void CommentOutDirective (Lexer &DirectivesLex, const Token &StartToken,
9096 const MemoryBuffer &FromFile, StringRef EOL,
9197 unsigned &NextToWrite, int &Lines);
92- bool HandleHasInclude (FileID FileId, Lexer &RawLex,
93- const DirectoryLookup *Lookup, Token &Tok,
94- bool &FileExists);
9598 const IncludedFile *FindIncludeAtLocation (SourceLocation Loc) const ;
9699 const Module *FindModuleAtLocation (SourceLocation Loc) const ;
97100 const Module *FindEnteredModule (SourceLocation Loc) const ;
101+ bool IsIfAtLocationTrue (SourceLocation Loc) const ;
98102 StringRef NextIdentifierName (Lexer &RawLex, Token &RawToken);
99103};
100104
@@ -203,6 +207,23 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc,
203207 LastInclusionLocation = HashLoc;
204208}
205209
210+ void InclusionRewriter::If (SourceLocation Loc, SourceRange ConditionRange,
211+ ConditionValueKind ConditionValue) {
212+ auto P = IfConditions.insert (
213+ std::make_pair (Loc.getRawEncoding (), ConditionValue == CVK_True));
214+ (void )P;
215+ assert (P.second && " Unexpected revisitation of the same if directive" );
216+ }
217+
218+ void InclusionRewriter::Elif (SourceLocation Loc, SourceRange ConditionRange,
219+ ConditionValueKind ConditionValue,
220+ SourceLocation IfLoc) {
221+ auto P = IfConditions.insert (
222+ std::make_pair (Loc.getRawEncoding (), ConditionValue == CVK_True));
223+ (void )P;
224+ assert (P.second && " Unexpected revisitation of the same elif directive" );
225+ }
226+
206227// / Simple lookup for a SourceLocation (specifically one denoting the hash in
207228// / an inclusion directive) in the map of inclusion information, FileChanges.
208229const InclusionRewriter::IncludedFile *
@@ -233,6 +254,13 @@ InclusionRewriter::FindEnteredModule(SourceLocation Loc) const {
233254 return nullptr ;
234255}
235256
257+ bool InclusionRewriter::IsIfAtLocationTrue (SourceLocation Loc) const {
258+ const auto I = IfConditions.find (Loc.getRawEncoding ());
259+ if (I != IfConditions.end ())
260+ return I->second ;
261+ return false ;
262+ }
263+
236264// / Detect the likely line ending style of \p FromFile by examining the first
237265// / newline found within it.
238266static StringRef DetectEOL (const MemoryBuffer &FromFile) {
@@ -346,80 +374,6 @@ StringRef InclusionRewriter::NextIdentifierName(Lexer &RawLex,
346374 return StringRef ();
347375}
348376
349- // Expand __has_include and __has_include_next if possible. If there's no
350- // definitive answer return false.
351- bool InclusionRewriter::HandleHasInclude (
352- FileID FileId, Lexer &RawLex, const DirectoryLookup *Lookup, Token &Tok,
353- bool &FileExists) {
354- // Lex the opening paren.
355- RawLex.LexFromRawLexer (Tok);
356- if (Tok.isNot (tok::l_paren))
357- return false ;
358-
359- RawLex.LexFromRawLexer (Tok);
360-
361- SmallString<128 > FilenameBuffer;
362- StringRef Filename;
363- // Since the raw lexer doesn't give us angle_literals we have to parse them
364- // ourselves.
365- // FIXME: What to do if the file name is a macro?
366- if (Tok.is (tok::less)) {
367- RawLex.LexFromRawLexer (Tok);
368-
369- FilenameBuffer += ' <' ;
370- do {
371- if (Tok.is (tok::eod)) // Sanity check.
372- return false ;
373-
374- if (Tok.is (tok::raw_identifier))
375- PP.LookUpIdentifierInfo (Tok);
376-
377- // Get the string piece.
378- SmallVector<char , 128 > TmpBuffer;
379- bool Invalid = false ;
380- StringRef TmpName = PP.getSpelling (Tok, TmpBuffer, &Invalid);
381- if (Invalid)
382- return false ;
383-
384- FilenameBuffer += TmpName;
385-
386- RawLex.LexFromRawLexer (Tok);
387- } while (Tok.isNot (tok::greater));
388-
389- FilenameBuffer += ' >' ;
390- Filename = FilenameBuffer;
391- } else {
392- if (Tok.isNot (tok::string_literal))
393- return false ;
394-
395- bool Invalid = false ;
396- Filename = PP.getSpelling (Tok, FilenameBuffer, &Invalid);
397- if (Invalid)
398- return false ;
399- }
400-
401- // Lex the closing paren.
402- RawLex.LexFromRawLexer (Tok);
403- if (Tok.isNot (tok::r_paren))
404- return false ;
405-
406- // Now ask HeaderInfo if it knows about the header.
407- // FIXME: Subframeworks aren't handled here. Do we care?
408- bool isAngled = PP.GetIncludeFilenameSpelling (Tok.getLocation (), Filename);
409- const DirectoryLookup *CurDir;
410- const FileEntry *FileEnt = PP.getSourceManager ().getFileEntryForID (FileId);
411- SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 1 >
412- Includers;
413- Includers.push_back (std::make_pair (FileEnt, FileEnt->getDir ()));
414- // FIXME: Why don't we call PP.LookupFile here?
415- Optional<FileEntryRef> File = PP.getHeaderSearchInfo ().LookupFile (
416- Filename, SourceLocation (), isAngled, Lookup, CurDir, Includers, nullptr ,
417- nullptr , nullptr , nullptr , nullptr , nullptr );
418-
419- FileExists = File.hasValue ();
420- return true ;
421- }
422-
423377// / Use a raw lexer to analyze \p FileId, incrementally copying parts of it
424378// / and including content of included files recursively.
425379void InclusionRewriter::Process (FileID FileId,
@@ -519,53 +473,33 @@ void InclusionRewriter::Process(FileID FileId,
519473 case tok::pp_elif: {
520474 bool elif = (RawToken.getIdentifierInfo ()->getPPKeywordID () ==
521475 tok::pp_elif);
522- // Rewrite special builtin macros to avoid pulling in host details.
476+ bool isTrue = IsIfAtLocationTrue (RawToken.getLocation ());
477+ OutputContentUpTo (FromFile, NextToWrite,
478+ SM.getFileOffset (HashToken.getLocation ()),
479+ LocalEOL, Line, /* EnsureNewline=*/ true );
523480 do {
524- // Walk over the directive.
525481 RawLex.LexFromRawLexer (RawToken);
526- if (RawToken.is (tok::raw_identifier))
527- PP.LookUpIdentifierInfo (RawToken);
528-
529- if (RawToken.is (tok::identifier)) {
530- bool HasFile;
531- SourceLocation Loc = RawToken.getLocation ();
532-
533- // Rewrite __has_include(x)
534- if (RawToken.getIdentifierInfo ()->isStr (" __has_include" )) {
535- if (!HandleHasInclude (FileId, RawLex, nullptr , RawToken,
536- HasFile))
537- continue ;
538- // Rewrite __has_include_next(x)
539- } else if (RawToken.getIdentifierInfo ()->isStr (
540- " __has_include_next" )) {
541- if (DirLookup)
542- ++DirLookup;
543-
544- if (!HandleHasInclude (FileId, RawLex, DirLookup, RawToken,
545- HasFile))
546- continue ;
547- } else {
548- continue ;
549- }
550- // Replace the macro with (0) or (1), followed by the commented
551- // out macro for reference.
552- OutputContentUpTo (FromFile, NextToWrite, SM.getFileOffset (Loc),
553- LocalEOL, Line, false );
554- OS << ' (' << (int ) HasFile << " )/*" ;
555- OutputContentUpTo (FromFile, NextToWrite,
556- SM.getFileOffset (RawToken.getLocation ()) +
557- RawToken.getLength (),
558- LocalEOL, Line, false );
559- OS << " */" ;
560- }
561- } while (RawToken.isNot (tok::eod));
482+ } while (!RawToken.is (tok::eod) && RawToken.isNot (tok::eof));
483+ // We need to disable the old condition, but that is tricky.
484+ // Trying to comment it out can easily lead to comment nesting.
485+ // So instead make the condition harmless by making it enclose
486+ // and empty block. Moreover, put it itself inside an #if 0 block
487+ // to disable it from getting evaluated (e.g. __has_include_next
488+ // warns if used from the primary source file).
489+ OS << " #if 0 /* disabled by -frewrite-includes */" << MainEOL;
562490 if (elif) {
563- OutputContentUpTo (FromFile, NextToWrite,
564- SM.getFileOffset (RawToken.getLocation ()) +
565- RawToken.getLength (),
566- LocalEOL, Line, /* EnsureNewline=*/ true );
567- WriteLineInfo (FileName, Line, FileType);
491+ OS << " #if 0" << MainEOL;
568492 }
493+ OutputContentUpTo (FromFile, NextToWrite,
494+ SM.getFileOffset (RawToken.getLocation ()) +
495+ RawToken.getLength (),
496+ LocalEOL, Line, /* EnsureNewline=*/ true );
497+ // Close the empty block and the disabling block.
498+ OS << " #endif" << MainEOL;
499+ OS << " #endif /* disabled by -frewrite-includes */" << MainEOL;
500+ OS << (elif ? " #elif " : " #if " ) << (isTrue ? " 1" : " 0" )
501+ << " /* evaluated by -frewrite-includes */" << MainEOL;
502+ WriteLineInfo (FileName, Line, FileType);
569503 break ;
570504 }
571505 case tok::pp_endif:
0 commit comments