]> granicus.if.org Git - clang/commitdiff
Diagnose likely typos in #include directives.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 13 Sep 2018 21:10:08 +0000 (21:10 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 13 Sep 2018 21:10:08 +0000 (21:10 +0000)
Summary:
When someone writes

  #include "<some_file>"

or

  #include " some_file "

the compiler returns "file not fuond..." with fonts and quotes that may
make it hard to see there are excess quotes or surprising bytes in the
filename.  Assuming that files are usually logically named and start and
end with an alphanumeric character, we can check for the file's
existence by stripping the non-alphanumeric leading or trailing
characters.  If the file is found, emit a non-fatal error with a
FixItHint.

Patch by Christy Lee!

Reviewers: aaron.ballman, erikjv, rsmith

Reviewed By: rsmith

Subscribers: lebedev.ri, xbolva00, sammccall, modocache, erikjv, aaron.ballman, cfe-commits

Differential Revision: https://reviews.llvm.org/D51333

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342177 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticLexKinds.td
lib/Lex/PPDirectives.cpp
test/Preprocessor/empty_file_to_include.h [new file with mode: 0644]
test/Preprocessor/include-likely-typo.c [new file with mode: 0644]

index 7e8bea7c2496144ab49f312dbfe0aff58bf2719b..085648c65d1d2fcf39c96271ce2e1cbec826595a 100644 (file)
@@ -422,8 +422,10 @@ def warn_pp_hdrstop_filename_ignored : Warning<
   "#pragma hdrstop filename not supported, "
   "/Fp can be used to specify precompiled header filename">,
   InGroup<ClangClPch>;
-def err_pp_file_not_found_not_fatal : Error<
+def err_pp_file_not_found_angled_include_not_fatal : Error<
   "'%0' file not found with <angled> include; use \"quotes\" instead">;
+def err_pp_file_not_found_typo_not_fatal
+    : Error<"'%0' file not found, did you mean '%1'?">;
 def err_pp_error_opening_file : Error<
   "error opening file '%0': %1">, DefaultFatal;
 def err_pp_empty_filename : Error<"empty filename">;
index 2bb96c1f15adf280931b5d61747868fed894f375..ca2b3d5d027a16ab28a822ef136a4b87b6c856bf 100644 (file)
@@ -1879,12 +1879,40 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
             Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped);
         if (File) {
           SourceRange Range(FilenameTok.getLocation(), CharEnd);
-          Diag(FilenameTok, diag::err_pp_file_not_found_not_fatal) <<
+          Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal) <<
             Filename <<
             FixItHint::CreateReplacement(Range, "\"" + Filename.str() + "\"");
         }
       }
 
+      // Check for likely typos due to leading or trailing non-isAlphanumeric
+      // characters
+      if (!File) {
+        StringRef OriginalFilename = Filename;
+        while (!isAlphanumeric(Filename.front())) {
+          Filename = Filename.drop_front();
+        }
+        while (!isAlphanumeric(Filename.back())) {
+          Filename = Filename.drop_back();
+        }
+
+        File = LookupFile(
+            FilenameLoc,
+            LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
+            LookupFrom, LookupFromFile, CurDir,
+            Callbacks ? &SearchPath : nullptr,
+            Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped);
+        if (File) {
+          SourceRange Range(FilenameTok.getLocation(), CharEnd);
+          auto Hint = isAngled ? FixItHint::CreateReplacement(
+                                     Range, "<" + Filename.str() + ">")
+                               : FixItHint::CreateReplacement(
+                                     Range, "\"" + Filename.str() + "\"");
+          Diag(FilenameTok, diag::err_pp_file_not_found_typo_not_fatal)
+              << OriginalFilename << Filename << Hint;
+        }
+      }
+
       // If the file is still not found, just go with the vanilla diagnostic
       if (!File)
         Diag(FilenameTok, diag::err_pp_file_not_found) << Filename
diff --git a/test/Preprocessor/empty_file_to_include.h b/test/Preprocessor/empty_file_to_include.h
new file mode 100644 (file)
index 0000000..48ffc75
--- /dev/null
@@ -0,0 +1,7 @@
+
+#ifndef EMPTY_FILE_TO_INCLUDE_H
+#define EMPTY_FILE_TO_INCLUDE_H
+
+// empty file
+
+#endif
diff --git a/test/Preprocessor/include-likely-typo.c b/test/Preprocessor/include-likely-typo.c
new file mode 100644 (file)
index 0000000..88942ae
--- /dev/null
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 %s -verify
+
+#include "<empty_file_to_include.h>" // expected-error {{'<empty_file_to_include.h>' file not found, did you mean 'empty_file_to_include.h'?}}