diff --git a/llvm/lib/Support/StringExtras.cpp b/llvm/lib/Support/StringExtras.cpp index 5683d7005584e..6ae26267337b1 100644 --- a/llvm/lib/Support/StringExtras.cpp +++ b/llvm/lib/Support/StringExtras.cpp @@ -98,15 +98,16 @@ std::string llvm::convertToSnakeFromCamelCase(StringRef input) { std::string snakeCase; snakeCase.reserve(input.size()); - for (char c : input) { - if (!std::isupper(c)) { - snakeCase.push_back(c); - continue; - } - - if (!snakeCase.empty() && snakeCase.back() != '_') + auto check = [&input](size_t j, function_ref predicate) { + return j < input.size() && predicate(input[j]); + }; + for (size_t i = 0; i < input.size(); ++i) { + snakeCase.push_back(tolower(input[i])); + // Handles "runs" of capitals, such as in OPName -> op_name. + if (check(i, isupper) && check(i + 1, isupper) && check(i + 2, islower)) + snakeCase.push_back('_'); + if ((check(i, islower) || check(i, isdigit)) && check(i + 1, isupper)) snakeCase.push_back('_'); - snakeCase.push_back(llvm::toLower(c)); } return snakeCase; } diff --git a/llvm/unittests/ADT/StringExtrasTest.cpp b/llvm/unittests/ADT/StringExtrasTest.cpp index 6f4eb0b85ba54..1fb1fea657791 100644 --- a/llvm/unittests/ADT/StringExtrasTest.cpp +++ b/llvm/unittests/ADT/StringExtrasTest.cpp @@ -184,6 +184,13 @@ TEST(StringExtrasTest, ConvertToSnakeFromCamelCase) { testConvertToSnakeCase("OpName", "op_name"); testConvertToSnakeCase("opName", "op_name"); + testConvertToSnakeCase("OPName", "op_name"); + testConvertToSnakeCase("Intel_OCL_BI", "intel_ocl_bi"); + testConvertToSnakeCase("I32Attr", "i32_attr"); + testConvertToSnakeCase("opNAME", "op_name"); + testConvertToSnakeCase("opNAMe", "op_na_me"); + testConvertToSnakeCase("opnameE", "opname_e"); + testConvertToSnakeCase("OPNameOPName", "op_name_op_name"); testConvertToSnakeCase("_OpName", "_op_name"); testConvertToSnakeCase("Op_Name", "op_name"); testConvertToSnakeCase("", "");