2013-07-08 20:17:37 +08:00
|
|
|
//===-- 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.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-06-06 00:39:24 +08:00
|
|
|
#include "Core/Transform.h"
|
2013-06-13 03:52:13 +08:00
|
|
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
2013-06-18 23:31:01 +08:00
|
|
|
#include "clang/Basic/LangOptions.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
2013-06-13 03:52:13 +08:00
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
2013-06-18 02:18:15 +08:00
|
|
|
#include "clang/Tooling/Tooling.h"
|
2013-07-29 23:58:47 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2013-06-06 00:39:24 +08:00
|
|
|
|
2014-07-03 22:12:37 +08:00
|
|
|
template class llvm::Registry<TransformFactory>;
|
|
|
|
|
2013-06-06 00:39:24 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2013-07-05 01:49:59 +08:00
|
|
|
llvm::cl::OptionCategory TransformsOptionsCategory("Transforms' options");
|
|
|
|
|
2013-06-13 03:52:13 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
using namespace tooling;
|
|
|
|
using namespace ast_matchers;
|
|
|
|
|
2013-06-18 02:18:15 +08:00
|
|
|
/// \brief Custom FrontendActionFactory to produce FrontendActions that simply
|
|
|
|
/// forward (Begin|End)SourceFileAction calls to a given Transform.
|
2013-06-13 03:52:13 +08:00
|
|
|
class ActionFactory : public clang::tooling::FrontendActionFactory {
|
|
|
|
public:
|
2013-06-18 02:18:15 +08:00
|
|
|
ActionFactory(MatchFinder &Finder, Transform &Owner)
|
|
|
|
: Finder(Finder), Owner(Owner) {}
|
2013-06-13 03:52:13 +08:00
|
|
|
|
2014-11-15 03:27:22 +08:00
|
|
|
FrontendAction *create() override {
|
2013-06-18 02:18:15 +08:00
|
|
|
return new FactoryAdaptor(Finder, Owner);
|
2013-06-13 03:52:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
class FactoryAdaptor : public ASTFrontendAction {
|
|
|
|
public:
|
2013-06-18 02:18:15 +08:00
|
|
|
FactoryAdaptor(MatchFinder &Finder, Transform &Owner)
|
|
|
|
: Finder(Finder), Owner(Owner) {}
|
2013-06-13 03:52:13 +08:00
|
|
|
|
2014-08-11 03:56:59 +08:00
|
|
|
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &,
|
2014-10-03 14:34:41 +08:00
|
|
|
StringRef) override {
|
2013-06-13 03:52:13 +08:00
|
|
|
return Finder.newASTConsumer();
|
|
|
|
}
|
|
|
|
|
2015-04-11 15:59:33 +08:00
|
|
|
bool BeginSourceFileAction(CompilerInstance &CI,
|
|
|
|
StringRef Filename) override {
|
2013-06-13 03:52:13 +08:00
|
|
|
if (!ASTFrontendAction::BeginSourceFileAction(CI, Filename))
|
|
|
|
return false;
|
|
|
|
|
2013-06-18 02:18:15 +08:00
|
|
|
return Owner.handleBeginSource(CI, Filename);
|
2013-06-13 03:52:13 +08:00
|
|
|
}
|
|
|
|
|
2014-11-15 03:27:22 +08:00
|
|
|
void EndSourceFileAction() override {
|
2013-06-18 02:18:15 +08:00
|
|
|
Owner.handleEndSource();
|
2013-06-13 03:52:13 +08:00
|
|
|
return ASTFrontendAction::EndSourceFileAction();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
MatchFinder &Finder;
|
2013-06-18 02:18:15 +08:00
|
|
|
Transform &Owner;
|
2013-06-13 03:52:13 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
MatchFinder &Finder;
|
2013-06-18 02:18:15 +08:00
|
|
|
Transform &Owner;
|
2013-06-13 03:52:13 +08:00
|
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|
2013-06-18 23:31:01 +08:00
|
|
|
Transform::Transform(llvm::StringRef Name, const TransformOptions &Options)
|
2013-10-05 20:15:58 +08:00
|
|
|
: Name(Name), GlobalOptions(Options) {
|
2013-06-18 23:31:01 +08:00
|
|
|
Reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
Transform::~Transform() {}
|
|
|
|
|
2013-06-18 23:44:58 +08:00
|
|
|
bool Transform::isFileModifiable(const SourceManager &SM,
|
2015-09-21 09:33:03 +08:00
|
|
|
SourceLocation Loc) const {
|
2013-08-22 08:48:18 +08:00
|
|
|
if (SM.isWrittenInMainFile(Loc))
|
2013-06-18 23:44:58 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Loc));
|
|
|
|
if (!FE)
|
|
|
|
return false;
|
2013-07-08 20:17:37 +08:00
|
|
|
|
2013-09-13 04:10:59 +08:00
|
|
|
return GlobalOptions.ModifiableFiles.isFileIncluded(FE->getName());
|
2013-06-18 23:44:58 +08:00
|
|
|
}
|
|
|
|
|
2013-06-06 00:39:24 +08:00
|
|
|
bool Transform::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
|
2013-09-03 21:16:02 +08:00
|
|
|
CurrentSource = Filename;
|
2013-06-18 23:31:01 +08:00
|
|
|
|
2013-06-18 02:18:15 +08:00
|
|
|
if (Options().EnableTiming) {
|
|
|
|
Timings.push_back(std::make_pair(Filename.str(), llvm::TimeRecord()));
|
|
|
|
Timings.back().second -= llvm::TimeRecord::getCurrentTime(true);
|
|
|
|
}
|
2013-06-06 00:39:24 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Transform::handleEndSource() {
|
2013-09-03 21:16:02 +08:00
|
|
|
CurrentSource.clear();
|
2013-06-18 23:31:01 +08:00
|
|
|
if (Options().EnableTiming)
|
|
|
|
Timings.back().second += llvm::TimeRecord::getCurrentTime(false);
|
2013-06-06 00:39:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Transform::addTiming(llvm::StringRef Label, llvm::TimeRecord Duration) {
|
|
|
|
Timings.push_back(std::make_pair(Label.str(), Duration));
|
|
|
|
}
|
2013-06-13 03:52:13 +08:00
|
|
|
|
2013-09-03 21:16:02 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-08-09 00:06:07 +08:00
|
|
|
std::unique_ptr<FrontendActionFactory>
|
|
|
|
Transform::createActionFactory(MatchFinder &Finder) {
|
|
|
|
return llvm::make_unique<ActionFactory>(Finder, /*Owner=*/*this);
|
2013-06-13 03:52:13 +08:00
|
|
|
}
|
2013-07-24 22:24:33 +08:00
|
|
|
|
2013-07-29 23:58:47 +08:00
|
|
|
Version Version::getFromString(llvm::StringRef VersionStr) {
|
|
|
|
llvm::StringRef MajorStr, MinorStr;
|
|
|
|
Version V;
|
|
|
|
|
2014-03-02 21:48:32 +08:00
|
|
|
std::tie(MajorStr, MinorStr) = VersionStr.split('.');
|
2013-07-29 23:58:47 +08:00
|
|
|
if (!MinorStr.empty()) {
|
|
|
|
llvm::StringRef Ignore;
|
2014-03-02 21:48:32 +08:00
|
|
|
std::tie(MinorStr, Ignore) = MinorStr.split('.');
|
2013-07-29 23:58:47 +08:00
|
|
|
if (MinorStr.getAsInteger(10, V.Minor))
|
|
|
|
return Version();
|
|
|
|
}
|
|
|
|
if (MajorStr.getAsInteger(10, V.Major))
|
|
|
|
return Version();
|
|
|
|
return V;
|
|
|
|
}
|
|
|
|
|
2013-07-24 22:24:33 +08:00
|
|
|
TransformFactory::~TransformFactory() {}
|
2013-07-29 23:58:47 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|