forked from OSchip/llvm-project
clang-modernize: Apply replacements using clang-apply-replacements
Summary: The clang-apply-replacements process is now invoked to apply replacements between applying transforms. This resulted in a massive simplification of the tool: - FileOverrides class no longer needed. - Change tracking and code formatting no longer needed. - No more dependency on libclangApplyReplacements. - Final syntax check is easier to do directly now than with a separate header/source pair. Replacement handling stuff abstracted into a new header/source pair to de-clutter ClangModernize.cpp somewhat. Tests updated. Differential Revision: http://llvm-reviews.chandlerc.com/D1836 llvm-svn: 192032
This commit is contained in:
parent
c83946f7f5
commit
c0f00b79f7
|
@ -228,7 +228,7 @@ int main(int argc, char **argv) {
|
|||
if (ErrorCode) {
|
||||
errs() << "Trouble iterating over directory '" << Directory
|
||||
<< "': " << ErrorCode.message() << "\n";
|
||||
return false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Remove the TUReplacementFiles (triggered by "remove-change-desc-files"
|
||||
|
|
|
@ -29,8 +29,7 @@ static cl::opt<bool> DetectMacros(
|
|||
cl::desc("Detect and use macros that expand to the 'override' keyword."),
|
||||
cl::cat(TransformsOptionsCategory));
|
||||
|
||||
int AddOverrideTransform::apply(const FileOverrides &InputStates,
|
||||
const CompilationDatabase &Database,
|
||||
int AddOverrideTransform::apply(const CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) {
|
||||
ClangTool AddOverrideTool(Database, SourcePaths);
|
||||
unsigned AcceptedChanges = 0;
|
||||
|
@ -42,8 +41,6 @@ int AddOverrideTransform::apply(const FileOverrides &InputStates,
|
|||
// Make Fixer available to handleBeginSource().
|
||||
this->Fixer = &Fixer;
|
||||
|
||||
setOverrides(InputStates);
|
||||
|
||||
if (int result = AddOverrideTool.run(createActionFactory(Finder))) {
|
||||
llvm::errs() << "Error encountered during translation.\n";
|
||||
return result;
|
||||
|
|
|
@ -31,8 +31,7 @@ public:
|
|||
: Transform("AddOverride", Options) {}
|
||||
|
||||
/// \see Transform::run().
|
||||
virtual int apply(const FileOverrides &InputStates,
|
||||
const clang::tooling::CompilationDatabase &Database,
|
||||
virtual int apply(const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||
|
||||
virtual bool handleBeginSource(clang::CompilerInstance &CI,
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
get_filename_component(ClangReplaceLocation
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../clang-apply-replacements/include" ABSOLUTE)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${ClangReplaceLocation}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
set(LLVM_LINK_COMPONENTS support)
|
||||
|
||||
add_clang_library(modernizeCore
|
||||
FileOverrides.cpp
|
||||
SyntaxCheck.cpp
|
||||
ReplacementHandling.cpp
|
||||
Transforms.cpp
|
||||
Transform.cpp
|
||||
IncludeExcludeInfo.cpp
|
||||
PerfSupport.cpp
|
||||
Reformatting.cpp
|
||||
IncludeDirectives.cpp
|
||||
)
|
||||
target_link_libraries(modernizeCore
|
||||
|
|
|
@ -1,198 +0,0 @@
|
|||
//===-- Core/FileOverrides.cpp --------------------------------------------===//
|
||||
//
|
||||
// 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 types and functionality for dealing with source
|
||||
/// and header file content overrides.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Core/FileOverrides.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/DiagnosticOptions.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Rewrite/Core/Rewriter.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
#include "clang/Tooling/ReplacementsYaml.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/system_error.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::tooling;
|
||||
|
||||
bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
|
||||
llvm::SmallVectorImpl<char> &Result,
|
||||
llvm::SmallVectorImpl<char> &Error) {
|
||||
using namespace llvm::sys;
|
||||
|
||||
Error.clear();
|
||||
if (llvm::error_code EC = fs::createUniqueFile(
|
||||
MainSourceFile + "_%%_%%_%%_%%_%%_%%.yaml", Result)) {
|
||||
Error.append(EC.message().begin(), EC.message().end());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief Comparator to be able to order tooling::Range based on their offset.
|
||||
bool rangeLess(clang::tooling::Range A, clang::tooling::Range B) {
|
||||
if (A.getOffset() == B.getOffset())
|
||||
return A.getLength() < B.getLength();
|
||||
return A.getOffset() < B.getOffset();
|
||||
}
|
||||
|
||||
/// \brief Functor that returns the given range without its overlaps with the
|
||||
/// replacement given in the constructor.
|
||||
struct RangeReplacedAdjuster {
|
||||
RangeReplacedAdjuster(const tooling::Replacement &Replace)
|
||||
: Replace(Replace.getOffset(), Replace.getLength()),
|
||||
ReplaceNewSize(Replace.getReplacementText().size()) {}
|
||||
|
||||
tooling::Range operator()(clang::tooling::Range Range) const {
|
||||
if (!Range.overlapsWith(Replace))
|
||||
return Range;
|
||||
// range inside replacement -> make the range length null
|
||||
if (Replace.contains(Range))
|
||||
return tooling::Range(Range.getOffset(), 0);
|
||||
// replacement inside range -> resize the range
|
||||
if (Range.contains(Replace)) {
|
||||
int Difference = ReplaceNewSize - Replace.getLength();
|
||||
return tooling::Range(Range.getOffset(), Range.getLength() + Difference);
|
||||
}
|
||||
// beginning of the range replaced -> truncate range beginning
|
||||
if (Range.getOffset() > Replace.getOffset()) {
|
||||
unsigned ReplaceEnd = Replace.getOffset() + Replace.getLength();
|
||||
unsigned RangeEnd = Range.getOffset() + Range.getLength();
|
||||
return tooling::Range(ReplaceEnd, RangeEnd - ReplaceEnd);
|
||||
}
|
||||
// end of the range replaced -> truncate range end
|
||||
if (Range.getOffset() < Replace.getOffset())
|
||||
return tooling::Range(Range.getOffset(),
|
||||
Replace.getOffset() - Range.getOffset());
|
||||
llvm_unreachable("conditions not handled properly");
|
||||
}
|
||||
|
||||
const tooling::Range Replace;
|
||||
const unsigned ReplaceNewSize;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
void
|
||||
ChangedRanges::adjustChangedRanges(const tooling::ReplacementsVec &Replaces) {
|
||||
// first adjust existing ranges in case they overlap with the replacements
|
||||
for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
const tooling::Replacement &Replace = *I;
|
||||
|
||||
std::transform(Ranges.begin(), Ranges.end(), Ranges.begin(),
|
||||
RangeReplacedAdjuster(Replace));
|
||||
}
|
||||
|
||||
// then shift existing ranges to reflect the new positions
|
||||
for (RangeVec::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
|
||||
unsigned ShiftedOffset =
|
||||
tooling::shiftedCodePosition(Replaces, I->getOffset());
|
||||
*I = tooling::Range(ShiftedOffset, I->getLength());
|
||||
}
|
||||
|
||||
// then generate the new ranges from the replacements
|
||||
for (ReplacementsVec::const_iterator I = Replaces.begin(), E = Replaces.end();
|
||||
I != E; ++I) {
|
||||
const tooling::Replacement &R = *I;
|
||||
unsigned Offset = tooling::shiftedCodePosition(Replaces, R.getOffset());
|
||||
unsigned Length = R.getReplacementText().size();
|
||||
|
||||
Ranges.push_back(tooling::Range(Offset, Length));
|
||||
}
|
||||
|
||||
// cleanups unecessary ranges to finish
|
||||
coalesceRanges();
|
||||
}
|
||||
|
||||
void ChangedRanges::coalesceRanges() {
|
||||
// sort the ranges by offset and then for each group of adjacent/overlapping
|
||||
// ranges the first one in the group is extended to cover the whole group.
|
||||
std::sort(Ranges.begin(), Ranges.end(), &rangeLess);
|
||||
RangeVec::iterator FirstInGroup = Ranges.begin();
|
||||
assert(!Ranges.empty() && "unexpected empty vector");
|
||||
for (RangeVec::iterator I = Ranges.begin() + 1, E = Ranges.end(); I != E;
|
||||
++I) {
|
||||
unsigned GroupEnd = FirstInGroup->getOffset() + FirstInGroup->getLength();
|
||||
|
||||
// no contact
|
||||
if (I->getOffset() > GroupEnd)
|
||||
FirstInGroup = I;
|
||||
else {
|
||||
unsigned GrpBegin = FirstInGroup->getOffset();
|
||||
unsigned GrpEnd = std::max(GroupEnd, I->getOffset() + I->getLength());
|
||||
*FirstInGroup = tooling::Range(GrpBegin, GrpEnd - GrpBegin);
|
||||
}
|
||||
}
|
||||
|
||||
// remove the ranges that are covered by the first member of the group
|
||||
Ranges.erase(std::unique(Ranges.begin(), Ranges.end(),
|
||||
std::mem_fun_ref(&Range::contains)),
|
||||
Ranges.end());
|
||||
}
|
||||
|
||||
void FileOverrides::applyOverrides(clang::SourceManager &SM) const {
|
||||
FileManager &FM = SM.getFileManager();
|
||||
|
||||
for (FileStateMap::const_iterator I = FileStates.begin(),
|
||||
E = FileStates.end();
|
||||
I != E; ++I) {
|
||||
SM.overrideFileContents(FM.getFile(I->getKey()),
|
||||
llvm::MemoryBuffer::getMemBuffer(I->getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
void FileOverrides::adjustChangedRanges(
|
||||
const clang::replace::FileToReplacementsMap &Replaces) {
|
||||
|
||||
for (replace::FileToReplacementsMap::const_iterator I = Replaces.begin(),
|
||||
E = Replaces.end(); I != E; ++I) {
|
||||
ChangeTracking[I->getKey()].adjustChangedRanges(I->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
void FileOverrides::updateState(const clang::Rewriter &Rewrites) {
|
||||
for (Rewriter::const_buffer_iterator BufferI = Rewrites.buffer_begin(),
|
||||
BufferE = Rewrites.buffer_end();
|
||||
BufferI != BufferE; ++BufferI) {
|
||||
const char *FileName =
|
||||
Rewrites.getSourceMgr().getFileEntryForID(BufferI->first)->getName();
|
||||
const RewriteBuffer &RewriteBuf = BufferI->second;
|
||||
FileStates[FileName].assign(RewriteBuf.begin(), RewriteBuf.end());
|
||||
}
|
||||
}
|
||||
|
||||
bool FileOverrides::writeToDisk(DiagnosticsEngine &Diagnostics) const {
|
||||
bool Errors = false;
|
||||
for (FileStateMap::const_iterator I = FileStates.begin(),
|
||||
E = FileStates.end();
|
||||
I != E; ++I) {
|
||||
std::string ErrorInfo;
|
||||
// The extra transform through std::string is to ensure null-termination
|
||||
// of the filename stored as the key of the StringMap.
|
||||
llvm::raw_fd_ostream FileStream(I->getKey().str().c_str(), ErrorInfo);
|
||||
if (!ErrorInfo.empty()) {
|
||||
llvm::errs() << "Failed to write new state for " << I->getKey() << ".\n";
|
||||
Errors = true;
|
||||
}
|
||||
FileStream << I->getValue();
|
||||
}
|
||||
return !Errors;
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
//===-- Core/FileOverrides.h ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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 types and functionality for dealing with source
|
||||
/// and header file content overrides.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_MODERNIZE_FILE_OVERRIDES_H
|
||||
#define CLANG_MODERNIZE_FILE_OVERRIDES_H
|
||||
|
||||
#include "Core/Refactoring.h"
|
||||
#include "clang-apply-replacements/Tooling/ApplyReplacements.h"
|
||||
#include "clang/Tooling/ReplacementsYaml.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
|
||||
// Forward Declarations
|
||||
namespace llvm {
|
||||
template <typename T>
|
||||
class SmallVectorImpl;
|
||||
} // namespace llvm
|
||||
namespace clang {
|
||||
class SourceManager;
|
||||
class Rewriter;
|
||||
} // namespace clang
|
||||
|
||||
/// \brief Class encapsulating a list of \c tooling::Range with some
|
||||
/// convenience methods.
|
||||
///
|
||||
/// The ranges stored are used to keep track of the overriden parts of a file.
|
||||
class ChangedRanges {
|
||||
typedef std::vector<clang::tooling::Range> RangeVec;
|
||||
|
||||
public:
|
||||
typedef RangeVec::const_iterator const_iterator;
|
||||
|
||||
/// \brief Create new ranges from the replacements and adjust existing one
|
||||
/// to remove replaced parts.
|
||||
///
|
||||
/// Note that all replacements should come from the same file.
|
||||
void adjustChangedRanges(const clang::tooling::ReplacementsVec &Replaces);
|
||||
|
||||
/// \brief Iterators.
|
||||
/// \{
|
||||
const_iterator begin() const { return Ranges.begin(); }
|
||||
const_iterator end() const { return Ranges.end(); }
|
||||
/// \}
|
||||
|
||||
private:
|
||||
void coalesceRanges();
|
||||
|
||||
RangeVec Ranges;
|
||||
};
|
||||
|
||||
/// \brief Maintains current state of transformed files and tracks source ranges
|
||||
/// where changes have been made.
|
||||
class FileOverrides {
|
||||
public:
|
||||
/// \brief Maps file names to file contents.
|
||||
typedef llvm::StringMap<std::string> FileStateMap;
|
||||
|
||||
/// \brief Maps file names to change tracking info for a file.
|
||||
typedef llvm::StringMap<ChangedRanges> ChangeMap;
|
||||
|
||||
|
||||
/// \brief Override file contents seen by \c SM for all files stored by this
|
||||
/// object.
|
||||
void applyOverrides(clang::SourceManager &SM) const;
|
||||
|
||||
/// \brief Update change tracking information based on replacements stored in
|
||||
/// \c Replaces.
|
||||
void
|
||||
adjustChangedRanges(const clang::replace::FileToReplacementsMap &Replaces);
|
||||
|
||||
/// \brief Accessor for change tracking information.
|
||||
const ChangeMap &getChangedRanges() const {
|
||||
return ChangeTracking;
|
||||
}
|
||||
|
||||
/// \brief Coalesce changes stored in \c Rewrites and replace file contents
|
||||
/// overrides stored in this object.
|
||||
///
|
||||
/// \param Rewrites Rewriter containing changes to files.
|
||||
void updateState(const clang::Rewriter &Rewrites);
|
||||
|
||||
/// \brief Accessor for current file state.
|
||||
const FileStateMap &getState() const { return FileStates; }
|
||||
|
||||
/// \brief Write all file contents overrides to disk.
|
||||
///
|
||||
/// \param Diagnostics DiagnosticsEngine for error output.
|
||||
///
|
||||
/// \returns \li true if all files with overridden file contents were written
|
||||
/// to disk successfully.
|
||||
/// \li false if any failure occurred.
|
||||
bool writeToDisk(clang::DiagnosticsEngine &Diagnostics) const;
|
||||
|
||||
private:
|
||||
FileStateMap FileStates;
|
||||
ChangeMap ChangeTracking;
|
||||
};
|
||||
|
||||
/// \brief Generate a unique filename to store the replacements.
|
||||
///
|
||||
/// Generates a unique filename in the same directory as \c MainSourceFile. The
|
||||
/// filename is generated following this pattern:
|
||||
///
|
||||
/// MainSourceFile_%%_%%_%%_%%_%%_%%.yaml
|
||||
///
|
||||
/// where all '%' will be replaced by a randomly chosen hex number.
|
||||
///
|
||||
/// \param[in] MainSourceFile Full path to the source file.
|
||||
/// \param[out] Result The resulting unique filename in the same directory as
|
||||
/// the \c MainSourceFile.
|
||||
/// \param[out] Error If an error occurs a description of that error is
|
||||
/// placed in this string.
|
||||
/// \returns true on success, false if a unique file name could not be created.
|
||||
bool generateReplacementsFileName(const llvm::StringRef MainSourceFile,
|
||||
llvm::SmallVectorImpl<char> &Result,
|
||||
llvm::SmallVectorImpl<char> &Error);
|
||||
|
||||
#endif // CLANG_MODERNIZE_FILE_OVERRIDES_H
|
|
@ -1,62 +0,0 @@
|
|||
//===-- Core/Reformatting.cpp - LibFormat integration ---------------------===//
|
||||
//
|
||||
// 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 LibFormat integration used to reformat
|
||||
/// migrated code.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Core/Reformatting.h"
|
||||
#include "Core/FileOverrides.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/DiagnosticOptions.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
void Reformatter::reformatChanges(const FileOverrides &FileStates,
|
||||
clang::SourceManager &SM,
|
||||
clang::tooling::ReplacementsVec &Replaces) {
|
||||
FileStates.applyOverrides(SM);
|
||||
|
||||
for (FileOverrides::ChangeMap::const_iterator
|
||||
I = FileStates.getChangedRanges().begin(),
|
||||
E = FileStates.getChangedRanges().end();
|
||||
I != E; ++I) {
|
||||
reformatSingleFile(I->getKey(), I->getValue(), SM, Replaces);
|
||||
}
|
||||
}
|
||||
|
||||
void Reformatter::reformatSingleFile(
|
||||
const llvm::StringRef FileName, const ChangedRanges &Changes,
|
||||
SourceManager &SM, clang::tooling::ReplacementsVec &FormatReplacements) {
|
||||
|
||||
const clang::FileEntry *Entry = SM.getFileManager().getFile(FileName);
|
||||
assert(Entry && "expected an existing file");
|
||||
|
||||
FileID ID = SM.translateFile(Entry);
|
||||
if (ID.isInvalid())
|
||||
ID = SM.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
|
||||
|
||||
std::vector<CharSourceRange> ReformatRanges;
|
||||
SourceLocation StartOfFile = SM.getLocForStartOfFile(ID);
|
||||
for (ChangedRanges::const_iterator I = Changes.begin(), E = Changes.end();
|
||||
I != E; ++I) {
|
||||
SourceLocation Start = StartOfFile.getLocWithOffset(I->getOffset());
|
||||
SourceLocation End = Start.getLocWithOffset(I->getLength());
|
||||
ReformatRanges.push_back(CharSourceRange::getCharRange(Start, End));
|
||||
}
|
||||
|
||||
Lexer Lex(ID, SM.getBuffer(ID), SM, getFormattingLangOpts(Style.Standard));
|
||||
const tooling::Replacements &R =
|
||||
format::reformat(Style, Lex, SM, ReformatRanges);
|
||||
std::copy(R.begin(), R.end(), std::back_inserter(FormatReplacements));
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
//===-- Core/Reformatting.h - LibFormat integration -------------*- C++ -*-===//
|
||||
//
|
||||
// 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 LibFormat integration used to reformat
|
||||
/// migrated code.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_MODERNIZE_REFORMATTING_H
|
||||
#define CLANG_MODERNIZE_REFORMATTING_H
|
||||
|
||||
#include "Core/Refactoring.h"
|
||||
#include "clang/Format/Format.h"
|
||||
|
||||
class FileOverrides;
|
||||
class ChangedRanges;
|
||||
|
||||
class Reformatter {
|
||||
public:
|
||||
Reformatter(const clang::format::FormatStyle &Style) : Style(Style) {}
|
||||
|
||||
/// \brief Reformat the changes made to the file overrides.
|
||||
///
|
||||
/// This function will apply the state of files stored in \c FileState to \c
|
||||
/// SM.
|
||||
///
|
||||
/// \param[in] FileState Files to reformat.
|
||||
/// \param[in] SM SourceManager for access to source files.
|
||||
/// \param[out] Replaces Container to store all reformatting replacements.
|
||||
void reformatChanges(const FileOverrides &FileState, clang::SourceManager &SM,
|
||||
clang::tooling::ReplacementsVec &Replaces);
|
||||
|
||||
/// \brief Produce a list of replacements to apply on \p FileName, only the
|
||||
/// ranges in \p Changes are replaced.
|
||||
///
|
||||
/// Since this routine use \c clang::format::reformat() the rules that
|
||||
/// function applies to ranges also apply here.
|
||||
///
|
||||
/// \param[in] FileName Name of file to reformat.
|
||||
/// \param[in] Changes Description of where changes were made to the file.
|
||||
/// \param[in] SM SourceManager required to create replacements.
|
||||
/// \param[out] FormatReplacements New reformatting replacements are appended
|
||||
/// to this container.
|
||||
void reformatSingleFile(const llvm::StringRef FileName,
|
||||
const ChangedRanges &Changes,
|
||||
clang::SourceManager &SM,
|
||||
clang::tooling::ReplacementsVec &FormatReplacements);
|
||||
|
||||
private:
|
||||
clang::format::FormatStyle Style;
|
||||
};
|
||||
|
||||
#endif // CLANG_MODERNIZE_REFORMATTING_H
|
|
@ -0,0 +1,155 @@
|
|||
//===-- Core/ReplacementHandling.cpp --------------------------------------===//
|
||||
//
|
||||
// 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 implementations for the ReplacementHandling class.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Core/ReplacementHandling.h"
|
||||
#include "clang/Tooling/ReplacementsYaml.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Program.h"
|
||||
#include "llvm/Support/system_error.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::sys;
|
||||
using namespace clang::tooling;
|
||||
|
||||
bool ReplacementHandling::findClangApplyReplacements(const char *Argv0) {
|
||||
CARPath = FindProgramByName("clang-apply-replacements");
|
||||
|
||||
if (!CARPath.empty())
|
||||
return true;
|
||||
|
||||
static int StaticSymbol;
|
||||
CARPath = fs::getMainExecutable(Argv0, &StaticSymbol);
|
||||
SmallString<128> TestPath = path::parent_path(CARPath);
|
||||
path::append(TestPath, "clang-apply-replacements");
|
||||
if (fs::can_execute(Twine(TestPath)))
|
||||
CARPath = TestPath.str();
|
||||
|
||||
return !CARPath.empty();
|
||||
}
|
||||
|
||||
StringRef ReplacementHandling::useTempDestinationDir() {
|
||||
DestinationDir = generateTempDir();
|
||||
return DestinationDir;
|
||||
}
|
||||
|
||||
void ReplacementHandling::enableFormatting(StringRef Style,
|
||||
StringRef StyleConfigDir) {
|
||||
DoFormat = true;
|
||||
FormatStyle = Style;
|
||||
this->StyleConfigDir = StyleConfigDir;
|
||||
}
|
||||
|
||||
bool ReplacementHandling::serializeReplacements(
|
||||
const TUReplacementsMap &Replacements) {
|
||||
assert(!DestinationDir.empty() && "Destination directory not set");
|
||||
|
||||
bool Errors = false;
|
||||
|
||||
for (TUReplacementsMap::const_iterator I = Replacements.begin(),
|
||||
E = Replacements.end();
|
||||
I != E; ++I) {
|
||||
SmallString<128> ReplacementsFileName;
|
||||
SmallString<64> Error;
|
||||
bool Result = generateReplacementsFileName(DestinationDir,
|
||||
I->getValue().MainSourceFile,
|
||||
ReplacementsFileName, Error);
|
||||
if (!Result) {
|
||||
errs() << "Failed to generate replacements filename:" << Error << "\n";
|
||||
Errors = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string ErrorInfo;
|
||||
raw_fd_ostream ReplacementsFile(ReplacementsFileName.c_str(), ErrorInfo,
|
||||
fs::F_Binary);
|
||||
if (!ErrorInfo.empty()) {
|
||||
errs() << "Error opening file: " << ErrorInfo << "\n";
|
||||
Errors = true;
|
||||
continue;
|
||||
}
|
||||
yaml::Output YAML(ReplacementsFile);
|
||||
YAML << const_cast<TranslationUnitReplacements &>(I->getValue());
|
||||
}
|
||||
return !Errors;
|
||||
}
|
||||
|
||||
bool ReplacementHandling::applyReplacements() {
|
||||
SmallVector<const char *, 8> Argv;
|
||||
Argv.push_back(CARPath.c_str());
|
||||
std::string Style = "--style=" + FormatStyle;
|
||||
std::string StyleConfig = "--style-config=" + StyleConfigDir;
|
||||
if (DoFormat) {
|
||||
Argv.push_back("--format");
|
||||
Argv.push_back(Style.c_str());
|
||||
if (!StyleConfigDir.empty())
|
||||
Argv.push_back(StyleConfig.c_str());
|
||||
}
|
||||
Argv.push_back("--remove-change-desc-files");
|
||||
Argv.push_back(DestinationDir.c_str());
|
||||
|
||||
// Argv array needs to be null terminated.
|
||||
Argv.push_back(0);
|
||||
|
||||
std::string ErrorMsg;
|
||||
bool ExecutionFailed = false;
|
||||
int ReturnCode = ExecuteAndWait(CARPath.c_str(), Argv.data(), /* env */ 0,
|
||||
/* redirects */ 0,
|
||||
/* secondsToWait */ 0, /* memoryLimit */ 0,
|
||||
&ErrorMsg, &ExecutionFailed);
|
||||
if (ExecutionFailed || !ErrorMsg.empty()) {
|
||||
errs() << "Failed to launch clang-apply-replacements: " << ErrorMsg << "\n";
|
||||
errs() << "Command Line:\n";
|
||||
for (const char **I = Argv.begin(), **E = Argv.end(); I != E; ++I) {
|
||||
if (*I)
|
||||
errs() << *I << "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ReturnCode != 0) {
|
||||
errs() << "clang-apply-replacements failed with return code " << ReturnCode
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ReplacementHandling::generateTempDir() {
|
||||
SmallString<128> Prefix;
|
||||
path::system_temp_directory(true, Prefix);
|
||||
path::append(Prefix, "clang-modernize");
|
||||
SmallString<128> Result;
|
||||
fs::createUniqueDirectory(Twine(Prefix), Result);
|
||||
return Result.str();
|
||||
}
|
||||
|
||||
bool ReplacementHandling::generateReplacementsFileName(
|
||||
StringRef DestinationDir, StringRef MainSourceFile,
|
||||
SmallVectorImpl<char> &Result, SmallVectorImpl<char> &Error) {
|
||||
|
||||
Error.clear();
|
||||
SmallString<128> Prefix = DestinationDir;
|
||||
path::append(Prefix, path::filename(MainSourceFile));
|
||||
if (error_code EC =
|
||||
fs::createUniqueFile(Prefix + "_%%_%%_%%_%%_%%_%%.yaml", Result)) {
|
||||
const std::string &Msg = EC.message();
|
||||
Error.append(Msg.begin(), Msg.end());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
//===-- Core/ReplacementHandling.h ------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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 defines the ReplacementHandling class which abstracts
|
||||
/// serialization and application of serialized replacements.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_MODERNIZE_REPLACEMENTHANDLING_H
|
||||
#define CLANG_MODERNIZE_REPLACEMENTHANDLING_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "Core/Transform.h"
|
||||
|
||||
class ReplacementHandling {
|
||||
public:
|
||||
|
||||
/// \brief Finds the path to the executable 'clang-apply-replacements'.
|
||||
///
|
||||
/// The executable is searched for on the PATH. If not found, looks in the
|
||||
/// same directory as the image used to start the current executable.
|
||||
///
|
||||
/// \param[in] Argv0 argv[0] as passed to main().
|
||||
///
|
||||
/// \returns \li true if clang-apply-replacements was found.
|
||||
/// \li false otherwise.
|
||||
bool findClangApplyReplacements(const char *Argv0);
|
||||
|
||||
/// \brief Set the name of the directory in which replacements will be
|
||||
/// serialized.
|
||||
///
|
||||
/// \param[in] Dir Destination directory name
|
||||
void setDestinationDir(llvm::StringRef Dir) { DestinationDir = Dir; }
|
||||
|
||||
/// \brief Create a new temporary directory to serialize replacements into.
|
||||
///
|
||||
/// \returns The name of the directory createdy.
|
||||
llvm::StringRef useTempDestinationDir();
|
||||
|
||||
/// \brief Enable clang-apply-replacements do code reformatting when applying
|
||||
/// serialized replacements.
|
||||
///
|
||||
/// \param[in] Style Value to pass to clang-apply-replacement's --style
|
||||
/// option.
|
||||
/// \param[in] StyleConfigDir If non-empty, value to pass to
|
||||
/// clang-apply-replacement's --style-config option.
|
||||
void enableFormatting(llvm::StringRef Style,
|
||||
llvm::StringRef StyleConfigDir = "");
|
||||
|
||||
/// \brief Write all TranslationUnitReplacements stored in \c Replacements
|
||||
/// to disk.
|
||||
///
|
||||
/// \pre Destination directory must have been previously set by calling
|
||||
/// setDestiantionDir() or useTempDestinationDir().
|
||||
/// \pre Destination dir must exist.
|
||||
///
|
||||
/// \param[in] Replacements Container of replacements to serialize.
|
||||
///
|
||||
/// \returns \li true if all replacements were serialized successfully to
|
||||
/// disk.
|
||||
/// \li false otherwise.
|
||||
bool serializeReplacements(const TUReplacementsMap &Replacements);
|
||||
|
||||
/// \brief Invoke clang-apply-replacements to apply all serialized
|
||||
/// replacements stored in the destination directory.
|
||||
///
|
||||
/// \pre Destination directory must have been previously set by calling
|
||||
/// setDestiantionDir() or useTempDestinationDir().
|
||||
///
|
||||
/// \returns \li true if clang-apply-replacements was successfully launched
|
||||
/// and successfully completed.
|
||||
/// \li false otherwise.
|
||||
bool applyReplacements();
|
||||
|
||||
/// \brief Generate a unique filename to store the replacements.
|
||||
///
|
||||
/// Generates a unique filename in \c DestinationDir. The filename is generated
|
||||
/// following this pattern:
|
||||
///
|
||||
/// DestinationDir/Prefix_%%_%%_%%_%%_%%_%%.yaml
|
||||
///
|
||||
/// where Prefix := llvm::sys::path::filename(MainSourceFile) and all '%' will
|
||||
/// be replaced by a randomly chosen hex digit.
|
||||
///
|
||||
/// \param[in] DestinationDir Directory the unique file should be placed in.
|
||||
/// \param[in] MainSourceFile Full path to the source file.
|
||||
/// \param[out] Result The resulting unique filename.
|
||||
/// \param[out] Error If an error occurs a description of that error is
|
||||
/// placed in this string.
|
||||
///
|
||||
/// \returns \li true on success
|
||||
/// \li false if a unique file name could not be created.
|
||||
static bool generateReplacementsFileName(llvm::StringRef DestinationDir,
|
||||
llvm::StringRef MainSourceFile,
|
||||
llvm::SmallVectorImpl<char> &Result,
|
||||
llvm::SmallVectorImpl<char> &Error);
|
||||
|
||||
/// \brief Helper to create a temporary directory name.
|
||||
///
|
||||
/// \param[out] Resulting name is placed here.
|
||||
static std::string generateTempDir();
|
||||
|
||||
private:
|
||||
|
||||
std::string CARPath;
|
||||
std::string DestinationDir;
|
||||
bool DoFormat;
|
||||
std::string FormatStyle;
|
||||
std::string StyleConfigDir;
|
||||
};
|
||||
|
||||
#endif // CLANG_MODERNIZE_REPLACEMENTHANDLING_H
|
|
@ -1,73 +0,0 @@
|
|||
//===-- Core/SyntaxCheck.cpp ----------------------------------------------===//
|
||||
//
|
||||
// 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 exposes functionaliy for doing a syntax-only check on
|
||||
/// files with overridden contents.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Core/SyntaxCheck.h"
|
||||
#include "Core/FileOverrides.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/FrontendActions.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace tooling;
|
||||
|
||||
class SyntaxCheck : public SyntaxOnlyAction {
|
||||
public:
|
||||
SyntaxCheck(const FileOverrides &Overrides) : Overrides(Overrides) {}
|
||||
|
||||
virtual bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) {
|
||||
if (!SyntaxOnlyAction::BeginSourceFileAction(CI, Filename))
|
||||
return false;
|
||||
|
||||
Overrides.applyOverrides(CI.getSourceManager());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const FileOverrides &Overrides;
|
||||
};
|
||||
|
||||
class SyntaxCheckFactory : public FrontendActionFactory {
|
||||
public:
|
||||
SyntaxCheckFactory(const FileOverrides &Overrides)
|
||||
: Overrides(Overrides) {}
|
||||
|
||||
virtual FrontendAction *create() { return new SyntaxCheck(Overrides); }
|
||||
|
||||
private:
|
||||
const FileOverrides &Overrides;
|
||||
};
|
||||
|
||||
class SyntaxArgumentsAdjuster : public ArgumentsAdjuster {
|
||||
CommandLineArguments Adjust(const CommandLineArguments &Args) {
|
||||
CommandLineArguments AdjustedArgs = Args;
|
||||
AdjustedArgs.push_back("-fsyntax-only");
|
||||
AdjustedArgs.push_back("-std=c++11");
|
||||
return AdjustedArgs;
|
||||
}
|
||||
};
|
||||
|
||||
bool doSyntaxCheck(const CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths,
|
||||
const FileOverrides &Overrides) {
|
||||
ClangTool SyntaxTool(Database, SourcePaths);
|
||||
|
||||
// Ensure C++11 support is enabled.
|
||||
// FIXME: This isn't necessary anymore since the Modernizer requires C++11
|
||||
// to be enabled in the CompilationDatabase. Remove later.
|
||||
SyntaxTool.setArgumentsAdjuster(new SyntaxArgumentsAdjuster);
|
||||
|
||||
return SyntaxTool.run(new SyntaxCheckFactory(Overrides)) == 0;
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
//===-- Core/SyntaxCheck.h --------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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 exposes functionaliy for doing a syntax-only check on
|
||||
/// files with overridden contents.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_MODERNIZE_SYNTAX_CHECK_H
|
||||
#define CLANG_MODERNIZE_SYNTAX_CHECK_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Forward Declarations
|
||||
namespace clang {
|
||||
namespace tooling {
|
||||
class CompilationDatabase;
|
||||
} // namespace tooling
|
||||
} // namespace clang
|
||||
|
||||
class FileOverrides;
|
||||
|
||||
/// \brief Perform a syntax-only check over all files in \c SourcePaths using
|
||||
/// options provided by \c Database using file contents from \c Overrides if
|
||||
/// available.
|
||||
extern bool doSyntaxCheck(const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths,
|
||||
const FileOverrides &Overrides);
|
||||
|
||||
#endif // CLANG_MODERNIZE_SYNTAX_CHECK_H
|
|
@ -14,7 +14,6 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Core/Transform.h"
|
||||
#include "Core/FileOverrides.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
|
@ -76,7 +75,7 @@ private:
|
|||
} // namespace
|
||||
|
||||
Transform::Transform(llvm::StringRef Name, const TransformOptions &Options)
|
||||
: Name(Name), GlobalOptions(Options), Overrides(0) {
|
||||
: Name(Name), GlobalOptions(Options) {
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
@ -95,9 +94,6 @@ bool Transform::isFileModifiable(const SourceManager &SM,
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -50,9 +50,6 @@ class MatchFinder;
|
|||
} // namespace ast_matchers
|
||||
} // namespace clang
|
||||
|
||||
class FileOverrides;
|
||||
|
||||
|
||||
// \brief Maps main source file names to a TranslationUnitReplacements
|
||||
// structure storing replacements for that translation unit.
|
||||
typedef llvm::StringMap<clang::tooling::TranslationUnitReplacements>
|
||||
|
@ -95,13 +92,13 @@ public:
|
|||
|
||||
/// \brief Apply a transform to all files listed in \p SourcePaths.
|
||||
///
|
||||
/// \p Database must contain information for how to compile all files in \p
|
||||
/// SourcePaths. \p InputStates contains the file contents of files in \p
|
||||
/// SourcePaths and should take precedence over content of files on disk.
|
||||
/// Upon return, \p ResultStates shall contain the result of performing this
|
||||
/// transform on the files listed in \p SourcePaths.
|
||||
virtual int apply(const FileOverrides &InputStates,
|
||||
const clang::tooling::CompilationDatabase &Database,
|
||||
/// \param[in] Database Contains information for how to compile all files in
|
||||
/// \p SourcePaths.
|
||||
/// \param[in] SourcePaths list of sources to transform.
|
||||
///
|
||||
/// \returns \li 0 if successful
|
||||
/// \li 1 otherwise
|
||||
virtual int apply(const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) = 0;
|
||||
|
||||
/// \brief Query if changes were made during the last call to apply().
|
||||
|
@ -207,15 +204,6 @@ protected:
|
|||
/// created with.
|
||||
const TransformOptions &Options() { return GlobalOptions; }
|
||||
|
||||
/// \brief Affords a subclass to provide file contents overrides before
|
||||
/// applying frontend actions.
|
||||
///
|
||||
/// It is an error not to call this function before calling ClangTool::run()
|
||||
/// with the factory provided by createActionFactory().
|
||||
void setOverrides(const FileOverrides &Overrides) {
|
||||
this->Overrides = &Overrides;
|
||||
}
|
||||
|
||||
/// \brief Subclasses must call this function to create a
|
||||
/// FrontendActionFactory to pass to ClangTool.
|
||||
///
|
||||
|
@ -227,7 +215,6 @@ protected:
|
|||
private:
|
||||
const std::string Name;
|
||||
const TransformOptions &GlobalOptions;
|
||||
const FileOverrides *Overrides;
|
||||
TUReplacementsMap Replacements;
|
||||
std::string CurrentSource;
|
||||
TimingVec Timings;
|
||||
|
|
|
@ -24,8 +24,7 @@ using clang::ast_matchers::MatchFinder;
|
|||
using namespace clang::tooling;
|
||||
using namespace clang;
|
||||
|
||||
int LoopConvertTransform::apply(const FileOverrides &InputStates,
|
||||
const CompilationDatabase &Database,
|
||||
int LoopConvertTransform::apply(const CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) {
|
||||
ClangTool LoopTool(Database, SourcePaths);
|
||||
|
||||
|
@ -49,8 +48,6 @@ int LoopConvertTransform::apply(const FileOverrides &InputStates,
|
|||
LFK_PseudoArray, /*Owner=*/ *this);
|
||||
Finder.addMatcher(makePseudoArrayLoopMatcher(), &PseudoarrrayLoopFixer);
|
||||
|
||||
setOverrides(InputStates);
|
||||
|
||||
if (int result = LoopTool.run(createActionFactory(Finder))) {
|
||||
llvm::errs() << "Error encountered during translation.\n";
|
||||
return result;
|
||||
|
|
|
@ -31,8 +31,7 @@ public:
|
|||
: Transform("LoopConvert", Options) {}
|
||||
|
||||
/// \see Transform::run().
|
||||
virtual int apply(const FileOverrides &InputStates,
|
||||
const clang::tooling::CompilationDatabase &Database,
|
||||
virtual int apply(const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||
|
||||
virtual bool handleBeginSource(clang::CompilerInstance &CI,
|
||||
|
|
|
@ -21,8 +21,7 @@ using namespace clang;
|
|||
using namespace clang::tooling;
|
||||
using namespace clang::ast_matchers;
|
||||
|
||||
int PassByValueTransform::apply(const FileOverrides &InputStates,
|
||||
const tooling::CompilationDatabase &Database,
|
||||
int PassByValueTransform::apply(const tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) {
|
||||
ClangTool Tool(Database, SourcePaths);
|
||||
unsigned AcceptedChanges = 0;
|
||||
|
@ -36,8 +35,6 @@ int PassByValueTransform::apply(const FileOverrides &InputStates,
|
|||
// make the replacer available to handleBeginSource()
|
||||
this->Replacer = &Replacer;
|
||||
|
||||
setOverrides(InputStates);
|
||||
|
||||
if (Tool.run(createActionFactory(Finder))) {
|
||||
llvm::errs() << "Error encountered during translation.\n";
|
||||
return 1;
|
||||
|
|
|
@ -58,8 +58,7 @@ public:
|
|||
: Transform("PassByValue", Options), Replacer(0) {}
|
||||
|
||||
/// \see Transform::apply().
|
||||
virtual int apply(const FileOverrides &InputStates,
|
||||
const clang::tooling::CompilationDatabase &Database,
|
||||
virtual int apply(const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
|
|
@ -22,8 +22,7 @@ using namespace clang::tooling;
|
|||
using namespace clang::ast_matchers;
|
||||
|
||||
int
|
||||
ReplaceAutoPtrTransform::apply(const FileOverrides &InputStates,
|
||||
const CompilationDatabase &Database,
|
||||
ReplaceAutoPtrTransform::apply(const CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) {
|
||||
ClangTool Tool(Database, SourcePaths);
|
||||
unsigned AcceptedChanges = 0;
|
||||
|
@ -35,8 +34,6 @@ ReplaceAutoPtrTransform::apply(const FileOverrides &InputStates,
|
|||
Finder.addMatcher(makeAutoPtrUsingDeclMatcher(), &Replacer);
|
||||
Finder.addMatcher(makeTransferOwnershipExprMatcher(), &Fixer);
|
||||
|
||||
setOverrides(InputStates);
|
||||
|
||||
if (Tool.run(createActionFactory(Finder))) {
|
||||
llvm::errs() << "Error encountered during translation.\n";
|
||||
return 1;
|
||||
|
|
|
@ -47,8 +47,7 @@ public:
|
|||
: Transform("ReplaceAutoPtr", Options) {}
|
||||
|
||||
/// \see Transform::run().
|
||||
virtual int apply(const FileOverrides &InputStates,
|
||||
const clang::tooling::CompilationDatabase &Database,
|
||||
virtual int apply(const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||
};
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@ using clang::ast_matchers::MatchFinder;
|
|||
using namespace clang;
|
||||
using namespace clang::tooling;
|
||||
|
||||
int UseAutoTransform::apply(const FileOverrides &InputStates,
|
||||
const clang::tooling::CompilationDatabase &Database,
|
||||
int UseAutoTransform::apply(const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) {
|
||||
ClangTool UseAutoTool(Database, SourcePaths);
|
||||
|
||||
|
@ -37,8 +36,6 @@ int UseAutoTransform::apply(const FileOverrides &InputStates,
|
|||
Finder.addMatcher(makeIteratorDeclMatcher(), &ReplaceIterators);
|
||||
Finder.addMatcher(makeDeclWithNewMatcher(), &ReplaceNew);
|
||||
|
||||
setOverrides(InputStates);
|
||||
|
||||
if (int Result = UseAutoTool.run(createActionFactory(Finder))) {
|
||||
llvm::errs() << "Error encountered during translation.\n";
|
||||
return Result;
|
||||
|
|
|
@ -34,8 +34,7 @@ public:
|
|||
: Transform("UseAuto", Options) {}
|
||||
|
||||
/// \see Transform::run().
|
||||
virtual int apply(const FileOverrides &InputStates,
|
||||
const clang::tooling::CompilationDatabase &Database,
|
||||
virtual int apply(const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,8 +24,7 @@ using clang::ast_matchers::MatchFinder;
|
|||
using namespace clang::tooling;
|
||||
using namespace clang;
|
||||
|
||||
int UseNullptrTransform::apply(const FileOverrides &InputStates,
|
||||
const CompilationDatabase &Database,
|
||||
int UseNullptrTransform::apply(const CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) {
|
||||
ClangTool UseNullptrTool(Database, SourcePaths);
|
||||
|
||||
|
@ -36,8 +35,6 @@ int UseNullptrTransform::apply(const FileOverrides &InputStates,
|
|||
|
||||
Finder.addMatcher(makeCastSequenceMatcher(), &Fixer);
|
||||
|
||||
setOverrides(InputStates);
|
||||
|
||||
if (int result = UseNullptrTool.run(createActionFactory(Finder))) {
|
||||
llvm::errs() << "Error encountered during translation.\n";
|
||||
return result;
|
||||
|
|
|
@ -28,8 +28,7 @@ public:
|
|||
: Transform("UseNullptr", Options) {}
|
||||
|
||||
/// \see Transform::run().
|
||||
virtual int apply(const FileOverrides &InputStates,
|
||||
const clang::tooling::CompilationDatabase &Database,
|
||||
virtual int apply(const clang::tooling::CompilationDatabase &Database,
|
||||
const std::vector<std::string> &SourcePaths) LLVM_OVERRIDE;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ add_dependencies(clang-modernize
|
|||
)
|
||||
|
||||
target_link_libraries(clang-modernize
|
||||
clangApplyReplacements
|
||||
modernizeCore
|
||||
)
|
||||
|
||||
|
|
|
@ -15,23 +15,20 @@
|
|||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Core/FileOverrides.h"
|
||||
#include "Core/PerfSupport.h"
|
||||
#include "Core/SyntaxCheck.h"
|
||||
#include "Core/ReplacementHandling.h"
|
||||
#include "Core/Transform.h"
|
||||
#include "Core/Transforms.h"
|
||||
#include "Core/Reformatting.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/DiagnosticOptions.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Format/Format.h"
|
||||
#include "clang/Frontend/FrontendActions.h"
|
||||
#include "clang/Rewrite/Core/Rewriter.h"
|
||||
#include "clang/Tooling/CommonOptionsParser.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
#include "clang-apply-replacements/Tooling/ApplyReplacements.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
|
||||
namespace cl = llvm::cl;
|
||||
|
@ -81,13 +78,29 @@ static cl::opt<bool> FinalSyntaxCheck(
|
|||
cl::desc("Check for correct syntax after applying transformations"),
|
||||
cl::init(false));
|
||||
|
||||
static cl::opt<std::string> FormatStyleOpt(
|
||||
"format-style",
|
||||
cl::desc("Coding style to use on the replacements, either a builtin style\n"
|
||||
"or a YAML config file (see: clang-format -dump-config).\n"
|
||||
"Currently supports 4 builtins style:\n"
|
||||
" LLVM, Google, Chromium, Mozilla.\n"),
|
||||
cl::value_desc("string"));
|
||||
static cl::OptionCategory FormattingCategory("Formatting Options");
|
||||
|
||||
static cl::opt<bool> DoFormat(
|
||||
"format",
|
||||
cl::desc("Enable formatting of code changed by applying replacements.\n"
|
||||
"Use -style to choose formatting style.\n"),
|
||||
cl::cat(FormattingCategory));
|
||||
|
||||
static cl::opt<std::string>
|
||||
FormatStyleOpt("style", cl::desc(format::StyleOptionHelpDescription),
|
||||
cl::init("LLVM"), cl::cat(FormattingCategory));
|
||||
|
||||
// FIXME: Consider making the default behaviour for finding a style
|
||||
// configuration file to start the search anew for every file being changed to
|
||||
// handle situations where the style is different for different parts of a
|
||||
// project.
|
||||
|
||||
static cl::opt<std::string> FormatStyleConfig(
|
||||
"style-config",
|
||||
cl::desc("Path to a directory containing a .clang-format file\n"
|
||||
"describing a formatting style to use for formatting\n"
|
||||
"code when -style=file.\n"),
|
||||
cl::init(""), cl::cat(FormattingCategory));
|
||||
|
||||
static cl::opt<bool>
|
||||
SummaryMode("summary", cl::desc("Print transform summary"),
|
||||
|
@ -98,29 +111,46 @@ static cl::opt<std::string> TimingDirectoryName(
|
|||
"directory. Default: ./migrate_perf"),
|
||||
cl::ValueOptional, cl::value_desc("directory name"));
|
||||
|
||||
static cl::OptionCategory IncludeExcludeCategory("Inclusion/Exclusion Options");
|
||||
|
||||
static cl::opt<std::string>
|
||||
IncludePaths("include",
|
||||
cl::desc("Comma seperated list of paths to consider to be "
|
||||
"transformed"));
|
||||
"transformed"),
|
||||
cl::cat(IncludeExcludeCategory));
|
||||
|
||||
static cl::opt<std::string>
|
||||
ExcludePaths("exclude",
|
||||
cl::desc("Comma seperated list of paths that can not "
|
||||
"be transformed"));
|
||||
ExcludePaths("exclude", cl::desc("Comma seperated list of paths that can not "
|
||||
"be transformed"),
|
||||
cl::cat(IncludeExcludeCategory));
|
||||
|
||||
static cl::opt<std::string>
|
||||
IncludeFromFile("include-from", cl::value_desc("filename"),
|
||||
cl::desc("File containing a list of paths to consider to "
|
||||
"be transformed"));
|
||||
"be transformed"),
|
||||
cl::cat(IncludeExcludeCategory));
|
||||
|
||||
static cl::opt<std::string>
|
||||
ExcludeFromFile("exclude-from", cl::value_desc("filename"),
|
||||
cl::desc("File containing a list of paths that can not be "
|
||||
"transforms"));
|
||||
"transforms"),
|
||||
cl::cat(IncludeExcludeCategory));
|
||||
|
||||
static cl::OptionCategory SerializeCategory("Serialization Options");
|
||||
|
||||
static cl::opt<bool>
|
||||
SerializeReplacements("serialize-replacements",
|
||||
cl::Hidden,
|
||||
cl::desc("Serialize translation unit replacements to "
|
||||
"disk instead of changing files."),
|
||||
cl::init(false));
|
||||
SerializeOnly("serialize-replacements",
|
||||
cl::desc("Serialize translation unit replacements to "
|
||||
"disk instead of changing files."),
|
||||
cl::init(false),
|
||||
cl::cat(SerializeCategory));
|
||||
|
||||
static cl::opt<std::string>
|
||||
SerializeLocation("serialize-dir",
|
||||
cl::desc("Path to an existing directory in which to write\n"
|
||||
"serialized replacements. Default behaviour is to\n"
|
||||
"write to a temporary directory.\n"),
|
||||
cl::cat(SerializeCategory));
|
||||
|
||||
cl::opt<std::string> SupportedCompilers(
|
||||
"for-compilers", cl::value_desc("string"),
|
||||
|
@ -184,102 +214,6 @@ static CompilerVersions handleSupportedCompilers(const char *ProgName,
|
|||
return RequiredVersions;
|
||||
}
|
||||
|
||||
/// \brief Creates the Reformatter if the format style option is provided,
|
||||
/// return a null pointer otherwise.
|
||||
///
|
||||
/// \param ProgName The name of the program, \c argv[0], used to print errors.
|
||||
/// \param Error If the \c -format-style is provided but with wrong parameters
|
||||
/// this is parameter is set to \c true, left untouched otherwise. An error
|
||||
/// message is printed with an explanation.
|
||||
static Reformatter *handleFormatStyle(const char *ProgName, bool &Error) {
|
||||
if (FormatStyleOpt.getNumOccurrences() > 0) {
|
||||
format::FormatStyle Style;
|
||||
if (!format::getPredefinedStyle(FormatStyleOpt, &Style)) {
|
||||
llvm::StringRef ConfigFilePath = FormatStyleOpt;
|
||||
llvm::OwningPtr<llvm::MemoryBuffer> Text;
|
||||
llvm::error_code ec;
|
||||
|
||||
ec = llvm::MemoryBuffer::getFile(ConfigFilePath, Text);
|
||||
if (!ec)
|
||||
ec = parseConfiguration(Text->getBuffer(), &Style);
|
||||
|
||||
if (ec) {
|
||||
llvm::errs() << ProgName << ": invalid format style " << FormatStyleOpt
|
||||
<< ": " << ec.message() << "\n";
|
||||
Error = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// force mode to C++11
|
||||
Style.Standard = clang::format::FormatStyle::LS_Cpp11;
|
||||
return new Reformatter(Style);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \brief Use \c ChangesReformatter to reformat all changed regions of all
|
||||
/// files stored in \c Overrides and write the result to disk.
|
||||
///
|
||||
/// \returns \li true if reformatting replacements were successfully applied
|
||||
/// without conflicts and all files were successfully written to
|
||||
/// disk.
|
||||
/// \li false if reformatting could not be successfully applied or
|
||||
/// if at least one file failed to write to disk.
|
||||
void reformat(Reformatter &ChangesReformatter, FileOverrides &Overrides,
|
||||
DiagnosticsEngine &Diagnostics) {
|
||||
FileManager Files((FileSystemOptions()));
|
||||
SourceManager SM(Diagnostics, Files);
|
||||
|
||||
replace::TUReplacements AllReplacements(1);
|
||||
ChangesReformatter.reformatChanges(Overrides, SM,
|
||||
AllReplacements.front().Replacements);
|
||||
|
||||
replace::FileToReplacementsMap GroupedReplacements;
|
||||
if (!replace::mergeAndDeduplicate(AllReplacements, GroupedReplacements, SM)) {
|
||||
llvm::errs() << "Warning: Reformatting produced conflicts.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
Rewriter DestRewriter(SM, LangOptions());
|
||||
if (!replace::applyReplacements(GroupedReplacements, DestRewriter)) {
|
||||
llvm::errs() << "Warning: Failed to apply reformatting conflicts!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
Overrides.updateState(DestRewriter);
|
||||
}
|
||||
|
||||
bool serializeReplacements(const replace::TUReplacements &Replacements) {
|
||||
bool Errors = false;
|
||||
for (replace::TUReplacements::const_iterator I = Replacements.begin(),
|
||||
E = Replacements.end();
|
||||
I != E; ++I) {
|
||||
llvm::SmallString<128> ReplacementsFileName;
|
||||
llvm::SmallString<64> Error;
|
||||
bool Result = generateReplacementsFileName(I->MainSourceFile,
|
||||
ReplacementsFileName, Error);
|
||||
if (!Result) {
|
||||
llvm::errs() << "Failed to generate replacements filename:" << Error
|
||||
<< "\n";
|
||||
Errors = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string ErrorInfo;
|
||||
llvm::raw_fd_ostream ReplacementsFile(ReplacementsFileName.c_str(),
|
||||
ErrorInfo, llvm::sys::fs::F_Binary);
|
||||
if (!ErrorInfo.empty()) {
|
||||
llvm::errs() << "Error opening file: " << ErrorInfo << "\n";
|
||||
Errors = true;
|
||||
continue;
|
||||
}
|
||||
llvm::yaml::Output YAML(ReplacementsFile);
|
||||
YAML << const_cast<TranslationUnitReplacements &>(*I);
|
||||
}
|
||||
return !Errors;
|
||||
}
|
||||
|
||||
CompilationDatabase *autoDetectCompilations(std::string &ErrorMessage) {
|
||||
// Auto-detect a compilation database from BuildPath.
|
||||
if (BuildPath.getNumOccurrences() > 0)
|
||||
|
@ -332,6 +266,7 @@ static bool isFileExplicitlyExcludedPredicate(llvm::StringRef FilePath) {
|
|||
int main(int argc, const char **argv) {
|
||||
llvm::sys::PrintStackTraceOnErrorSignal();
|
||||
Transforms TransformManager;
|
||||
ReplacementHandling ReplacementHandler;
|
||||
|
||||
TransformManager.registerTransforms();
|
||||
|
||||
|
@ -386,11 +321,7 @@ int main(int argc, const char **argv) {
|
|||
// Enable timming.
|
||||
GlobalOptions.EnableTiming = TimingDirectoryName.getNumOccurrences() > 0;
|
||||
|
||||
// Check the reformatting style option
|
||||
bool CmdSwitchError = false;
|
||||
llvm::OwningPtr<Reformatter> ChangesReformatter(
|
||||
handleFormatStyle(argv[0], CmdSwitchError));
|
||||
|
||||
CompilerVersions RequiredVersions =
|
||||
handleSupportedCompilers(argv[0], CmdSwitchError);
|
||||
if (CmdSwitchError)
|
||||
|
@ -398,15 +329,6 @@ int main(int argc, const char **argv) {
|
|||
|
||||
TransformManager.createSelectedTransforms(GlobalOptions, RequiredVersions);
|
||||
|
||||
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
|
||||
new DiagnosticOptions());
|
||||
DiagnosticsEngine Diagnostics(
|
||||
llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
|
||||
DiagOpts.getPtr());
|
||||
|
||||
// FIXME: Make this DiagnosticsEngine available to all Transforms probably via
|
||||
// GlobalOptions.
|
||||
|
||||
if (TransformManager.begin() == TransformManager.end()) {
|
||||
if (SupportedCompilers.empty())
|
||||
llvm::errs() << llvm::sys::path::filename(argv[0])
|
||||
|
@ -417,28 +339,52 @@ int main(int argc, const char **argv) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// If SerializeReplacements is requested, then change reformatting must be
|
||||
// turned off and only one transform should be requested. Reformatting is
|
||||
// basically another transform so even if there's only one other transform,
|
||||
// the reformatting pass would make two.
|
||||
if (SerializeReplacements &&
|
||||
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts(
|
||||
new DiagnosticOptions());
|
||||
DiagnosticsEngine Diagnostics(
|
||||
llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
|
||||
DiagOpts.getPtr());
|
||||
|
||||
// FIXME: Make this DiagnosticsEngine available to all Transforms probably via
|
||||
// GlobalOptions.
|
||||
|
||||
// If SerializeReplacements is requested, then code reformatting must be
|
||||
// turned off and only one transform should be requested.
|
||||
if (SerializeOnly &&
|
||||
(std::distance(TransformManager.begin(), TransformManager.end()) > 1 ||
|
||||
ChangesReformatter)) {
|
||||
DoFormat)) {
|
||||
llvm::errs() << "Serialization of replacements requested for multiple "
|
||||
"transforms.\nChanges from only one transform can be "
|
||||
"serialized.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// If we're asked to apply changes to files on disk, need to locate
|
||||
// clang-apply-replacements.
|
||||
if (!SerializeOnly) {
|
||||
if (!ReplacementHandler.findClangApplyReplacements(argv[0])) {
|
||||
llvm::errs() << "Could not find clang-apply-replacements\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (DoFormat)
|
||||
ReplacementHandler.enableFormatting(FormatStyleOpt, FormatStyleConfig);
|
||||
}
|
||||
|
||||
StringRef TempDestinationDir;
|
||||
if (SerializeLocation.getNumOccurrences() > 0)
|
||||
ReplacementHandler.setDestinationDir(SerializeLocation);
|
||||
else
|
||||
TempDestinationDir = ReplacementHandler.useTempDestinationDir();
|
||||
|
||||
SourcePerfData PerfData;
|
||||
FileOverrides FileStates;
|
||||
|
||||
for (Transforms::const_iterator I = TransformManager.begin(),
|
||||
E = TransformManager.end();
|
||||
I != E; ++I) {
|
||||
Transform *T = *I;
|
||||
|
||||
if (T->apply(FileStates, *Compilations, Sources) != 0) {
|
||||
if (T->apply(*Compilations, Sources) != 0) {
|
||||
// FIXME: Improve ClangTool to not abort if just one file fails.
|
||||
return 1;
|
||||
}
|
||||
|
@ -456,65 +402,25 @@ int main(int argc, const char **argv) {
|
|||
llvm::outs() << "\n";
|
||||
}
|
||||
|
||||
// Collect all TranslationUnitReplacements generated from the translation
|
||||
// units the transform worked on and store them in AllReplacements.
|
||||
replace::TUReplacements AllReplacements;
|
||||
const TUReplacementsMap &ReplacementsMap = T->getAllReplacements();
|
||||
const TranslationUnitReplacements &(
|
||||
TUReplacementsMap::value_type::*getValue)() const =
|
||||
&TUReplacementsMap::value_type::getValue;
|
||||
std::transform(ReplacementsMap.begin(), ReplacementsMap.end(),
|
||||
std::back_inserter(AllReplacements),
|
||||
std::mem_fun_ref(getValue));
|
||||
|
||||
if (SerializeReplacements)
|
||||
serializeReplacements(AllReplacements);
|
||||
|
||||
FileManager Files((FileSystemOptions()));
|
||||
SourceManager SM(Diagnostics, Files);
|
||||
|
||||
// Make sure SourceManager is updated to have the same initial state as the
|
||||
// transforms.
|
||||
FileStates.applyOverrides(SM);
|
||||
|
||||
replace::FileToReplacementsMap GroupedReplacements;
|
||||
if (!replace::mergeAndDeduplicate(AllReplacements, GroupedReplacements,
|
||||
SM)) {
|
||||
llvm::outs() << "Transform " << T->getName()
|
||||
<< " resulted in conflicts. Discarding all "
|
||||
<< "replacements.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Apply replacements and update FileStates with new state.
|
||||
Rewriter DestRewriter(SM, LangOptions());
|
||||
if (!replace::applyReplacements(GroupedReplacements, DestRewriter)) {
|
||||
llvm::outs() << "Some replacements failed to apply. Discarding "
|
||||
"all replacements.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update contents of files in memory to serve as initial state for next
|
||||
// transform.
|
||||
FileStates.updateState(DestRewriter);
|
||||
|
||||
// Update changed ranges for reformatting
|
||||
if (ChangesReformatter)
|
||||
FileStates.adjustChangedRanges(GroupedReplacements);
|
||||
}
|
||||
|
||||
// Skip writing final file states to disk if we were asked to serialize
|
||||
// replacements. Otherwise reformat changes if reformatting is enabled.
|
||||
if (!SerializeReplacements) {
|
||||
if (ChangesReformatter)
|
||||
reformat(*ChangesReformatter, FileStates, Diagnostics);
|
||||
FileStates.writeToDisk(Diagnostics);
|
||||
}
|
||||
|
||||
if (FinalSyntaxCheck)
|
||||
if (!doSyntaxCheck(*Compilations, Sources, FileStates))
|
||||
if (!ReplacementHandler.serializeReplacements(T->getAllReplacements()))
|
||||
return 1;
|
||||
|
||||
if (!SerializeOnly)
|
||||
if (!ReplacementHandler.applyReplacements())
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Let the user know which temporary directory the replacements got written
|
||||
// to.
|
||||
if (SerializeOnly && !TempDestinationDir.empty())
|
||||
llvm::errs() << "Replacements serialized to: " << TempDestinationDir << "\n";
|
||||
|
||||
if (FinalSyntaxCheck) {
|
||||
ClangTool SyntaxTool(*Compilations, SourcePaths);
|
||||
if (SyntaxTool.run(newFrontendActionFactory<SyntaxOnlyAction>()) != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Report execution times.
|
||||
if (GlobalOptions.EnableTiming && !PerfData.empty()) {
|
||||
std::string DirectoryName = TimingDirectoryName;
|
||||
|
|
|
@ -36,14 +36,14 @@ SOURCES += $(addprefix ../ReplaceAutoPtr/,$(notdir $(wildcard $(PROJ_SRC_DIR)/..
|
|||
BUILT_SOURCES += $(ObjDir)/../ReplaceAutoPtr/.objdir
|
||||
|
||||
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc mcparser option
|
||||
USEDLIBS = modernizeCore.a clangFormat.a clangApplyReplacements.a clangTooling.a clangFrontend.a \
|
||||
USEDLIBS = modernizeCore.a clangFormat.a clangTooling.a clangFrontend.a \
|
||||
clangSerialization.a clangDriver.a clangRewriteFrontend.a \
|
||||
clangRewriteCore.a clangParse.a clangSema.a clangAnalysis.a \
|
||||
clangAST.a clangASTMatchers.a clangEdit.a clangLex.a clangBasic.a
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
||||
CPP.Flags += -I$(PROJ_SRC_DIR)/.. -I$(PROJ_SRC_DIR)/../../clang-apply-replacements/include
|
||||
CPP.Flags += -I$(PROJ_SRC_DIR)/..
|
||||
|
||||
# BUILT_SOURCES gets used as a prereq for many top-level targets. However, at
|
||||
# the point those targets are defined, $(ObjDir) hasn't been defined and so the
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
---
|
||||
# BasedOnStyle: Google
|
||||
AccessModifierOffset: -1
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
AlignEscapedNewlinesLeft: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BinPackParameters: true
|
||||
ColumnLimit: 80
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
DerivePointerBinding: true
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
IndentCaseLabels: true
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
PenaltyBreakComment: 60
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerBindsToType: true
|
||||
SpacesBeforeTrailingComments: 2
|
||||
Cpp11BracedListStyle: true
|
||||
Standard: Auto
|
||||
IndentWidth: 2
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
BreakBeforeBraces: Attach
|
||||
IndentFunctionDeclarationAfterType: true
|
||||
SpacesInParentheses: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpaceAfterControlStatementKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
...
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
|
||||
// RUN: clang-modernize -format-style=LLVM -use-auto %t.cpp -- -std=c++11
|
||||
// RUN: FileCheck --strict-whitespace -input-file=%t.cpp %s
|
||||
|
||||
class C {};
|
||||
|
||||
void f() { //
|
||||
C *a = new C();
|
||||
// CHECK: {{^\ \ auto\ a\ \=\ new\ C\(\);}}
|
||||
}
|
|
@ -1,11 +1,37 @@
|
|||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
|
||||
// RUN: not clang-modernize -format-style=non_existent_file.yaml -use-auto %t.cpp -- -std=c++11
|
||||
// RUN: touch %T/non_format_config.yaml
|
||||
// RUN: not clang-modernize -format-style=%T/non_format_config.yaml -use-auto %t.cpp -- -std=c++11
|
||||
// RUN: clang-modernize -format-style=LLVM -use-auto %t.cpp -- -std=c++11
|
||||
// RUN: clang-modernize -format -use-auto %t.cpp
|
||||
// RUN: FileCheck --strict-whitespace -input-file=%t.cpp %s
|
||||
|
||||
class MyType012345678901234567890123456789 {};
|
||||
// Ensure that -style is forwarded to clang-apply-replacements by using a style
|
||||
// other than LLVM and ensuring the result is styled as requested.
|
||||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
|
||||
// RUN: clang-modernize -format -style=Google -use-nullptr %t.cpp
|
||||
// RUN: FileCheck --check-prefix=Google --strict-whitespace -input-file=%t.cpp %s
|
||||
|
||||
// Ensure -style-config is forwarded to clang-apply-replacements. The .clang-format
|
||||
// in %S/Inputs is a dump of the Google style so the same test can be used.
|
||||
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
|
||||
// RUN: clang-modernize -format -style=file -style-config=%S/Inputs -use-nullptr %t.cpp
|
||||
// RUN: FileCheck --check-prefix=Google --strict-whitespace -input-file=%t.cpp %s
|
||||
|
||||
class MyType012345678901234567890123456789 {
|
||||
public:
|
||||
MyType012345678901234567890123456789()
|
||||
: iiiiiiiiiiii(0), jjjjjjjjjjjj(0), kkkkkkkkkkkk(0), mmmmmmmmmmmm(0),
|
||||
nnnnnnnnnnnn(0) {}
|
||||
// Google: iiiiiiiiiiii(nullptr),
|
||||
// Google-NEXT: jjjjjjjjjjjj(nullptr),
|
||||
// Google-NEXT: kkkkkkkkkkkk(nullptr),
|
||||
// Google-NEXT: mmmmmmmmmmmm(nullptr),
|
||||
// Google-NEXT: nnnnnnnnnnnn(nullptr) {}
|
||||
|
||||
private:
|
||||
int *iiiiiiiiiiii;
|
||||
int *jjjjjjjjjjjj;
|
||||
int *kkkkkkkkkkkk;
|
||||
int *mmmmmmmmmmmm;
|
||||
int *nnnnnnnnnnnn;
|
||||
};
|
||||
|
||||
int f() {
|
||||
MyType012345678901234567890123456789 *a =
|
||||
|
@ -13,4 +39,6 @@ int f() {
|
|||
// CHECK: {{^\ \ auto\ a\ \=\ new\ MyType012345678901234567890123456789\(\);}}
|
||||
|
||||
delete a;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
// RUN: rm -rf %T/SerializeTest
|
||||
// RUN: mkdir -p %T/SerializeTest
|
||||
// RUN: cp %S/main.cpp %S/common.cpp %S/common.h %T/SerializeTest
|
||||
// RUN: clang-modernize -loop-convert -serialize-replacements -include=%T/SerializeTest %T/SerializeTest/main.cpp %T/SerializeTest/common.cpp --
|
||||
// RUN: clang-modernize -loop-convert -serialize-replacements -serialize-dir=%T/SerializeTest -include=%T/SerializeTest %T/SerializeTest/main.cpp %T/SerializeTest/common.cpp --
|
||||
// Check that only 1 file is generated per translation unit
|
||||
// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=MAIN_CPP
|
||||
// RUN: ls -1 %T/SerializeTest | FileCheck %s --check-prefix=COMMON_CPP
|
||||
|
|
|
@ -15,8 +15,6 @@ include_directories(
|
|||
)
|
||||
|
||||
add_extra_unittest(ClangModernizeTests
|
||||
FileOverridesTest.cpp
|
||||
ReformattingTest.cpp
|
||||
IncludeExcludeTest.cpp
|
||||
PerfSupportTest.cpp
|
||||
TransformTest.cpp
|
||||
|
|
|
@ -1,187 +0,0 @@
|
|||
//===- clang-modernize/FileOverridesTest.cpp - File overrides unit tests --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Core/FileOverrides.h"
|
||||
#include "Core/Refactoring.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "common/VirtualFileHelper.h"
|
||||
#include "clang/Rewrite/Core/Rewriter.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::tooling;
|
||||
|
||||
static Replacement makeReplacement(unsigned Offset, unsigned Length,
|
||||
unsigned ReplacementLength,
|
||||
llvm::StringRef FilePath) {
|
||||
return Replacement(FilePath, Offset, Length,
|
||||
std::string(ReplacementLength, '~'));
|
||||
}
|
||||
|
||||
// generate a set of replacements containing one element
|
||||
static ReplacementsVec makeReplacements(unsigned Offset, unsigned Length,
|
||||
unsigned ReplacementLength,
|
||||
llvm::StringRef FilePath = "~") {
|
||||
ReplacementsVec Replaces;
|
||||
Replaces.push_back(
|
||||
makeReplacement(Offset, Length, ReplacementLength, FilePath));
|
||||
return Replaces;
|
||||
}
|
||||
|
||||
static bool equalRanges(Range A, Range B) {
|
||||
return A.getOffset() == B.getOffset() && A.getLength() == B.getLength();
|
||||
}
|
||||
|
||||
TEST(ChangedRangesTest, adjustChangedRangesShrink) {
|
||||
ChangedRanges Changes;
|
||||
Changes.adjustChangedRanges(makeReplacements(0, 0, 4));
|
||||
EXPECT_NE(Changes.begin(), Changes.end());
|
||||
EXPECT_TRUE(equalRanges(Range(0, 4), *Changes.begin()));
|
||||
// create a replacement that cuts the end of the last insertion
|
||||
Changes.adjustChangedRanges(makeReplacements(2, 4, 0));
|
||||
Range ExpectedChanges[] = { Range(0, 2) };
|
||||
EXPECT_TRUE(
|
||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
||||
}
|
||||
|
||||
TEST(ChangedRangesTest, adjustChangedRangesExtend) {
|
||||
ChangedRanges Changes;
|
||||
Changes.adjustChangedRanges(makeReplacements(1, 0, 4));
|
||||
// cut the old one by a bigger one
|
||||
Changes.adjustChangedRanges(makeReplacements(3, 4, 6));
|
||||
Range ExpectedChanges[] = { Range(1, 8) };
|
||||
EXPECT_TRUE(
|
||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
||||
}
|
||||
|
||||
TEST(ChangedRangesTest, adjustChangedRangesNoOverlap) {
|
||||
ChangedRanges Changes;
|
||||
Changes.adjustChangedRanges(makeReplacements(0, 0, 4));
|
||||
Changes.adjustChangedRanges(makeReplacements(6, 0, 4));
|
||||
Range ExpectedChanges[] = { Range(0, 4), Range(6, 4) };
|
||||
EXPECT_TRUE(
|
||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
||||
}
|
||||
|
||||
TEST(ChangedRangesTest, adjustChangedRangesNullRange) {
|
||||
ChangedRanges Changes;
|
||||
Changes.adjustChangedRanges(makeReplacements(0, 4, 0));
|
||||
Range ExpectedChanges[] = { Range(0, 0) };
|
||||
EXPECT_TRUE(
|
||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
||||
}
|
||||
|
||||
TEST(ChangedRangesTest, adjustChangedRangesExtendExisting) {
|
||||
ChangedRanges Changes;
|
||||
Changes.adjustChangedRanges(makeReplacements(0, 0, 3));
|
||||
Changes.adjustChangedRanges(makeReplacements(2, 5, 8));
|
||||
Range ExpectedChanges[] = { Range(0, 10) };
|
||||
EXPECT_TRUE(
|
||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
||||
}
|
||||
|
||||
TEST(ChangedRangesTest, adjustChangedRangesSplit) {
|
||||
ChangedRanges Changes;
|
||||
Changes.adjustChangedRanges(makeReplacements(0, 0, 3));
|
||||
Changes.adjustChangedRanges(makeReplacements(1, 1, 0));
|
||||
Range ExpectedChanges[] = { Range(0, 2) };
|
||||
EXPECT_TRUE(
|
||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
||||
}
|
||||
|
||||
TEST(ChangedRangesTest, adjustChangedRangesRangeContained) {
|
||||
ChangedRanges Changes;
|
||||
Changes.adjustChangedRanges(makeReplacements(3, 0, 2));
|
||||
Changes.adjustChangedRanges(makeReplacements(1, 4, 5));
|
||||
Range ExpectedChanges[] = { Range(1, 5) };
|
||||
EXPECT_TRUE(
|
||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
||||
}
|
||||
|
||||
TEST(ChangedRangesTest, adjustChangedRangesRangeResized) {
|
||||
ChangedRanges Changes;
|
||||
Changes.adjustChangedRanges(makeReplacements(2, 0, 5));
|
||||
// first make the range bigger
|
||||
Changes.adjustChangedRanges(makeReplacements(4, 1, 3));
|
||||
Range ExpectedChanges[] = { Range(2, 7) };
|
||||
EXPECT_TRUE(
|
||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
||||
// then smaller
|
||||
Changes.adjustChangedRanges(makeReplacements(3, 3, 1));
|
||||
ExpectedChanges[0] = Range(2, 5);
|
||||
EXPECT_TRUE(
|
||||
std::equal(Changes.begin(), Changes.end(), ExpectedChanges, equalRanges));
|
||||
}
|
||||
|
||||
TEST(FileOverridesTest, applyOverrides) {
|
||||
|
||||
// Set up initial state
|
||||
VirtualFileHelper VFHelper;
|
||||
|
||||
SmallString<128> fileAPath("fileA.cpp");
|
||||
ASSERT_FALSE(llvm::sys::fs::make_absolute(fileAPath));
|
||||
SmallString<128> fileBPath("fileB.cpp");
|
||||
ASSERT_FALSE(llvm::sys::fs::make_absolute(fileBPath));
|
||||
VFHelper.mapFile(fileAPath, "Content A");
|
||||
VFHelper.mapFile(fileBPath, "Content B");
|
||||
SourceManager &SM = VFHelper.getNewSourceManager();
|
||||
|
||||
// Fill a Rewriter with changes
|
||||
Rewriter Rewrites(SM, LangOptions());
|
||||
ReplacementsVec R(1, Replacement(fileAPath, 0, 7, "Stuff"));
|
||||
ASSERT_TRUE(applyAllReplacements(R, Rewrites));
|
||||
|
||||
FileOverrides Overrides;
|
||||
Overrides.updateState(Rewrites);
|
||||
|
||||
const FileOverrides::FileStateMap &State = Overrides.getState();
|
||||
|
||||
// Ensure state updated
|
||||
ASSERT_TRUE(State.end() == State.find(fileBPath));
|
||||
ASSERT_TRUE(State.begin() == State.find(fileAPath));
|
||||
ASSERT_EQ("Stuff A", State.begin()->getValue());
|
||||
|
||||
Overrides.applyOverrides(SM);
|
||||
|
||||
const FileEntry *EntryA = SM.getFileManager().getFile(fileAPath);
|
||||
FileID IdA = SM.translateFile(EntryA);
|
||||
ASSERT_FALSE(IdA.isInvalid());
|
||||
|
||||
// Ensure the contents of the buffer matches what we'd expect.
|
||||
const llvm::MemoryBuffer *BufferA = SM.getBuffer(IdA);
|
||||
ASSERT_FALSE(0 == BufferA);
|
||||
ASSERT_EQ("Stuff A", BufferA->getBuffer());
|
||||
}
|
||||
|
||||
TEST(FileOverridesTest, adjustChangedRanges) {
|
||||
SmallString<128> fileAPath("fileA.cpp");
|
||||
ASSERT_FALSE(llvm::sys::fs::make_absolute(fileAPath));
|
||||
SmallString<128> fileBPath("fileB.cpp");
|
||||
ASSERT_FALSE(llvm::sys::fs::make_absolute(fileBPath));
|
||||
|
||||
replace::FileToReplacementsMap GroupedReplacements;
|
||||
GroupedReplacements[fileAPath] = makeReplacements(0, 5, 4, fileAPath);
|
||||
GroupedReplacements[fileBPath] = makeReplacements(10, 0, 6, fileBPath);
|
||||
|
||||
FileOverrides Overrides;
|
||||
|
||||
const FileOverrides::ChangeMap &Map = Overrides.getChangedRanges();
|
||||
|
||||
ASSERT_TRUE(Map.empty());
|
||||
|
||||
Overrides.adjustChangedRanges(GroupedReplacements);
|
||||
|
||||
ASSERT_TRUE(Map.end() != Map.find(fileAPath));
|
||||
ASSERT_TRUE(Map.end() != Map.find(fileBPath));
|
||||
const Range &RA = *Map.find(fileAPath)->second.begin();
|
||||
EXPECT_EQ(0u, RA.getOffset());
|
||||
EXPECT_EQ(4u, RA.getLength());
|
||||
const Range &RB = *Map.find(fileBPath)->second.begin();
|
||||
EXPECT_EQ(10u, RB.getOffset());
|
||||
EXPECT_EQ(6u, RB.getLength());
|
||||
}
|
|
@ -18,8 +18,7 @@ public:
|
|||
TransformA(const TransformOptions &Options)
|
||||
: Transform("TransformA", Options) {}
|
||||
|
||||
virtual int apply(const FileOverrides &,
|
||||
const tooling::CompilationDatabase &,
|
||||
virtual int apply(const tooling::CompilationDatabase &,
|
||||
const std::vector<std::string> &) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -34,8 +33,7 @@ public:
|
|||
TransformB(const TransformOptions &Options)
|
||||
: Transform("TransformB", Options) {}
|
||||
|
||||
virtual int apply(const FileOverrides &,
|
||||
const tooling::CompilationDatabase &,
|
||||
virtual int apply(const tooling::CompilationDatabase &,
|
||||
const std::vector<std::string> &) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
//===- clang-modernize/ReformattingTest.cpp - Reformatting unit tests -----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Core/Reformatting.h"
|
||||
#include "Core/FileOverrides.h"
|
||||
#include "Core/Refactoring.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "common/VirtualFileHelper.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::tooling;
|
||||
|
||||
namespace {
|
||||
// convenience function to create a ChangedRanges containing one Range
|
||||
ChangedRanges makeChangedRanges(unsigned Offset, unsigned Length) {
|
||||
ChangedRanges Changes;
|
||||
ReplacementsVec Replaces;
|
||||
|
||||
Replaces.push_back(Replacement("", Offset, 0, std::string(Length, '~')));
|
||||
Changes.adjustChangedRanges(Replaces);
|
||||
return Changes;
|
||||
}
|
||||
} // end anonymous namespace
|
||||
|
||||
TEST(Reformatter, SingleReformat) {
|
||||
VirtualFileHelper VFHelper;
|
||||
llvm::StringRef FileName = "<test>";
|
||||
VFHelper.mapFile(FileName, "int a;\n"
|
||||
"int b;\n");
|
||||
|
||||
Reformatter ChangesReformatter(format::getLLVMStyle());
|
||||
ChangedRanges Changes = makeChangedRanges(0, 6);
|
||||
tooling::ReplacementsVec Replaces;
|
||||
ChangesReformatter.reformatSingleFile(
|
||||
FileName, Changes, VFHelper.getNewSourceManager(), Replaces);
|
||||
|
||||
// We expect the code above to reformatted like so:
|
||||
//
|
||||
// int a;
|
||||
// int b;
|
||||
//
|
||||
// This test is slightly fragile since there's more than one Replacement that
|
||||
// results in the above change. However, testing the result of applying the
|
||||
// replacement is more trouble than it's worth in this context.
|
||||
ASSERT_EQ(1u, Replaces.size());
|
||||
EXPECT_EQ(3u, Replaces[0].getOffset());
|
||||
EXPECT_EQ(2u, Replaces[0].getLength());
|
||||
EXPECT_EQ(" ", Replaces[0].getReplacementText());
|
||||
}
|
|
@ -8,7 +8,6 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "Core/FileOverrides.h"
|
||||
#include "Core/Transform.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/DeclGroup.h"
|
||||
|
@ -26,8 +25,7 @@ public:
|
|||
DummyTransform(llvm::StringRef Name, const TransformOptions &Options)
|
||||
: Transform(Name, Options) {}
|
||||
|
||||
virtual int apply(const FileOverrides &,
|
||||
const tooling::CompilationDatabase &,
|
||||
virtual int apply(const tooling::CompilationDatabase &,
|
||||
const std::vector<std::string> &) { return 0; }
|
||||
|
||||
void setAcceptedChanges(unsigned Changes) {
|
||||
|
@ -40,10 +38,6 @@ public:
|
|||
Transform::setDeferredChanges(Changes);
|
||||
}
|
||||
|
||||
void setOverrides(FileOverrides &Overrides) {
|
||||
Transform::setOverrides(Overrides);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST(Transform, Interface) {
|
||||
|
@ -159,11 +153,6 @@ TEST(Transform, Timings) {
|
|||
// handleEndSource() calls to it.
|
||||
CallbackForwarder Callbacks(T);
|
||||
|
||||
// Transform's handle* functions require FileOverrides to be set, even if
|
||||
// there aren't any.
|
||||
FileOverrides Overrides;
|
||||
T.setOverrides(Overrides);
|
||||
|
||||
Tool.run(clang::tooling::newFrontendActionFactory(&Factory, &Callbacks));
|
||||
|
||||
EXPECT_TRUE(Factory.Called);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "Core/FileOverrides.h"
|
||||
#include "Core/ReplacementHandling.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
|
@ -28,10 +28,13 @@ TEST(UniqueHeaderName, testUniqueHeaderName) {
|
|||
append(SourceFile, "project/lib/feature.cpp");
|
||||
native(SourceFile.str().str(), SourceFile);
|
||||
|
||||
llvm::SmallString<128> DestDir(TmpDir);
|
||||
append(DestDir, "replacements");
|
||||
|
||||
llvm::SmallString<128> FullActualPath;
|
||||
llvm::SmallString<128> Error;
|
||||
bool Result =
|
||||
generateReplacementsFileName(SourceFile, FullActualPath, Error);
|
||||
bool Result = ReplacementHandling::generateReplacementsFileName(
|
||||
DestDir, SourceFile, FullActualPath, Error);
|
||||
|
||||
ASSERT_TRUE(Result);
|
||||
EXPECT_TRUE(Error.empty());
|
||||
|
@ -45,7 +48,7 @@ TEST(UniqueHeaderName, testUniqueHeaderName) {
|
|||
llvm::SmallString<128> ActualName =
|
||||
llvm::sys::path::filename(FullActualPath);
|
||||
|
||||
EXPECT_STREQ(ExpectedPath.c_str(), ActualPath.c_str());
|
||||
EXPECT_STREQ(DestDir.c_str(), ActualPath.c_str());
|
||||
|
||||
llvm::StringRef ExpectedName =
|
||||
"^feature.cpp_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_[0-9a-f]{2}_["
|
||||
|
|
Loading…
Reference in New Issue