r280999 - C++ Modules TS: Add parsing and some semantic analysis support for
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 8 16:14:55 PDT 2016
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 at -4 {{expected module declaration at start of module interface}}
-module foo;
-#if TEST == 1
-// expected-error at -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 at -2 {{redefinition of 'n'}}
-// expected-note at -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 at -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 at -2 {{redefinition of '}}
+// expected-note at -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 at -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:
More information about the cfe-commits
mailing list