[cfe-commits] r147207 - in /cfe/trunk: include/clang/Basic/DiagnosticLexKinds.td lib/Lex/PPLexerChange.cpp test/Modules/Inputs/Module.framework/Headers/Module.h test/Modules/on-demand-build.m

Douglas Gregor dgregor at apple.com
Thu Dec 22 16:23:59 PST 2011


Author: dgregor
Date: Thu Dec 22 18:23:59 2011
New Revision: 147207

URL: http://llvm.org/viewvc/llvm-project?rev=147207&view=rev
Log:
When building a module with an umbrella header, warn about any headers
found within that umbrella directory that were not actually included
by the umbrella header. They should either be referenced in the module
map or included by the umbrella header.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
    cfe/trunk/lib/Lex/PPLexerChange.cpp
    cfe/trunk/test/Modules/Inputs/Module.framework/Headers/Module.h
    cfe/trunk/test/Modules/on-demand-build.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=147207&r1=147206&r2=147207&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Thu Dec 22 18:23:59 2011
@@ -425,5 +425,7 @@
 def warn_auto_module_import : Warning<
   "treating #%select{include|import|include_next|__include_macros}0 as an "
   "import of module '%1'">, InGroup<AutoImport>, DefaultIgnore;
+def warn_uncovered_module_header : Warning<
+  "umbrella header does not include header '%0'">, InGroup<IncompleteUmbrella>;
 
 }

Modified: cfe/trunk/lib/Lex/PPLexerChange.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPLexerChange.cpp?rev=147207&r1=147206&r2=147207&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPLexerChange.cpp (original)
+++ cfe/trunk/lib/Lex/PPLexerChange.cpp Thu Dec 22 18:23:59 2011
@@ -18,7 +18,10 @@
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PathV2.h"
+#include "llvm/ADT/StringSwitch.h"
 using namespace clang;
 
 PPCallbacks::~PPCallbacks() {}
@@ -199,6 +202,31 @@
     CurLexerKind = CLK_TokenLexer;
 }
 
+/// \brief Compute the relative path that names the given file relative to
+/// the given directory.
+static void computeRelativePath(FileManager &FM, const DirectoryEntry *Dir,
+                                const FileEntry *File,
+                                llvm::SmallString<128> &Result) {
+  Result.clear();
+
+  StringRef FilePath = File->getDir()->getName();
+  StringRef Path = FilePath;
+  while (!Path.empty()) {
+    if (const DirectoryEntry *CurDir = FM.getDirectory(Path)) {
+      if (CurDir == Dir) {
+        Result = FilePath.substr(Path.size());
+        llvm::sys::path::append(Result, 
+                                llvm::sys::path::filename(File->getName()));
+        return;
+      }
+    }
+    
+    Path = llvm::sys::path::parent_path(Path);
+  }
+  
+  Result = File->getName();
+}
+
 /// HandleEndOfFile - This callback is invoked when the lexer hits the end of
 /// the current file.  This either returns the EOF token or pops a level off
 /// the include stack and keeps going.
@@ -316,6 +344,45 @@
          I=WarnUnusedMacroLocs.begin(), E=WarnUnusedMacroLocs.end(); I!=E; ++I)
     Diag(*I, diag::pp_macro_not_used);
 
+  // If we are building a module that has an umbrella header, make sure that
+  // each of the headers within the directory covered by the umbrella header
+  // was actually included by the umbrella header.
+  if (Module *Mod = getCurrentModule()) {
+    if (Mod->getUmbrellaHeader()) {
+      SourceLocation StartLoc
+        = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+
+      if (getDiagnostics().getDiagnosticLevel(
+            diag::warn_uncovered_module_header, 
+            StartLoc) != DiagnosticsEngine::Ignored) {
+        typedef typename llvm::sys::fs::recursive_directory_iterator
+          recursive_directory_iterator;
+        const DirectoryEntry *Dir = Mod->getUmbrellaDir();
+        llvm::error_code EC;
+        for (recursive_directory_iterator Entry(Dir->getName(), EC), End;
+             Entry != End && !EC; Entry.increment(EC)) {
+          using llvm::StringSwitch;
+          
+          // Check whether this entry has an extension typically associated with 
+          // headers.
+          if (!StringSwitch<bool>(llvm::sys::path::extension(Entry->path()))
+              .Cases(".h", ".H", ".hh", ".hpp", true)
+              .Default(false))
+            continue;
+
+          if (const FileEntry *Header = getFileManager().getFile(Entry->path()))
+            if (!getSourceManager().hasFileInfo(Header)) {
+              // Find the 
+              llvm::SmallString<128> RelativePath;
+              computeRelativePath(FileMgr, Dir, Header, RelativePath);              
+              Diag(StartLoc, diag::warn_uncovered_module_header)
+                << RelativePath;
+            }
+        }
+      }
+    }
+  }
+  
   return true;
 }
 

Modified: cfe/trunk/test/Modules/Inputs/Module.framework/Headers/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/Module.framework/Headers/Module.h?rev=147207&r1=147206&r2=147207&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/Module.framework/Headers/Module.h (original)
+++ cfe/trunk/test/Modules/Inputs/Module.framework/Headers/Module.h Thu Dec 22 18:23:59 2011
@@ -1,3 +1,5 @@
+// expected-warning{{umbrella header}}
+
 #ifndef MODULE_H
 #define MODULE_H
 const char *getModuleVersion(void);

Modified: cfe/trunk/test/Modules/on-demand-build.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/on-demand-build.m?rev=147207&r1=147206&r2=147207&view=diff
==============================================================================
--- cfe/trunk/test/Modules/on-demand-build.m (original)
+++ cfe/trunk/test/Modules/on-demand-build.m Thu Dec 22 18:23:59 2011
@@ -1,13 +1,15 @@
 // RUN: rm -rf %t
-// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Werror -fmodule-cache-path %t -F %S/Inputs -verify %s
-// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Werror -x objective-c++ -fmodule-cache-path %t -F %S/Inputs -verify %s
-// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Werror -fmodule-cache-path %t -F %S/Inputs -verify %s
+// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Werror -Wno-error=incomplete-umbrella -fmodule-cache-path %t -F %S/Inputs -verify %s
+// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Werror -Wno-error=incomplete-umbrella -x objective-c++ -fmodule-cache-path %t -F %S/Inputs -verify %s
+// RUN: %clang_cc1 -fno-objc-infer-related-result-type -Werror -Wno-error=incomplete-umbrella -fmodule-cache-path %t -F %S/Inputs -verify %s
 #define FOO
 __import_module__ Module;
 @interface OtherClass
 @end
 
 
+
+
 // in module: expected-note{{class method 'alloc' is assumed to return an instance of its receiver type ('Module *')}}
 void test_getModuleVersion() {
   const char *version = getModuleVersion();





More information about the cfe-commits mailing list