summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-09-08 23:14:54 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-09-08 23:14:54 +0000
commit8df390f9ebc87702ae2b6155e5d81477c481db6f (patch)
tree493246882f1e97949bb1b2966ca99a3a1da21aaa /clang/lib
parent10037b93e90672f1819b3bc32d8d2dbeec68ae83 (diff)
downloadbcm5719-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.cpp15
-rw-r--r--clang/lib/AST/DeclBase.cpp12
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp1
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp31
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h2
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp47
-rw-r--r--clang/lib/Parse/Parser.cpp8
-rw-r--r--clang/lib/Sema/SemaDecl.cpp30
-rw-r--r--clang/lib/Sema/SemaLookup.cpp4
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp4
-rw-r--r--clang/lib/Serialization/ASTCommon.cpp2
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp9
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp7
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());
OpenPOWER on IntegriCloud