diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/Module.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 21 | ||||
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 41 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 36 |
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); |