[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