================ @@ -0,0 +1,190 @@ +//===--- NumericLiteralCaseFixer.cpp -----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements NumericLiteralCaseFixer that standardizes character +/// case within numeric literal constants. +/// +//===----------------------------------------------------------------------===// + +#include "NumericLiteralCaseFixer.h" +#include "NumericLiteralInfo.h" + +#include "llvm/ADT/StringExtras.h" + +#include <algorithm> + +namespace clang { +namespace format { + +static std::string +transformComponent(StringRef Component, + FormatStyle::NumericLiteralComponentStyle ConfigValue) { + switch (ConfigValue) { + case FormatStyle::NLCS_Upper: + return Component.upper(); + case FormatStyle::NLCS_Lower: + return Component.lower(); + case FormatStyle::NLCS_Leave: + default: + return Component.str(); + } +} + +/// @brief Test if Suffix matches a C++ literal reserved by the library. +/// Matches against all suffixes reserved in the C++23 standard +static bool matchesReservedSuffix(StringRef Suffix) { + static constexpr std::array<StringRef, 11> SortedReservedSuffixes = { + "d", "h", "i", "if", "il", "min", "ms", "ns", "s", "us", "y"}; + + // This can be static_assert when we have access to constexpr is_sorted in + // C++ 20. + assert(llvm::is_sorted(SortedReservedSuffixes) && + "Must be sorted as precondition for lower_bound()."); + + auto entry = llvm::lower_bound(SortedReservedSuffixes, Suffix); + if (entry == SortedReservedSuffixes.cend()) + return false; + return *entry == Suffix; +} + +static std::optional<std::string> formatIfNeeded(StringRef IntegerLiteral, + const FormatStyle &Style) { + char Separator; + switch (Style.Language) { + case FormatStyle::LK_CSharp: + case FormatStyle::LK_Java: + case FormatStyle::LK_JavaScript: + Separator = '_'; + break; + case FormatStyle::LK_C: + case FormatStyle::LK_Cpp: + case FormatStyle::LK_ObjC: + default: + Separator = '\''; + } + const NumericLiteralInfo N{IntegerLiteral, Separator}; + + std::string Formatted{""}; + + if (N.BaseLetterPos != llvm::StringRef::npos) { + Formatted += + transformComponent(IntegerLiteral.take_front(1 + N.BaseLetterPos), + Style.NumericLiteralCase.Prefix); + } + // Reformat this slice as HexDigit whether or not the digit has hexadecimal + // characters because binary/decimal/octal digits are unchanged. + Formatted += transformComponent( + IntegerLiteral.slice( + N.BaseLetterPos == llvm::StringRef::npos ? 0 : 1 + N.BaseLetterPos, + N.ExponentLetterPos == llvm::StringRef::npos + ? N.SuffixPos == llvm::StringRef::npos ? IntegerLiteral.size() + : N.SuffixPos + : N.ExponentLetterPos), + Style.NumericLiteralCase.HexDigit); + + if (N.ExponentLetterPos != llvm::StringRef::npos) { + Formatted += transformComponent( + IntegerLiteral.slice(N.ExponentLetterPos, + N.SuffixPos == llvm::StringRef::npos + ? IntegerLiteral.size() + : N.SuffixPos), + Style.NumericLiteralCase.ExponentLetter); + } + + if (N.SuffixPos != llvm::StringRef::npos) { + StringRef Suffix = IntegerLiteral.drop_front(N.SuffixPos); + if (matchesReservedSuffix(Suffix) || Suffix.front() == '_') { + // In C++, it is idiomatic, but NOT standardized to define user-defined + // literals with a leading '_'. Omit user defined literals and standard + // reserved suffixes from transformation. + Formatted += Suffix.str(); + } else { + Formatted += transformComponent(Suffix, Style.NumericLiteralCase.Suffix); + } + } + + if (Formatted == IntegerLiteral) + return std::nullopt; + else + return Formatted; +} + +std::pair<tooling::Replacements, unsigned> +NumericLiteralCaseFixer::process(const Environment &Env, + const FormatStyle &Style) { + + const auto &SourceMgr = Env.getSourceManager(); + AffectedRangeManager AffectedRangeMgr(SourceMgr, Env.getCharRanges()); + + const auto ID = Env.getFileID(); + const auto LangOpts = getFormattingLangOpts(Style); + Lexer Lex(ID, SourceMgr.getBufferOrFake(ID), SourceMgr, LangOpts); + Lex.SetCommentRetentionState(true); + + Token Tok; + tooling::Replacements Result; + bool Skip = false; + + while (!Lex.LexFromRawLexer(Tok)) { ---------------- owenca wrote:
```suggestion for (bool Skip = false; !Lex.LexFromRawLexer(Tok);) { ``` as in `IntegerLiteralSeparatorFixer::process()`. https://github.com/llvm/llvm-project/pull/151590 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits