Add [extern_c] attribute for modules, allowing a C module to be imported within an extern "C" block in C++ code.
llvm-svn: 202615
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 69dd490..abcd886 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12957,6 +12957,36 @@
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 @@
/*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 @@
}
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);