//===--- HeaderSearch.cpp - Resolve Header File Locations ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the DirectoryLookup and HeaderSearch interfaces.
//
//===----------------------------------------------------------------------===//
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/Lexer.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Capacity.h"
#include <cstdio>
using namespace clang;
const IdentifierInfo *
HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) {
if (ControllingMacro)
return ControllingMacro;
if (!ControllingMacroID || !External)
return 0;
ControllingMacro = External->GetIdentifier(ControllingMacroID);
return ControllingMacro;
}
ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {}
HeaderSearch::HeaderSearch(FileManager &FM, DiagnosticsEngine &Diags,
const LangOptions &LangOpts,
const TargetInfo *Target)
: FileMgr(FM), Diags(Diags), FrameworkMap(64),
ModMap(FileMgr, *Diags.getClient(), LangOpts, Target)
{
AngledDirIdx = 0;
SystemDirIdx = 0;
NoCurDirSearch = false;
ExternalLookup = 0;
ExternalSource = 0;
NumIncluded = 0;
NumMultiIncludeFileOptzn = 0;
NumFrameworkLookups = NumSubFrameworkLookups = 0;
}
HeaderSearch::~HeaderSearch() {
// Delete headermaps.
for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
delete HeaderMaps[i].second;
}
void HeaderSearch::PrintStats() {
fprintf(stderr, "\n*** HeaderSearch Stats:\n");
fprintf(stderr, "%d files tracked.\n", (int)FileInfo.size());
unsigned NumOnceOnlyFiles = 0, MaxNumIncludes = 0, NumSingleIncludedFiles = 0;
for (unsigned i = 0, e = FileInfo.size(); i != e; ++i) {
NumOnceOnlyFiles += FileInfo[i].isImport;
if (MaxNumIncludes < FileInfo[i].NumIncludes)
MaxNumIncludes = FileInfo[i].NumIncludes;
NumSingleIncludedFiles += FileInfo[i].NumIncludes == 1;
}
fprintf(stderr, " %d #import/#pragma once files.\n", NumOnceOnlyFiles);
fprintf(stderr, " %d included exactly once.\n", NumSingleIncludedFiles);
fprintf(stderr, " %d max times a file is included.\n", MaxNumIncludes);
fprintf(stderr, " %d #include/#include_next/#import.\n", NumIncluded);
fprintf(stderr, " %d #includes skipped due to"
" the multi-include optimization.\n", NumMultiIncludeFileOptzn);
fprintf(stderr, "%d framework lookups.\n", NumFrameworkLookups);
fprintf(stderr, "%d subframework lookups.\n", NumSubFrameworkLookups);
}
/// CreateHeaderMap - This method returns a HeaderMap for the specified
/// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
// We expect the number of headermaps to be small, and almost always empty.
// If it ever grows, use of a linear search should be re-evaluated.
if (!HeaderMaps.empty()) {
for (unsigned i = 0, e = HeaderMaps.size(); i != e; ++i)
// Pointer equality comparison of FileEntries works because they are
// already uniqued by inode.
if (HeaderMaps[i].first == FE)
return HeaderMaps[i].second;
}
if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr)) {
HeaderMaps.push_back(std::make_pair(FE, HM));
return HM;
}
return 0;
}
std::string HeaderSearch::getModuleFileName(Module *Module) {
// If we don't have a module cache path, we can't do anything.
if (ModuleCachePath.empty())
return std::string();
SmallString<256> Result(ModuleCachePath);
llvm::sys::path::append(Result, Module->getTopLevelModule()->Name + ".pcm");
return Result.str().str();
}
std::string HeaderSearch::getModuleFileName(StringRef ModuleName) {
// If we don't have a module cache path, we can't do anything.
if (ModuleCachePath.empty