diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-09-08 23:14:54 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-09-08 23:14:54 +0000 |
commit | 8df390f9ebc87702ae2b6155e5d81477c481db6f (patch) | |
tree | 493246882f1e97949bb1b2966ca99a3a1da21aaa /clang/lib | |
parent | 10037b93e90672f1819b3bc32d8d2dbeec68ae83 (diff) | |
download | bcm5719-llvm-8df390f9ebc87702ae2b6155e5d81477c481db6f.tar.gz bcm5719-llvm-8df390f9ebc87702ae2b6155e5d81477c481db6f.zip |
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.
llvm-svn: 280999
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 15 | ||||
-rw-r--r-- | clang/lib/AST/DeclBase.cpp | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 31 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 47 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 30 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTCommon.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 7 |
13 files changed, 145 insertions, 27 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index cfdd5579c3f..fec7df0ffb7 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4310,3 +4310,18 @@ SourceRange ImportDecl::getSourceRange() const { 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()); +} diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 4586d4bd2aa..4d4e725dbdd 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -672,6 +672,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case FriendTemplate: case AccessSpec: case LinkageSpec: + case Export: case FileScopeAsm: case StaticAssert: case ObjCPropertyImpl: @@ -957,7 +958,7 @@ bool DeclContext::isDependentContext() const { 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::getPrimaryContext() { 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::SingleElementDummyList = nullptr; 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) const { 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) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 5b4017cad37..a7920473d7c 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -78,6 +78,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::PragmaDetectMismatch: case Decl::AccessSpec: case Decl::LinkageSpec: + case Decl::Export: case Decl::ObjCPropertyImpl: case Decl::FileScopeAsm: case Decl::Friend: diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e296a4cc514..dad49f5dbca 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3754,17 +3754,6 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) { 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(const LinkageSpecDecl *LSD) { 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(Decl *D) { // 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(Decl *D) { break; } + case Decl::Export: + EmitDeclContext(cast<ExportDecl>(D)); + break; + case Decl::OMPThreadPrivate: EmitOMPThreadPrivateDecl(cast<OMPThreadPrivateDecl>(D)); break; diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index ed18156a082..a069ce1436e 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -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); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index ed99fedeab3..f7349b118f6 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -372,6 +372,53 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { : 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, diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 0a54ea0e6b8..8cc97e5f0d7 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -770,11 +770,17 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, : 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. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e6381fbe49f..773d00bf2d7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15422,6 +15422,36 @@ void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc, 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, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 40ad686321b..044a3aaa4bb 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1538,8 +1538,8 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) { // 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. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 7d573293f4e..bef36206e09 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5892,9 +5892,7 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { 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 diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index 07d0c1c9ae5..79ccffc5abb 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -183,6 +183,7 @@ serialization::getDefinitiveDeclContext(const DeclContext *DC) { 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::isRedeclarableDeclKind(unsigned Kind) { case Decl::ObjCProperty: case Decl::ObjCCompatibleAlias: case Decl::LinkageSpec: + case Decl::Export: case Decl::ObjCPropertyImpl: case Decl::PragmaComment: case Decl::PragmaDetectMismatch: diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 620e1fed300..3cc54048188 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -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(LinkageSpecDecl *D) { 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 ID) { 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; diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 158123b1c06..a923d276fe9 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -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(LinkageSpecDecl *D) { 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()); |