summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-09-13 21:10:08 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-09-13 21:10:08 +0000
commit2ce63b4246329ee0fb20aa6f768f1f57eda6d5f0 (patch)
tree4be210b1e56cdc21224b46cb709dbf767159f538 /clang
parent2f88006cedd06b8e2be1e9d282ba7e3bf88f57ca (diff)
downloadbcm5719-llvm-2ce63b4246329ee0fb20aa6f768f1f57eda6d5f0.tar.gz
bcm5719-llvm-2ce63b4246329ee0fb20aa6f768f1f57eda6d5f0.zip
Diagnose likely typos in #include directives.
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 llvm-svn: 342177
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticLexKinds.td4
-rw-r--r--clang/lib/Lex/PPDirectives.cpp30
-rw-r--r--clang/test/Preprocessor/empty_file_to_include.h7
-rw-r--r--clang/test/Preprocessor/include-likely-typo.c3
4 files changed, 42 insertions, 2 deletions
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 7e8bea7c249..085648c65d1 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -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">;
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 2bb96c1f15a..ca2b3d5d027 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -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/clang/test/Preprocessor/empty_file_to_include.h b/clang/test/Preprocessor/empty_file_to_include.h
new file mode 100644
index 00000000000..48ffc751538
--- /dev/null
+++ b/clang/test/Preprocessor/empty_file_to_include.h
@@ -0,0 +1,7 @@
+
+#ifndef EMPTY_FILE_TO_INCLUDE_H
+#define EMPTY_FILE_TO_INCLUDE_H
+
+// empty file
+
+#endif
diff --git a/clang/test/Preprocessor/include-likely-typo.c b/clang/test/Preprocessor/include-likely-typo.c
new file mode 100644
index 00000000000..88942ae6f89
--- /dev/null
+++ b/clang/test/Preprocessor/include-likely-typo.c
@@ -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'?}}
OpenPOWER on IntegriCloud