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