forked from OSchip/llvm-project
173 lines
5.0 KiB
C++
173 lines
5.0 KiB
C++
//===-- Core/Transform.cpp - Transform Base Class Def'n -------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// \brief This file provides the definition for the base Transform class from
|
|
/// which all transforms must subclass.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Core/Transform.h"
|
|
#include "Core/FileOverrides.h"
|
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
|
#include "clang/Basic/LangOptions.h"
|
|
#include "clang/Basic/SourceManager.h"
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
#include "clang/Tooling/Tooling.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
using namespace clang;
|
|
|
|
llvm::cl::OptionCategory TransformsOptionsCategory("Transforms' options");
|
|
|
|
namespace {
|
|
|
|
using namespace tooling;
|
|
using namespace ast_matchers;
|
|
|
|
/// \brief Custom FrontendActionFactory to produce FrontendActions that simply
|
|
/// forward (Begin|End)SourceFileAction calls to a given Transform.
|
|
class ActionFactory : public clang::tooling::FrontendActionFactory {
|
|
public:
|
|
ActionFactory(MatchFinder &Finder, Transform &Owner)
|
|
: Finder(Finder), Owner(Owner) {}
|
|
|
|
virtual FrontendAction *create() LLVM_OVERRIDE {
|
|
return new FactoryAdaptor(Finder, Owner);
|
|
}
|
|
|
|
private:
|
|
class FactoryAdaptor : public ASTFrontendAction {
|
|
public:
|
|
FactoryAdaptor(MatchFinder &Finder, Transform &Owner)
|
|
: Finder(Finder), Owner(Owner) {}
|
|
|
|
ASTConsumer *CreateASTConsumer(CompilerInstance &, StringRef) {
|
|
return Finder.newASTConsumer();
|
|
}
|
|
|
|
virtual bool BeginSourceFileAction(CompilerInstance &CI,
|
|
StringRef Filename) LLVM_OVERRIDE {
|
|
if (!ASTFrontendAction::BeginSourceFileAction(CI, Filename))
|
|
return false;
|
|
|
|
return Owner.handleBeginSource(CI, Filename);
|
|
}
|
|
|
|
virtual void EndSourceFileAction() LLVM_OVERRIDE {
|
|
Owner.handleEndSource();
|
|
return ASTFrontendAction::EndSourceFileAction();
|
|
}
|
|
|
|
private:
|
|
MatchFinder &Finder;
|
|
Transform &Owner;
|
|
};
|
|
|
|
MatchFinder &Finder;
|
|
Transform &Owner;
|
|
};
|
|
} // namespace
|
|
|
|
Transform::Transform(llvm::StringRef Name, const TransformOptions &Options)
|
|
: Name(Name), GlobalOptions(Options), Overrides(0) {
|
|
Reset();
|
|
}
|
|
|
|
Transform::~Transform() {}
|
|
|
|
bool Transform::isFileModifiable(const SourceManager &SM,
|
|
const SourceLocation &Loc) const {
|
|
if (SM.isWrittenInMainFile(Loc))
|
|
return true;
|
|
|
|
if (!GlobalOptions.EnableHeaderModifications)
|
|
return false;
|
|
|
|
const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Loc));
|
|
if (!FE)
|
|
return false;
|
|
|
|
return GlobalOptions.ModifiableHeaders.isFileIncluded(FE->getName());
|
|
}
|
|
|
|
bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
|
|
assert(Overrides != 0 && "Subclass transform didn't provide InputState");
|
|
|
|
Overrides->applyOverrides(CI.getSourceManager());
|
|
CurrentSource = Filename;
|
|
|
|
if (Options().EnableTiming) {
|
|
Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord()));
|
|
Timings.back().second -= llvm::TimeRecord::getCurrentTime(true);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Transform::handleEndSource() {
|
|
CurrentSource.clear();
|
|
if (Options().EnableTiming)
|
|
Timings.back().second += llvm::TimeRecord::getCurrentTime(false);
|
|
}
|
|
|
|
void Transform::addTiming(llvm::StringRef Label, llvm::TimeRecord Duration) {
|
|
Timings.push_back(std::make_pair(Label.str(), Duration));
|
|
}
|
|
|
|
bool
|
|
Transform::addReplacementForCurrentTU(const clang::tooling::Replacement &R) {
|
|
if (CurrentSource.empty())
|
|
return false;
|
|
|
|
TranslationUnitReplacements &TU = Replacements[CurrentSource];
|
|
if (TU.MainSourceFile.empty())
|
|
TU.MainSourceFile = CurrentSource;
|
|
TU.Replacements.push_back(R);
|
|
|
|
return true;
|
|
}
|
|
|
|
FrontendActionFactory *Transform::createActionFactory(MatchFinder &Finder) {
|
|
return new ActionFactory(Finder, /*Owner=*/ *this);
|
|
}
|
|
|
|
Version Version::getFromString(llvm::StringRef VersionStr) {
|
|
llvm::StringRef MajorStr, MinorStr;
|
|
Version V;
|
|
|
|
llvm::tie(MajorStr, MinorStr) = VersionStr.split('.');
|
|
if (!MinorStr.empty()) {
|
|
llvm::StringRef Ignore;
|
|
llvm::tie(MinorStr, Ignore) = MinorStr.split('.');
|
|
if (MinorStr.getAsInteger(10, V.Minor))
|
|
return Version();
|
|
}
|
|
if (MajorStr.getAsInteger(10, V.Major))
|
|
return Version();
|
|
return V;
|
|
}
|
|
|
|
TransformFactory::~TransformFactory() {}
|
|
|
|
namespace {
|
|
bool versionSupported(Version Required, Version AvailableSince) {
|
|
// null version, means no requirements, means supported
|
|
if (Required.isNull())
|
|
return true;
|
|
return Required >= AvailableSince;
|
|
}
|
|
} // end anonymous namespace
|
|
|
|
bool TransformFactory::supportsCompilers(CompilerVersions Required) const {
|
|
return versionSupported(Required.Clang, Since.Clang) &&
|
|
versionSupported(Required.Gcc, Since.Gcc) &&
|
|
versionSupported(Required.Icc, Since.Icc) &&
|
|
versionSupported(Required.Msvc, Since.Msvc);
|
|
}
|