forked from OSchip/llvm-project
Add an experimental flag -fauto-module-import that automatically turns
#include or #import direcctives of framework headers into module imports of the corresponding framework module. llvm-svn: 139860
This commit is contained in:
parent
112ec17e1b
commit
97eec24b0b
|
@ -607,7 +607,10 @@ def fmodule_cache_path : Separate<"-fmodule-cache-path">,
|
|||
HelpText<"Specify the module cache path">;
|
||||
def fdisable_module_hash : Flag<"-fdisable-module-hash">,
|
||||
HelpText<"Disable the module hash">;
|
||||
|
||||
def fauto_module_import : Flag<"-fauto-module-import">,
|
||||
HelpText<"Automatically translate #include/#import into module imports "
|
||||
"when possible">;
|
||||
|
||||
def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">,
|
||||
HelpText<"Add directory to framework include search path">;
|
||||
def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">,
|
||||
|
|
|
@ -344,6 +344,9 @@ def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>;
|
|||
def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, Group<f_Group>;
|
||||
def fmodule_cache_path : Separate<"-fmodule-cache-path">, Group<i_Group>,
|
||||
Flags<[NoForward]>;
|
||||
def fauto_module_import : Flag <"-fauto-module-import">, Group<f_Group>,
|
||||
Flags<[NoForward]>;
|
||||
|
||||
def fmudflapth : Flag<"-fmudflapth">, Group<f_Group>;
|
||||
def fmudflap : Flag<"-fmudflap">, Group<f_Group>;
|
||||
def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>;
|
||||
|
|
|
@ -50,6 +50,10 @@ public:
|
|||
/// record of all macro definitions and
|
||||
/// expansions.
|
||||
|
||||
/// \brief Whether we should automatically translate #include or #import
|
||||
/// operations into module imports when possible.
|
||||
unsigned AutoModuleImport : 1;
|
||||
|
||||
/// \brief Whether the detailed preprocessing record includes nested macro
|
||||
/// expansions.
|
||||
unsigned DetailedRecordIncludesNestedMacroExpansions : 1;
|
||||
|
@ -162,6 +166,7 @@ public:
|
|||
|
||||
public:
|
||||
PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
|
||||
AutoModuleImport(false),
|
||||
DetailedRecordIncludesNestedMacroExpansions(true),
|
||||
DisablePCHValidation(false), DisableStatCache(false),
|
||||
DumpDeserializedPCHDecls(false),
|
||||
|
|
|
@ -140,15 +140,25 @@ public:
|
|||
/// \param RelativePath If not NULL, will be set to the path relative to
|
||||
/// SearchPath at which the file was found. This only differs from the
|
||||
/// Filename for framework includes.
|
||||
///
|
||||
/// \param BuildingModule The name of the module we're currently building.
|
||||
///
|
||||
/// \param SuggestedModule If non-null, and the file found is semantically
|
||||
/// part of a known module, this will be set to the name of the module that
|
||||
/// could be imported instead of preprocessing/parsing the file found.
|
||||
const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath) const;
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
StringRef BuildingModule,
|
||||
StringRef *SuggestedModule) const;
|
||||
|
||||
private:
|
||||
const FileEntry *DoFrameworkLookup(
|
||||
StringRef Filename, HeaderSearch &HS,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath) const;
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
StringRef BuildingModule,
|
||||
StringRef *SuggestedModule) const;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -132,6 +132,9 @@ class HeaderSearch {
|
|||
/// \brief The path to the module cache.
|
||||
std::string ModuleCachePath;
|
||||
|
||||
/// \brief The name of the module we're building.
|
||||
std::string BuildingModule;
|
||||
|
||||
/// FileInfo - This contains all of the preprocessor-specific data about files
|
||||
/// that are included. The vector is indexed by the FileEntry's UID.
|
||||
///
|
||||
|
@ -196,9 +199,11 @@ public:
|
|||
//LookupFileCache.clear();
|
||||
}
|
||||
|
||||
/// \brief Set the path to the module cache.
|
||||
void setModuleCachePath(StringRef Path) {
|
||||
ModuleCachePath = Path;
|
||||
/// \brief Set the path to the module cache and the name of the module
|
||||
/// we're building
|
||||
void configureModules(StringRef CachePath, StringRef BuildingModule) {
|
||||
ModuleCachePath = CachePath;
|
||||
this->BuildingModule = BuildingModule;
|
||||
}
|
||||
|
||||
/// ClearFileInfo - Forget everything we know about headers so far.
|
||||
|
@ -240,12 +245,17 @@ public:
|
|||
/// \param RelativePath If non-null, will be set to the path relative to
|
||||
/// SearchPath at which the file was found. This only differs from the
|
||||
/// Filename for framework includes.
|
||||
///
|
||||
/// \param SuggestedModule If non-null, and the file found is semantically
|
||||
/// part of a known module, this will be set to the name of the module that
|
||||
/// could be imported instead of preprocessing/parsing the file found.
|
||||
const FileEntry *LookupFile(StringRef Filename, bool isAngled,
|
||||
const DirectoryLookup *FromDir,
|
||||
const DirectoryLookup *&CurDir,
|
||||
const FileEntry *CurFileEnt,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath);
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
StringRef *SuggestedModule);
|
||||
|
||||
/// LookupSubframeworkHeader - Look up a subframework for the specified
|
||||
/// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from
|
||||
|
|
|
@ -106,7 +106,8 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> {
|
|||
bool KeepComments : 1;
|
||||
bool KeepMacroComments : 1;
|
||||
bool SuppressIncludeNotFoundError : 1;
|
||||
|
||||
bool AutoModuleImport : 1;
|
||||
|
||||
// State that changes while the preprocessor runs:
|
||||
bool InMacroArgs : 1; // True if parsing fn macro invocation args.
|
||||
|
||||
|
@ -383,6 +384,11 @@ public:
|
|||
return SuppressIncludeNotFoundError;
|
||||
}
|
||||
|
||||
/// \brief Specify whether automatic module imports are enabled.
|
||||
void setAutoModuleImport(bool AutoModuleImport = true) {
|
||||
this->AutoModuleImport = AutoModuleImport;
|
||||
}
|
||||
|
||||
/// isCurrentLexer - Return true if we are lexing directly from the specified
|
||||
/// lexer.
|
||||
bool isCurrentLexer(const PreprocessorLexer *L) const {
|
||||
|
@ -973,7 +979,8 @@ public:
|
|||
bool isAngled, const DirectoryLookup *FromDir,
|
||||
const DirectoryLookup *&CurDir,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath);
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
StringRef *SuggestedModule);
|
||||
|
||||
/// GetCurLookup - The DirectoryLookup structure used to find the current
|
||||
/// FileEntry, if CurLexer is non-null and if applicable. This allows us to
|
||||
|
|
|
@ -390,6 +390,8 @@ void Clang::AddPreprocessingOptions(const Driver &D,
|
|||
CmdArgs.push_back("-fmodule-cache-path");
|
||||
CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache));
|
||||
}
|
||||
|
||||
Args.AddAllArgs(CmdArgs, options::OPT_fauto_module_import);
|
||||
}
|
||||
|
||||
/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting.
|
||||
|
|
|
@ -228,7 +228,10 @@ void CompilerInstance::createPreprocessor() {
|
|||
if (!getHeaderSearchOpts().DisableModuleHash)
|
||||
llvm::sys::path::append(SpecificModuleCache,
|
||||
getInvocation().getModuleHash());
|
||||
PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache);
|
||||
PP->getHeaderSearchInfo().configureModules(SpecificModuleCache,
|
||||
getPreprocessorOpts().ModuleBuildPath.empty()
|
||||
? std::string()
|
||||
: getPreprocessorOpts().ModuleBuildPath.back());
|
||||
|
||||
// Handle generating dependencies, if requested.
|
||||
const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
|
||||
|
|
|
@ -1753,6 +1753,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
|
|||
Opts.TokenCache = Opts.ImplicitPTHInclude;
|
||||
Opts.UsePredefines = !Args.hasArg(OPT_undef);
|
||||
Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
|
||||
Opts.AutoModuleImport = Args.hasArg(OPT_fauto_module_import);
|
||||
Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
|
||||
|
||||
Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls);
|
||||
|
|
|
@ -710,6 +710,10 @@ void clang::InitializePreprocessor(Preprocessor &PP,
|
|||
InitializeFileRemapping(PP.getDiagnostics(), PP.getSourceManager(),
|
||||
PP.getFileManager(), InitOpts);
|
||||
|
||||
// Specify whether the preprocessor should replace #include/#import with
|
||||
// module imports when plausible.
|
||||
PP.setAutoModuleImport(InitOpts.AutoModuleImport);
|
||||
|
||||
// Emit line markers for various builtin sections of the file. We don't do
|
||||
// this in asm preprocessor mode, because "# 4" is not a line marker directive
|
||||
// in this mode.
|
||||
|
@ -783,7 +787,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
|
|||
|
||||
// Copy PredefinedBuffer into the Preprocessor.
|
||||
PP.setPredefines(Predefines.str());
|
||||
|
||||
|
||||
// Initialize the header search object.
|
||||
ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), HSOpts,
|
||||
PP.getLangOptions(),
|
||||
|
|
|
@ -139,7 +139,8 @@ const FileEntry *HeaderSearch::lookupModule(StringRef ModuleName,
|
|||
|
||||
// Look for the umbrella header in this directory.
|
||||
if (const FileEntry *HeaderFile
|
||||
= SearchDirs[Idx].LookupFile(UmbrellaHeaderName, *this, 0, 0)) {
|
||||
= SearchDirs[Idx].LookupFile(UmbrellaHeaderName, *this, 0, 0,
|
||||
StringRef(), 0)) {
|
||||
*UmbrellaHeader = HeaderFile->getName();
|
||||
return 0;
|
||||
}
|
||||
|
@ -173,7 +174,9 @@ const FileEntry *DirectoryLookup::LookupFile(
|
|||
StringRef Filename,
|
||||
HeaderSearch &HS,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath) const {
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
StringRef BuildingModule,
|
||||
StringRef *SuggestedModule) const {
|
||||
llvm::SmallString<1024> TmpDir;
|
||||
if (isNormalDir()) {
|
||||
// Concatenate the requested file onto the directory.
|
||||
|
@ -192,7 +195,8 @@ const FileEntry *DirectoryLookup::LookupFile(
|
|||
}
|
||||
|
||||
if (isFramework())
|
||||
return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath);
|
||||
return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
|
||||
BuildingModule, SuggestedModule);
|
||||
|
||||
assert(isHeaderMap() && "Unknown directory lookup");
|
||||
const FileEntry * const Result = getHeaderMap()->LookupFile(
|
||||
|
@ -218,7 +222,10 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
|
|||
StringRef Filename,
|
||||
HeaderSearch &HS,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath) const {
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
StringRef BuildingModule,
|
||||
StringRef *SuggestedModule) const
|
||||
{
|
||||
FileManager &FileMgr = HS.getFileMgr();
|
||||
|
||||
// Framework names must have a '/' in the filename.
|
||||
|
@ -280,9 +287,15 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
|
|||
SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1);
|
||||
}
|
||||
|
||||
/// Determine whether this is the module we're building or not.
|
||||
bool AutomaticImport = SuggestedModule &&
|
||||
(BuildingModule != StringRef(Filename.begin(), SlashPos));
|
||||
|
||||
FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
|
||||
if (const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
|
||||
/*openFile=*/true)) {
|
||||
/*openFile=*/!AutomaticImport)) {
|
||||
if (AutomaticImport)
|
||||
*SuggestedModule = StringRef(Filename.begin(), SlashPos);
|
||||
return FE;
|
||||
}
|
||||
|
||||
|
@ -294,7 +307,11 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
|
|||
SearchPath->insert(SearchPath->begin()+OrigSize, Private,
|
||||
Private+strlen(Private));
|
||||
|
||||
return FileMgr.getFile(FrameworkName.str(), /*openFile=*/true);
|
||||
const FileEntry *FE = FileMgr.getFile(FrameworkName.str(),
|
||||
/*openFile=*/!AutomaticImport);
|
||||
if (FE && AutomaticImport)
|
||||
*SuggestedModule = StringRef(Filename.begin(), SlashPos);
|
||||
return FE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -315,7 +332,12 @@ const FileEntry *HeaderSearch::LookupFile(
|
|||
const DirectoryLookup *&CurDir,
|
||||
const FileEntry *CurFileEnt,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath) {
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
StringRef *SuggestedModule)
|
||||
{
|
||||
if (SuggestedModule)
|
||||
*SuggestedModule = StringRef();
|
||||
|
||||
// If 'Filename' is absolute, check to see if it exists and no searching.
|
||||
if (llvm::sys::path::is_absolute(Filename)) {
|
||||
CurDir = 0;
|
||||
|
@ -400,7 +422,8 @@ const FileEntry *HeaderSearch::LookupFile(
|
|||
// Check each directory in sequence to see if it contains this file.
|
||||
for (; i != SearchDirs.size(); ++i) {
|
||||
const FileEntry *FE =
|
||||
SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath);
|
||||
SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath,
|
||||
BuildingModule, SuggestedModule);
|
||||
if (!FE) continue;
|
||||
|
||||
CurDir = &SearchDirs[i];
|
||||
|
@ -439,7 +462,8 @@ const FileEntry *HeaderSearch::LookupFile(
|
|||
|
||||
const FileEntry *Result = LookupFile(ScratchFilename, /*isAngled=*/true,
|
||||
FromDir, CurDir, CurFileEnt,
|
||||
SearchPath, RelativePath);
|
||||
SearchPath, RelativePath,
|
||||
SuggestedModule);
|
||||
std::pair<unsigned, unsigned> &CacheLookup
|
||||
= LookupFileCache.GetOrCreateValue(Filename).getValue();
|
||||
CacheLookup.second
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "clang/Lex/MacroInfo.h"
|
||||
#include "clang/Lex/LexDiagnostic.h"
|
||||
#include "clang/Lex/CodeCompletionHandler.h"
|
||||
#include "clang/Lex/ModuleLoader.h"
|
||||
#include "clang/Lex/Pragma.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
|
@ -478,7 +479,8 @@ const FileEntry *Preprocessor::LookupFile(
|
|||
const DirectoryLookup *FromDir,
|
||||
const DirectoryLookup *&CurDir,
|
||||
SmallVectorImpl<char> *SearchPath,
|
||||
SmallVectorImpl<char> *RelativePath) {
|
||||
SmallVectorImpl<char> *RelativePath,
|
||||
StringRef *SuggestedModule) {
|
||||
// If the header lookup mechanism may be relative to the current file, pass in
|
||||
// info about where the current file is.
|
||||
const FileEntry *CurFileEnt = 0;
|
||||
|
@ -502,12 +504,13 @@ const FileEntry *Preprocessor::LookupFile(
|
|||
CurDir = CurDirLookup;
|
||||
const FileEntry *FE = HeaderInfo.LookupFile(
|
||||
Filename, isAngled, FromDir, CurDir, CurFileEnt,
|
||||
SearchPath, RelativePath);
|
||||
SearchPath, RelativePath, SuggestedModule);
|
||||
if (FE) return FE;
|
||||
|
||||
// Otherwise, see if this is a subframework header. If so, this is relative
|
||||
// to one of the headers on the #include stack. Walk the list of the current
|
||||
// headers on the #include stack and pass them to HeaderInfo.
|
||||
// FIXME: SuggestedModule!
|
||||
if (IsFileLexer()) {
|
||||
if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID())))
|
||||
if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt,
|
||||
|
@ -1214,10 +1217,21 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
|||
llvm::SmallString<1024> RelativePath;
|
||||
// We get the raw path only if we have 'Callbacks' to which we later pass
|
||||
// the path.
|
||||
StringRef SuggestedModule;
|
||||
const FileEntry *File = LookupFile(
|
||||
Filename, isAngled, LookupFrom, CurDir,
|
||||
Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL);
|
||||
Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL,
|
||||
AutoModuleImport? &SuggestedModule : 0);
|
||||
|
||||
// If we are supposed to import a module rather than including the header,
|
||||
// do so now.
|
||||
if (!SuggestedModule.empty()) {
|
||||
TheModuleLoader.loadModule(IncludeTok.getLocation(),
|
||||
Identifiers.get(SuggestedModule),
|
||||
FilenameTok.getLocation());
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify the callback object that we've seen an inclusion directive.
|
||||
if (Callbacks)
|
||||
Callbacks->InclusionDirective(HashLoc, IncludeTok, Filename, isAngled, File,
|
||||
|
|
|
@ -785,7 +785,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
|
|||
// Search include directories.
|
||||
const DirectoryLookup *CurDir;
|
||||
const FileEntry *File =
|
||||
PP.LookupFile(Filename, isAngled, LookupFrom, CurDir, NULL, NULL);
|
||||
PP.LookupFile(Filename, isAngled, LookupFrom, CurDir, NULL, NULL, NULL);
|
||||
|
||||
// Get the result value. Result = true means the file exists.
|
||||
bool Result = File != 0;
|
||||
|
|
|
@ -366,7 +366,8 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
|
|||
|
||||
// Search include directories for this file.
|
||||
const DirectoryLookup *CurDir;
|
||||
const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir, NULL, NULL);
|
||||
const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir, NULL, NULL,
|
||||
NULL);
|
||||
if (File == 0) {
|
||||
if (!SuppressIncludeNotFoundError)
|
||||
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
|
||||
|
|
|
@ -133,6 +133,7 @@ void Preprocessor::Initialize(const TargetInfo &Target) {
|
|||
KeepComments = false;
|
||||
KeepMacroComments = false;
|
||||
SuppressIncludeNotFoundError = false;
|
||||
AutoModuleImport = false;
|
||||
|
||||
// Macro expansion is enabled.
|
||||
DisableMacroExpansion = false;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#include <Module/Module.h>
|
||||
|
||||
#define DEPENDS_ON_MODULE 1
|
|
@ -9,3 +9,4 @@ const char *getModuleVersion(void);
|
|||
+alloc;
|
||||
@end
|
||||
|
||||
#define MODULE_H_MACRO 1
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -x objective-c -fmodule-cache-path %t -fauto-module-import -F %S/Inputs -verify %s
|
||||
|
||||
#include <DependsOnModule/DependsOnModule.h>
|
||||
|
||||
#ifdef MODULE_H_MACRO
|
||||
# error MODULE_H_MACRO should have been hidden
|
||||
#endif
|
||||
|
||||
#ifdef DEPENDS_ON_MODULE
|
||||
# error DEPENDS_ON_MODULE should have been hidden
|
||||
#endif
|
Loading…
Reference in New Issue