[PATCH] D25311: Add FixItHint for missing #include (err_module_unimported_use_header)

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 6 04:45:37 PDT 2016


sammccall created this revision.
sammccall added a subscriber: cfe-commits.
Herald added subscribers: mgorny, beanz.

The line is inserted using clang-format's logic with LLVM style.
Users must run clang-format afterwards if they want some other style.

Alternatives:

  respect .clang-format: this would be surprising in the compiler
  insert at offset 0: this is bad people who don't use clang-format
  apply $simple_heuristic: clang-format handles lots of special cases for us


https://reviews.llvm.org/D25311

Files:
  lib/Sema/CMakeLists.txt
  lib/Sema/SemaLookup.cpp
  test/Modules/suggest-include.cpp


Index: test/Modules/suggest-include.cpp
===================================================================
--- test/Modules/suggest-include.cpp
+++ test/Modules/suggest-include.cpp
@@ -1,7 +1,11 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs/suggest-include %s -verify
+// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs/suggest-include %s -fdiagnostics-parseable-fixits 2>&1 | FileCheck --match-full-lines --implicit-check-not "fix-it:{{.*}}" %s
 
 #include "empty.h" // import the module file
+// CHECK: fix-it:"{{.*}}":{[[@LINE]]:1-[[@LINE]]:84}:"#include \"usetextual1.h\"\n"
+// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:1-[[@LINE-1]]:84}:"#include \"usetextual2.h\"\n"
+// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:1-[[@LINE-2]]:84}:"#include \"usetextual3.h\"\n"
 
 // expected-note at usetextual1.h:2 {{previous}}
 // expected-note at textual2.h:1 {{previous}}
Index: lib/Sema/SemaLookup.cpp
===================================================================
--- lib/Sema/SemaLookup.cpp
+++ lib/Sema/SemaLookup.cpp
@@ -23,6 +23,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Format/Format.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/Preprocessor.h"
@@ -35,6 +36,7 @@
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "clang/Sema/TypoCorrection.h"
+#include "clang/Tooling/Core/Replacement.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/TinyPtrVector.h"
@@ -4982,6 +4984,26 @@
   return (IsSystem ? '<' : '"') + Path + (IsSystem ? '>' : '"');
 }
 
+/// Hint where to insert a missing #include into the file.
+/// We reuse clang-format's header-insertion logic, always with LLVM-style.
+static FixItHint AddInclude(FileID File, SourceManager &SourceMgr,
+                            std::string &IncludeTarget) {
+  StringRef Code = SourceMgr.getBufferData(File);
+  auto StartOfFile = SourceMgr.getLocForStartOfFile(File);
+  tooling::Replacement Unplaced(SourceMgr.getFilename(StartOfFile), UINT_MAX, 0,
+                                "#include " + IncludeTarget);
+  auto Reps = cleanupAroundReplacements(Code, tooling::Replacements(Unplaced),
+                                        format::getLLVMStyle());
+  if (Reps)
+    for (const auto &Placed : *Reps) {
+      auto Begin = StartOfFile.getLocWithOffset(Placed.getOffset());
+      auto End = Begin.getLocWithOffset(Placed.getLength());
+      return FixItHint::CreateReplacement(SourceRange(Begin, End),
+                                          Placed.getReplacementText());
+    }
+  return FixItHint();
+}
+
 void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
                                  SourceLocation DeclLoc,
                                  ArrayRef<Module *> Modules,
@@ -5006,12 +5028,10 @@
                  PP.getModuleHeaderToIncludeForDiagnostics(UseLoc, DeclLoc)) {
     // The right way to make the declaration visible is to include a header;
     // suggest doing so.
-    //
-    // FIXME: Find a smart place to suggest inserting a #include, and add
-    // a FixItHint there.
+    std::string Include = getIncludeStringForHeader(PP, E);
     Diag(UseLoc, diag::err_module_unimported_use_header)
-      << (int)MIK << Decl << Modules[0]->getFullModuleName()
-      << getIncludeStringForHeader(PP, E);
+        << (int)MIK << Decl << Modules[0]->getFullModuleName() << Include
+        << AddInclude(SourceMgr.getFileID(UseLoc), SourceMgr, Include);
   } else {
     // FIXME: Add a FixItHint that imports the corresponding module.
     Diag(UseLoc, diag::err_module_unimported_use)
Index: lib/Sema/CMakeLists.txt
===================================================================
--- lib/Sema/CMakeLists.txt
+++ lib/Sema/CMakeLists.txt
@@ -61,4 +61,5 @@
   clangBasic
   clangEdit
   clangLex
+  clangFormat
   )


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D25311.73763.patch
Type: text/x-patch
Size: 4040 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161006/687217df/attachment-0001.bin>


More information about the cfe-commits mailing list