Author: Amelia Jochna Date: 2026-05-21T14:42:25+02:00 New Revision: 4d7b7dff60c3c3c3858e91858d2f74a512d71538
URL: https://github.com/llvm/llvm-project/commit/4d7b7dff60c3c3c3858e91858d2f74a512d71538 DIFF: https://github.com/llvm/llvm-project/commit/4d7b7dff60c3c3c3858e91858d2f74a512d71538.diff LOG: [Clang] Add warning for non-portable include paths with trailing whitespace or dots (#190610) This patch extends -Wnonportable-include-path to detect and warn about trailing whitespace and dots in #include directives. Such paths are non-portable and can lead to build failures on different operating systems. The warning is triggered when an include filename ends with a space or a dot, which is common when copy-pasting paths or due to typos. Fixes #96064 Added: clang/test/Preprocessor/nonportable-trailing-whitespace-win.c clang/test/Preprocessor/nonportable-trailing-whitespace.c Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticGroups.td clang/include/clang/Basic/DiagnosticLexKinds.td clang/lib/Lex/PPDirectives.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6838cf3defcc13..e88e134c3a9b56 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -541,9 +541,11 @@ Improvements to Clang's diagnostics - Clang now errors when a function declaration aliases a variable or vice versa. (#GH195550) - Added ``-Wattribute-alias`` to diagnose type mismatches between an alias and its aliased function. (#GH195550) - + - The diagnostics around ``__block`` now explain why a variable cannot be marked ``__block``. (#GH197213) +- Extended ``-Wnonportable-include-path`` to warn about trailing whitespace and dots in ``#include`` paths. (#GH190610) + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 264013ed7306a5..8031f99419bdc9 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -977,6 +977,7 @@ def MemsetTransposedArgs : DiagGroup<"memset-transposed-args">; def DynamicClassMemaccess : DiagGroup<"dynamic-class-memaccess">; def NonTrivialMemcall : DiagGroup<"nontrivial-memcall">; def NonTrivialMemaccess : DiagGroup<"nontrivial-memaccess", [NonTrivialMemcall]>; +def NonportableSystemIncludePath : DiagGroup<"nonportable-system-include-path">; def SuspiciousBzero : DiagGroup<"suspicious-bzero">; def SuspiciousMemaccess : DiagGroup<"suspicious-memaccess", [SizeofPointerMemaccess, DynamicClassMemaccess, diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 0ac7ac27a0271f..383bf1a7fdb3f5 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -373,13 +373,21 @@ def ext_missing_whitespace_after_macro_name : ExtWarn< def warn_missing_whitespace_after_macro_name : Warning< "whitespace recommended after macro name">; -class NonportablePath : Warning< +class NonportablePath : Warning< "non-portable path to file '%0'; specified path diff ers in case from file" " name on disk">; def pp_nonportable_path : NonportablePath, InGroup<NonportableIncludePath>; def pp_nonportable_system_path : NonportablePath, DefaultIgnore, - InGroup<DiagGroup<"nonportable-system-include-path">>; + InGroup<NonportableSystemIncludePath>; + +class NonportablePathTrailing : Warning< + "non-portable path to file '%0'; specified path contains trailing" + " %select{whitespace|dot}1">; +def pp_nonportable_path_trailing : NonportablePathTrailing, + InGroup<NonportableIncludePath>; +def pp_nonportable_system_path_trailing : NonportablePathTrailing, DefaultIgnore, + InGroup<NonportableSystemIncludePath>; def pp_nonportable_path_separator : Warning< "non-portable path to file '%0'; specified path contains backslashes">, DefaultIgnore, InGroup<NonportableIncludePathSeparator>; diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 6e90f20572f1f5..12d3c765b15bc5 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -2382,6 +2382,11 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // error. if (Filename.empty()) return {ImportAction::None}; + if (Filename.ends_with(' ') || Filename.ends_with('.')) { + unsigned Selection = Filename.ends_with('.') ? 1 : 0; + Diag(FilenameTok, diag::pp_nonportable_path_trailing) + << Filename << Selection; + } bool IsImportDecl = HashLoc.isInvalid(); SourceLocation StartLoc = IsImportDecl ? IncludeTok.getLocation() : HashLoc; diff --git a/clang/test/Preprocessor/nonportable-trailing-whitespace-win.c b/clang/test/Preprocessor/nonportable-trailing-whitespace-win.c new file mode 100644 index 00000000000000..f957877a68d146 --- /dev/null +++ b/clang/test/Preprocessor/nonportable-trailing-whitespace-win.c @@ -0,0 +1,18 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: touch %t/simple.h +// RUN: %clang_cc1 -fsyntax-only -I%t -Wnonportable-include-path -verify %s +// REQUIRES: system-windows + +// On Windows, the filesystem silently strips trailing whitespace and dots +// from filenames, so the include succeeds. We should still emit a +// portability warning but no file-not-found error. + +// Trailing whitespace: warn about non-portable path, but file is found. +#include "simple.h " // expected-warning {{non-portable path to file 'simple.h '; specified path contains trailing whitespace}} + +// Trailing dots: warn about non-portable path, but file is found. +#include "simple.h." // expected-warning {{non-portable path to file 'simple.h.'; specified path contains trailing dot}} + +// Correct path: no diagnostics expected. +#include "simple.h" // no-warning diff --git a/clang/test/Preprocessor/nonportable-trailing-whitespace.c b/clang/test/Preprocessor/nonportable-trailing-whitespace.c new file mode 100644 index 00000000000000..569fe3ec34b38f --- /dev/null +++ b/clang/test/Preprocessor/nonportable-trailing-whitespace.c @@ -0,0 +1,20 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: touch %t/simple.h +// RUN: %clang_cc1 -fsyntax-only -I%t -Wnonportable-include-path -verify %s +// UNSUPPORTED: system-windows + +// On non-Windows systems, trailing whitespace and dots in include paths +// produce both a portability warning and a file-not-found error, +// because the filesystem treats them as part of the filename. + +// Trailing whitespace: warn about non-portable path, error because file not found. +#include "simple.h " // expected-warning {{non-portable path to file 'simple.h '; specified path contains trailing whitespace}} \ + // expected-error {{'simple.h ' file not found}} + +// Trailing dots: warn about non-portable path, error because file not found. +#include "simple.h." // expected-warning {{non-portable path to file 'simple.h.'; specified path contains trailing dot}} \ + // expected-error {{'simple.h.' file not found}} + +// Correct path: no diagnostics expected. +#include "simple.h" // no-warning _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
