Skip to content

Commit f0691bc

Browse files
authored
[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
1 parent 2a8f40d commit f0691bc

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

clang/lib/Lex/PPDirectives.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,11 +1858,18 @@ static void diagnoseAutoModuleImport(
18581858
// path to the file, build a properly-cased replacement in the vector,
18591859
// and return true if the replacement should be suggested.
18601860
static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components,
1861-
StringRef RealPathName) {
1861+
StringRef RealPathName,
1862+
llvm::sys::path::Style Separator) {
18621863
auto RealPathComponentIter = llvm::sys::path::rbegin(RealPathName);
18631864
auto RealPathComponentEnd = llvm::sys::path::rend(RealPathName);
18641865
int Cnt = 0;
18651866
bool SuggestReplacement = false;
1867+
1868+
auto IsSep = [Separator](StringRef Component) {
1869+
return Component.size() == 1 &&
1870+
llvm::sys::path::is_separator(Component[0], Separator);
1871+
};
1872+
18661873
// Below is a best-effort to handle ".." in paths. It is admittedly
18671874
// not 100% correct in the presence of symlinks.
18681875
for (auto &Component : llvm::reverse(Components)) {
@@ -1872,10 +1879,11 @@ static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components,
18721879
} else if (Cnt) {
18731880
--Cnt;
18741881
} else if (RealPathComponentIter != RealPathComponentEnd) {
1875-
if (Component != *RealPathComponentIter) {
1876-
// If these path components differ by more than just case, then we
1877-
// may be looking at symlinked paths. Bail on this diagnostic to avoid
1878-
// noisy false positives.
1882+
if (!IsSep(Component) && !IsSep(*RealPathComponentIter) &&
1883+
Component != *RealPathComponentIter) {
1884+
// If these non-separator path components differ by more than just case,
1885+
// then we may be looking at symlinked paths. Bail on this diagnostic to
1886+
// avoid noisy false positives.
18791887
SuggestReplacement =
18801888
RealPathComponentIter->equals_insensitive(Component);
18811889
if (!SuggestReplacement)
@@ -2451,7 +2459,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
24512459
}
24522460
#endif
24532461

2454-
if (trySimplifyPath(Components, RealPathName)) {
2462+
if (trySimplifyPath(Components, RealPathName, BackslashStyle)) {
24552463
SmallString<128> Path;
24562464
Path.reserve(Name.size()+2);
24572465
Path.push_back(isAngled ? '<' : '"');
@@ -2474,7 +2482,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
24742482
// got copied when the C: was processed and we want to skip that entry.
24752483
if (!(Component.size() == 1 && IsSep(Component[0])))
24762484
Path.append(Component);
2477-
else if (!Path.empty())
2485+
else if (Path.size() != 1)
24782486
continue;
24792487

24802488
// Append the separator(s) the user used, or the close quote
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// REQUIRES: case-insensitive-filesystem
2+
3+
// RUN: rm -rf %t && split-file %s %t
4+
// RUN: sed "s|DIR|%/t|g" %t/tu.c.in > %t/tu.c
5+
// RUN: %clang_cc1 -fsyntax-only %t/tu.c 2>&1 | FileCheck %s --DDIR=%/t
6+
7+
//--- header.h
8+
//--- tu.c.in
9+
#import "DIR/Header.h"
10+
// CHECK: tu.c:1:9: warning: non-portable path to file '"[[DIR]]/header.h"'; specified path differs in case from file name on disk [-Wnonportable-include-path]
11+
// CHECK-NEXT: 1 | #import "[[DIR]]/Header.h"
12+
// CHECK-NEXT: | ^~~~~~~~~~~~~~~~~~
13+
// CHECK-NEXT: | "[[DIR]]/header.h"

0 commit comments

Comments
 (0)