1 #include "../../lib/Format/Macros.h"
3 #include "clang/Basic/FileManager.h"
5 #include "gtest/gtest.h"
12 class MacroExpanderTest
: public testing::Test
{
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
)));
42 struct MacroAttributes
{
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())
58 ("for token " + Twine(I
) + ": " + Tokens
[I
]->Tok
.getName() + " / " +
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
;
75 llvm::SpecificBumpPtrAllocator
<FormatToken
> Allocator
;
76 std::vector
<std::unique_ptr
<llvm::MemoryBuffer
>> Buffers
;
80 #define EXPECT_ATTRIBUTES(Tokens, Attributes) \
81 expectAttributes(Tokens, Attributes, __FILE__, __LINE__)
83 TEST_F(MacroExpanderTest
, SkipsDefinitionOnError
) {
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({
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({
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; }",
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
));
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({
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"}));
217 } // namespace format