summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/Module.cpp7
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp21
-rw-r--r--clang/lib/Lex/ModuleMap.cpp16
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp41
-rw-r--r--clang/lib/Sema/SemaDecl.cpp36
5 files changed, 102 insertions, 19 deletions
diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index c6a1d602a94..24c480a7667 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -24,15 +24,14 @@
using namespace clang;
-Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
+Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit)
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
Umbrella(), ASTFile(0), IsAvailable(true), IsFromModuleFile(false),
IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
- InferSubmodules(false), InferExplicitSubmodules(false),
+ IsExternC(false), InferSubmodules(false), InferExplicitSubmodules(false),
InferExportWildcard(false), ConfigMacrosExhaustive(false),
- NameVisibility(Hidden)
-{
+ NameVisibility(Hidden) {
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index eda21c5f3f7..f587d829b39 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -130,19 +130,25 @@ operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
static void addHeaderInclude(StringRef HeaderName,
SmallVectorImpl<char> &Includes,
- const LangOptions &LangOpts) {
+ const LangOptions &LangOpts,
+ bool IsExternC) {
+ if (IsExternC)
+ Includes += "extern \"C\" {\n";
if (LangOpts.ObjC1)
Includes += "#import \"";
else
Includes += "#include \"";
Includes += HeaderName;
Includes += "\"\n";
+ if (IsExternC)
+ Includes += "}\n";
}
static void addHeaderInclude(const FileEntry *Header,
SmallVectorImpl<char> &Includes,
- const LangOptions &LangOpts) {
- addHeaderInclude(Header->getName(), Includes, LangOpts);
+ const LangOptions &LangOpts,
+ bool IsExternC) {
+ addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC);
}
/// \brief Collect the set of header includes needed to construct the given
@@ -165,7 +171,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
for (unsigned I = 0, N = Module->NormalHeaders.size(); I != N; ++I) {
const FileEntry *Header = Module->NormalHeaders[I];
Module->addTopHeader(Header);
- addHeaderInclude(Header, Includes, LangOpts);
+ addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC);
}
// Note that Module->PrivateHeaders will not be a TopHeader.
@@ -173,7 +179,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
Module->addTopHeader(UmbrellaHeader);
if (Module->Parent) {
// Include the umbrella header for submodules.
- addHeaderInclude(UmbrellaHeader, Includes, LangOpts);
+ addHeaderInclude(UmbrellaHeader, Includes, LangOpts, Module->IsExternC);
}
} else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
// Add all of the headers we find in this subdirectory.
@@ -199,7 +205,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
}
// Include this header umbrella header for submodules.
- addHeaderInclude(Dir->path(), Includes, LangOpts);
+ addHeaderInclude(Dir->path(), Includes, LangOpts, Module->IsExternC);
}
}
@@ -267,7 +273,8 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
// Collect the set of #includes we need to build the module.
SmallString<256> HeaderContents;
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader())
- addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts());
+ addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts(),
+ Module->IsExternC);
collectModuleHeaderIncludes(CI.getLangOpts(), FileMgr,
CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(),
Module, HeaderContents);
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 05238278bad..0d9cd109537 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -906,11 +906,14 @@ namespace clang {
/// \brief The set of attributes that can be attached to a module.
struct Attributes {
- Attributes() : IsSystem(), IsExhaustive() { }
+ Attributes() : IsSystem(), IsExternC(), IsExhaustive() { }
/// \brief Whether this is a system module.
unsigned IsSystem : 1;
+ /// \brief Whether this is an extern "C" module.
+ unsigned IsExternC : 1;
+
/// \brief Whether this is an exhaustive set of configuration macros.
unsigned IsExhaustive : 1;
};
@@ -1178,6 +1181,8 @@ namespace {
AT_unknown,
/// \brief The 'system' attribute.
AT_system,
+ /// \brief The 'extern_c' attribute.
+ AT_extern_c,
/// \brief The 'exhaustive' attribute.
AT_exhaustive
};
@@ -1334,7 +1339,9 @@ void ModuleMapParser::parseModuleDecl() {
ActiveModule->DefinitionLoc = ModuleNameLoc;
if (Attrs.IsSystem || IsSystem)
ActiveModule->IsSystem = true;
-
+ if (Attrs.IsExternC)
+ ActiveModule->IsExternC = true;
+
bool Done = false;
do {
switch (Tok.Kind) {
@@ -2097,6 +2104,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
AttributeKind Attribute
= llvm::StringSwitch<AttributeKind>(Tok.getString())
.Case("exhaustive", AT_exhaustive)
+ .Case("extern_c", AT_extern_c)
.Case("system", AT_system)
.Default(AT_unknown);
switch (Attribute) {
@@ -2109,6 +2117,10 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
Attrs.IsSystem = true;
break;
+ case AT_extern_c:
+ Attrs.IsExternC = true;
+ break;
+
case AT_exhaustive:
Attrs.IsExhaustive = true;
break;
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 7d198efa2e3..33d10407594 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -313,11 +313,42 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
BalancedDelimiterTracker T(*this, tok::l_brace);
T.consumeOpen();
- while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
- ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs);
- MaybeParseMicrosoftAttributes(attrs);
- ParseExternalDeclaration(attrs);
+
+ unsigned NestedModules = 0;
+ while (true) {
+ switch (Tok.getKind()) {
+ case tok::annot_module_begin:
+ ++NestedModules;
+ ParseTopLevelDecl();
+ continue;
+
+ case tok::annot_module_end:
+ if (!NestedModules)
+ break;
+ --NestedModules;
+ ParseTopLevelDecl();
+ continue;
+
+ case tok::annot_module_include:
+ ParseTopLevelDecl();
+ continue;
+
+ case tok::eof:
+ break;
+
+ case tok::r_brace:
+ if (!NestedModules)
+ break;
+ // Fall through.
+ default:
+ ParsedAttributesWithRange attrs(AttrFactory);
+ MaybeParseCXX11Attributes(attrs);
+ MaybeParseMicrosoftAttributes(attrs);
+ ParseExternalDeclaration(attrs);
+ continue;
+ }
+
+ break;
}
T.consumeClose();
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 69dd4905cb5..abcd886da6b 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12957,6 +12957,36 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
return New;
}
+static void checkModuleImportContext(Sema &S, Module *M,
+ SourceLocation ImportLoc,
+ DeclContext *DC) {
+ if (auto *LSD = dyn_cast<LinkageSpecDecl>(DC)) {
+ switch (LSD->getLanguage()) {
+ case LinkageSpecDecl::lang_c:
+ if (!M->IsExternC) {
+ S.Diag(ImportLoc, diag::err_module_import_in_extern_c)
+ << M->getFullModuleName();
+ S.Diag(LSD->getLocStart(), diag::note_module_import_in_extern_c);
+ return;
+ }
+ break;
+ case LinkageSpecDecl::lang_cxx:
+ break;
+ }
+ DC = LSD->getParent();
+ }
+
+ while (isa<LinkageSpecDecl>(DC))
+ DC = DC->getParent();
+ if (!isa<TranslationUnitDecl>(DC)) {
+ S.Diag(ImportLoc, diag::err_module_import_not_at_top_level)
+ << M->getFullModuleName() << DC;
+ S.Diag(cast<Decl>(DC)->getLocStart(),
+ diag::note_module_import_not_at_top_level)
+ << DC;
+ }
+}
+
DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
@@ -12965,7 +12995,9 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
/*IsIncludeDirective=*/false);
if (!Mod)
return true;
-
+
+ checkModuleImportContext(*this, Mod, ImportLoc, CurContext);
+
SmallVector<SourceLocation, 2> IdentifierLocs;
Module *ModCheck = Mod;
for (unsigned I = 0, N = Path.size(); I != N; ++I) {
@@ -12987,6 +13019,8 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc,
}
void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) {
+ checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext);
+
// FIXME: Should we synthesize an ImportDecl here?
PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, DirectiveLoc,
/*Complain=*/true);
OpenPOWER on IntegriCloud