Author: rsmith Date: Thu Sep 8 18:14:54 2016 New Revision: 280999 URL: http://llvm.org/viewvc/llvm-project?rev=280999&view=rev Log: C++ Modules TS: Add parsing and some semantic analysis support for export-declarations. These don't yet have an effect on name visibility; we still export everything by default.
Added: cfe/trunk/test/CodeGenCXX/modules-ts.cppm cfe/trunk/test/SemaCXX/modules-ts.cppm Modified: cfe/trunk/include/clang/AST/Decl.h cfe/trunk/include/clang/AST/DeclBase.h cfe/trunk/include/clang/AST/RecursiveASTVisitor.h cfe/trunk/include/clang/Basic/DeclNodes.td cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/include/clang/Sema/Template.h cfe/trunk/include/clang/Serialization/ASTBitCodes.h cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/AST/DeclBase.cpp cfe/trunk/lib/CodeGen/CGDecl.cpp cfe/trunk/lib/CodeGen/CodeGenModule.cpp cfe/trunk/lib/CodeGen/CodeGenModule.h cfe/trunk/lib/Parse/ParseDeclCXX.cpp cfe/trunk/lib/Parse/Parser.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/lib/Serialization/ASTCommon.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp cfe/trunk/test/Parser/cxx-modules-interface.cppm cfe/trunk/tools/libclang/CIndex.cpp Modified: cfe/trunk/include/clang/AST/Decl.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Decl.h (original) +++ cfe/trunk/include/clang/AST/Decl.h Thu Sep 8 18:14:54 2016 @@ -3792,6 +3792,55 @@ public: static bool classofKind(Kind K) { return K == Import; } }; +/// \brief Represents a C++ Modules TS module export declaration. +/// +/// For example: +/// \code +/// export void foo(); +/// \endcode +class ExportDecl final : public Decl, public DeclContext { + virtual void anchor(); +private: + /// \brief The source location for the right brace (if valid). + SourceLocation RBraceLoc; + + ExportDecl(DeclContext *DC, SourceLocation ExportLoc) + : Decl(Export, DC, ExportLoc), DeclContext(Export), + RBraceLoc(SourceLocation()) { } + + friend class ASTDeclReader; + +public: + static ExportDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation ExportLoc); + static ExportDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceLocation getExportLoc() const { return getLocation(); } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + + SourceLocation getLocEnd() const LLVM_READONLY { + if (RBraceLoc.isValid()) + return RBraceLoc; + // No braces: get the end location of the (only) declaration in context + // (if present). + return decls_empty() ? getLocation() : decls_begin()->getLocEnd(); + } + + SourceRange getSourceRange() const override LLVM_READONLY { + return SourceRange(getLocation(), getLocEnd()); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Export; } + static DeclContext *castToDeclContext(const ExportDecl *D) { + return static_cast<DeclContext *>(const_cast<ExportDecl*>(D)); + } + static ExportDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<ExportDecl *>(const_cast<DeclContext*>(DC)); + } +}; + /// \brief Represents an empty-declaration. class EmptyDecl : public Decl { virtual void anchor(); Modified: cfe/trunk/include/clang/AST/DeclBase.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclBase.h (original) +++ cfe/trunk/include/clang/AST/DeclBase.h Thu Sep 8 18:14:54 2016 @@ -33,6 +33,7 @@ class DeclContext; class DeclarationName; class DependentDiagnostic; class EnumDecl; +class ExportDecl; class FunctionDecl; class FunctionType; enum Linkage : unsigned char; @@ -1135,6 +1136,7 @@ public: /// ObjCMethodDecl /// ObjCContainerDecl /// LinkageSpecDecl +/// ExportDecl /// BlockDecl /// OMPDeclareReductionDecl /// @@ -1279,7 +1281,8 @@ public: /// \brief Test whether the context supports looking up names. bool isLookupContext() const { - return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec; + return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec && + DeclKind != Decl::Export; } bool isFileContext() const { Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Thu Sep 8 18:14:54 2016 @@ -1388,6 +1388,8 @@ DEF_TRAVERSE_DECL(ClassScopeFunctionSpec DEF_TRAVERSE_DECL(LinkageSpecDecl, {}) +DEF_TRAVERSE_DECL(ExportDecl, {}) + DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this }) Modified: cfe/trunk/include/clang/Basic/DeclNodes.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DeclNodes.td (original) +++ cfe/trunk/include/clang/Basic/DeclNodes.td Thu Sep 8 18:14:54 2016 @@ -80,6 +80,7 @@ def Named : Decl<1>; def ObjCProperty : DDecl<Named>; def ObjCCompatibleAlias : DDecl<Named>; def LinkageSpec : Decl, DeclContext; +def Export : Decl, DeclContext; def ObjCPropertyImpl : Decl; def FileScopeAsm : Decl; def AccessSpec : Decl; Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Sep 8 18:14:54 2016 @@ -1040,6 +1040,8 @@ def err_attribute_not_import_attr : Erro def err_module_expected_semi : Error< "expected ';' after module name">; def err_missing_before_module_end : Error<"expected %0 at end of module">; + +def err_export_empty : Error<"export declaration cannot be empty">; } let CategoryName = "Generics Issue" in { Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Thu Sep 8 18:14:54 2016 @@ -2412,6 +2412,7 @@ private: ParsedAttributes& attrs, BalancedDelimiterTracker &Tracker); Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context); + Decl *ParseExportDeclaration(); Decl *ParseUsingDirectiveOrDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation &DeclEnd, Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Sep 8 18:14:54 2016 @@ -1922,6 +1922,11 @@ public: SourceLocation DeclLoc, ArrayRef<Module *> Modules, MissingImportKind MIK, bool Recover); + Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, + SourceLocation LBraceLoc); + Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl, + SourceLocation RBraceLoc); + /// \brief We've found a use of a templated declaration that would trigger an /// implicit instantiation. Check that any relevant explicit specializations /// and partial specializations are visible, and diagnose if not. Modified: cfe/trunk/include/clang/Sema/Template.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Template.h (original) +++ cfe/trunk/include/clang/Sema/Template.h Thu Sep 8 18:14:54 2016 @@ -410,6 +410,7 @@ namespace clang { #define OBJCCONTAINER(DERIVED, BASE) #define FILESCOPEASM(DERIVED, BASE) #define IMPORT(DERIVED, BASE) +#define EXPORT(DERIVED, BASE) #define LINKAGESPEC(DERIVED, BASE) #define OBJCCOMPATIBLEALIAS(DERIVED, BASE) #define OBJCMETHOD(DERIVED, BASE) Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original) +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Thu Sep 8 18:14:54 2016 @@ -1103,6 +1103,8 @@ namespace clang { DECL_UNRESOLVED_USING_TYPENAME, /// \brief A LinkageSpecDecl record. DECL_LINKAGE_SPEC, + /// \brief An ExportDecl record. + DECL_EXPORT, /// \brief A CXXRecordDecl record. DECL_CXX_RECORD, /// \brief A CXXMethodDecl record. Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Thu Sep 8 18:14:54 2016 @@ -4310,3 +4310,18 @@ SourceRange ImportDecl::getSourceRange() return SourceRange(getLocation(), getIdentifierLocs().back()); } + +//===----------------------------------------------------------------------===// +// ExportDecl Implementation +//===----------------------------------------------------------------------===// + +void ExportDecl::anchor() {} + +ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation ExportLoc) { + return new (C, DC) ExportDecl(DC, ExportLoc); +} + +ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) ExportDecl(nullptr, SourceLocation()); +} Modified: cfe/trunk/lib/AST/DeclBase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclBase.cpp (original) +++ cfe/trunk/lib/AST/DeclBase.cpp Thu Sep 8 18:14:54 2016 @@ -672,6 +672,7 @@ unsigned Decl::getIdentifierNamespaceFor case FriendTemplate: case AccessSpec: case LinkageSpec: + case Export: case FileScopeAsm: case StaticAssert: case ObjCPropertyImpl: @@ -957,7 +958,7 @@ bool DeclContext::isDependentContext() c bool DeclContext::isTransparentContext() const { if (DeclKind == Decl::Enum) return !cast<EnumDecl>(this)->isScoped(); - else if (DeclKind == Decl::LinkageSpec) + else if (DeclKind == Decl::LinkageSpec || DeclKind == Decl::Export) return true; return false; @@ -996,6 +997,7 @@ DeclContext *DeclContext::getPrimaryCont case Decl::TranslationUnit: case Decl::ExternCContext: case Decl::LinkageSpec: + case Decl::Export: case Decl::Block: case Decl::Captured: case Decl::OMPDeclareReduction: @@ -1408,8 +1410,8 @@ NamedDecl *const DeclContextLookupResult DeclContext::lookup_result DeclContext::lookup(DeclarationName Name) const { - assert(DeclKind != Decl::LinkageSpec && - "Should not perform lookups into linkage specs!"); + assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + "should not perform lookups into transparent contexts"); // If we have an external source, ensure that any later redeclarations of this // context have been loaded, since they may add names to the result of this @@ -1472,8 +1474,8 @@ DeclContext::lookup(DeclarationName Name DeclContext::lookup_result DeclContext::noload_lookup(DeclarationName Name) { - assert(DeclKind != Decl::LinkageSpec && - "Should not perform lookups into linkage specs!"); + assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export && + "should not perform lookups into transparent contexts"); DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Sep 8 18:14:54 2016 @@ -78,6 +78,7 @@ void CodeGenFunction::EmitDecl(const Dec case Decl::PragmaDetectMismatch: case Decl::AccessSpec: case Decl::LinkageSpec: + case Decl::Export: case Decl::ObjCPropertyImpl: case Decl::FileScopeAsm: case Decl::Friend: Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Sep 8 18:14:54 2016 @@ -3754,17 +3754,6 @@ void CodeGenModule::EmitObjCIvarInitiali D->setHasNonZeroConstructors(true); } -/// EmitNamespace - Emit all declarations in a namespace. -void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) { - for (auto *I : ND->decls()) { - if (const auto *VD = dyn_cast<VarDecl>(I)) - if (VD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization && - VD->getTemplateSpecializationKind() != TSK_Undeclared) - continue; - EmitTopLevelDecl(I); - } -} - // EmitLinkageSpec - Emit all declarations in a linkage spec. void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) { if (LSD->getLanguage() != LinkageSpecDecl::lang_c && @@ -3773,13 +3762,21 @@ void CodeGenModule::EmitLinkageSpec(cons return; } - for (auto *I : LSD->decls()) { - // Meta-data for ObjC class includes references to implemented methods. - // Generate class's method definitions first. + EmitDeclContext(LSD); +} + +void CodeGenModule::EmitDeclContext(const DeclContext *DC) { + for (auto *I : DC->decls()) { + // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope + // are themselves considered "top-level", so EmitTopLevelDecl on an + // ObjCImplDecl does not recursively visit them. We need to do that in + // case they're nested inside another construct (LinkageSpecDecl / + // ExportDecl) that does stop them from being considered "top-level". if (auto *OID = dyn_cast<ObjCImplDecl>(I)) { for (auto *M : OID->methods()) EmitTopLevelDecl(M); } + EmitTopLevelDecl(I); } } @@ -3825,7 +3822,7 @@ void CodeGenModule::EmitTopLevelDecl(Dec // C++ Decls case Decl::Namespace: - EmitNamespace(cast<NamespaceDecl>(D)); + EmitDeclContext(cast<NamespaceDecl>(D)); break; case Decl::CXXRecord: // Emit any static data members, they may be definitions. @@ -3976,6 +3973,10 @@ void CodeGenModule::EmitTopLevelDecl(Dec break; } + case Decl::Export: + EmitDeclContext(cast<ExportDecl>(D)); + break; + case Decl::OMPThreadPrivate: EmitOMPThreadPrivateDecl(cast<OMPThreadPrivateDecl>(D)); break; Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Sep 8 18:14:54 2016 @@ -1182,7 +1182,7 @@ private: // C++ related functions. - void EmitNamespace(const NamespaceDecl *D); + void EmitDeclContext(const DeclContext *DC); void EmitLinkageSpec(const LinkageSpecDecl *D); void CompleteDIClassType(const CXXMethodDecl* D); Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Sep 8 18:14:54 2016 @@ -372,6 +372,53 @@ Decl *Parser::ParseLinkage(ParsingDeclSp : nullptr; } +/// Parse a C++ Modules TS export-declaration. +/// +/// export-declaration: +/// 'export' declaration +/// 'export' '{' declaration-seq[opt] '}' +/// +Decl *Parser::ParseExportDeclaration() { + assert(Tok.is(tok::kw_export)); + SourceLocation ExportLoc = ConsumeToken(); + + ParseScope ExportScope(this, Scope::DeclScope); + Decl *ExportDecl = Actions.ActOnStartExportDecl( + getCurScope(), ExportLoc, + Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation()); + + if (Tok.isNot(tok::l_brace)) { + // FIXME: Factor out a ParseExternalDeclarationWithAttrs. + ParsedAttributesWithRange Attrs(AttrFactory); + MaybeParseCXX11Attributes(Attrs); + MaybeParseMicrosoftAttributes(Attrs); + ParseExternalDeclaration(Attrs); + return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl, + SourceLocation()); + } + + BalancedDelimiterTracker T(*this, tok::l_brace); + T.consumeOpen(); + + // The Modules TS draft says "An export-declaration shall declare at least one + // entity", but the intent is that it shall contain at least one declaration. + if (Tok.is(tok::r_brace)) + Diag(ExportLoc, diag::err_export_empty) + << SourceRange(ExportLoc, Tok.getLocation()); + + while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && + Tok.isNot(tok::eof)) { + ParsedAttributesWithRange Attrs(AttrFactory); + MaybeParseCXX11Attributes(Attrs); + MaybeParseMicrosoftAttributes(Attrs); + ParseExternalDeclaration(Attrs); + } + + T.consumeClose(); + return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl, + T.getCloseLocation()); +} + /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or /// using-directive. Assumes that current token is 'using'. Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, Modified: cfe/trunk/lib/Parse/Parser.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/Parse/Parser.cpp (original) +++ cfe/trunk/lib/Parse/Parser.cpp Thu Sep 8 18:14:54 2016 @@ -770,11 +770,17 @@ Parser::ParseExternalDeclaration(ParsedA : Sema::PCC_Namespace); cutOffParsing(); return nullptr; + case tok::kw_export: + if (getLangOpts().ModulesTS) { + SingleDecl = ParseExportDeclaration(); + break; + } + // This must be 'export template'. Parse it so we can diagnose our lack + // of support. case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: case tok::kw_template: - case tok::kw_export: // As in 'export template' case tok::kw_static_assert: case tok::kw__Static_assert: // A function definition cannot start with any of these keywords. Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep 8 18:14:54 2016 @@ -15422,6 +15422,36 @@ void Sema::createImplicitModuleImportFor VisibleModules.setVisible(Mod, Loc); } +/// We have parsed the start of an export declaration, including the '{' +/// (if present). +Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, + SourceLocation LBraceLoc) { + // FIXME: C++ Modules TS: + // An export-declaration [...] shall not contain more than one + // export keyword. + // + // The intent here is that an export-declaration cannot appear within another + // export-declaration. + + ExportDecl *D = ExportDecl::Create(Context, CurContext, ExportLoc); + CurContext->addDecl(D); + PushDeclContext(S, D); + return D; +} + +/// Complete the definition of an export declaration. +Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) { + auto *ED = cast<ExportDecl>(D); + if (RBraceLoc.isValid()) + ED->setRBraceLoc(RBraceLoc); + + // FIXME: Diagnose export of internal-linkage declaration (including + // anonymous namespace). + + PopDeclContext(); + return D; +} + void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, IdentifierInfo* AliasName, SourceLocation PragmaLoc, Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Sep 8 18:14:54 2016 @@ -1538,8 +1538,8 @@ bool LookupResult::isVisibleSlow(Sema &S // If this declaration is not at namespace scope nor module-private, // then it is visible if its lexical parent has a visible definition. DeclContext *DC = D->getLexicalDeclContext(); - if (!D->isModulePrivate() && - DC && !DC->isFileContext() && !isa<LinkageSpecDecl>(DC)) { + if (!D->isModulePrivate() && DC && !DC->isFileContext() && + !isa<LinkageSpecDecl>(DC) && !isa<ExportDecl>(DC)) { // For a parameter, check whether our current template declaration's // lexical context is visible, not whether there's some other visible // definition of it, because parameters aren't "within" the definition. Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Sep 8 18:14:54 2016 @@ -5892,9 +5892,7 @@ Sema::CheckTemplateDeclScope(Scope *S, T if (Ctx && Ctx->isExternCContext()) return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage) << TemplateParams->getSourceRange(); - - while (Ctx && isa<LinkageSpecDecl>(Ctx)) - Ctx = Ctx->getParent(); + Ctx = Ctx->getRedeclContext(); // C++ [temp]p2: // A template-declaration can appear only as a namespace scope or Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTCommon.cpp (original) +++ cfe/trunk/lib/Serialization/ASTCommon.cpp Thu Sep 8 18:14:54 2016 @@ -183,6 +183,7 @@ serialization::getDefinitiveDeclContext( case Decl::ExternCContext: case Decl::Namespace: case Decl::LinkageSpec: + case Decl::Export: return nullptr; // C/C++ tag types can only be defined in one place. @@ -291,6 +292,7 @@ bool serialization::isRedeclarableDeclKi case Decl::ObjCProperty: case Decl::ObjCCompatibleAlias: case Decl::LinkageSpec: + case Decl::Export: case Decl::ObjCPropertyImpl: case Decl::PragmaComment: case Decl::PragmaDetectMismatch: Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Sep 8 18:14:54 2016 @@ -327,6 +327,7 @@ namespace clang { void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); + void VisitExportDecl(ExportDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); void VisitImportDecl(ImportDecl *D); void VisitAccessSpecDecl(AccessSpecDecl *D); @@ -1366,6 +1367,11 @@ void ASTDeclReader::VisitLinkageSpecDecl D->setRBraceLoc(ReadSourceLocation(Record, Idx)); } +void ASTDeclReader::VisitExportDecl(ExportDecl *D) { + VisitDecl(D); + D->RBraceLoc = ReadSourceLocation(Record, Idx); +} + void ASTDeclReader::VisitLabelDecl(LabelDecl *D) { VisitNamedDecl(D); D->setLocStart(ReadSourceLocation(Record, Idx)); @@ -3266,6 +3272,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID I case DECL_LINKAGE_SPEC: D = LinkageSpecDecl::CreateDeserialized(Context, ID); break; + case DECL_EXPORT: + D = ExportDecl::CreateDeserialized(Context, ID); + break; case DECL_LABEL: D = LabelDecl::CreateDeserialized(Context, ID); break; Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Thu Sep 8 18:14:54 2016 @@ -110,6 +110,7 @@ namespace clang { void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); + void VisitExportDecl(ExportDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); void VisitImportDecl(ImportDecl *D); void VisitAccessSpecDecl(AccessSpecDecl *D); @@ -1080,6 +1081,12 @@ void ASTDeclWriter::VisitLinkageSpecDecl Code = serialization::DECL_LINKAGE_SPEC; } +void ASTDeclWriter::VisitExportDecl(ExportDecl *D) { + VisitDecl(D); + Record.AddSourceLocation(D->getRBraceLoc()); + Code = serialization::DECL_EXPORT; +} + void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) { VisitNamedDecl(D); Record.AddSourceLocation(D->getLocStart()); Added: cfe/trunk/test/CodeGenCXX/modules-ts.cppm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/modules-ts.cppm?rev=280999&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/modules-ts.cppm (added) +++ cfe/trunk/test/CodeGenCXX/modules-ts.cppm Thu Sep 8 18:14:54 2016 @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu -emit-module-interface %s -o %t.pcm +// RUN: %clang_cc1 -fmodules-ts -std=c++1z -triple=x86_64-linux-gnu %t.pcm -emit-llvm -o - | FileCheck %s + +module FooBar; + +export { + // CHECK-LABEL: define i32 @_Z1fv( + int f() { return 0; } +} + +// FIXME: Emit global variables and their initializers with this TU. +// Emit an initialization function that other TUs can call, with guard variable. + +// FIXME: Mangle non-exported symbols so they don't collide with +// non-exported symbols from other modules? + +// FIXME: Formally-internal-linkage symbols that are used from an exported +// symbol need a mangled name and external linkage. + +// FIXME: const-qualified variables don't have implicit internal linkage when owned by a module. Modified: cfe/trunk/test/Parser/cxx-modules-interface.cppm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-modules-interface.cppm?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx-modules-interface.cppm (original) +++ cfe/trunk/test/Parser/cxx-modules-interface.cppm Thu Sep 8 18:14:54 2016 @@ -1,21 +1,32 @@ -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -DTEST=0 -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -Dmodule=int -DTEST=1 -// RUN: not %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -DTEST=2 2>&1 | FileCheck %s --check-prefix=CHECK-2 -// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -verify -Dfoo=bar -DTEST=3 +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -Dmodule=int -DERRORS -#if TEST == 0 +module foo; +#ifndef ERRORS // expected-no-diagnostics -#endif +#else +// expected-error@-4 {{expected module declaration at start of module interface}} -module foo; -#if TEST == 1 -// expected-error@-2 {{expected module declaration at start of module interface}} -#elif TEST == 2 -// CHECK-2: error: redefinition of module 'foo' -#endif +// FIXME: support 'export module X;' and 'export { int n; module X; }' +// FIXME: proclaimed-ownership-declarations? + +export { + int a; + int b; +} +export int c; + +namespace N { + export void f() {} +} + +export struct T {} t; -int n; -#if TEST == 3 -// expected-error@-2 {{redefinition of 'n'}} -// expected-note@-3 {{previous}} +struct S { + export int n; // expected-error {{expected member name or ';'}} + export static int n; // expected-error {{expected member name or ';'}} +}; +void f() { + export int n; // expected-error {{expected expression}} +} #endif Added: cfe/trunk/test/SemaCXX/modules-ts.cppm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/modules-ts.cppm?rev=280999&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/modules-ts.cppm (added) +++ cfe/trunk/test/SemaCXX/modules-ts.cppm Thu Sep 8 18:14:54 2016 @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -DTEST=0 +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -o %t.pcm -verify -Dmodule=int -DTEST=1 +// RUN: not %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -DTEST=2 2>&1 | FileCheck %s --check-prefix=CHECK-2 +// RUN: %clang_cc1 -std=c++1z -fmodules-ts -emit-module-interface %s -fmodule-file=%t.pcm -o %t.pcm -verify -Dfoo=bar -DTEST=3 + +#if TEST == 0 +// expected-no-diagnostics +#endif + +module foo; +#if TEST == 1 +// expected-error@-2 {{expected module declaration at start of module interface}} +#elif TEST == 2 +// CHECK-2: error: redefinition of module 'foo' +#endif + +static int m; // ok, internal linkage, so no redefinition error +int n; +#if TEST == 3 +// expected-error@-2 {{redefinition of '}} +// expected-note@-3 {{previous}} +#endif + +#if TEST == 0 +export { + int a; + int b; + constexpr int *p = &n; +} +export int c; + +namespace N { + export void f() {} +} + +export struct T {} t; +#elif TEST == 3 +int use_a = a; // expected-error {{declaration of 'a' must be imported from module 'foo' before it is required}} +// expected-note@-13 {{previous}} + +#undef foo +import foo; + +export {} // expected-error {{export declaration cannot be empty}} +export { ; } +export { static_assert(true); } + +// FIXME: These diagnostics are not very good. +export import foo; // expected-error {{expected unqualified-id}} +export { import foo; } // expected-error {{expected unqualified-id}} + +int use_b = b; +int use_n = n; // FIXME: this should not be visible, because it is not exported + +extern int n; +static_assert(&n == p); // FIXME: these are not the same entity +#endif + + +#if TEST == 1 +struct S { + export int n; // expected-error {{expected member name or ';'}} + export static int n; // expected-error {{expected member name or ';'}} +}; +#endif + +// FIXME: Exports of declarations without external linkage are disallowed. +// Exports of declarations with non-external-linkage types are disallowed. Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=280999&r1=280998&r2=280999&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Thu Sep 8 18:14:54 2016 @@ -5635,6 +5635,7 @@ CXCursor clang_getCursorDefinition(CXCur case Decl::ObjCImplementation: case Decl::AccessSpec: case Decl::LinkageSpec: + case Decl::Export: case Decl::ObjCPropertyImpl: case Decl::FileScopeAsm: case Decl::StaticAssert: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits