"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">,
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
void RecomputeNeedsHandleIdentifier() {
NeedsHandleIdentifier =
(isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() |
- isExtensionToken());
+ isExtensionToken() | getTokenID() == tok::kw___import__);
}
};
// Apple Extension.
KEYWORD(__private_extern__ , KEYALL)
+KEYWORD(__import__ , KEYALL)
// Microsoft Extension.
KEYWORD(__declspec , KEYALL)
#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"
/// \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;
///
/// \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
#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"
/// 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;
/// 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();
const FrontendOptions &Opts);
/// }
+
+ virtual ModuleKey loadModule(SourceLocation ImportLoc,
+ IdentifierInfo &ModuleName,
+ SourceLocation ModuleNameLoc);
};
} // end namespace clang
+//===--- 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
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
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;
Preprocessor(Diagnostic &diags, const LangOptions &opts,
const TargetInfo &target,
SourceManager &SM, HeaderSearch &Headers,
+ ModuleLoader &TheModuleLoader,
IdentifierInfoLookup *IILookup = 0,
bool OwnsHeaderSearch = false);
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) {
/// 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
SourceLocation TemplateLoc,
SourceLocation &DeclEnd);
+ //===--------------------------------------------------------------------===//
+ // Modules
+ DeclGroupPtrTy ParseModuleImport();
+
//===--------------------------------------------------------------------===//
// GNU G++: Type Traits [Type-Traits.html in the GCC manual]
ExprResult ParseUnaryTypeTrait();
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);
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());
// 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);
AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath,
/*ShowDepth=*/false);
}
-
- return PP;
}
// ASTContext
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;
+}
// preprocessor, which may macro expand it or something.
if (II->isHandleIdentifierCase())
PP->HandleIdentifier(Result);
+
return;
}
#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"
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),
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
// 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) {
return true;
}
+ModuleLoader::~ModuleLoader() { }
+
CommentHandler::~CommentHandler() { }
CodeCompletionHandler::~CodeCompletionHandler() { }
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.
}
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());
+}
// 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>
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) {
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
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
+__import__ diamond_left;
+__import__ diamond_right;
+
char bottom(char *x);
+__import__ diamond_top;
+
float left(float *);
int top_left(char *c);
+__import__ diamond_top;
+
double right(double *);
struct left_and_right {
--- /dev/null
+int fail(int);
+
+
+
// 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);
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
--- /dev/null
+#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
+
+
+
+#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);
::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 *);
// 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