[llvm-branch-commits] [clang] afd20aa - [clang-scan-deps] Fix "unterminated conditional directive" bug (#146645)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Jul 6 19:11:05 PDT 2025


Author: Ziqing Luo
Date: 2025-07-04T12:53:23+08:00
New Revision: afd20aaca5fd89dd14992c3fe2f735c5e16ad986

URL: https://github.com/llvm/llvm-project/commit/afd20aaca5fd89dd14992c3fe2f735c5e16ad986
DIFF: https://github.com/llvm/llvm-project/commit/afd20aaca5fd89dd14992c3fe2f735c5e16ad986.diff

LOG: [clang-scan-deps] Fix "unterminated conditional directive" bug (#146645)

`clang-scan-deps` threw "unterminated conditional directive" error
falsely on the following example:

```
#ifndef __TEST
#define __TEST

#if defined(__TEST_DUMMY)
 #if defined(__TEST_DUMMY2)
  #pragma GCC warning                                                          \
      "Hello!"
 #else
  #pragma GCC error                                                            \
      "World!"
 #endif // defined(__TEST_DUMMY2)
#endif  // defined(__TEST_DUMMY)

#endif // #ifndef __TEST
```

The issue comes from PR #143950, where the flag `LastNonWhitespace` does
not correctly represent the state for the example above. The PR aimed to
support that a line-continuation can be followed by whitespaces.  
This commit fixes the issue by moving the `LastNonWhitespace` variable
to the inner loop so that it will be correctly reset.

rdar://153742186

Added: 
    

Modified: 
    clang/lib/Lex/DependencyDirectivesScanner.cpp
    clang/unittests/Lex/DependencyDirectivesScannerTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Lex/DependencyDirectivesScanner.cpp b/clang/lib/Lex/DependencyDirectivesScanner.cpp
index a862abcc44b38..d894c265a07a2 100644
--- a/clang/lib/Lex/DependencyDirectivesScanner.cpp
+++ b/clang/lib/Lex/DependencyDirectivesScanner.cpp
@@ -419,7 +419,6 @@ static bool isQuoteCppDigitSeparator(const char *const Start,
 }
 
 void Scanner::skipLine(const char *&First, const char *const End) {
-  char LastNonWhitespace = ' ';
   for (;;) {
     assert(First <= End);
     if (First == End)
@@ -430,6 +429,9 @@ void Scanner::skipLine(const char *&First, const char *const End) {
       return;
     }
     const char *Start = First;
+    // Use `LastNonWhitespace`to track if a line-continuation has ever been seen
+    // before a new-line character:
+    char LastNonWhitespace = ' ';
     while (First != End && !isVerticalWhitespace(*First)) {
       // Iterate over strings correctly to avoid comments and newlines.
       if (*First == '"' ||

diff  --git a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp
index 61f74929c1e98..d2ef27155df94 100644
--- a/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp
+++ b/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp
@@ -880,6 +880,37 @@ TEST(MinimizeSourceToDependencyDirectivesTest,
   EXPECT_EQ(pp_eof, Directives[22].Kind);
 }
 
+TEST(MinimizeSourceToDependencyDirectivesTest,
+     TestFixedBugThatReportUnterminatedDirectiveFalsely) {
+  SmallVector<char, 512> Out;
+  SmallVector<dependency_directives_scan::Token, 16> Tokens;
+  SmallVector<Directive, 16> Directives;
+
+  StringRef Input = "#ifndef __TEST \n"
+                    "#define __TEST \n"
+                    "#if defined(__TEST_DUMMY) \n"
+                    "#if defined(__TEST_DUMMY2) \n"
+                    "#pragma GCC warning        \\  \n"
+                    "\"hello!\"\n"
+                    "#else\n"
+                    "#pragma GCC error          \\  \n"
+                    "\"world!\" \n"
+                    "#endif // defined(__TEST_DUMMY2) \n"
+                    "#endif  // defined(__TEST_DUMMY) \n"
+                    "#endif // #ifndef __TEST \n";
+  ASSERT_FALSE( // False on no error:
+      minimizeSourceToDependencyDirectives(Input, Out, Tokens, Directives));
+  ASSERT_TRUE(Directives.size() == 8);
+  EXPECT_EQ(pp_ifndef, Directives[0].Kind);
+  EXPECT_EQ(pp_define, Directives[1].Kind);
+  EXPECT_EQ(pp_if, Directives[2].Kind);
+  EXPECT_EQ(pp_if, Directives[3].Kind);
+  EXPECT_EQ(pp_endif, Directives[4].Kind);
+  EXPECT_EQ(pp_endif, Directives[5].Kind);
+  EXPECT_EQ(pp_endif, Directives[6].Kind);
+  EXPECT_EQ(pp_eof, Directives[7].Kind);
+}
+
 TEST(MinimizeSourceToDependencyDirectivesTest, PoundWarningAndError) {
   SmallVector<char, 128> Out;
 


        


More information about the llvm-branch-commits mailing list