[clang] a82a844 - [clang][deps] Keep #pragma push_macro, pop_macro and include_alias when minimizing source code.
Sylvain Audi via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 1 13:09:20 PDT 2021
Author: Sylvain Audi
Date: 2021-11-01T16:04:52-04:00
New Revision: a82a844961a55c8a5879453ce0e78774b33bf06a
URL: https://github.com/llvm/llvm-project/commit/a82a844961a55c8a5879453ce0e78774b33bf06a
DIFF: https://github.com/llvm/llvm-project/commit/a82a844961a55c8a5879453ce0e78774b33bf06a.diff
LOG: [clang][deps] Keep #pragma push_macro, pop_macro and include_alias when minimizing source code.
The #pragma directives push_macro/pop_macro and include_alias may influence the #include / import directives encountered by dependency scanning tools like clang-scan-deps.
This patch ensures that those directives are not removed during source code minimization.
Differential Revision: https://reviews.llvm.org/D112088
Added:
clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas.h
clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas_cdb.json
clang/test/ClangScanDeps/preprocess_minimized_pragmas.cpp
clang/test/Lexer/minimize_source_to_dependency_directives_pragmas.c
Modified:
clang/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Lex/DependencyDirectivesSourceMinimizer.h b/clang/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
index 9bb820156c252..121ca893e314f 100644
--- a/clang/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
+++ b/clang/include/clang/Lex/DependencyDirectivesSourceMinimizer.h
@@ -39,6 +39,9 @@ enum TokenKind {
pp_import,
pp_pragma_import,
pp_pragma_once,
+ pp_pragma_push_macro,
+ pp_pragma_pop_macro,
+ pp_pragma_include_alias,
pp_include_next,
pp_if,
pp_ifdef,
diff --git a/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp b/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
index f5cbd5e51b9b9..f597c56837fb4 100644
--- a/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
+++ b/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
@@ -734,6 +734,27 @@ bool Minimizer::lexPragma(const char *&First, const char *const End) {
append("#pragma once\n");
return false;
}
+ if (FoundId.Name == "push_macro") {
+ // #pragma push_macro
+ makeToken(pp_pragma_push_macro);
+ append("#pragma push_macro");
+ printDirectiveBody(First, End);
+ return false;
+ }
+ if (FoundId.Name == "pop_macro") {
+ // #pragma pop_macro
+ makeToken(pp_pragma_pop_macro);
+ append("#pragma pop_macro");
+ printDirectiveBody(First, End);
+ return false;
+ }
+ if (FoundId.Name == "include_alias") {
+ // #pragma include_alias
+ makeToken(pp_pragma_include_alias);
+ append("#pragma include_alias");
+ printDirectiveBody(First, End);
+ return false;
+ }
if (FoundId.Name != "clang") {
skipLine(First, End);
@@ -835,6 +856,10 @@ bool Minimizer::lexPPLine(const char *&First, const char *const End) {
// Figure out the token.
IdInfo Id = lexIdentifier(First, End);
First = Id.Last;
+
+ if (Id.Name == "pragma")
+ return lexPragma(First, End);
+
auto Kind = llvm::StringSwitch<TokenKind>(Id.Name)
.Case("include", pp_include)
.Case("__include_macros", pp___include_macros)
@@ -850,7 +875,6 @@ bool Minimizer::lexPPLine(const char *&First, const char *const End) {
.Case("elifndef", pp_elifndef)
.Case("else", pp_else)
.Case("endif", pp_endif)
- .Case("pragma", pp_pragma_import)
.Default(pp_none);
if (Kind == pp_none) {
skipDirective(Id.Name, First, End);
@@ -863,9 +887,6 @@ bool Minimizer::lexPPLine(const char *&First, const char *const End) {
if (Kind == pp_define)
return lexDefine(First, End);
- if (Kind == pp_pragma_import)
- return lexPragma(First, End);
-
// Everything else.
return lexDefault(Kind, Id.Name, First, End);
}
diff --git a/clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas.h b/clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas.h
new file mode 100644
index 0000000000000..f0d6b090991b3
--- /dev/null
+++ b/clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas.h
@@ -0,0 +1,27 @@
+// #pragma push_macro/pop_macro
+#define INCLUDE_A
+#pragma push_macro("INCLUDE_A")
+#undef INCLUDE_A
+#pragma pop_macro("INCLUDE_A")
+
+#ifdef INCLUDE_A
+#include "a.h"
+#endif
+
+// #pragma push_macro/pop_macro with argument macro expansion
+#define INCLUDE_B
+#define MACRO_NAME "INCLUDE_B"
+
+#pragma push_macro(MACRO_NAME)
+#undef INCLUDE_B
+#pragma pop_macro(MACRO_NAME)
+
+#ifdef INCLUDE_B
+#include "b.h"
+#endif
+
+// #pragma include_alias (MS specific)
+// When compiling without MS Extensions, the pragma is not recognized,
+// and the file c_alias.h is included instead of c.h
+#pragma include_alias("c_alias.h", "c.h")
+#include "c_alias.h"
diff --git a/clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas_cdb.json b/clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas_cdb.json
new file mode 100644
index 0000000000000..f642b94c1d9bc
--- /dev/null
+++ b/clang/test/ClangScanDeps/Inputs/preprocess_minimized_pragmas_cdb.json
@@ -0,0 +1,12 @@
+[
+{
+ "directory": "DIR",
+ "command": "clang -E DIR/preprocess_minimized_pragmas_basic.cpp -IInputs -target x86_64-linux",
+ "file": "DIR/preprocess_minimized_pragmas_basic.cpp"
+},
+{
+ "directory": "DIR",
+ "command": "clang -E DIR/preprocess_minimized_pragmas_ms.cpp -IInputs -target x86_64-windows",
+ "file": "DIR/preprocess_minimized_pragmas_ms.cpp"
+}
+]
diff --git a/clang/test/ClangScanDeps/preprocess_minimized_pragmas.cpp b/clang/test/ClangScanDeps/preprocess_minimized_pragmas.cpp
new file mode 100644
index 0000000000000..fa906f94df9ea
--- /dev/null
+++ b/clang/test/ClangScanDeps/preprocess_minimized_pragmas.cpp
@@ -0,0 +1,32 @@
+// RUN: rm -rf %t.dir
+// RUN: rm -rf %t.cdb
+// RUN: mkdir -p %t.dir
+// RUN: cp %s %t.dir/preprocess_minimized_pragmas_basic.cpp
+// RUN: cp %s %t.dir/preprocess_minimized_pragmas_ms.cpp
+// RUN: mkdir %t.dir/Inputs
+// RUN: cp %S/Inputs/preprocess_minimized_pragmas.h %t.dir/Inputs/preprocess_minimized_pragmas.h
+// RUN: touch %t.dir/Inputs/a.h
+// RUN: touch %t.dir/Inputs/b.h
+// RUN: touch %t.dir/Inputs/c.h
+// RUN: touch %t.dir/Inputs/c_alias.h
+// RUN: sed -e "s|DIR|%/t.dir|g" %S/Inputs/preprocess_minimized_pragmas_cdb.json > %t.cdb
+//
+// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess-minimized-sources | \
+// RUN: FileCheck %s
+// RUN: clang-scan-deps -compilation-database %t.cdb -j 1 -mode preprocess | \
+// RUN: FileCheck %s
+
+#include "preprocess_minimized_pragmas.h"
+
+// CHECK: preprocess_minimized_pragmas_basic.cpp
+// CHECK-NEXT: Inputs{{/|\\}}preprocess_minimized_pragmas.h
+// CHECK-NEXT: Inputs{{/|\\}}a.h
+// CHECK-NEXT: Inputs{{/|\\}}b.h
+// Expect include aliasing alias "c_alias.h" -> "c.h" to fail when Microsoft extensions are off.
+// CHECK-NEXT: Inputs{{/|\\}}c_alias.h
+
+// CHECK: preprocess_minimized_pragmas_ms.cpp
+// CHECK-NEXT: Inputs{{/|\\}}preprocess_minimized_pragmas.h
+// CHECK-NEXT: Inputs{{/|\\}}a.h
+// CHECK-NEXT: Inputs{{/|\\}}b.h
+// CHECK-NEXT: Inputs{{/|\\}}c.h
diff --git a/clang/test/Lexer/minimize_source_to_dependency_directives_pragmas.c b/clang/test/Lexer/minimize_source_to_dependency_directives_pragmas.c
new file mode 100644
index 0000000000000..98b1cc88e7c18
--- /dev/null
+++ b/clang/test/Lexer/minimize_source_to_dependency_directives_pragmas.c
@@ -0,0 +1,21 @@
+// Test that the required #pragma directives are minimized
+// RUN: %clang_cc1 -print-dependency-directives-minimized-source %s 2>&1 | FileCheck %s
+
+#pragma once
+
+// some pragmas not needed in minimized source.
+#pragma region TestRegion
+#pragma endregion
+#pragma warning "message"
+
+// pragmas required in the minimized source.
+#pragma push_macro( "MYMACRO" )
+#pragma pop_macro("MYMACRO")
+#pragma clang module import mymodule
+#pragma include_alias(<string>, "mystring.h")
+
+// CHECK: #pragma once
+// CHECK-NEXT: #pragma push_macro( "MYMACRO" )
+// CHECK-NEXT: #pragma pop_macro("MYMACRO")
+// CHECK-NEXT: #pragma clang module import mymodule
+// CHECK-NEXT: #pragma include_alias(<string>, "mystring.h")
diff --git a/clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp b/clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp
index 81945cf4618c1..d65c8de7f0e19 100644
--- a/clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp
+++ b/clang/unittests/Lex/DependencyDirectivesSourceMinimizerTest.cpp
@@ -63,6 +63,9 @@ TEST(MinimizeSourceToDependencyDirectivesTest, AllTokens) {
"#import <A>\n"
"@import A;\n"
"#pragma clang module import A\n"
+ "#pragma push_macro(A)\n"
+ "#pragma pop_macro(A)\n"
+ "#pragma include_alias(<A>, <B>)\n"
"export module m;\n"
"import m;\n",
Out, Tokens));
@@ -82,10 +85,13 @@ TEST(MinimizeSourceToDependencyDirectivesTest, AllTokens) {
EXPECT_EQ(pp_import, Tokens[13].K);
EXPECT_EQ(decl_at_import, Tokens[14].K);
EXPECT_EQ(pp_pragma_import, Tokens[15].K);
- EXPECT_EQ(cxx_export_decl, Tokens[16].K);
- EXPECT_EQ(cxx_module_decl, Tokens[17].K);
- EXPECT_EQ(cxx_import_decl, Tokens[18].K);
- EXPECT_EQ(pp_eof, Tokens[19].K);
+ EXPECT_EQ(pp_pragma_push_macro, Tokens[16].K);
+ EXPECT_EQ(pp_pragma_pop_macro, Tokens[17].K);
+ EXPECT_EQ(pp_pragma_include_alias, Tokens[18].K);
+ EXPECT_EQ(cxx_export_decl, Tokens[19].K);
+ EXPECT_EQ(cxx_module_decl, Tokens[20].K);
+ EXPECT_EQ(cxx_import_decl, Tokens[21].K);
+ EXPECT_EQ(pp_eof, Tokens[22].K);
}
TEST(MinimizeSourceToDependencyDirectivesTest, Define) {
@@ -406,6 +412,22 @@ TEST(MinimizeSourceToDependencyDirectivesTest, Pragma) {
ASSERT_FALSE(minimizeSourceToDependencyDirectives("#pragma A\n", Out));
EXPECT_STREQ("", Out.data());
+ ASSERT_FALSE(minimizeSourceToDependencyDirectives(
+ "#pragma push_macro(\"MACRO\")\n", Out));
+ EXPECT_STREQ("#pragma push_macro(\"MACRO\")\n", Out.data());
+
+ ASSERT_FALSE(minimizeSourceToDependencyDirectives(
+ "#pragma pop_macro(\"MACRO\")\n", Out));
+ EXPECT_STREQ("#pragma pop_macro(\"MACRO\")\n", Out.data());
+
+ ASSERT_FALSE(minimizeSourceToDependencyDirectives(
+ "#pragma include_alias(\"A\", \"B\")\n", Out));
+ EXPECT_STREQ("#pragma include_alias(\"A\", \"B\")\n", Out.data());
+
+ ASSERT_FALSE(minimizeSourceToDependencyDirectives(
+ "#pragma include_alias(<A>, <B>)\n", Out));
+ EXPECT_STREQ("#pragma include_alias(<A>, <B>)\n", Out.data());
+
ASSERT_FALSE(minimizeSourceToDependencyDirectives("#pragma clang\n", Out));
EXPECT_STREQ("", Out.data());
More information about the cfe-commits
mailing list