diff options
author | Ben Langmuir <blangmuir@apple.com> | 2023-05-04 09:12:52 -0700 |
---|---|---|
committer | Ben Langmuir <blangmuir@apple.com> | 2023-05-09 10:05:12 -0700 |
commit | ee8ed0b3099e63ba0a18cca42b9cfdf098bc6201 (patch) | |
tree | 1623cca40ed615f081bb1a0cfe93a503ccc3d0cb /clang/unittests | |
parent | ec77d1f3d9fcf7105b6bda25fb4d0e5ed5afd0c5 (diff) | |
download | llvm-ee8ed0b3099e63ba0a18cca42b9cfdf098bc6201.tar.gz |
[clang][deps] Teach dep directive scanner about _Pragma
While we cannot handle `_Pragma` used inside macros, we can handle
this at the top level, and it some projects use the `_Pragma("once")`
spelling like that, which was causing spurious failures in the scanner.
Limitations
* Cannot handle #define ONCE _Pragma("once"), same issue as using
@import in a macro -- ideally we should diagnose this in obvious cases
* Our LangOpts are currently fixed, so we are not handling u"" strings
or R"()" strings that require C11/C++11.
rdar://108629982
Differential Revision: https://reviews.llvm.org/D149884
Diffstat (limited to 'clang/unittests')
-rw-r--r-- | clang/unittests/Lex/DependencyDirectivesScannerTest.cpp | 98 |
1 files changed, 95 insertions, 3 deletions
diff --git a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp index 2f8804784a2e..bc4eee73c1c2 100644 --- a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp +++ b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp @@ -503,6 +503,92 @@ TEST(MinimizeSourceToDependencyDirectivesTest, Pragma) { EXPECT_STREQ("#pragma clang module import\n", Out.data()); } +TEST(MinimizeSourceToDependencyDirectivesTest, UnderscorePragma) { + SmallVector<char, 128> Out; + + ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_)", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma)", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma()", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma())", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma(")", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma("A"))", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"x(_Pragma("push_macro(\"MACRO\")"))x", Out)); + EXPECT_STREQ(R"x(_Pragma("push_macro(\"MACRO\")"))x" + "\n", + Out.data()); + + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"x(_Pragma("pop_macro(\"MACRO\")"))x", Out)); + EXPECT_STREQ(R"x(_Pragma("pop_macro(\"MACRO\")"))x" + "\n", + Out.data()); + + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"x(_Pragma("include_alias(\"A\", \"B\")"))x", Out)); + EXPECT_STREQ(R"x(_Pragma("include_alias(\"A\", \"B\")"))x" + "\n", + Out.data()); + + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"x(_Pragma("include_alias(<A>, <B>)"))x", Out)); + EXPECT_STREQ(R"x(_Pragma("include_alias(<A>, <B>)"))x" + "\n", + Out.data()); + + ASSERT_FALSE( + minimizeSourceToDependencyDirectives(R"(_Pragma("clang"))", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + + ASSERT_FALSE( + minimizeSourceToDependencyDirectives(R"(_Pragma("clang module"))", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"(_Pragma("clang module impor"))", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"(_Pragma("clang module import"))", Out)); + EXPECT_STREQ(R"(_Pragma("clang module import"))" + "\n", + Out.data()); + + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"(_Pragma("clang \ + module \ + import"))", + Out)); + EXPECT_STREQ(R"(_Pragma("clang \ + module \ + import"))" + "\n", + Out.data()); + + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"(_Pragma(L"clang module import"))", Out)); + EXPECT_STREQ(R"(_Pragma(L"clang module import"))" + "\n", + Out.data()); + + // FIXME: u"" strings depend on using C11 language mode + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"(_Pragma(u"clang module import"))", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); + + // FIXME: R"()" strings depend on using C++ 11 language mode + ASSERT_FALSE(minimizeSourceToDependencyDirectives( + R"(_Pragma(R"abc(clang module import)abc"))", Out)); + EXPECT_STREQ("<TokBeforeEOF>\n", Out.data()); +} + TEST(MinimizeSourceToDependencyDirectivesTest, Include) { SmallVector<char, 128> Out; @@ -757,20 +843,26 @@ TEST(MinimizeSourceToDependencyDirectivesTest, PragmaOnce) { #pragma once // another comment #include <test.h> +_Pragma("once") )"; ASSERT_FALSE( minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives)); - EXPECT_STREQ("#pragma once\n#include <test.h>\n", Out.data()); - ASSERT_EQ(Directives.size(), 3u); + EXPECT_STREQ("#pragma once\n#include <test.h>\n_Pragma(\"once\")\n", + Out.data()); + ASSERT_EQ(Directives.size(), 4u); EXPECT_EQ(Directives[0].Kind, dependency_directives_scan::pp_pragma_once); + EXPECT_EQ(Directives[2].Kind, dependency_directives_scan::pp_pragma_once); Source = R"(// comment #pragma once extra tokens // another comment #include <test.h> + _Pragma("once") extra tokens )"; ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); - EXPECT_STREQ("#pragma once extra tokens\n#include <test.h>\n", Out.data()); + EXPECT_STREQ("#pragma once extra tokens\n#include " + "<test.h>\n_Pragma(\"once\")<TokBeforeEOF>\n", + Out.data()); } TEST(MinimizeSourceToDependencyDirectivesTest, |