mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-12 21:56:54 +00:00
container_info: switch to boost::regex (#465)
Summary: OI was previously using `std::regex_match` to match container names. This was bad because `libstdc++`'s implementation of regex is awful. In the case of limited inlining it was causing a stack overflow when running CodeGen for large types (I think types with large names but I never got to the bottom of it). Replace this with the competent `boost::regex_match` that we already have a dependency on. Reviewed By: ajor Differential Revision: D53002752
This commit is contained in:
parent
1c65ed8ec7
commit
b5b94ed236
@ -34,6 +34,8 @@ add_library(container_info
|
||||
)
|
||||
target_link_libraries(container_info
|
||||
features
|
||||
|
||||
Boost::regex
|
||||
glog::glog
|
||||
toml
|
||||
)
|
||||
|
@ -75,12 +75,12 @@ const char* containerTypeEnumToStr(ContainerTypeEnum ty) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::regex matcher;
|
||||
boost::regex matcher;
|
||||
if (std::optional<std::string> str =
|
||||
(*info)["matcher"].value<std::string>()) {
|
||||
matcher = std::regex(*str, std::regex_constants::grep);
|
||||
matcher = boost::regex(*str, boost::regex_constants::grep);
|
||||
} else {
|
||||
matcher = std::regex("^" + typeName, std::regex_constants::grep);
|
||||
matcher = boost::regex("^" + typeName, boost::regex_constants::grep);
|
||||
}
|
||||
|
||||
std::optional<size_t> numTemplateParams =
|
||||
@ -194,8 +194,9 @@ namespace {
|
||||
*
|
||||
* The type name "name" should match "name" and "name<xxx>".
|
||||
*/
|
||||
std::regex getMatcher(const std::string& typeName) {
|
||||
return std::regex("^" + typeName + "$|^" + typeName + "<.*>$");
|
||||
boost::regex getMatcher(const std::string& typeName) {
|
||||
return boost::regex("^" + typeName + "$|^" + typeName + "<.*>$",
|
||||
boost::regex_constants::extended);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@ -225,7 +226,7 @@ ContainerInfo::ContainerInfo(const fs::path& path) {
|
||||
throw ContainerInfoError(path, "`info.type_name` is a required field");
|
||||
}
|
||||
|
||||
matcher = getMatcher(typeName);
|
||||
matcher_ = getMatcher(typeName);
|
||||
|
||||
if (std::optional<std::string> str = info["ctype"].value<std::string>()) {
|
||||
ctype = containerTypeEnumFromStr(*str);
|
||||
@ -334,9 +335,9 @@ ContainerInfo::ContainerInfo(std::string typeName_,
|
||||
ContainerTypeEnum ctype_,
|
||||
std::string header_)
|
||||
: typeName(std::move(typeName_)),
|
||||
matcher(getMatcher(typeName)),
|
||||
ctype(ctype_),
|
||||
header(std::move(header_)),
|
||||
codegen(Codegen{
|
||||
"// DummyDecl %1%\n", "// DummyFunc %1%\n", "// DummyFunc\n"}) {
|
||||
"// DummyDecl %1%\n", "// DummyFunc %1%\n", "// DummyFunc\n"}),
|
||||
matcher_(getMatcher(typeName)) {
|
||||
}
|
||||
|
@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
#pragma once
|
||||
#include <boost/regex.hpp>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <regex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -49,7 +49,7 @@ struct ContainerInfo {
|
||||
// Old ctors, remove with OICodeGen:
|
||||
ContainerInfo() = default;
|
||||
ContainerInfo(std::string typeName_,
|
||||
std::regex matcher_,
|
||||
boost::regex matcher,
|
||||
std::optional<size_t> numTemplateParams_,
|
||||
ContainerTypeEnum ctype_,
|
||||
std::string header_,
|
||||
@ -61,7 +61,6 @@ struct ContainerInfo {
|
||||
oi::detail::FeatureSet requiredFeatures,
|
||||
ContainerInfo::Codegen codegen_)
|
||||
: typeName(std::move(typeName_)),
|
||||
matcher(std::move(matcher_)),
|
||||
numTemplateParams(numTemplateParams_),
|
||||
ctype(ctype_),
|
||||
header(std::move(header_)),
|
||||
@ -71,7 +70,8 @@ struct ContainerInfo {
|
||||
underlyingContainerIndex(underlyingContainerIndex_),
|
||||
stubTemplateParams(std::move(stubTemplateParams_)),
|
||||
requiredFeatures(requiredFeatures),
|
||||
codegen(std::move(codegen_)) {
|
||||
codegen(std::move(codegen_)),
|
||||
matcher_(std::move(matcher)) {
|
||||
}
|
||||
|
||||
ContainerInfo(ContainerInfo&&) = default;
|
||||
@ -83,8 +83,11 @@ struct ContainerInfo {
|
||||
return copy;
|
||||
}
|
||||
|
||||
bool matches(std::string_view sv) const {
|
||||
return boost::regex_search(sv.begin(), sv.end(), matcher_);
|
||||
}
|
||||
|
||||
std::string typeName;
|
||||
std::regex matcher;
|
||||
std::optional<size_t> numTemplateParams;
|
||||
ContainerTypeEnum ctype = UNKNOWN_TYPE;
|
||||
std::string header;
|
||||
@ -110,6 +113,8 @@ struct ContainerInfo {
|
||||
private:
|
||||
ContainerInfo(const ContainerInfo&) = default;
|
||||
ContainerInfo& operator=(const ContainerInfo& other) = default;
|
||||
|
||||
boost::regex matcher_;
|
||||
};
|
||||
|
||||
class ContainerInfoError : public std::runtime_error {
|
||||
|
@ -150,7 +150,7 @@ OICodeGen::getContainerInfo(drgn_type* type) {
|
||||
for (auto it = containerInfoList.rbegin(); it != containerInfoList.rend();
|
||||
++it) {
|
||||
const ContainerInfo& info = **it;
|
||||
if (std::regex_search(nameStr, info.matcher)) {
|
||||
if (info.matches(nameStr)) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <clang/Sema/Sema.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <regex>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "oi/type_graph/Types.h"
|
||||
@ -423,7 +422,7 @@ bool ClangTypeParser::chasePointer() const {
|
||||
ContainerInfo* ClangTypeParser::getContainerInfo(
|
||||
const std::string& fqName) const {
|
||||
for (const auto& containerInfo : containers_) {
|
||||
if (std::regex_search(fqName, containerInfo->matcher)) {
|
||||
if (containerInfo->matches(fqName)) {
|
||||
return containerInfo.get();
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,6 @@
|
||||
*/
|
||||
#include "IdentifyContainers.h"
|
||||
|
||||
#include <regex>
|
||||
|
||||
#include "TypeGraph.h"
|
||||
#include "oi/ContainerInfo.h"
|
||||
|
||||
@ -53,7 +51,7 @@ Type& IdentifyContainers::mutate(Type& type) {
|
||||
|
||||
Type& IdentifyContainers::visit(Class& c) {
|
||||
for (const auto& containerInfo : containers_) {
|
||||
if (!std::regex_search(c.fqName(), containerInfo->matcher)) {
|
||||
if (!containerInfo->matches(c.fqName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ void TypeIdentifier::visit(Container& c) {
|
||||
if (Class* paramClass = dynamic_cast<Class*>(¶m.type())) {
|
||||
bool replaced = false;
|
||||
for (const auto& info : passThroughTypes_) {
|
||||
if (std::regex_search(paramClass->fqName(), info.matcher)) {
|
||||
if (info.matches(paramClass->fqName())) {
|
||||
// Create dummy containers. Use a map so previously deduplicated nodes
|
||||
// remain deduplicated.
|
||||
Container* dummy;
|
||||
|
@ -5,19 +5,17 @@
|
||||
TEST(ContainerInfoTest, matcher) {
|
||||
ContainerInfo info{"std::vector", SEQ_TYPE, "vector"};
|
||||
|
||||
EXPECT_TRUE(std::regex_search("std::vector<int>", info.matcher));
|
||||
EXPECT_TRUE(std::regex_search("std::vector<std::list<int>>", info.matcher));
|
||||
EXPECT_TRUE(std::regex_search("std::vector", info.matcher));
|
||||
EXPECT_TRUE(info.matches("std::vector<int>"));
|
||||
EXPECT_TRUE(info.matches("std::vector<std::list<int>>"));
|
||||
EXPECT_TRUE(info.matches("std::vector"));
|
||||
|
||||
EXPECT_FALSE(std::regex_search("vector", info.matcher));
|
||||
EXPECT_FALSE(std::regex_search("non_std::vector<int>", info.matcher));
|
||||
EXPECT_FALSE(std::regex_search("std::vector_other<int>", info.matcher));
|
||||
EXPECT_FALSE(std::regex_search("std::list<std::vector<int>>", info.matcher));
|
||||
EXPECT_FALSE(std::regex_search("std::vector::value_type", info.matcher));
|
||||
EXPECT_FALSE(std::regex_search("std::vector<int>::value_type", info.matcher));
|
||||
EXPECT_FALSE(std::regex_search("std::vector<std::vector<int>>::value_type",
|
||||
info.matcher));
|
||||
EXPECT_FALSE(info.matches("vector"));
|
||||
EXPECT_FALSE(info.matches("non_std::vector<int>"));
|
||||
EXPECT_FALSE(info.matches("std::vector_other<int>"));
|
||||
EXPECT_FALSE(info.matches("std::list<std::vector<int>>"));
|
||||
EXPECT_FALSE(info.matches("std::vector::value_type"));
|
||||
EXPECT_FALSE(info.matches("std::vector<int>::value_type"));
|
||||
EXPECT_FALSE(info.matches("std::vector<std::vector<int>>::value_type"));
|
||||
// Uh-oh, here's a case that I don't think regexes are powerful enough to
|
||||
// match: EXPECT_FALSE(std::regex_search("std::vector<int>::subtype<bool>",
|
||||
// info.matcher));
|
||||
// match: EXPECT_FALSE(info.matches("std::vector<int>::subtype<bool>"));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user