[cfe-commits] r138679 - in /cfe/trunk: include/clang/Basic/ include/clang/Frontend/ include/clang/Lex/ include/clang/Parse/ include/clang/Sema/ lib/Frontend/ lib/Lex/ lib/Parse/ lib/Sema/ test/Misc/ test/Modules/ test/Modules/Inputs/

Douglas Gregor dgregor at apple.com
Fri Aug 26 16:56:07 PDT 2011


Author: dgregor
Date: Fri Aug 26 18:56:07 2011
New Revision: 138679

URL: http://llvm.org/viewvc/llvm-project?rev=138679&view=rev
Log:
Introduce support for a simple module import declaration, which
loads the named module. The syntax itself is intentionally hideous and
will be replaced at some later point with something more
palatable. For now, we're focusing on the semantics:
  - Module imports are handled first by the preprocessor (to get macro
  definitions) and then the same tokens are also handled by the parser
  (to get declarations). If both happen (as in normal compilation),
  the second one is redundant, because we currently have no way to
  hide macros or declarations when loading a module. Chris gets credit
  for this mad-but-workable scheme.
  - The Preprocessor now holds on to a reference to a module loader,
  which is responsible for loading named modules. CompilerInstance is
  the only important module loader: it now knows how to create and
  wire up an AST reader on demand to actually perform the module load.
  - We search for modules in the include path, using the module name
  with the suffix ".pcm" (precompiled module) for the file name. This
  is a temporary hack; we hope to improve the situation in the
  future.


Added:
    cfe/trunk/test/Modules/Inputs/load_failure.h
    cfe/trunk/test/Modules/load_failure.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/include/clang/Frontend/ASTUnit.h
    cfe/trunk/include/clang/Frontend/CompilerInstance.h
    cfe/trunk/include/clang/Lex/ModuleLoader.h
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Lex/Lexer.cpp
    cfe/trunk/lib/Lex/Preprocessor.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Misc/warning-flags.c
    cfe/trunk/test/Modules/Inputs/diamond_bottom.h
    cfe/trunk/test/Modules/Inputs/diamond_left.h
    cfe/trunk/test/Modules/Inputs/diamond_right.h
    cfe/trunk/test/Modules/diamond.c
    cfe/trunk/test/Modules/lookup.cpp
    cfe/trunk/test/Modules/lookup.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Fri Aug 26 18:56:07 2011
@@ -59,7 +59,8 @@
   "cannot define a function with non-namespace scope in a friend declaration">;
 def err_deleted_non_function : Error<
   "only functions can have deleted definitions">;
-
+def warn_module_not_found : Warning<"module '%0' not found">, DefaultFatal;
+  
 // Sema && Lex
 def ext_longlong : Extension<
   "'long long' is an extension when C99 mode is not enabled">,

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Aug 26 18:56:07 2011
@@ -569,5 +569,11 @@
 def err_seh___finally_block : Error<
   "%0 only allowed in __finally block">;
 
+// Modules
+def err_module_expected_ident : Error<
+  "expected a module name after '__import__'">;
+def err_module_expected_semi : Error<
+  "expected a semicolon name after module name">;
+  
 } // end of Parse Issue category.
 } // end of Parser diagnostics

Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Fri Aug 26 18:56:07 2011
@@ -252,7 +252,7 @@
   void RecomputeNeedsHandleIdentifier() {
     NeedsHandleIdentifier =
       (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() |
-       isExtensionToken());
+       isExtensionToken() | getTokenID() == tok::kw___import__);
   }
 };
 

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Fri Aug 26 18:56:07 2011
@@ -397,6 +397,7 @@
 
 // Apple Extension.
 KEYWORD(__private_extern__          , KEYALL)
+KEYWORD(__import__                  , KEYALL)
 
 // Microsoft Extension.
 KEYWORD(__declspec                  , KEYALL)

Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Fri Aug 26 18:56:07 2011
@@ -18,6 +18,7 @@
 #include "clang/Serialization/ASTBitCodes.h"
 #include "clang/Sema/Sema.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/FileManager.h"
