Commit 7a2cd85b authored by Jan Wilken Dörrie's avatar Jan Wilken Dörrie Committed by Chromium LUCI CQ

[clang] Add StringPiece Rewriter Tool

This change adds a clang tool to rewrite deprecated base::StringPiece
APIs. To do so, it makes use Clang Transformer [1], significantly
reducing the required boilerplate. For now, it only removes usages of
the `as_string()` API, replacing it with explicit std::string
constructions or omitting it entirely, if possible.

The edits generated by the tool compile cleanly, except when used
in complicated macro expressions. In these cases commas might not be
enclosed in parentheses correctly. While it'd be possible to modify
the tool to handle these cases properly, the required effort likely
outweighs a small manual pass over the result to fix these issues.

[1] http://lists.llvm.org/pipermail/cfe-dev/2018-November/060184.html

Bug: 1049498
Change-Id: I77a0945d6cb59bde6f2ad65f079a399f67bbd054
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2601742
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarŁukasz Anforowicz <lukasza@chromium.org>
Cr-Commit-Position: refs/heads/master@{#841008}
parent abfa914a
set(LLVM_LINK_COMPONENTS
BitReader
MCParser
Option
Support
X86AsmParser
X86CodeGen
X86Desc
X86Info
)
add_llvm_executable(string_piece_rewriters
StringPieceRewriters.cpp
)
target_link_libraries(string_piece_rewriters
clangAST
clangASTMatchers
clangAnalysis
clangBasic
clangDriver
clangEdit
clangFrontend
clangLex
clangParse
clangSema
clangSerialization
clangTooling
clangToolingCore
clangTransformer
)
cr_install(TARGETS string_piece_rewriters RUNTIME DESTINATION bin)
This diff is collapsed.
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <iostream>
#include <memory>
#include "base/strings/string_piece.h"
void RemoveAsStringInExplicitStringConstruction() {
base::StringPiece piece = "Hello";
std::string str{piece};
}
void RemoveAsStringWhenConstructingStringPiece() {
auto* piece_ptr = new base::StringPiece("Hello");
const base::StringPiece& piece_ref = *piece_ptr;
}
void RemoveAsStringForMembers() {
base::StringPiece piece = "Hello";
piece.begin();
piece.cbegin();
piece.end();
piece.cend();
piece.rbegin();
piece.crbegin();
piece.rend();
piece.crend();
piece.at(0);
piece.front();
piece.back();
piece.size();
auto* piece_ptr = &piece;
piece_ptr->length();
piece_ptr->max_size();
piece_ptr->empty();
piece_ptr->copy(nullptr, 0);
piece_ptr->compare(std::string(*piece_ptr));
piece_ptr->find('\0');
piece_ptr->rfind('\0');
piece_ptr->find_first_of('\0');
piece_ptr->find_last_of('\0');
piece_ptr->find_first_not_of('\0');
piece_ptr->find_last_not_of('\0');
piece_ptr->npos;
// Negative tests, where simply removing as_string() is incorrect. It should
// rather be replaced by an explicit std::string construction.
std::string(piece).data();
std::string(*piece_ptr).substr(0);
}
void RemoveAsStringForOperators() {
base::StringPiece piece = "Hello";
std::cout << piece;
piece == "Hello";
piece != "Hello";
piece < "Hello";
piece > "Hello";
piece <= "Hello";
piece >= "Hello";
// Negative tests, where simply removing as_string() is incorrect. It should
// rather be replaced by an explicit std::string construction.
std::string(piece) += "Hello";
std::string(piece) + "Hello";
std::string(piece) = "Hello";
std::string(piece)[0];
}
void RemoveAsStringWhenConstructingStringMember() {
class S {
public:
explicit S(base::StringPiece piece) : str_(piece) {}
private:
std::string str_;
};
}
void RewriteCStyleStringInitialization() {
auto piece_ptr = std::make_unique<base::StringPiece>("Hello");
const std::string str(*piece_ptr);
}
void ReplaceAsStringWithStringConstructor() {
auto piece_ptr = std::make_unique<base::StringPiece>("Hello");
std::string str = std::string(*piece_ptr).append(" World");
}
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <iostream>
#include <memory>
#include "base/strings/string_piece.h"
void RemoveAsStringInExplicitStringConstruction() {
base::StringPiece piece = "Hello";
std::string str{piece.as_string()};
}
void RemoveAsStringWhenConstructingStringPiece() {
auto* piece_ptr = new base::StringPiece("Hello");
const base::StringPiece& piece_ref = piece_ptr->as_string();
}
void RemoveAsStringForMembers() {
base::StringPiece piece = "Hello";
piece.as_string().begin();
piece.as_string().cbegin();
piece.as_string().end();
piece.as_string().cend();
piece.as_string().rbegin();
piece.as_string().crbegin();
piece.as_string().rend();
piece.as_string().crend();
piece.as_string().at(0);
piece.as_string().front();
piece.as_string().back();
piece.as_string().size();
auto* piece_ptr = &piece;
piece_ptr->as_string().length();
piece_ptr->as_string().max_size();
piece_ptr->as_string().empty();
piece_ptr->as_string().copy(nullptr, 0);
piece_ptr->as_string().compare(piece_ptr->as_string());
piece_ptr->as_string().find('\0');
piece_ptr->as_string().rfind('\0');
piece_ptr->as_string().find_first_of('\0');
piece_ptr->as_string().find_last_of('\0');
piece_ptr->as_string().find_first_not_of('\0');
piece_ptr->as_string().find_last_not_of('\0');
piece_ptr->as_string().npos;
// Negative tests, where simply removing as_string() is incorrect. It should
// rather be replaced by an explicit std::string construction.
piece.as_string().data();
piece_ptr->as_string().substr(0);
}
void RemoveAsStringForOperators() {
base::StringPiece piece = "Hello";
std::cout << piece.as_string();
piece.as_string() == "Hello";
piece.as_string() != "Hello";
piece.as_string() < "Hello";
piece.as_string() > "Hello";
piece.as_string() <= "Hello";
piece.as_string() >= "Hello";
// Negative tests, where simply removing as_string() is incorrect. It should
// rather be replaced by an explicit std::string construction.
piece.as_string() += "Hello";
piece.as_string() + "Hello";
piece.as_string() = "Hello";
piece.as_string()[0];
}
void RemoveAsStringWhenConstructingStringMember() {
class S {
public:
explicit S(base::StringPiece piece) : str_(piece.as_string()) {}
private:
std::string str_;
};
}
void RewriteCStyleStringInitialization() {
auto piece_ptr = std::make_unique<base::StringPiece>("Hello");
const std::string str = piece_ptr->as_string();
}
void ReplaceAsStringWithStringConstructor() {
auto piece_ptr = std::make_unique<base::StringPiece>("Hello");
std::string str = piece_ptr->as_string().append(" World");
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment