summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticLexKinds.td2
-rw-r--r--clang/include/clang/Lex/ModuleMap.h10
-rw-r--r--clang/include/clang/Lex/Preprocessor.h5
-rw-r--r--clang/lib/Lex/HeaderSearch.cpp61
-rw-r--r--clang/lib/Lex/ModuleMap.cpp86
-rw-r--r--clang/lib/Lex/PPDirectives.cpp28
-rw-r--r--clang/test/Modules/Inputs/modular_maps/common.h4
-rw-r--r--clang/test/Modules/Inputs/modular_maps/modulea.map1
-rw-r--r--clang/test/Modules/Inputs/modular_maps/moduleb.map1
-rw-r--r--clang/test/Modules/Inputs/separate_map_tree/maps/modulea.map12
-rw-r--r--clang/test/Modules/Inputs/separate_map_tree/maps/moduleb.map4
-rw-r--r--clang/test/Modules/Inputs/separate_map_tree/maps/modulec.map5
-rw-r--r--clang/test/Modules/Inputs/separate_map_tree/src/common.h4
-rw-r--r--clang/test/Modules/Inputs/separate_map_tree/src/private-in-c.h4
-rw-r--r--clang/test/Modules/Inputs/separate_map_tree/src/public-in-b.h4
-rw-r--r--clang/test/Modules/Inputs/separate_map_tree/src/public-in-c.h4
-rw-r--r--clang/test/Modules/modular_maps.cpp4
-rw-r--r--clang/test/Modules/separate_map_tree.cpp8
18 files changed, 166 insertions, 81 deletions
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 2603307775a..871f5f65447 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -551,8 +551,6 @@ def err_mmap_expected_mmap_file : Error<"expected a module map file name">;
def err_mmap_module_redefinition : Error<
"redefinition of module '%0'">;
def note_mmap_prev_definition : Note<"previously defined here">;
-def err_mmap_header_conflict : Error<
- "header '%0' is already part of module '%1'">;
def err_mmap_header_not_found : Error<
"%select{|umbrella }0header '%1' not found">;
def err_mmap_umbrella_dir_not_found : Error<
diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h
index 90cfc6c7e18..b7982a17aa5 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -106,7 +106,8 @@ public:
};
private:
- typedef llvm::DenseMap<const FileEntry *, KnownHeader> HeadersMap;
+ typedef llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1> >
+ HeadersMap;
/// \brief Mapping from each header to the module that owns the contents of
/// that header.
@@ -208,10 +209,15 @@ public:
///
/// \param File The header file that is likely to be included.
///
+ /// \param RequestingModule Specifies the module the header is intended to be
+ /// used from. Used to disambiguate if a header is present in multiple
+ /// modules.
+ ///
/// \returns The module KnownHeader, which provides the module that owns the
/// given header file. The KnownHeader is default constructed to indicate
/// that no module owns this header file.
- KnownHeader findModuleForHeader(const FileEntry *File);
+ KnownHeader findModuleForHeader(const FileEntry *File,
+ Module *RequestingModule = NULL);
/// \brief Determine whether the given header is part of a module
/// marked 'unavailable'.
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index f9eae976348..adfc6f1951b 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -1461,10 +1461,9 @@ private:
/// \brief Verify that it is legal for the source file that \p FilenameLoc
/// points to to include the file \p Filename.
///
- /// Tries to reuse \p IncFileEnt and \p SuggestedModule.
+ /// Tries to reuse \p IncFileEnt.
void verifyModuleInclude(SourceLocation FilenameLoc, StringRef Filename,
- const FileEntry *IncFileEnt,
- ModuleMap::KnownHeader *SuggestedModule);
+ const FileEntry *IncFileEnt);
// Macro handling.
void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index 5bcc4ea0441..84d205acdae 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -247,16 +247,18 @@ const FileEntry *DirectoryLookup::LookupFile(
// If we have a module map that might map this header, load it and
// check whether we'll have a suggestion for a module.
- if (SuggestedModule &&
- HS.hasModuleMap(TmpDir, getDir(), isSystemHeaderDirectory())) {
- const FileEntry *File = HS.getFileMgr().getFile(TmpDir.str(),
+ HS.hasModuleMap(TmpDir, getDir(), isSystemHeaderDirectory());
+ if (SuggestedModule) {
+ const FileEntry *File = HS.getFileMgr().getFile(TmpDir.str(),
/*openFile=*/false);
if (!File)
return File;
- // If there is a module that corresponds to this header,
- // suggest it.
+ // If there is a module that corresponds to this header, suggest it.
*SuggestedModule = HS.findModuleForHeader(File);
+ if (!SuggestedModule->getModule() &&
+ HS.hasModuleMap(TmpDir, getDir(), isSystemHeaderDirectory()))
+ *SuggestedModule = HS.findModuleForHeader(File);
return File;
}
@@ -503,6 +505,24 @@ const FileEntry *HeaderSearch::LookupFile(
ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache)
{
+ if (!HSOpts->ModuleMapFiles.empty()) {
+ // Preload all explicitly specified module map files. This enables modules
+ // map files lying in a directory structure separate from the header files
+ // that they describe. These cannot be loaded lazily upon encountering a
+ // header file, as there is no other knwon mapping from a header file to its
+ // module map file.
+ for (llvm::SetVector<std::string>::iterator
+ I = HSOpts->ModuleMapFiles.begin(),
+ E = HSOpts->ModuleMapFiles.end();
+ I != E; ++I) {
+ const FileEntry *File = FileMgr.getFile(*I);
+ if (!File)
+ continue;
+ loadModuleMapFile(File, /*IsSystem=*/false);
+ }
+ HSOpts->ModuleMapFiles.clear();
+ }
+
if (SuggestedModule)
*SuggestedModule = ModuleMap::KnownHeader();
@@ -946,43 +966,20 @@ bool HeaderSearch::hasModuleMap(StringRef FileName,
const DirectoryEntry *Dir = FileMgr.getDirectory(DirName);
if (!Dir)
return false;
-
- // Load user-specified module map files in 'Dir'.
- bool ModuleMapFound = false;
- for (llvm::SetVector<std::string>::iterator
- I = HSOpts->ModuleMapFiles.begin(),
- E = HSOpts->ModuleMapFiles.end();
- I != E; ++I) {
- StringRef ModuleMapFileDir = llvm::sys::path::parent_path(*I);
- if (!llvm::sys::fs::equivalent(ModuleMapFileDir, DirName))
- continue;
-
- const FileEntry *File = FileMgr.getFile(*I);
- if (!File)
- continue;
-
- loadModuleMapFile(File, /*IsSystem=*/false);
- ModuleMapFound = true;
- }
// Try to load the "module.map" file in this directory.
switch (loadModuleMapFile(Dir, IsSystem)) {
case LMM_NewlyLoaded:
case LMM_AlreadyLoaded:
- ModuleMapFound = true;
- break;
-
- case LMM_NoDirectory:
- case LMM_InvalidModuleMap:
- break;
- }
-
- if (ModuleMapFound) {
// Success. All of the directories we stepped through inherit this module
// map file.
for (unsigned I = 0, N = FixUpDirectories.size(); I != N; ++I)
DirectoryHasModuleMap[FixUpDirectories[I]] = true;
return true;
+
+ case LMM_NoDirectory:
+ case LMM_InvalidModuleMap:
+ break;
}
// If we hit the top of our search, we're done.
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index a10679af158..25d68ace0f1 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -168,14 +168,41 @@ static bool isBuiltinHeader(StringRef FileName) {
.Default(false);
}
-ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
+ModuleMap::KnownHeader
+ModuleMap::findModuleForHeader(const FileEntry *File,
+ Module *RequestingModule) {
HeadersMap::iterator Known = Headers.find(File);
if (Known != Headers.end()) {
- // If a header is not available, don't report that it maps to anything.
- if (!Known->second.isAvailable())
- return KnownHeader();
+ ModuleMap::KnownHeader Result = KnownHeader();
+
+ // Iterate over all modules that 'File' is part of to find the best fit.
+ for (SmallVectorImpl<KnownHeader>::iterator I = Known->second.begin(),
+ E = Known->second.end();
+ I != E; ++I) {
+ // Cannot use a module if the header is excluded or unavailable in it.
+ if (I->getRole() == ModuleMap::ExcludedHeader ||
+ !I->getModule()->isAvailable())
+ continue;
- return Known->second;
+ // If 'File' is part of 'RequestingModule', 'RequestingModule' is the
+ // module we are looking for.
+ if (I->getModule() == RequestingModule)
+ return *I;
+
+ // If uses need to be specified explicitly, we are only allowed to return
+ // modules that are explicitly used by the requesting module.
+ if (RequestingModule && LangOpts.ModulesDeclUse &&
+ std::find(RequestingModule->DirectUses.begin(),
+ RequestingModule->DirectUses.end(),
+ I->getModule()) == RequestingModule->DirectUses.end())
+ continue;
+ Result = *I;
+ // If 'File' is a public header of this module, this is as good as we
+ // are going to get.
+ if (I->getRole() == ModuleMap::NormalHeader)
+ break;
+ }
+ return Result;
}
// If we've found a builtin header within Clang's builtin include directory,
@@ -186,14 +213,8 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
HeaderInfo.loadTopLevelSystemModules();
// Check again.
- Known = Headers.find(File);
- if (Known != Headers.end()) {
- // If a header is not available, don't report that it maps to anything.
- if (!Known->second.isAvailable())
- return KnownHeader();
-
- return Known->second;
- }
+ if (Headers.find(File) != Headers.end())
+ return findModuleForHeader(File, RequestingModule);
}
const DirectoryEntry *Dir = File->getDir();
@@ -262,14 +283,14 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
UmbrellaDirs[SkippedDirs[I]] = Result;
}
- Headers[File] = KnownHeader(Result, NormalHeader);
+ Headers[File].push_back(KnownHeader(Result, NormalHeader));
// If a header corresponds to an unavailable module, don't report
// that it maps to anything.
if (!Result->isAvailable())
return KnownHeader();
- return Headers[File];
+ return Headers[File].back();
}
SkippedDirs.push_back(Dir);
@@ -288,8 +309,16 @@ ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
HeadersMap::const_iterator Known = Headers.find(Header);
- if (Known != Headers.end())
- return !Known->second.isAvailable();
+ if (Known != Headers.end()) {
+ for (SmallVectorImpl<KnownHeader>::const_iterator
+ I = Known->second.begin(),
+ E = Known->second.end();
+ I != E; ++I) {
+ if (I->isAvailable())
+ return false;
+ }
+ return true;
+ }
const DirectoryEntry *Dir = Header->getDir();
SmallVector<const DirectoryEntry *, 2> SkippedDirs;
@@ -534,7 +563,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
// umbrella header "umbrella-header-name"
Result->Umbrella = UmbrellaHeader;
- Headers[UmbrellaHeader] = KnownHeader(Result, NormalHeader);
+ Headers[UmbrellaHeader].push_back(KnownHeader(Result, NormalHeader));
UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
// export *
@@ -598,7 +627,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
}
void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
- Headers[UmbrellaHeader] = KnownHeader(Mod, NormalHeader);
+ Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
Mod->Umbrella = UmbrellaHeader;
UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
}
@@ -620,7 +649,7 @@ void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
HeaderInfo.MarkFileModuleHeader(Header, Role, isCompilingModuleHeader);
}
- Headers[Header] = KnownHeader(Mod, Role);
+ Headers[Header].push_back(KnownHeader(Mod, Role));
}
const FileEntry *
@@ -642,8 +671,15 @@ void ModuleMap::dump() {
llvm::errs() << "Headers:";
for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
H != HEnd; ++H) {
- llvm::errs() << " \"" << H->first->getName() << "\" -> "
- << H->second.getModule()->getFullModuleName() << "\n";
+ llvm::errs() << " \"" << H->first->getName() << "\" -> ";
+ for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
+ E = H->second.end();
+ I != E; ++I) {
+ if (I != H->second.begin())
+ llvm::errs() << ",";
+ llvm::errs() << I->getModule()->getFullModuleName();
+ }
+ llvm::errs() << "\n";
}
}
@@ -1494,11 +1530,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
// Come up with a lazy way to do this.
if (File) {
- if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
- Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
- << FileName << OwningModule.getModule()->getFullModuleName();
- HadError = true;
- } else if (LeadingToken == MMToken::UmbrellaKeyword) {
+ if (LeadingToken == MMToken::UmbrellaKeyword) {
const DirectoryEntry *UmbrellaDir = File->getDir();
if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash)
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 99b30c67ac3..a952b2ef1b9 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -583,33 +583,33 @@ bool Preprocessor::violatesUseDeclarations(
return Declared == AllowedUses.end();
}
-void Preprocessor::verifyModuleInclude(
- SourceLocation FilenameLoc,
- StringRef Filename,
- const FileEntry *IncFileEnt,
- ModuleMap::KnownHeader *SuggestedModule) {
+void Preprocessor::verifyModuleInclude(SourceLocation FilenameLoc,
+ StringRef Filename,
+ const FileEntry *IncFileEnt) {
Module *RequestingModule = getModuleForLocation(FilenameLoc);
- Module *RequestedModule = SuggestedModule->getModule();
- if (!RequestedModule)
- RequestedModule = HeaderInfo.findModuleForHeader(IncFileEnt).getModule();
+ if (RequestingModule)
+ HeaderInfo.getModuleMap().resolveUses(RequestingModule, /*Complain=*/false);
+ ModuleMap::KnownHeader RequestedModule =
+ HeaderInfo.getModuleMap().findModuleForHeader(IncFileEnt,
+ RequestingModule);
- if (RequestingModule == RequestedModule)
+ if (RequestingModule == RequestedModule.getModule())
return; // No faults wihin a module, or between files both not in modules.
if (RequestingModule != HeaderInfo.getModuleMap().SourceModule)
return; // No errors for indirect modules.
// This may be a bit of a problem for modules with no source files.
- if (RequestedModule &&
- violatesPrivateInclude(RequestingModule, IncFileEnt,
- SuggestedModule->getRole(), RequestedModule))
+ if (RequestedModule && violatesPrivateInclude(RequestingModule, IncFileEnt,
+ RequestedModule.getRole(),
+ RequestedModule.getModule()))
Diag(FilenameLoc, diag::error_use_of_private_header_outside_module)
<< Filename;
// FIXME: Add support for FixIts in module map files and offer adding the
// required use declaration.
if (RequestingModule && getLangOpts().ModulesDeclUse &&
- violatesUseDeclarations(RequestingModule, RequestedModule))
+ violatesUseDeclarations(RequestingModule, RequestedModule.getModule()))
Diag(FilenameLoc, diag::error_undeclared_use_of_module)
<< Filename;
}
@@ -650,7 +650,7 @@ const FileEntry *Preprocessor::LookupFile(
SearchPath, RelativePath, SuggestedModule, SkipCache);
if (FE) {
if (SuggestedModule)
- verifyModuleInclude(FilenameLoc, Filename, FE, SuggestedModule);
+ verifyModuleInclude(FilenameLoc, Filename, FE);
return FE;
}
diff --git a/clang/test/Modules/Inputs/modular_maps/common.h b/clang/test/Modules/Inputs/modular_maps/common.h
new file mode 100644
index 00000000000..f690bcbd399
--- /dev/null
+++ b/clang/test/Modules/Inputs/modular_maps/common.h
@@ -0,0 +1,4 @@
+#ifndef COMMON_H
+#define COMMON_H
+const int c = 2;
+#endif
diff --git a/clang/test/Modules/Inputs/modular_maps/modulea.map b/clang/test/Modules/Inputs/modular_maps/modulea.map
index 7018c413042..58c5f6464e4 100644
--- a/clang/test/Modules/Inputs/modular_maps/modulea.map
+++ b/clang/test/Modules/Inputs/modular_maps/modulea.map
@@ -1,4 +1,5 @@
module A {
+ header "common.h"
header "a.h"
}
diff --git a/clang/test/Modules/Inputs/modular_maps/moduleb.map b/clang/test/Modules/Inputs/modular_maps/moduleb.map
index 6f36ccd3baa..7b35e8f91e4 100644
--- a/clang/test/Modules/Inputs/modular_maps/moduleb.map
+++ b/clang/test/Modules/Inputs/modular_maps/moduleb.map
@@ -1,3 +1,4 @@
module B {
+ header "common.h"
private header "b.h"
}
diff --git a/clang/test/Modules/Inputs/separate_map_tree/maps/modulea.map b/clang/test/Modules/Inputs/separate_map_tree/maps/modulea.map
new file mode 100644
index 00000000000..736503ecaeb
--- /dev/null
+++ b/clang/test/Modules/Inputs/separate_map_tree/maps/modulea.map
@@ -0,0 +1,12 @@
+module D {
+ header "../src/common.h"
+}
+
+module A {
+ header "../src/common.h"
+ use C
+}
+
+extern module B "moduleb.map"
+extern module C "modulec.map"
+
diff --git a/clang/test/Modules/Inputs/separate_map_tree/maps/moduleb.map b/clang/test/Modules/Inputs/separate_map_tree/maps/moduleb.map
new file mode 100644
index 00000000000..d3877965c71
--- /dev/null
+++ b/clang/test/Modules/Inputs/separate_map_tree/maps/moduleb.map
@@ -0,0 +1,4 @@
+module B {
+ header "../src/public-in-b.h"
+ private header "../src/public-in-c.h"
+}
diff --git a/clang/test/Modules/Inputs/separate_map_tree/maps/modulec.map b/clang/test/Modules/Inputs/separate_map_tree/maps/modulec.map
new file mode 100644
index 00000000000..91063b65f37
--- /dev/null
+++ b/clang/test/Modules/Inputs/separate_map_tree/maps/modulec.map
@@ -0,0 +1,5 @@
+module C {
+ header "../src/public-in-c.h"
+ private header "../src/public-in-b.h"
+ private header "../src/private-in-c.h"
+}
diff --git a/clang/test/Modules/Inputs/separate_map_tree/src/common.h b/clang/test/Modules/Inputs/separate_map_tree/src/common.h
new file mode 100644
index 00000000000..1d2ecb5a194
--- /dev/null
+++ b/clang/test/Modules/Inputs/separate_map_tree/src/common.h
@@ -0,0 +1,4 @@
+#ifndef COMMON_H
+#define COMMON_H
+const int common = 2;
+#endif
diff --git a/clang/test/Modules/Inputs/separate_map_tree/src/private-in-c.h b/clang/test/Modules/Inputs/separate_map_tree/src/private-in-c.h
new file mode 100644
index 00000000000..bc9e2c1bb34
--- /dev/null
+++ b/clang/test/Modules/Inputs/separate_map_tree/src/private-in-c.h
@@ -0,0 +1,4 @@
+#ifndef PRIVATE_IN_C_H
+#define PRIVATE_IN_C_H
+const int c_ = 2;
+#endif
diff --git a/clang/test/Modules/Inputs/separate_map_tree/src/public-in-b.h b/clang/test/Modules/Inputs/separate_map_tree/src/public-in-b.h
new file mode 100644
index 00000000000..9ea6c1b4410
--- /dev/null
+++ b/clang/test/Modules/Inputs/separate_map_tree/src/public-in-b.h
@@ -0,0 +1,4 @@
+#ifndef PUBLIC_IN_B_H
+#define PUBLIC_IN_B_H
+const int b = 3;
+#endif
diff --git a/clang/test/Modules/Inputs/separate_map_tree/src/public-in-c.h b/clang/test/Modules/Inputs/separate_map_tree/src/public-in-c.h
new file mode 100644
index 00000000000..fa3d2fd2cb7
--- /dev/null
+++ b/clang/test/Modules/Inputs/separate_map_tree/src/public-in-c.h
@@ -0,0 +1,4 @@
+#ifndef PUBLIC_IN_C_H
+#define PUBLIC_IN_C_H
+const int c = 2;
+#endif
diff --git a/clang/test/Modules/modular_maps.cpp b/clang/test/Modules/modular_maps.cpp
index 5070f7d5bf9..9c9aba85a91 100644
--- a/clang/test/Modules/modular_maps.cpp
+++ b/clang/test/Modules/modular_maps.cpp
@@ -1,6 +1,8 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodule-map-file=%S/Inputs/modular_maps/modulea.map -I %S/Inputs/modular_maps %s -verify
+#include "common.h"
#include "a.h"
#include "b.h" // expected-error {{private header}}
-const int val = a + b; // expected-error {{undeclared identifier}}
+const int v = a + c;
+const int val = a + b + c; // expected-error {{undeclared identifier}}
diff --git a/clang/test/Modules/separate_map_tree.cpp b/clang/test/Modules/separate_map_tree.cpp
new file mode 100644
index 00000000000..5a1fff4efc7
--- /dev/null
+++ b/clang/test/Modules/separate_map_tree.cpp
@@ -0,0 +1,8 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fmodules-decluse -fmodule-name=A -fmodule-map-file=%S/Inputs/separate_map_tree/maps/modulea.map -I %S/Inputs/separate_map_tree/src %s -verify
+
+#include "common.h"
+#include "public-in-b.h" // expected-error {{private header}}
+#include "public-in-c.h"
+#include "private-in-c.h" // expected-error {{private header}}
+const int val = common + b + c + c_; // expected-error {{undeclared identifier}}
OpenPOWER on IntegriCloud