[clang][www] Remove ClangDataFormat.py from docs (#117943)
[llvm-project.git] / clang / unittests / Format / MacroExpanderTest.cpp
blobe001c986dc2b87ea005ac1974f1c54a52e95acc3
1 #include "../../lib/Format/Macros.h"
2 #include "TestLexer.h"
3 #include "clang/Basic/FileManager.h"
5 #include "gtest/gtest.h"
7 namespace clang {
8 namespace format {
10 namespace {
12 class MacroExpanderTest : public testing::Test {
13 public:
14 MacroExpanderTest() : Lex(Allocator, Buffers) {}
15 std::unique_ptr<MacroExpander>
16 create(const std::vector<std::string> &MacroDefinitions) {
17 return std::make_unique<MacroExpander>(MacroDefinitions,
18 Lex.SourceMgr.get(), Lex.Style,
19 Lex.Allocator, Lex.IdentTable);
22 std::string expand(MacroExpander &Macros, StringRef Name) {
23 EXPECT_TRUE(Macros.defined(Name))
24 << "Macro not defined: \"" << Name << "\"";
25 return text(Macros.expand(Lex.id(Name), {}));
28 std::string expand(MacroExpander &Macros, StringRef Name,
29 const std::vector<std::string> &Args) {
30 EXPECT_TRUE(Macros.defined(Name))
31 << "Macro not defined: \"" << Name << "\"";
32 return text(Macros.expand(Lex.id(Name), lexArgs(Args)));
35 SmallVector<TokenList, 1> lexArgs(const std::vector<std::string> &Args) {
36 SmallVector<TokenList, 1> Result;
37 for (const auto &Arg : Args)
38 Result.push_back(uneof(Lex.lex(Arg)));
39 return Result;
42 struct MacroAttributes {
43 tok::TokenKind Kind;
44 MacroRole Role;
45 unsigned Start;
46 unsigned End;
47 SmallVector<FormatToken *, 1> ExpandedFrom;
50 void expectAttributes(const TokenList &Tokens,
51 const std::vector<MacroAttributes> &Attributes,
52 const std::string &File, unsigned Line) {
53 EXPECT_EQ(Tokens.size(), Attributes.size()) << text(Tokens);
54 for (size_t I = 0, E = Tokens.size(); I != E; ++I) {
55 if (I >= Attributes.size())
56 continue;
57 std::string Context =
58 ("for token " + Twine(I) + ": " + Tokens[I]->Tok.getName() + " / " +
59 Tokens[I]->TokenText)
60 .str();
61 EXPECT_TRUE(Tokens[I]->is(Attributes[I].Kind))
62 << Context << " in " << text(Tokens) << " at " << File << ":" << Line;
63 EXPECT_EQ(Tokens[I]->MacroCtx->Role, Attributes[I].Role)
64 << Context << " in " << text(Tokens) << " at " << File << ":" << Line;
65 EXPECT_EQ(Tokens[I]->MacroCtx->StartOfExpansion, Attributes[I].Start)
66 << Context << " in " << text(Tokens) << " at " << File << ":" << Line;
67 EXPECT_EQ(Tokens[I]->MacroCtx->EndOfExpansion, Attributes[I].End)
68 << Context << " in " << text(Tokens) << " at " << File << ":" << Line;
69 EXPECT_EQ(Tokens[I]->MacroCtx->ExpandedFrom, Attributes[I].ExpandedFrom)
70 << Context << " in " << text(Tokens) << " at " << File << ":" << Line;
74 protected:
75 llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
76 std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;
77 TestLexer Lex;
80 #define EXPECT_ATTRIBUTES(Tokens, Attributes) \
81 expectAttributes(Tokens, Attributes, __FILE__, __LINE__)
83 TEST_F(MacroExpanderTest, SkipsDefinitionOnError) {
84 auto Macros =
85 create({"A(", "B(,", "C(a,", "D(a a", "E(a, a", "F(,)", "G(a;"});
86 for (const auto *Name : {"A", "B", "C", "D", "E", "F", "G"})
87 EXPECT_FALSE(Macros->defined(Name)) << "for Name " << Name;
90 TEST_F(MacroExpanderTest, ExpandsWithoutArguments) {
91 auto Macros = create({
92 "A",
93 "B=b",
94 "C=c + c",
95 "D()",
96 });
97 EXPECT_TRUE(Macros->objectLike("A"));
98 EXPECT_TRUE(Macros->objectLike("B"));
99 EXPECT_TRUE(Macros->objectLike("C"));
100 EXPECT_TRUE(!Macros->objectLike("D"));
101 EXPECT_EQ("", expand(*Macros, "A"));
102 EXPECT_EQ("b", expand(*Macros, "B"));
103 EXPECT_EQ("c+c", expand(*Macros, "C"));
104 EXPECT_EQ("", expand(*Macros, "D", {}));
107 TEST_F(MacroExpanderTest, ExpandsWithArguments) {
108 auto Macros = create({
109 "A(x)",
110 "B(x, y)=x + y",
112 EXPECT_EQ("", expand(*Macros, "A", {"a"}));
113 EXPECT_EQ("b1+b2+b3", expand(*Macros, "B", {"b1", "b2 + b3"}));
116 TEST_F(MacroExpanderTest, AttributizesTokens) {
117 auto Macros = create({
118 "A(x, y)={ x + y; }",
119 "B(x, y)=x + 3 + y",
121 auto *A = Lex.id("A");
122 auto AArgs = lexArgs({"a1 * a2", "a3 * a4"});
123 auto Result = Macros->expand(A, AArgs);
124 EXPECT_EQ(11U, Result.size()) << text(Result) << " / " << Result;
125 EXPECT_EQ("{a1*a2+a3*a4;}", text(Result));
126 std::vector<MacroAttributes> Attributes = {
127 {tok::l_brace, MR_Hidden, 1, 0, {A}},
128 {tok::identifier, MR_ExpandedArg, 0, 0, {A}},
129 {tok::star, MR_ExpandedArg, 0, 0, {A}},
130 {tok::identifier, MR_ExpandedArg, 0, 0, {A}},
131 {tok::plus, MR_Hidden, 0, 0, {A}},
132 {tok::identifier, MR_ExpandedArg, 0, 0, {A}},
133 {tok::star, MR_ExpandedArg, 0, 0, {A}},
134 {tok::identifier, MR_ExpandedArg, 0, 0, {A}},
135 {tok::semi, MR_Hidden, 0, 0, {A}},
136 {tok::r_brace, MR_Hidden, 0, 1, {A}},
137 {tok::eof, MR_Hidden, 0, 0, {A}},
139 EXPECT_ATTRIBUTES(Result, Attributes);
141 auto *B = Lex.id("B");
142 auto BArgs = lexArgs({"b1", "b2"});
143 Result = Macros->expand(B, BArgs);
144 EXPECT_EQ(6U, Result.size()) << text(Result) << " / " << Result;
145 EXPECT_EQ("b1+3+b2", text(Result));
146 Attributes = {
147 {tok::identifier, MR_ExpandedArg, 1, 0, {B}},
148 {tok::plus, MR_Hidden, 0, 0, {B}},
149 {tok::numeric_constant, MR_Hidden, 0, 0, {B}},
150 {tok::plus, MR_Hidden, 0, 0, {B}},
151 {tok::identifier, MR_ExpandedArg, 0, 1, {B}},
152 {tok::eof, MR_Hidden, 0, 0, {B}},
154 EXPECT_ATTRIBUTES(Result, Attributes);
157 TEST_F(MacroExpanderTest, RecursiveExpansion) {
158 auto Macros = create({
159 "A(x)=x",
160 "B(x)=x",
161 "C(x)=x",
164 auto *A = Lex.id("A");
165 auto *B = Lex.id("B");
166 auto *C = Lex.id("C");
168 auto Args = lexArgs({"id"});
169 auto CResult = uneof(Macros->expand(C, Args));
170 auto BResult = uneof(Macros->expand(B, CResult));
171 auto AResult = uneof(Macros->expand(A, BResult));
173 std::vector<MacroAttributes> Attributes = {
174 {tok::identifier, MR_ExpandedArg, 3, 3, {C, B, A}},
176 EXPECT_ATTRIBUTES(AResult, Attributes);
179 TEST_F(MacroExpanderTest, SingleExpansion) {
180 auto Macros = create({"A(x)=x+x"});
181 auto *A = Lex.id("A");
182 auto Args = lexArgs({"id"});
183 auto Result = uneof(Macros->expand(A, Args));
184 std::vector<MacroAttributes> Attributes = {
185 {tok::identifier, MR_ExpandedArg, 1, 0, {A}},
186 {tok::plus, MR_Hidden, 0, 0, {A}},
187 {tok::identifier, MR_Hidden, 0, 1, {A}},
189 EXPECT_ATTRIBUTES(Result, Attributes);
192 TEST_F(MacroExpanderTest, UnderstandsCppTokens) {
193 auto Macros = create({"A(T,name)=T name = 0;"});
194 auto *A = Lex.id("A");
195 auto Args = lexArgs({"const int", "x"});
196 auto Result = uneof(Macros->expand(A, Args));
197 std::vector<MacroAttributes> Attributes = {
198 {tok::kw_const, MR_ExpandedArg, 1, 0, {A}},
199 {tok::kw_int, MR_ExpandedArg, 0, 0, {A}},
200 {tok::identifier, MR_ExpandedArg, 0, 0, {A}},
201 {tok::equal, MR_Hidden, 0, 0, {A}},
202 {tok::numeric_constant, MR_Hidden, 0, 0, {A}},
203 {tok::semi, MR_Hidden, 0, 1, {A}},
205 EXPECT_ATTRIBUTES(Result, Attributes);
208 TEST_F(MacroExpanderTest, Overloads) {
209 auto Macros = create({"A=x", "A()=y", "A(a)=a", "A(a, b)=a b"});
210 EXPECT_EQ("x", expand(*Macros, "A"));
211 EXPECT_EQ("y", expand(*Macros, "A", {}));
212 EXPECT_EQ("z", expand(*Macros, "A", {"z"}));
213 EXPECT_EQ("xy", expand(*Macros, "A", {"x", "y"}));
216 } // namespace
217 } // namespace format
218 } // namespace clang