Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/lib/Format/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ add_clang_library(clangFormat
MacroExpander.cpp
MatchFilePath.cpp
NamespaceEndCommentsFixer.cpp
NumericLiteralInfo.cpp
ObjCPropertyAttributeOrderFixer.cpp
QualifierAlignmentFixer.cpp
SortJavaScriptImports.cpp
Expand Down
65 changes: 65 additions & 0 deletions clang/lib/Format/NumericLiteralInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//===--- NumericLiteralInfo.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 the functionality of getting information about a
/// numeric literal string, including 0-based positions of the base letter, the
/// decimal/hexadecimal point, the exponent letter, and the suffix, or npos if
/// absent.
///
//===----------------------------------------------------------------------===//

#include "NumericLiteralInfo.h"
#include "llvm/ADT/StringExtras.h"

namespace clang {
namespace format {

using namespace llvm;

NumericLiteralInfo::NumericLiteralInfo(StringRef Text, char Separator) {
if (Text.size() < 2)
return;

bool IsHex = false;
if (Text[0] == '0') {
switch (Text[1]) {
case 'x':
case 'X':
IsHex = true;
[[fallthrough]];
case 'b':
case 'B':
case 'o':
case 'O':
BaseLetterPos = 1; // e.g. 0xF
break;
}
}

DotPos = Text.find('.', BaseLetterPos + 1); // e.g. 0x.1 or .1

// e.g. 1.e2 or 0xFp2
const auto Pos = DotPos != StringRef::npos ? DotPos + 1 : BaseLetterPos + 2;

ExponentLetterPos =
// Trim C++ user-defined suffix as in `1_Pa`.
(Separator == '\'' ? Text.take_front(Text.find('_')) : Text)
.find_insensitive(IsHex ? 'p' : 'e', Pos);

const bool HasExponent = ExponentLetterPos != StringRef::npos;
SuffixPos = Text.find_if_not(
[&](char C) {
return (HasExponent || !IsHex ? isDigit : isHexDigit)(C) ||
C == Separator;
},
HasExponent ? ExponentLetterPos + 2 : Pos); // e.g. 1e-2f
}

} // namespace format
} // namespace clang
29 changes: 29 additions & 0 deletions clang/lib/Format/NumericLiteralInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===--- NumericLiteralInfo.h -----------------------------------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_FORMAT_NUMERICLITERALINFO_H
#define LLVM_CLANG_LIB_FORMAT_NUMERICLITERALINFO_H

#include "llvm/ADT/StringRef.h"

namespace clang {
namespace format {

struct NumericLiteralInfo {
size_t BaseLetterPos = llvm::StringRef::npos; // as in 0b1, 0xF, etc.
size_t DotPos = llvm::StringRef::npos; // pos of decimal/hex point
size_t ExponentLetterPos = llvm::StringRef::npos; // as in 9e9 and 0xFp9
size_t SuffixPos = llvm::StringRef::npos; // starting pos of suffix

NumericLiteralInfo(llvm::StringRef Text, char Separator = '\'');
};

} // end namespace format
} // end namespace clang

#endif
1 change: 1 addition & 0 deletions clang/unittests/Format/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ add_distinct_clang_unittest(FormatTests
MacroExpanderTest.cpp
MatchFilePathTest.cpp
NamespaceEndCommentsFixerTest.cpp
NumericLiteralInfoTest.cpp
ObjCPropertyAttributeOrderFixerTest.cpp
QualifierFixerTest.cpp
SortImportsTestJS.cpp
Expand Down
71 changes: 71 additions & 0 deletions clang/unittests/Format/NumericLiteralInfoTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//===- unittest/Format/NumericLiteralInfoTest.cpp -------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "../../lib/Format/NumericLiteralInfo.h"
#include "gtest/gtest.h"

namespace clang {
namespace format {
namespace {

static constexpr auto npos = llvm::StringRef::npos;

class NumericLiteralInfoTest : public testing::Test {
protected:
bool verifyInfo(const NumericLiteralInfo &Info, size_t BaseLetterPos = npos,
size_t DotPos = npos, size_t ExponentLetterPos = npos,
size_t SuffixPos = npos) {
return Info.BaseLetterPos == BaseLetterPos && Info.DotPos == DotPos &&
Info.ExponentLetterPos == ExponentLetterPos &&
Info.SuffixPos == SuffixPos;
}
};

TEST_F(NumericLiteralInfoTest, IntegerLiteral) {
// Decimal.
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("90")));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9L"), npos, npos, npos, 1));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9'0U"), npos, npos, npos, 3));

// Octal.
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0")));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("07")));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0z"), npos, npos, npos, 1));
// JavaScript.
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0o7"), 1));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0O7_0", '_'), 1));

// Binary.
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0b1"), 1));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0B1ul"), 1, npos, npos, 3));

// Hexadecimal.
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xF"), 1));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0XfZ"), 1, npos, npos, 3));
}

TEST_F(NumericLiteralInfoTest, FloatingPointLiteral) {
// Decimal.
EXPECT_TRUE(verifyInfo(NumericLiteralInfo(".9"), npos, 0));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9."), npos, 1));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9.F"), npos, 1, npos, 2));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9e9"), npos, npos, 1));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9E-9f"), npos, npos, 1, 4));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9.9e+9bf16"), npos, 1, 3, 6));

// Hexadecimal.
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0X.Fp9"), 1, 2, 4));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xF.P9"), 1, 3, 4));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xFp9"), 1, npos, 3));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xFp+9F128"), 1, npos, 3, 6));
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xF.Fp-9_Pa"), 1, 3, 5, 8));
}

} // namespace
} // namespace format
} // namespace clang