[modules] When we #include a local submodule header that we've already built,

and it has an include guard, produce callbacks for a module import, not for a
skipped non-modular header.

Fixes -E output when preprocessing a module to list these cases as a module
import, rather than suppressing the #include and losing the import side effect.

llvm-svn: 304183
This commit is contained in:
Richard Smith 2017-05-30 02:03:19 +00:00
parent 1da971706e
commit c5247e67e8
6 changed files with 93 additions and 20 deletions

View File

@ -1906,6 +1906,25 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
}
}
// The #included file will be considered to be a system header if either it is
// in a system include directory, or if the #includer is a system include
// header.
SrcMgr::CharacteristicKind FileCharacter =
SourceMgr.getFileCharacteristic(FilenameTok.getLocation());
if (File)
FileCharacter = std::max(HeaderInfo.getFileDirFlavor(File), FileCharacter);
// Ask HeaderInfo if we should enter this #include file. If not, #including
// this file will have no effect.
bool SkipHeader = false;
if (ShouldEnter && File &&
!HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport,
getLangOpts().Modules,
SuggestedModule.getModule())) {
ShouldEnter = false;
SkipHeader = true;
}
if (Callbacks) {
// Notify the callback object that we've seen an inclusion directive.
Callbacks->InclusionDirective(
@ -1913,18 +1932,13 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
FilenameRange, File, SearchPath, RelativePath,
ShouldEnter ? nullptr : SuggestedModule.getModule());
if (SkipHeader && !SuggestedModule.getModule())
Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
}
if (!File)
return;
// The #included file will be considered to be a system header if either it is
// in a system include directory, or if the #includer is a system include
// header.
SrcMgr::CharacteristicKind FileCharacter =
std::max(HeaderInfo.getFileDirFlavor(File),
SourceMgr.getFileCharacteristic(FilenameTok.getLocation()));
// FIXME: If we have a suggested module, and we've already visited this file,
// don't bother entering it again. We know it has no further effect.
@ -1964,19 +1978,6 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
}
}
// Ask HeaderInfo if we should enter this #include file. If not, #including
// this file will have no effect.
bool SkipHeader = false;
if (ShouldEnter &&
!HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport,
getLangOpts().Modules,
SuggestedModule.getModule())) {
ShouldEnter = false;
SkipHeader = true;
if (Callbacks)
Callbacks->FileSkipped(*File, FilenameTok, FileCharacter);
}
// If we don't need to enter the file, stop now.
if (!ShouldEnter) {
// If this is a module import, make it visible if needed.

View File

@ -0,0 +1,2 @@
#include "c.h"
T a();

View File

@ -0,0 +1,2 @@
#include "c.h"
T b();

View File

@ -0,0 +1,4 @@
#ifndef C_H
#define C_H
using T = int;
#endif

View File

@ -1,2 +1,7 @@
module fwd { header "fwd.h" export * }
module file { header "file.h" header "file2.h" export * }
module nested {
module a { header "a.h" }
module b { header "b.h" }
module c { header "c.h" }
}

View File

@ -0,0 +1,59 @@
// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -I%S/Inputs/preprocess -x c++-module-map %S/Inputs/preprocess/module.modulemap -E -o %t/no-rewrite.ii
// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -I%S/Inputs/preprocess -x c++-module-map %S/Inputs/preprocess/module.modulemap -E -frewrite-includes -o %t/rewrite.ii
// RUN: FileCheck %s --input-file %t/no-rewrite.ii --check-prefix=CHECK --check-prefix=NO-REWRITE
// RUN: FileCheck %s --input-file %t/rewrite.ii --check-prefix=CHECK --check-prefix=REWRITE
// Check that we can build a module from the preprocessed output.
// FIXME: For now, the files need to exist.
// RUN: touch %t/a.h %t/b.h %t/c.h
// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -x c++-module-map-cpp-output %t/no-rewrite.ii -emit-module -o %t/no-rewrite.pcm
// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o %t/rewrite.pcm
// Check the module we built works.
// RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -I%t -verify -fno-modules-error-recovery
// RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DREWRITE
// == module map
// CHECK: # 1 "{{.*}}module.modulemap"
// CHECK: module nested {
// CHECK: module a {
// CHECK: header "a.h"
// CHECK: }
// CHECK: module b {
// CHECK: header "b.h"
// CHECK: }
// CHECK: module c {
// CHECK: header "c.h"
// CHECK: }
// CHECK: }
// CHECK: #pragma clang module begin nested.a
// CHECK: #pragma clang module begin nested.c
// CHECK: using T = int;
// CHECK: #pragma clang module end
// CHECK: T a();
// CHECK: #pragma clang module end
// CHECK: #pragma clang module begin nested.b
// CHECK: #pragma clang module import nested.c
// CHECK-NOT: #pragma clang module begin nested.c
// CHECK-NOT: using T = int;
// CHECK-NOT: #pragma clang module end
// CHECK: T b();
// CHECK: #pragma clang module end
// CHECK: #pragma clang module import nested.c
#pragma clang module import nested.b
int n = b();
T c; // expected-error {{must be imported}}
#ifdef REWRITE
// expected-note@rewrite.ii:* {{declar}}
#else
// expected-note@no-rewrite.ii:* {{declar}}
#endif