Skip to content

Commit

Permalink
[Modules] Improve diagnostics for incomplete umbrella
Browse files Browse the repository at this point in the history
One of the -Wincomplete-umbrella warnings diagnoses when a header is present in
the directory but it's not present in the umbrella header. Currently, this
warning only happens on top level modules; any submodule using an umbrella
header does not get this warning. Fix that by also considering the submodules.

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

rdar://problem/22623686

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@301597 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
bcardosolopes committed Apr 27, 2017
1 parent c5a1b98 commit 4ef94de
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 4 deletions.
21 changes: 17 additions & 4 deletions lib/Lex/PPLexerChange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,14 @@ const char *Preprocessor::getCurLexerEndPos() {
return EndPos;
}

static void collectAllSubModulesWithUmbrellaHeader(
const Module &Mod, SmallVectorImpl<const Module *> &SubMods) {
if (Mod.getUmbrellaHeader())
SubMods.push_back(&Mod);
for (auto *M : Mod.submodules())
collectAllSubModulesWithUmbrellaHeader(*M, SubMods);
}

void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) {
assert(Mod.getUmbrellaHeader() && "Module must use umbrella header");
SourceLocation StartLoc =
Expand Down Expand Up @@ -507,10 +515,15 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
}

// 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())
diagnoseMissingHeaderInUmbrellaDir(*Mod);
// each of the headers within the directory, including all submodules, is
// covered by the umbrella header was actually included by the umbrella
// header.
if (Module *Mod = getCurrentModule()) {
llvm::SmallVector<const Module *, 4> AllMods;
collectAllSubModulesWithUmbrellaHeader(*Mod, AllMods);
for (auto *M : AllMods)
diagnoseMissingHeaderInUmbrellaDir(*M);
}

return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define BAR_PUBLIC 1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// FooPublic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
framework module Foo {
umbrella header "FooPublic.h"
requires objc
export *
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
explicit module Foo.Private {
umbrella header "Foo.h"
requires objc
export *
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define BAZ_PRIVATE 1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Foo.h
15 changes: 15 additions & 0 deletions test/Modules/incomplete-umbrella.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// RUN: rm -rf %t
// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F%S/Inputs/incomplete-umbrella -fsyntax-only %s 2>&1 | FileCheck %s

#import <Foo/Foo.h>
#import <Foo/Bar.h>
#import <Foo/Baz.h>
@import Foo.Private;

// CHECK: warning: umbrella header for module 'Foo' does not include header 'Bar.h'
// CHECK: warning: umbrella header for module 'Foo.Private' does not include header 'Baz.h'
int foo() {
int a = BAR_PUBLIC;
int b = BAZ_PRIVATE;
return 0;
}

0 comments on commit 4ef94de

Please sign in to comment.