[clang] f0691bc - [clang][lex] Fix non-portability diagnostics with absolute path (#74782)

via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 18 12:11:31 PST 2023


Author: Jan Svoboda
Date: 2023-12-18T12:11:27-08:00
New Revision: f0691bcdf90bc44d0737e3395423e84b075ab84a

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

LOG: [clang][lex] Fix non-portability diagnostics with absolute path (#74782)

The existing code incorrectly assumes that `Path` can be empty. It
can't, it always contains at least `<` or `"`. On Unix, this patch fixes
an incorrect diagnostics that instead of `"/Users/blah"` suggested
`"Userss/blah"`. In assert builds, this would outright crash.

This patch also fixes a bug on Windows that would prevent the diagnostic
being triggered due to separator mismatch.

rdar://91172342

Added: 
    clang/test/Lexer/case-insensitive-include-absolute.c

Modified: 
    clang/lib/Lex/PPDirectives.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 112bc8dc572c92..9f82a6d073e3ba 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -1858,11 +1858,18 @@ static void diagnoseAutoModuleImport(
 // path to the file, build a properly-cased replacement in the vector,
 // and return true if the replacement should be suggested.
 static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components,
-                            StringRef RealPathName) {
+                            StringRef RealPathName,
+                            llvm::sys::path::Style Separator) {
   auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);
   auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);
   int Cnt = 0;
   bool SuggestReplacement = false;
+
+  auto IsSep = [Separator](StringRef Component) {
+    return Component.size() == 1 &&
+           llvm::sys::path::is_separator(Component[0], Separator);
+  };
+
   // Below is a best-effort to handle ".." in paths. It is admittedly
   // not 100% correct in the presence of symlinks.
   for (auto &Component : llvm::reverse(Components)) {
@@ -1872,10 +1879,11 @@ static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components,
     } else if (Cnt) {
       --Cnt;
     } else if (RealPathComponentIter != RealPathComponentEnd) {
-      if (Component != *RealPathComponentIter) {
-        // If these path components 
diff er by more than just case, then we
-        // may be looking at symlinked paths. Bail on this diagnostic to avoid
-        // noisy false positives.
+      if (!IsSep(Component) && !IsSep(*RealPathComponentIter) &&
+          Component != *RealPathComponentIter) {
+        // If these non-separator path components 
diff er by more than just case,
+        // then we may be looking at symlinked paths. Bail on this diagnostic to
+        // avoid noisy false positives.
         SuggestReplacement =
             RealPathComponentIter->equals_insensitive(Component);
         if (!SuggestReplacement)
@@ -2451,7 +2459,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
     }
 #endif
 
-    if (trySimplifyPath(Components, RealPathName)) {
+    if (trySimplifyPath(Components, RealPathName, BackslashStyle)) {
       SmallString<128> Path;
       Path.reserve(Name.size()+2);
       Path.push_back(isAngled ? '<' : '"');
@@ -2474,7 +2482,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
         // got copied when the C: was processed and we want to skip that entry.
         if (!(Component.size() == 1 && IsSep(Component[0])))
           Path.append(Component);
-        else if (!Path.empty())
+        else if (Path.size() != 1)
           continue;
 
         // Append the separator(s) the user used, or the close quote

diff  --git a/clang/test/Lexer/case-insensitive-include-absolute.c b/clang/test/Lexer/case-insensitive-include-absolute.c
new file mode 100644
index 00000000000000..6247e4808c7fa2
--- /dev/null
+++ b/clang/test/Lexer/case-insensitive-include-absolute.c
@@ -0,0 +1,13 @@
+// REQUIRES: case-insensitive-filesystem
+
+// RUN: rm -rf %t && split-file %s %t
+// RUN: sed "s|DIR|%/t|g" %t/tu.c.in > %t/tu.c
+// RUN: %clang_cc1 -fsyntax-only %t/tu.c 2>&1 | FileCheck %s --DDIR=%/t
+
+//--- header.h
+//--- tu.c.in
+#import "DIR/Header.h"
+// CHECK:      tu.c:1:9: warning: non-portable path to file '"[[DIR]]/header.h"'; specified path 
diff ers in case from file name on disk [-Wnonportable-include-path]
+// CHECK-NEXT:    1 | #import "[[DIR]]/Header.h"
+// CHECK-NEXT:      |         ^~~~~~~~~~~~~~~~~~
+// CHECK-NEXT:      |         "[[DIR]]/header.h"


        


More information about the cfe-commits mailing list