llunak updated this revision to Diff 207220.
llunak added a comment.
Updated patch, removed ()'s around 1/0, fixed to use CommentOutDirective().
Repository:
rC Clang
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D63508/new/
https://reviews.llvm.org/D63508
Files:
clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
clang/test/Frontend/rewrite-includes-conditions.c
clang/test/Frontend/rewrite-includes.c
clang/test/Modules/preprocess-module.cpp
Index: clang/test/Modules/preprocess-module.cpp
===================================================================
--- clang/test/Modules/preprocess-module.cpp
+++ clang/test/Modules/preprocess-module.cpp
@@ -51,7 +51,7 @@
// RUN: %clang_cc1 -fmodules -fmodule-file=%t/file.rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DFILE_REWRITE -DINCLUDE -I%S/Inputs/preprocess
//
// Check that we can preprocess this user of the .pcm file.
-// RUN: %clang_cc1 -fmodules -fmodule-file=%t/file.pcm %s -I%t -E -frewrite-imports -o %t/preprocess-module.ii
+// RUN: %clang_cc1 -fmodules -fmodule-file=%t/file.pcm %s -I%t -E -frewrite-imports -DFILE_REWRITE_FULL -o %t/preprocess-module.ii
// RUN: %clang_cc1 -fmodules %t/preprocess-module.ii -verify -fno-modules-error-recovery -DFILE_REWRITE_FULL
//
// Check that language / header search options are ignored when preprocessing from a .pcm file.
Index: clang/test/Frontend/rewrite-includes.c
===================================================================
--- clang/test/Frontend/rewrite-includes.c
+++ clang/test/Frontend/rewrite-includes.c
@@ -110,12 +110,23 @@
// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
// CHECK-NEXT: {{^}}# 22 "{{.*}}rewrite-includes.c"{{$}}
// CHECK-NEXT: {{^}}# 1 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes8.h" 1{{$}}
-// CHECK-NEXT: {{^}}#if (0)/*__has_include_next(<rewrite-includes8.h>)*/{{$}}
-// CHECK-NEXT: {{^}}#elif (0)/*__has_include(<rewrite-includes8.hfail>)*/{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#/*if*/ __has_include_next(<rewrite-includes8.h>){{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* evaluated by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 2 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes8.h"{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#/*elif*/ __has_include(<rewrite-includes8.hfail>){{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#elif 0 /* evaluated by -frewrite-includes */{{$}}
// CHECK-NEXT: {{^}}# 3 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes8.h"{{$}}
// CHECK-NEXT: {{^}}#endif{{$}}
// CHECK-NEXT: {{^}}# 4 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes8.h"{{$}}
-// CHECK-NEXT: {{^}}#if !(1)/*__has_include("rewrite-includes8.h")*/{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#/*if*/ !__has_include("rewrite-includes8.h"){{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* evaluated by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 5 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes8.h"{{$}}
// CHECK-NEXT: {{^}}#endif{{$}}
// CHECK-NEXT: {{^}}# 6 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes8.h"{{$}}
// CHECK-NEXT: {{^}}# 23 "{{.*}}rewrite-includes.c" 2{{$}}
@@ -124,7 +135,11 @@
// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
// CHECK-NEXT: {{^}}# 23 "{{.*}}rewrite-includes.c"{{$}}
// CHECK-NEXT: {{^}}# 1 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes9.h" 1{{$}}
-// CHECK-NEXT: {{^}}#if (1)/*__has_include_next(<rewrite-includes9.h>)*/{{$}}
+// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#/*if*/ __has_include_next(<rewrite-includes9.h>){{$}}
+// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}#if 1 /* evaluated by -frewrite-includes */{{$}}
+// CHECK-NEXT: {{^}}# 2 "{{.*[/\\]Inputs(/|\\\\)}}rewrite-includes9.h"{{$}}
// CHECK-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
// CHECK-NEXT: {{^}}#include_next <rewrite-includes9.h>{{$}}
// CHECK-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
@@ -193,15 +208,27 @@
// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
// CHECKNL-NEXT: {{^}}#include "rewrite-includes8.h"{{$}}
// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
-// CHECKNL-NEXT: {{^}}#if (0)/*__has_include_next(<rewrite-includes8.h>)*/{{$}}
-// CHECKNL-NEXT: {{^}}#elif (0)/*__has_include(<rewrite-includes8.hfail>)*/{{$}}
+// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#/*if*/ __has_include_next(<rewrite-includes8.h>){{$}}
+// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#if 0 /* evaluated by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#/*elif*/ __has_include(<rewrite-includes8.hfail>){{$}}
+// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#elif 0 /* evaluated by -frewrite-includes */{{$}}
// CHECKNL-NEXT: {{^}}#endif{{$}}
-// CHECKNL-NEXT: {{^}}#if !(1)/*__has_include("rewrite-includes8.h")*/{{$}}
+// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#/*if*/ !__has_include("rewrite-includes8.h"){{$}}
+// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#if 0 /* evaluated by -frewrite-includes */{{$}}
// CHECKNL-NEXT: {{^}}#endif{{$}}
// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
// CHECKNL-NEXT: {{^}}#include "rewrite-includes9.h"{{$}}
// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
-// CHECKNL-NEXT: {{^}}#if (1)/*__has_include_next(<rewrite-includes9.h>)*/{{$}}
+// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#/*if*/ __has_include_next(<rewrite-includes9.h>){{$}}
+// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
+// CHECKNL-NEXT: {{^}}#if 1 /* evaluated by -frewrite-includes */{{$}}
// CHECKNL-NEXT: {{^}}#if 0 /* expanded by -frewrite-includes */{{$}}
// CHECKNL-NEXT: {{^}}#include_next <rewrite-includes9.h>{{$}}
// CHECKNL-NEXT: {{^}}#endif /* expanded by -frewrite-includes */{{$}}
Index: clang/test/Frontend/rewrite-includes-conditions.c
===================================================================
--- /dev/null
+++ clang/test/Frontend/rewrite-includes-conditions.c
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -verify -E -frewrite-includes -I %S/Inputs %s -o - | FileCheck -strict-whitespace %s
+// expected-no-diagnostics
+
+#define value1 1
+#if value1
+line1
+#else
+line2
+#endif
+
+#define value2 2
+
+#if value1 == value2
+line3
+#elif value1 > value2
+line4
+#elif value2 < value2
+line5
+#else
+line6
+#endif
+
+#if __has_include(<rewrite-includes1.h>)
+#endif
+
+#define HAS_INCLUDE(x) __has_include(x)
+
+#if HAS_INCLUDE(<rewrite-includes1.h>)
+#endif
+
+/*
+#if value1
+commented out
+*/
+
+#if value1 < value2 \
+|| value1 != value2
+line7
+#endif
+
+#if value1 /*
+*/
+#endif
+
+// ENDCOMPARE
+
+// CHECK: #if 0 /* expanded by -frewrite-includes */
+// CHECK-NEXT: #/*if*/ value1
+// CHECK-NEXT: #endif /* expanded by -frewrite-includes */
+// CHECK-NEXT: #if 1 /* evaluated by -frewrite-includes */
+// CHECK-NEXT: # 6 "{{.*}}rewrite-includes-conditions.c"
+
+// CHECK: #if 0 /* expanded by -frewrite-includes */
+// CHECK-NEXT: #/*if*/ value1 == value2
+// CHECK-NEXT: #endif /* expanded by -frewrite-includes */
+// CHECK-NEXT: #if 0 /* evaluated by -frewrite-includes */
+// CHECK-NEXT: # 14 "{{.*}}rewrite-includes-conditions.c"
+
+// CHECK: #if 0 /* expanded by -frewrite-includes */
+// CHECK-NEXT: #/*elif*/ value1 > value2
+// CHECK-NEXT: #endif /* expanded by -frewrite-includes */
+// CHECK-NEXT: #elif 0 /* evaluated by -frewrite-includes */
+// CHECK-NEXT: # 16 "{{.*}}rewrite-includes-conditions.c"
+
+// CHECK: #if 0 /* expanded by -frewrite-includes */
+// CHECK-NEXT: #/*elif*/ value2 < value2
+// CHECK-NEXT: #endif /* expanded by -frewrite-includes */
+// CHECK-NEXT: #elif 0 /* evaluated by -frewrite-includes */
+// CHECK-NEXT: # 18 "{{.*}}rewrite-includes-conditions.c"
+
+// CHECK: #if 0 /* expanded by -frewrite-includes */
+// CHECK-NEXT: #/*if*/ __has_include(<rewrite-includes1.h>)
+// CHECK-NEXT: #endif /* expanded by -frewrite-includes */
+// CHECK-NEXT: #if 1 /* evaluated by -frewrite-includes */
+// CHECK-NEXT: # 24 "{{.*}}rewrite-includes-conditions.c"
+
+// CHECK: #if 0 /* expanded by -frewrite-includes */
+// CHECK-NEXT: #/*if*/ HAS_INCLUDE(<rewrite-includes1.h>)
+// CHECK-NEXT: #endif /* expanded by -frewrite-includes */
+// CHECK-NEXT: #if 1 /* evaluated by -frewrite-includes */
+// CHECK-NEXT: # 29 "{{.*}}rewrite-includes-conditions.c"
+
+// CHECK: #if 0 /* expanded by -frewrite-includes */
+// CHECK-NEXT: #/*if*/ value1 < value2 \
+// CHECK-NEXT: || value1 != value2
+// CHECK-NEXT: #endif /* expanded by -frewrite-includes */
+// CHECK-NEXT: #if 1 /* evaluated by -frewrite-includes */
+// CHECK-NEXT: # 38 "{{.*}}rewrite-includes-conditions.c"
+
+// CHECK: #if 0 /* expanded by -frewrite-includes */
+// CHECK-NEXT: #/*if*/ value1 /*
+// CHECK-NEXT: */
+// CHECK-NEXT: #endif /* expanded by -frewrite-includes */
+// CHECK-NEXT: #if 1 /* evaluated by -frewrite-includes */
+// CHECK-NEXT: # 43 "{{.*}}rewrite-includes-conditions.c"
+
+// CHECK: {{^}}// ENDCOMPARE{{$}}
Index: clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -49,6 +49,8 @@
std::map<unsigned, const Module *> ModuleIncludes;
/// Tracks where inclusions that enter modules (in a module build) are found.
std::map<unsigned, const Module *> ModuleEntryIncludes;
+ /// Tracks where #if and #elif directives get evaluated and whether to true.
+ std::map<unsigned, bool> IfConditions;
/// Used transitively for building up the FileIncludes mapping over the
/// various \c PPCallbacks callbacks.
SourceLocation LastInclusionLocation;
@@ -78,6 +80,10 @@
StringRef SearchPath, StringRef RelativePath,
const Module *Imported,
SrcMgr::CharacteristicKind FileType) override;
+ void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) override;
+ void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) override;
void WriteLineInfo(StringRef Filename, int Line,
SrcMgr::CharacteristicKind FileType,
StringRef Extra = StringRef());
@@ -88,13 +94,12 @@
bool EnsureNewline);
void CommentOutDirective(Lexer &DirectivesLex, const Token &StartToken,
const MemoryBuffer &FromFile, StringRef EOL,
- unsigned &NextToWrite, int &Lines);
- bool HandleHasInclude(FileID FileId, Lexer &RawLex,
- const DirectoryLookup *Lookup, Token &Tok,
- bool &FileExists);
+ unsigned &NextToWrite, int &Lines,
+ const Token *explicitCommentOutToken = nullptr);
const IncludedFile *FindIncludeAtLocation(SourceLocation Loc) const;
const Module *FindModuleAtLocation(SourceLocation Loc) const;
const Module *FindEnteredModule(SourceLocation Loc) const;
+ bool IsIfAtLocationTrue(SourceLocation Loc) const;
StringRef NextIdentifierName(Lexer &RawLex, Token &RawToken);
};
@@ -203,6 +208,23 @@
LastInclusionLocation = HashLoc;
}
+void InclusionRewriter::If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) {
+ auto P = IfConditions.insert(
+ std::make_pair(Loc.getRawEncoding(), ConditionValue == CVK_True));
+ (void)P;
+ assert(P.second && "Unexpected revisitation of the same if directive");
+}
+
+void InclusionRewriter::Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue,
+ SourceLocation IfLoc) {
+ auto P = IfConditions.insert(
+ std::make_pair(Loc.getRawEncoding(), ConditionValue == CVK_True));
+ (void)P;
+ assert(P.second && "Unexpected revisitation of the same elif directive");
+}
+
/// Simple lookup for a SourceLocation (specifically one denoting the hash in
/// an inclusion directive) in the map of inclusion information, FileChanges.
const InclusionRewriter::IncludedFile *
@@ -233,6 +255,13 @@
return nullptr;
}
+bool InclusionRewriter::IsIfAtLocationTrue(SourceLocation Loc) const {
+ const auto I = IfConditions.find(Loc.getRawEncoding());
+ if (I != IfConditions.end())
+ return I->second;
+ return false;
+}
+
/// Detect the likely line ending style of \p FromFile by examining the first
/// newline found within it.
static StringRef DetectEOL(const MemoryBuffer &FromFile) {
@@ -311,11 +340,10 @@
/// inclusion directive disabled by a #if directive, updating \p NextToWrite
/// and \p Line to track the number of source lines visited and the progress
/// through the \p FromFile buffer.
-void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex,
- const Token &StartToken,
- const MemoryBuffer &FromFile,
- StringRef LocalEOL,
- unsigned &NextToWrite, int &Line) {
+void InclusionRewriter::CommentOutDirective(
+ Lexer &DirectiveLex, const Token &StartToken, const MemoryBuffer &FromFile,
+ StringRef LocalEOL, unsigned &NextToWrite, int &Line,
+ const Token *explicitCommentOutToken) {
OutputContentUpTo(FromFile, NextToWrite,
SM.getFileOffset(StartToken.getLocation()), LocalEOL, Line,
false);
@@ -328,6 +356,19 @@
return;
}
OS << "#if 0 /* expanded by -frewrite-includes */" << MainEOL;
+ // Directives such as #if need to be explicitly commented out, putting them
+ // inside #if 0 is insufficient as it would break the nesting.
+ if (explicitCommentOutToken) {
+ OutputContentUpTo(FromFile, NextToWrite,
+ SM.getFileOffset(explicitCommentOutToken->getLocation()),
+ LocalEOL, Line, false);
+ OS << "/*";
+ OutputContentUpTo(FromFile, NextToWrite,
+ SM.getFileOffset(explicitCommentOutToken->getLocation()) +
+ explicitCommentOutToken->getLength(),
+ LocalEOL, Line, false);
+ OS << "*/";
+ }
OutputContentUpTo(FromFile, NextToWrite,
SM.getFileOffset(DirectiveToken.getLocation()) +
DirectiveToken.getLength(),
@@ -346,80 +387,6 @@
return StringRef();
}
-// Expand __has_include and __has_include_next if possible. If there's no
-// definitive answer return false.
-bool InclusionRewriter::HandleHasInclude(
- FileID FileId, Lexer &RawLex, const DirectoryLookup *Lookup, Token &Tok,
- bool &FileExists) {
- // Lex the opening paren.
- RawLex.LexFromRawLexer(Tok);
- if (Tok.isNot(tok::l_paren))
- return false;
-
- RawLex.LexFromRawLexer(Tok);
-
- SmallString<128> FilenameBuffer;
- StringRef Filename;
- // Since the raw lexer doesn't give us angle_literals we have to parse them
- // ourselves.
- // FIXME: What to do if the file name is a macro?
- if (Tok.is(tok::less)) {
- RawLex.LexFromRawLexer(Tok);
-
- FilenameBuffer += '<';
- do {
- if (Tok.is(tok::eod)) // Sanity check.
- return false;
-
- if (Tok.is(tok::raw_identifier))
- PP.LookUpIdentifierInfo(Tok);
-
- // Get the string piece.
- SmallVector<char, 128> TmpBuffer;
- bool Invalid = false;
- StringRef TmpName = PP.getSpelling(Tok, TmpBuffer, &Invalid);
- if (Invalid)
- return false;
-
- FilenameBuffer += TmpName;
-
- RawLex.LexFromRawLexer(Tok);
- } while (Tok.isNot(tok::greater));
-
- FilenameBuffer += '>';
- Filename = FilenameBuffer;
- } else {
- if (Tok.isNot(tok::string_literal))
- return false;
-
- bool Invalid = false;
- Filename = PP.getSpelling(Tok, FilenameBuffer, &Invalid);
- if (Invalid)
- return false;
- }
-
- // Lex the closing paren.
- RawLex.LexFromRawLexer(Tok);
- if (Tok.isNot(tok::r_paren))
- return false;
-
- // Now ask HeaderInfo if it knows about the header.
- // FIXME: Subframeworks aren't handled here. Do we care?
- bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
- const DirectoryLookup *CurDir;
- const FileEntry *FileEnt = PP.getSourceManager().getFileEntryForID(FileId);
- SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 1>
- Includers;
- Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
- // FIXME: Why don't we call PP.LookupFile here?
- const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
- Filename, SourceLocation(), isAngled, Lookup, CurDir, Includers, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr);
-
- FileExists = File != nullptr;
- return true;
-}
-
/// Use a raw lexer to analyze \p FileId, incrementally copying parts of it
/// and including content of included files recursively.
void InclusionRewriter::Process(FileID FileId,
@@ -519,53 +486,12 @@
case tok::pp_elif: {
bool elif = (RawToken.getIdentifierInfo()->getPPKeywordID() ==
tok::pp_elif);
- // Rewrite special builtin macros to avoid pulling in host details.
- do {
- // Walk over the directive.
- RawLex.LexFromRawLexer(RawToken);
- if (RawToken.is(tok::raw_identifier))
- PP.LookUpIdentifierInfo(RawToken);
-
- if (RawToken.is(tok::identifier)) {
- bool HasFile;
- SourceLocation Loc = RawToken.getLocation();
-
- // Rewrite __has_include(x)
- if (RawToken.getIdentifierInfo()->isStr("__has_include")) {
- if (!HandleHasInclude(FileId, RawLex, nullptr, RawToken,
- HasFile))
- continue;
- // Rewrite __has_include_next(x)
- } else if (RawToken.getIdentifierInfo()->isStr(
- "__has_include_next")) {
- if (DirLookup)
- ++DirLookup;
-
- if (!HandleHasInclude(FileId, RawLex, DirLookup, RawToken,
- HasFile))
- continue;
- } else {
- continue;
- }
- // Replace the macro with (0) or (1), followed by the commented
- // out macro for reference.
- OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(Loc),
- LocalEOL, Line, false);
- OS << '(' << (int) HasFile << ")/*";
- OutputContentUpTo(FromFile, NextToWrite,
- SM.getFileOffset(RawToken.getLocation()) +
- RawToken.getLength(),
- LocalEOL, Line, false);
- OS << "*/";
- }
- } while (RawToken.isNot(tok::eod));
- if (elif) {
- OutputContentUpTo(FromFile, NextToWrite,
- SM.getFileOffset(RawToken.getLocation()) +
- RawToken.getLength(),
- LocalEOL, Line, /*EnsureNewline=*/ true);
- WriteLineInfo(FileName, Line, FileType);
- }
+ bool isTrue = IsIfAtLocationTrue(RawToken.getLocation());
+ CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
+ NextToWrite, Line, &RawToken);
+ OS << (elif ? "#elif " : "#if ") << (isTrue ? "1" : "0")
+ << " /* evaluated by -frewrite-includes */" << MainEOL;
+ WriteLineInfo(FileName, Line, FileType);
break;
}
case tok::pp_endif:
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits