Skip to content

Commit 5f1ea99

Browse files
committed
[clang-format] Add functionality of getting info about numeric literals
1 parent d696f81 commit 5f1ea99

File tree

5 files changed

+167
-0
lines changed

5 files changed

+167
-0
lines changed

clang/lib/Format/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ add_clang_library(clangFormat
1313
MacroExpander.cpp
1414
MatchFilePath.cpp
1515
NamespaceEndCommentsFixer.cpp
16+
NumericLiteralInfo.cpp
1617
ObjCPropertyAttributeOrderFixer.cpp
1718
QualifierAlignmentFixer.cpp
1819
SortJavaScriptImports.cpp
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//===--- NumericLiteralInfo.cpp ---------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// \file
10+
/// This file implements the functionality of getting information about a
11+
/// numeric literal string, including 0-based positions of the base letter, the
12+
/// decimal/hexadecimal point, the exponent letter, and the suffix, or npos if
13+
/// absent.
14+
///
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "NumericLiteralInfo.h"
18+
#include "llvm/ADT/StringExtras.h"
19+
20+
namespace clang {
21+
namespace format {
22+
23+
using namespace llvm;
24+
25+
NumericLiteralInfo::NumericLiteralInfo(StringRef Text, char Separator) {
26+
if (Text.size() < 2)
27+
return;
28+
29+
bool IsHex = false;
30+
if (Text[0] == '0') {
31+
switch (Text[1]) {
32+
case 'x':
33+
case 'X':
34+
IsHex = true;
35+
[[fallthrough]];
36+
case 'b':
37+
case 'B':
38+
case 'o':
39+
case 'O':
40+
BaseLetterPos = 1; // e.g. 0xF
41+
break;
42+
}
43+
}
44+
45+
DotPos = Text.find('.', BaseLetterPos == 1 ? 2 : 0); // e.g. 0x.1 or .1
46+
47+
// e.g. 1.e2 or 0xFp2
48+
const auto Pos = DotPos != StringRef::npos ? DotPos + 1 : BaseLetterPos + 2;
49+
50+
ExponentLetterPos =
51+
// Trim C++ user-defined suffix as in `1_Pa`.
52+
(Separator == '\'' ? Text.substr(0, Text.find('_')) : Text)
53+
.find_insensitive(IsHex ? 'p' : 'e', Pos);
54+
55+
const bool HasExponent = ExponentLetterPos != StringRef::npos;
56+
SuffixPos = Text.find_if_not(
57+
[&](char C) {
58+
return (HasExponent || !IsHex ? isDigit : isHexDigit)(C) ||
59+
C == Separator;
60+
},
61+
HasExponent ? ExponentLetterPos + 2 : Pos); // e.g. 1e-2f
62+
}
63+
64+
} // namespace format
65+
} // namespace clang

clang/lib/Format/NumericLiteralInfo.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===--- NumericLiteralInfo.h -----------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_LIB_FORMAT_NUMERICLITERALINFO_H
10+
#define LLVM_CLANG_LIB_FORMAT_NUMERICLITERALINFO_H
11+
12+
#include "llvm/ADT/StringRef.h"
13+
14+
namespace clang {
15+
namespace format {
16+
17+
struct NumericLiteralInfo {
18+
size_t BaseLetterPos = llvm::StringRef::npos; // as in 0b1, 0xF, etc.
19+
size_t DotPos = llvm::StringRef::npos; // pos of decimal/hex point
20+
size_t ExponentLetterPos = llvm::StringRef::npos; // as in 9e9 and 0xFp9
21+
size_t SuffixPos = llvm::StringRef::npos; // starting pos of suffix
22+
23+
NumericLiteralInfo(llvm::StringRef Text, char Separator = '\'');
24+
};
25+
26+
} // end namespace format
27+
} // end namespace clang
28+
29+
#endif

clang/unittests/Format/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ add_distinct_clang_unittest(FormatTests
2727
MacroExpanderTest.cpp
2828
MatchFilePathTest.cpp
2929
NamespaceEndCommentsFixerTest.cpp
30+
NumericLiteralInfoTest.cpp
3031
ObjCPropertyAttributeOrderFixerTest.cpp
3132
QualifierFixerTest.cpp
3233
SortImportsTestJS.cpp
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===- unittest/Format/NumericLiteralInfoTest.cpp -------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "../../lib/Format/NumericLiteralInfo.h"
10+
#include "gtest/gtest.h"
11+
12+
namespace clang {
13+
namespace format {
14+
namespace {
15+
16+
static constexpr auto npos = llvm::StringRef::npos;
17+
18+
class NumericLiteralInfoTest : public testing::Test {
19+
protected:
20+
bool verifyInfo(const NumericLiteralInfo &Info, size_t BaseLetterPos = npos,
21+
size_t DotPos = npos, size_t ExponentLetterPos = npos,
22+
size_t SuffixPos = npos) {
23+
return Info.BaseLetterPos == BaseLetterPos && Info.DotPos == DotPos &&
24+
Info.ExponentLetterPos == ExponentLetterPos &&
25+
Info.SuffixPos == SuffixPos;
26+
}
27+
};
28+
29+
TEST_F(NumericLiteralInfoTest, IntegerLiteral) {
30+
// Decimal.
31+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("90")));
32+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9L"), npos, npos, npos, 1));
33+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9'0U"), npos, npos, npos, 3));
34+
35+
// Octal.
36+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0")));
37+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("07")));
38+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0z"), npos, npos, npos, 1));
39+
// JavaScript.
40+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0o7"), 1));
41+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0O7_0", '_'), 1));
42+
43+
// Binary.
44+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0b1"), 1));
45+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0B1ul"), 1, npos, npos, 3));
46+
47+
// Hexadecimal.
48+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xF"), 1));
49+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0XfZ"), 1, npos, npos, 3));
50+
}
51+
52+
TEST_F(NumericLiteralInfoTest, FloatingPointLiteral) {
53+
// Decimal.
54+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo(".9"), npos, 0));
55+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9."), npos, 1));
56+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9.F"), npos, 1, npos, 2));
57+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9e9"), npos, npos, 1));
58+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9E-9f"), npos, npos, 1, 4));
59+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("9.9e+9bf16"), npos, 1, 3, 6));
60+
61+
// Hexadecimal.
62+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0X.Fp9"), 1, 2, 4));
63+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xF.P9"), 1, 3, 4));
64+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xFp9"), 1, npos, 3));
65+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xFp+9F128"), 1, npos, 3, 6));
66+
EXPECT_TRUE(verifyInfo(NumericLiteralInfo("0xF.Fp-9_Pa"), 1, 3, 5, 8));
67+
}
68+
69+
} // namespace
70+
} // namespace format
71+
} // namespace clang

0 commit comments

Comments
 (0)