@@ -66,7 +67,7 @@
   
 /// \brief Utility class for loading a ASTContext from an AST file.
 ///
-class ASTUnit {
+class ASTUnit : public ModuleLoader {
 public:
   typedef std::map<FileID, std::vector<PreprocessedEntity *> > 
     PreprocessedEntitiesByFileMap;
@@ -696,6 +697,13 @@
   ///
   /// \returns True if an error occurred, false otherwise.
   bool serialize(raw_ostream &OS);
+  
+  virtual ModuleKey loadModule(SourceLocation ImportLoc, 
+                               IdentifierInfo &ModuleName,
+                               SourceLocation ModuleNameLoc) {
+    // ASTUnit doesn't know how to load modules (not that this matters).
+    return 0;
+  }
 };
 
 } // namespace clang

Modified: cfe/trunk/include/clang/Frontend/CompilerInstance.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInstance.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/CompilerInstance.h (original)
+++ cfe/trunk/include/clang/Frontend/CompilerInstance.h Fri Aug 26 18:56:07 2011
@@ -11,6 +11,7 @@
 #define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_
 
 #include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Lex/ModuleLoader.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/OwningPtr.h"
@@ -56,7 +57,7 @@
 /// in to the compiler instance for everything. When possible, utility functions
 /// come in two forms; a short form that reuses the CompilerInstance objects,
 /// and a long form that takes explicit instances of any required objects.
-class CompilerInstance {
+class CompilerInstance : public ModuleLoader {
   /// The options used in this compiler instance.
   llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation;
 
@@ -498,20 +499,6 @@
   /// and replace any existing one with it.
   void createPreprocessor();
 
-  /// Create a Preprocessor object.
-  ///
-  /// Note that this also creates a new HeaderSearch object which will be owned
-  /// by the resulting Preprocessor.
-  ///
-  /// \return The new object on success, or null on failure.
-  static Preprocessor *createPreprocessor(Diagnostic &, const LangOptions &,
-                                          const PreprocessorOptions &,
-                                          const HeaderSearchOptions &,
-                                          const DependencyOutputOptions &,
-                                          const TargetInfo &,
-                                          const FrontendOptions &,
-                                          SourceManager &, FileManager &);
-
   /// Create the AST context.
   void createASTContext();
 
@@ -626,6 +613,10 @@
                                       const FrontendOptions &Opts);
 
   /// }
+  
+  virtual ModuleKey loadModule(SourceLocation ImportLoc, 
+                               IdentifierInfo &ModuleName,
+                               SourceLocation ModuleNameLoc);
 };
 
 } // end namespace clang

Modified: cfe/trunk/include/clang/Lex/ModuleLoader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleLoader.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleLoader.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleLoader.h Fri Aug 26 18:56:07 2011
@@ -0,0 +1,55 @@
+//===--- ModuleLoader.h - Module Loader Interface ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the ModuleLoader interface, which is responsible for 
+//  loading named modules.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_MODULE_LOADER_H
+#define LLVM_CLANG_LEX_MODULE_LOADER_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+
+class IdentifierInfo;
+  
+/// \brief An opaque key that is used to describe the module and can be 
+/// interpreted by the module loader itself.
+typedef void *ModuleKey;
+  
+/// \brief Abstract interface for a module loader.
+///
+/// This abstract interface describes a module loader, which is responsible
+/// for resolving a module name (e.g., "std") to an actual module file, and
+/// then loading that module.
+class ModuleLoader {
+public:
+  virtual ~ModuleLoader();
+  
+  /// \brief Attempt to load the given module.
+  ///
+  /// This routine attempts to load the module described by the given 
+  /// parameters.
+  ///
+  /// \param ImportLoc The location of the 'import' keyword.
+  /// \param ModuleName The name of the module to be loaded.
+  /// \param ModuleNameLoc The location of the module name.
+  ///
+  /// \returns If successful, a non-NULL module key describing this module.
+  /// Otherwise, returns NULL to indicate that the module could not be
+  /// loaded.
+  virtual ModuleKey loadModule(SourceLocation ImportLoc, 
+                               IdentifierInfo &ModuleName,
+                               SourceLocation ModuleNameLoc) = 0;
+};
+  
+}
+
+#endif

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Fri Aug 26 18:56:07 2011
@@ -49,6 +49,7 @@
 class CodeCompletionHandler;
 class DirectoryLookup;
 class PreprocessingRecord;
+class ModuleLoader;
   
 /// Preprocessor - This object engages in a tight little dance with the lexer to
 /// efficiently preprocess tokens.  Lexers know only about tokens within a
@@ -63,10 +64,12 @@
   SourceManager     &SourceMgr;
   ScratchBuffer     *ScratchBuf;
   HeaderSearch      &HeaderInfo;
+  ModuleLoader      &TheModuleLoader;
 
   /// \brief External source of macros.
   ExternalPreprocessorSource *ExternalSource;
 
+  
   /// PTH - An optional PTHManager object used for getting tokens from
   ///  a token cache rather than lexing the original source file.
   llvm::OwningPtr<PTHManager> PTH;
@@ -294,6 +297,7 @@
   Preprocessor(Diagnostic &diags, const LangOptions &opts,
                const TargetInfo &target,
                SourceManager &SM, HeaderSearch &Headers,
+               ModuleLoader &TheModuleLoader,
                IdentifierInfoLookup *IILookup = 0,
                bool OwnsHeaderSearch = false);
 
@@ -325,6 +329,9 @@
     return ExternalSource;
   }
 
+  /// \brief Retrieve the module loader associated with this preprocessor.
+  ModuleLoader &getModuleLoader() const { return TheModuleLoader; }
+  
   /// SetCommentRetentionState - Control whether or not the preprocessor retains
   /// comments in output.
   void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
@@ -1008,6 +1015,9 @@
   /// the macro should not be expanded return true, otherwise return false.
   bool HandleMacroExpandedIdentifier(Token &Tok, MacroInfo *MI);
 
+  /// \brief Handle a module import directive.
+  void HandleModuleImport(Token &Import);
+  
   /// \brief Cache macro expanded tokens for TokenLexers.
   //
   /// Works like a stack; a TokenLexer adds the macro expanded tokens that is

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Aug 26 18:56:07 2011
@@ -1916,6 +1916,10 @@
                                         SourceLocation &DeclEnd);
 
   //===--------------------------------------------------------------------===//
+  // Modules
+  DeclGroupPtrTy ParseModuleImport();
+  
+  //===--------------------------------------------------------------------===//
   // GNU G++: Type Traits [Type-Traits.html in the GCC manual]
   ExprResult ParseUnaryTypeTrait();
   ExprResult ParseBinaryTypeTrait();

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Aug 26 18:56:07 2011
@@ -1073,6 +1073,17 @@
                               SourceLocation AsmLoc,
                               SourceLocation RParenLoc);
 
+  /// \brief The parser has processed a module import declaration.
+  ///
+  /// \param ImportLoc The location of the '__import__' keyword.
+  ///
+  /// \param ModuleName The name of the module.
+  ///
+  /// \param ModuleNameLoc The location of the module name.
+  DeclResult ActOnModuleImport(SourceLocation ImportLoc,
+                               IdentifierInfo &ModuleName,
+                               SourceLocation ModuleNameLoc);
+  
   /// Scope actions.
   void ActOnPopScope(SourceLocation Loc, Scope *S);
   void ActOnTranslationUnitScope(Scope *S);

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Fri Aug 26 18:56:07 2011
@@ -616,7 +616,7 @@
   AST->Target = TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
                                              TargetOpts);
   AST->PP = new Preprocessor(AST->getDiagnostics(), LangInfo, *AST->Target,
-                             AST->getSourceManager(), HeaderInfo);
+                             AST->getSourceManager(), HeaderInfo, *AST);
   Preprocessor &PP = *AST->PP;
 
   PP.setPredefines(Reader->getSuggestedPredefines());

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Fri Aug 26 18:56:07 2011
@@ -191,52 +191,38 @@
 // Preprocessor
 
 void CompilerInstance::createPreprocessor() {
-  PP = createPreprocessor(getDiagnostics(), getLangOpts(),
-                          getPreprocessorOpts(), getHeaderSearchOpts(),
-                          getDependencyOutputOpts(), getTarget(),
-                          getFrontendOpts(), getSourceManager(),
-                          getFileManager());
-}
-
-Preprocessor *
-CompilerInstance::createPreprocessor(Diagnostic &Diags,
-                                     const LangOptions &LangInfo,
-                                     const PreprocessorOptions &PPOpts,
-                                     const HeaderSearchOptions &HSOpts,
-                                     const DependencyOutputOptions &DepOpts,
-                                     const TargetInfo &Target,
-                                     const FrontendOptions &FEOpts,
-                                     SourceManager &SourceMgr,
-                                     FileManager &FileMgr) {
+  const PreprocessorOptions &PPOpts = getPreprocessorOpts();
+  
   // Create a PTH manager if we are using some form of a token cache.
   PTHManager *PTHMgr = 0;
   if (!PPOpts.TokenCache.empty())
-    PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
-
+    PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics());
+  
   // Create the Preprocessor.
-  HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
-  Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
-                                      SourceMgr, *HeaderInfo, PTHMgr,
-                                      /*OwnsHeaderSearch=*/true);
-
+  HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager());
+  PP = new Preprocessor(getDiagnostics(), getLangOpts(), getTarget(),
+                        getSourceManager(), *HeaderInfo, *this, PTHMgr,
+                        /*OwnsHeaderSearch=*/true);
+  
   // Note that this is different then passing PTHMgr to Preprocessor's ctor.
   // That argument is used as the IdentifierInfoLookup argument to
   // IdentifierTable's ctor.
   if (PTHMgr) {
-    PTHMgr->setPreprocessor(PP);
+    PTHMgr->setPreprocessor(&*PP);
     PP->setPTHManager(PTHMgr);
   }
-
+  
   if (PPOpts.DetailedRecord)
     PP->createPreprocessingRecord(
-                       PPOpts.DetailedRecordIncludesNestedMacroExpansions);
+                                  PPOpts.DetailedRecordIncludesNestedMacroExpansions);
+  
+  InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts());
   
-  InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
-
   // Handle generating dependencies, if requested.
+  const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
   if (!DepOpts.OutputFile.empty())
     AttachDependencyFileGen(*PP, DepOpts);
-
+  
   // Handle generating header include information, if requested.
   if (DepOpts.ShowHeaderIncludes)
     AttachHeaderIncludeGen(*PP);
@@ -247,8 +233,6 @@
     AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath,
                            /*ShowDepth=*/false);
   }
-
-  return PP;
 }
 
 // ASTContext
@@ -640,4 +624,68 @@
   return !getDiagnostics().getClient()->getNumErrors();
 }
 
+ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc, 
+                                       IdentifierInfo &ModuleName,
+                                       SourceLocation ModuleNameLoc) {  
+  // Determine what file we're searching from.
+  SourceManager &SourceMgr = getSourceManager();
+  SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc);
+  const FileEntry *CurFile
+    = SourceMgr.getFileEntryForID(SourceMgr.getFileID(ExpandedImportLoc));
+  if (!CurFile)
+    CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+
+  // Search for a module with the given name.
+  std::string Filename = ModuleName.getName().str();
+  Filename += ".pcm";
+  const DirectoryLookup *CurDir = 0;  
+  const FileEntry *ModuleFile
+    = PP->getHeaderSearchInfo().LookupFile(Filename, /*isAngled=*/false,
+                                           /*FromDir=*/0, CurDir, CurFile, 
+                                           /*SearchPath=*/0, 
+                                           /*RelativePath=*/0);
+  if (!ModuleFile) {
+    getDiagnostics().Report(ModuleNameLoc, diag::warn_module_not_found)
+      << ModuleName.getName()
+      << SourceRange(ImportLoc, ModuleNameLoc);
+    return 0;
+  }
+  
+  // If we don't already have an ASTReader, create one now.
+  if (!ModuleManager) {
+    std::string Sysroot = getHeaderSearchOpts().Sysroot;
+    const PreprocessorOptions &PPOpts = getPreprocessorOpts();
+    ModuleManager = new ASTReader(getPreprocessor(), &*Context,
+                                  Sysroot.empty() ? "" : Sysroot.c_str(),
+                                  PPOpts.DisablePCHValidation, 
+                                  PPOpts.DisableStatCache);
+    ModuleManager->setDeserializationListener(
+      getASTConsumer().GetASTDeserializationListener());
+    getASTContext().setASTMutationListener(
+      getASTConsumer().GetASTMutationListener());
+    llvm::OwningPtr<ExternalASTSource> Source;
+    Source.reset(ModuleManager);
+    getASTContext().setExternalSource(Source);
+    ModuleManager->InitializeSema(getSema());
+  }
+  
+  // Try to load the module we found.
+  switch (ModuleManager->ReadAST(ModuleFile->getName(),
+                                 serialization::MK_Module)) {
+  case ASTReader::Success:
+    break;
+
+  case ASTReader::IgnorePCH:
+    // FIXME: The ASTReader will already have complained, but can we showhorn
+    // that diagnostic information into a more useful form?
+    return 0;
+      
+  case ASTReader::Failure:
+    // Already complained.
+    return 0;
+  }
+  
+  // FIXME: The module file's FileEntry makes a poor key indeed!
+  return (ModuleKey)ModuleFile;
+}
 

Modified: cfe/trunk/lib/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Lexer.cpp?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Lexer.cpp (original)
+++ cfe/trunk/lib/Lex/Lexer.cpp Fri Aug 26 18:56:07 2011
@@ -1277,6 +1277,7 @@
     // preprocessor, which may macro expand it or something.
     if (II->isHandleIdentifierCase())
       PP->HandleIdentifier(Result);
+    
     return;
   }
 

Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Fri Aug 26 18:56:07 2011
@@ -35,6 +35,7 @@
 #include "clang/Lex/ScratchBuffer.h"
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Lex/ModuleLoader.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/TargetInfo.h"
@@ -50,12 +51,12 @@
 
 Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
                            const TargetInfo &target, SourceManager &SM,
-                           HeaderSearch &Headers,
+                           HeaderSearch &Headers, ModuleLoader &TheModuleLoader,
                            IdentifierInfoLookup* IILookup,
                            bool OwnsHeaders)
   : Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
-    SourceMgr(SM),
-    HeaderInfo(Headers), ExternalSource(0),
+    SourceMgr(SM), HeaderInfo(Headers), TheModuleLoader(TheModuleLoader),
+    ExternalSource(0), 
     Identifiers(opts, IILookup), BuiltinInfo(Target), CodeComplete(0),
     CodeCompletionFile(0), SkipMainFilePreamble(0, true), CurPPLexer(0), 
     CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0), MIChainHead(0),
@@ -483,7 +484,7 @@
     if (!DisableMacroExpansion && !Identifier.isExpandDisabled()) {
       if (MI->isEnabled()) {
         if (!HandleMacroExpandedIdentifier(Identifier, MI))
-          return;
+          goto finish;
       } else {
         // C99 6.10.3.4p2 says that a disabled macro may never again be
         // expanded, even if it's in a context where it could be expanded in the
@@ -505,6 +506,33 @@
   // like "#define TY typeof", "TY(1) x".
   if (II.isExtensionToken() && !DisableMacroExpansion)
     Diag(Identifier, diag::ext_token_used);
+  
+finish:
+  // If we have the start of a module import, handle it now.
+  if (Identifier.is(tok::kw___import__) &&
+      !InMacroArgs && !DisableMacroExpansion)
+    HandleModuleImport(Identifier);
+}
+
+void Preprocessor::HandleModuleImport(Token &Import) {
+  // The token sequence 
+  //
+  //   __import__ identifier
+  //
+  // indicates a module import directive. We load the module and then 
+  // leave the token sequence for the parser.
+  Token ModuleNameTok = LookAhead(0);
+  if (ModuleNameTok.getKind() != tok::identifier)
+    return;
+  
+  (void)TheModuleLoader.loadModule(Import.getLocation(),
+                                   *ModuleNameTok.getIdentifierInfo(), 
+                                   ModuleNameTok.getLocation());
+  
+  // FIXME: Transmogrify __import__ into some kind of AST-only __import__ that
+  // is not recognized by the preprocessor but is recognized by the parser.
+  // It would also be useful to stash the ModuleKey somewhere, so we don't try
+  // to load the module twice.
 }
 
 void Preprocessor::AddCommentHandler(CommentHandler *Handler) {
@@ -535,6 +563,8 @@
   return true;
 }
 
+ModuleLoader::~ModuleLoader() { }
+
 CommentHandler::~CommentHandler() { }
 
 CodeCompletionHandler::~CodeCompletionHandler() { }

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Fri Aug 26 18:56:07 2011
@@ -679,6 +679,9 @@
     ParseMicrosoftIfExistsExternalDeclaration();
     return DeclGroupPtrTy();
 
+  case tok::kw___import__:
+    return ParseModuleImport();
+      
   default:
   dont_know:
     // We can't tell whether this is a function-definition or declaration yet.
@@ -1541,3 +1544,24 @@
   }
   ConsumeBrace();
 }
+
+Parser::DeclGroupPtrTy Parser::ParseModuleImport() {
+  assert(Tok.is(tok::kw___import__) && "Improper start to module import");
+  SourceLocation ImportLoc = ConsumeToken();
+  
+  // Parse the module name.
+  if (!Tok.is(tok::identifier)) {
+    Diag(Tok, diag::err_module_expected_ident);
+    SkipUntil(tok::semi);
+    return DeclGroupPtrTy();
+  }
+  
+  IdentifierInfo &ModuleName = *Tok.getIdentifierInfo();
+  SourceLocation ModuleNameLoc = ConsumeToken();
+  DeclResult Import = Actions.ActOnModuleImport(ImportLoc, ModuleName, ModuleNameLoc);
+  ExpectAndConsumeSemi(diag::err_module_expected_semi);
+  if (Import.isInvalid())
+    return DeclGroupPtrTy();
+  
+  return Actions.ConvertDeclToDeclGroup(Import.get());
+}

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Aug 26 18:56:07 2011
@@ -38,6 +38,7 @@
 // FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's)
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/ModuleLoader.h"
 #include "llvm/ADT/Triple.h"
 #include <algorithm>
 #include <cstring>
@@ -9294,6 +9295,19 @@
   return New;
 }
 
+DeclResult Sema::ActOnModuleImport(SourceLocation ImportLoc,
+                                   IdentifierInfo &ModuleName,
+                                   SourceLocation ModuleNameLoc) {
+  ModuleKey Module = PP.getModuleLoader().loadModule(ImportLoc, 
+                                                     ModuleName, ModuleNameLoc);
+  if (!Module)
+    return true;
+  
+  // FIXME: Actually create a declaration to describe the module import.
+  (void)Module;
+  return DeclResult((Decl *)0);
+}
+
 void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
                              SourceLocation PragmaLoc,
                              SourceLocation NameLoc) {

Modified: cfe/trunk/test/Misc/warning-flags.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/warning-flags.c?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/test/Misc/warning-flags.c (original)
+++ cfe/trunk/test/Misc/warning-flags.c Fri Aug 26 18:56:07 2011
@@ -17,7 +17,7 @@
 
 The list of warnings below should NEVER grow.  It should gradually shrink to 0.
 
-CHECK: Warnings without flags (312):
+CHECK: Warnings without flags (313):
 CHECK-NEXT:   auto_storage_class
 CHECK-NEXT:   backslash_newline_space
 CHECK-NEXT:   charize_microsoft_ext
@@ -230,6 +230,7 @@
 CHECK-NEXT:   warn_missing_dependent_template_keyword
 CHECK-NEXT:   warn_missing_exception_specification
 CHECK-NEXT:   warn_missing_whitespace_after_macro_name
+CHECK-NEXT:   warn_module_not_found
 CHECK-NEXT:   warn_multiple_method_decl
 CHECK-NEXT:   warn_no_constructor_for_refconst
 CHECK-NEXT:   warn_nonnull_pointers_only

Modified: cfe/trunk/test/Modules/Inputs/diamond_bottom.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/diamond_bottom.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/diamond_bottom.h (original)
+++ cfe/trunk/test/Modules/Inputs/diamond_bottom.h Fri Aug 26 18:56:07 2011
@@ -1 +1,4 @@
+__import__ diamond_left;
+__import__ diamond_right;
+
 char bottom(char *x);

Modified: cfe/trunk/test/Modules/Inputs/diamond_left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/diamond_left.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/diamond_left.h (original)
+++ cfe/trunk/test/Modules/Inputs/diamond_left.h Fri Aug 26 18:56:07 2011
@@ -1,3 +1,5 @@
+__import__ diamond_top;
+
 float left(float *);
 
 int top_left(char *c);

Modified: cfe/trunk/test/Modules/Inputs/diamond_right.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/diamond_right.h?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/diamond_right.h (original)
+++ cfe/trunk/test/Modules/Inputs/diamond_right.h Fri Aug 26 18:56:07 2011
@@ -1,3 +1,5 @@
+__import__ diamond_top;
+
 double right(double *);
 
 struct left_and_right {

Added: cfe/trunk/test/Modules/Inputs/load_failure.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/load_failure.h?rev=138679&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/load_failure.h (added)
+++ cfe/trunk/test/Modules/Inputs/load_failure.h Fri Aug 26 18:56:07 2011
@@ -0,0 +1 @@
+int fail(int);

Modified: cfe/trunk/test/Modules/diamond.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/diamond.c?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/test/Modules/diamond.c (original)
+++ cfe/trunk/test/Modules/diamond.c Fri Aug 26 18:56:07 2011
@@ -1,4 +1,10 @@
+
+
+
 // in diamond-bottom.h: expected-note{{passing argument to parameter 'x' here}}
+
+__import__ diamond_bottom;
+
 void test_diamond(int i, float f, double d, char c) {
   top(&i);
   left(&f);
@@ -14,8 +20,8 @@
   lr.left = 17;
 }
 
-// RUN: %clang_cc1 -emit-pch -o %t_top.h.pch %S/Inputs/diamond_top.h
-// RUN: %clang_cc1 -import-module %t_top.h.pch -emit-pch -o %t_left.h.pch %S/Inputs/diamond_left.h
-// RUN: %clang_cc1 -import-module %t_top.h.pch -emit-pch -o %t_right.h.pch %S/Inputs/diamond_right.h
-// RUN: %clang_cc1 -import-module %t_left.h.pch -import-module %t_right.h.pch -emit-pch -o %t_bottom.h.pch %S/Inputs/diamond_bottom.h
-// RUN: %clang_cc1 -import-module %t_bottom.h.pch -verify %s 
+// RUN: %clang_cc1 -emit-module -o %T/diamond_top.pcm %S/Inputs/diamond_top.h
+// RUN: %clang_cc1 -I %T -emit-module -o %T/diamond_left.pcm %S/Inputs/diamond_left.h
+// RUN: %clang_cc1 -I %T -emit-module -o %T/diamond_right.pcm %S/Inputs/diamond_right.h
+// RUN: %clang_cc1 -I %T -emit-module -o %T/diamond_bottom.pcm %S/Inputs/diamond_bottom.h
+// RUN: %clang_cc1 -I %T %s -verify

Added: cfe/trunk/test/Modules/load_failure.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/load_failure.c?rev=138679&view=auto
==============================================================================
--- cfe/trunk/test/Modules/load_failure.c (added)
+++ cfe/trunk/test/Modules/load_failure.c Fri Aug 26 18:56:07 2011
@@ -0,0 +1,17 @@
+#ifdef NONEXISTENT
+__import__ load_nonexistent;
+#endif
+
+#ifdef FAILURE
+__import__ load_failure;
+#endif
+
+// RUN: %clang_cc1 -x c++ -emit-module -o %T/load_failure.pcm %S/Inputs/load_failure.h
+// RUN: %clang_cc1 -I %T %s -DNONEXISTENT 2>&1 | FileCheck -check-prefix=CHECK-NONEXISTENT %s
+// CHECK-NONEXISTENT: load_failure.c:2:12: fatal error: module 'load_nonexistent' not found
+
+// RUN: %clang_cc1 -I %T %s -DFAILURE 2>&1 | FileCheck -check-prefix=CHECK-FAILURE %s
+// FIXME: Clean up diagnostic text below and give it a location
+// CHECK-FAILURE: error: C99 support was disabled in PCH file but is currently enabled
+
+

Modified: cfe/trunk/test/Modules/lookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/lookup.cpp?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/test/Modules/lookup.cpp (original)
+++ cfe/trunk/test/Modules/lookup.cpp Fri Aug 26 18:56:07 2011
@@ -1,3 +1,9 @@
+
+#define import __import__
+import lookup_left_cxx;
+#define IMPORT(X) __import__ X
+IMPORT(lookup_right_cxx);
+
 void test(int i, float f) {
   // unqualified lookup
   f0(&i);
@@ -8,10 +14,10 @@
   ::f0(&f);
 }
 
-// RUN: %clang_cc1 -emit-module -x c++ -verify -o %t_lookup_left.h.pch %S/Inputs/lookup_left.hpp
-// RUN: %clang_cc1 -emit-module -x c++ -o %t_lookup_right.h.pch %S/Inputs/lookup_right.hpp
-// RUN: %clang_cc1 -x c++ -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch -verify %s
-// RUN: %clang_cc1 -ast-print -x c++ -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch %s | FileCheck -check-prefix=CHECK-PRINT %s
+// RUN: %clang_cc1 -emit-module -x c++ -verify -o %T/lookup_left_cxx.pcm %S/Inputs/lookup_left.hpp
+// RUN: %clang_cc1 -emit-module -x c++ -o %T/lookup_right_cxx.pcm %S/Inputs/lookup_right.hpp
+// RUN: %clang_cc1 -x c++ -I %T %s -verify
+// RUN: %clang_cc1 -ast-print -x c++ -I %T %s | FileCheck -check-prefix=CHECK-PRINT %s
 
 // CHECK-PRINT: int *f0(int *);
 // CHECK-PRINT: float *f0(float *);

Modified: cfe/trunk/test/Modules/lookup.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/lookup.m?rev=138679&r1=138678&r2=138679&view=diff
==============================================================================
--- cfe/trunk/test/Modules/lookup.m (original)
+++ cfe/trunk/test/Modules/lookup.m Fri Aug 26 18:56:07 2011
@@ -1,15 +1,17 @@
 
 // lookup_left.h: expected-note{{using}}
 // lookup_right.h: expected-note{{also found}}
+__import__ lookup_left_objc;
+__import__ lookup_right_objc;
 
 void test(id x) {
   [x method]; // expected-warning{{multiple methods named 'method' found}}
 }
 
-// RUN: %clang_cc1 -emit-module -x objective-c -o %t_lookup_left.h.pch %S/Inputs/lookup_left.h
-// RUN: %clang_cc1 -emit-module -x objective-c -o %t_lookup_right.h.pch %S/Inputs/lookup_right.h
-// RUN: %clang_cc1 -x objective-c -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch -verify %s
-// RUN: %clang_cc1 -ast-print -x objective-c -import-module %t_lookup_left.h.pch -import-module %t_lookup_right.h.pch %s | FileCheck -check-prefix=CHECK-PRINT %s
+// RUN: %clang_cc1 -emit-module -x objective-c -o %T/lookup_left_objc.pcm %S/Inputs/lookup_left.h
+// RUN: %clang_cc1 -emit-module -x objective-c -o %T/lookup_right_objc.pcm %S/Inputs/lookup_right.h
+// RUN: %clang_cc1 -x objective-c -I %T -verify %s
+// RUN: %clang_cc1 -ast-print -x objective-c -I %T %s | FileCheck -check-prefix=CHECK-PRINT %s
 
 // CHECK-PRINT: - (int) method;
 // CHECK-PRINT: - (double) method





More information about the cfe-commits mailing list