1 #include "../../lib/Format/Macros.h" 2 #include "TestLexer.h" 3 #include "clang/Basic/FileManager.h" 4 5 #include "gtest/gtest.h" 6 7 namespace clang { 8 namespace format { 9 10 namespace { 11 12 class MacroExpanderTest : public ::testing::Test { 13 public: 14 std::unique_ptr<MacroExpander> 15 create(const std::vector<std::string> &MacroDefinitions) { 16 return std::make_unique<MacroExpander>(MacroDefinitions, 17 Lex.SourceMgr.get(), Lex.Style, 18 Lex.Allocator, Lex.IdentTable); 19 } 20 21 std::string expand(MacroExpander &Macros, llvm::StringRef Name, 22 const std::vector<std::string> &Args = {}) { 23 EXPECT_TRUE(Macros.defined(Name)); 24 return text(Macros.expand(Lex.id(Name), lexArgs(Args))); 25 } 26 27 llvm::SmallVector<TokenList, 1> 28 lexArgs(const std::vector<std::string> &Args) { 29 llvm::SmallVector<TokenList, 1> Result; 30 for (const auto &Arg : Args) { 31 Result.push_back(uneof(Lex.lex(Arg))); 32 } 33 return Result; 34 } 35 36 struct MacroAttributes { 37 clang::tok::TokenKind Kind; 38 MacroRole Role; 39 unsigned Start; 40 unsigned End; 41 llvm::SmallVector<FormatToken *, 1> ExpandedFrom; 42 }; 43 44 void expectAttributes(const TokenList &Tokens, 45 const std::vector<MacroAttributes> &Attributes, 46 const std::string &File, unsigned Line) { 47 EXPECT_EQ(Tokens.size(), Attributes.size()) << text(Tokens); 48 for (size_t I = 0, E = Tokens.size(); I != E; ++I) { 49 if (I >= Attributes.size()) 50 continue; 51 std::string Context = 52 ("for token " + llvm::Twine(I) + ": " + Tokens[I]->Tok.getName() + 53 " / " + Tokens[I]->TokenText) 54 .str(); 55 EXPECT_TRUE(Tokens[I]->is(Attributes[I].Kind)) 56 << Context << " in " << text(Tokens) << " at " << File << ":" << Line; 57 EXPECT_EQ(Tokens[I]->MacroCtx->Role, Attributes[I].Role) 58 << Context << " in " << text(Tokens) << " at " << File << ":" << Line; 59 EXPECT_EQ(Tokens[I]->MacroCtx->StartOfExpansion, Attributes[I].Start) 60 << Context << " in " << text(Tokens) << " at " << File << ":" << Line; 61 EXPECT_EQ(Tokens[I]->MacroCtx->EndOfExpansion, Attributes[I].End) 62 << Context << " in " << text(Tokens) << " at " << File << ":" << Line; 63 EXPECT_EQ(Tokens[I]->MacroCtx->ExpandedFrom, Attributes[I].ExpandedFrom) 64 << Context << " in " << text(Tokens) << " at " << File << ":" << Line; 65 } 66 } 67 68 TestLexer Lex; 69 }; 70 71 #define EXPECT_ATTRIBUTES(Tokens, Attributes) \ 72 expectAttributes(Tokens, Attributes, __FILE__, __LINE__) 73 74 TEST_F(MacroExpanderTest, SkipsDefinitionOnError) { 75 auto Macros = 76 create({"A(", "B(,", "C(a,", "D(a a", "E(a, a", "F(,)", "G(a;"}); 77 for (const auto *Name : {"A", "B", "C", "D", "E", "F", "G"}) { 78 EXPECT_FALSE(Macros->defined(Name)) << "for Name " << Name; 79 } 80 } 81 82 TEST_F(MacroExpanderTest, ExpandsWithoutArguments) { 83 auto Macros = create({ 84 "A", 85 "B=b", 86 "C=c + c", 87 "D()", 88 }); 89 EXPECT_TRUE(Macros->objectLike("A")); 90 EXPECT_TRUE(Macros->objectLike("B")); 91 EXPECT_TRUE(Macros->objectLike("C")); 92 EXPECT_TRUE(!Macros->objectLike("D")); 93 EXPECT_EQ("", expand(*Macros, "A")); 94 EXPECT_EQ("b", expand(*Macros, "B")); 95 EXPECT_EQ("c+c", expand(*Macros, "C")); 96 EXPECT_EQ("", expand(*Macros, "D")); 97 } 98 99 TEST_F(MacroExpanderTest, ExpandsWithArguments) { 100 auto Macros = create({ 101 "A(x)", 102 "B(x, y)=x + y", 103 }); 104 EXPECT_EQ("", expand(*Macros, "A", {"a"})); 105 EXPECT_EQ("b1+b2+b3", expand(*Macros, "B", {"b1", "b2 + b3"})); 106 EXPECT_EQ("x+", expand(*Macros, "B", {"x"})); 107 } 108 109 TEST_F(MacroExpanderTest, AttributizesTokens) { 110 auto Macros = create({ 111 "A(x, y)={ x + y; }", 112 "B(x, y)=x + 3 + y", 113 }); 114 auto *A = Lex.id("A"); 115 auto AArgs = lexArgs({"a1 * a2", "a3 * a4"}); 116 auto Result = Macros->expand(A, AArgs); 117 EXPECT_EQ(11U, Result.size()) << text(Result) << " / " << Result; 118 EXPECT_EQ("{a1*a2+a3*a4;}", text(Result)); 119 std::vector<MacroAttributes> Attributes = { 120 {tok::l_brace, MR_Hidden, 1, 0, {A}}, 121 {tok::identifier, MR_ExpandedArg, 0, 0, {A}}, 122 {tok::star, MR_ExpandedArg, 0, 0, {A}}, 123 {tok::identifier, MR_ExpandedArg, 0, 0, {A}}, 124 {tok::plus, MR_Hidden, 0, 0, {A}}, 125 {tok::identifier, MR_ExpandedArg, 0, 0, {A}}, 126 {tok::star, MR_ExpandedArg, 0, 0, {A}}, 127 {tok::identifier, MR_ExpandedArg, 0, 0, {A}}, 128 {tok::semi, MR_Hidden, 0, 0, {A}}, 129 {tok::r_brace, MR_Hidden, 0, 1, {A}}, 130 {tok::eof, MR_Hidden, 0, 0, {A}}, 131 }; 132 EXPECT_ATTRIBUTES(Result, Attributes); 133 134 auto *B = Lex.id("B"); 135 auto BArgs = lexArgs({"b1", "b2"}); 136 Result = Macros->expand(B, BArgs); 137 EXPECT_EQ(6U, Result.size()) << text(Result) << " / " << Result; 138 EXPECT_EQ("b1+3+b2", text(Result)); 139 Attributes = { 140 {tok::identifier, MR_ExpandedArg, 1, 0, {B}}, 141 {tok::plus, MR_Hidden, 0, 0, {B}}, 142 {tok::numeric_constant, MR_Hidden, 0, 0, {B}}, 143 {tok::plus, MR_Hidden, 0, 0, {B}}, 144 {tok::identifier, MR_ExpandedArg, 0, 1, {B}}, 145 {tok::eof, MR_Hidden, 0, 0, {B}}, 146 }; 147 EXPECT_ATTRIBUTES(Result, Attributes); 148 } 149 150 TEST_F(MacroExpanderTest, RecursiveExpansion) { 151 auto Macros = create({ 152 "A(x)=x", 153 "B(x)=x", 154 "C(x)=x", 155 }); 156 157 auto *A = Lex.id("A"); 158 auto *B = Lex.id("B"); 159 auto *C = Lex.id("C"); 160 161 auto Args = lexArgs({"id"}); 162 auto CResult = uneof(Macros->expand(C, Args)); 163 auto BResult = uneof(Macros->expand(B, CResult)); 164 auto AResult = uneof(Macros->expand(A, BResult)); 165 166 std::vector<MacroAttributes> Attributes = { 167 {tok::identifier, MR_ExpandedArg, 3, 3, {C, B, A}}, 168 }; 169 EXPECT_ATTRIBUTES(AResult, Attributes); 170 } 171 172 TEST_F(MacroExpanderTest, SingleExpansion) { 173 auto Macros = create({"A(x)=x+x"}); 174 auto *A = Lex.id("A"); 175 auto Args = lexArgs({"id"}); 176 auto Result = uneof(Macros->expand(A, Args)); 177 std::vector<MacroAttributes> Attributes = { 178 {tok::identifier, MR_ExpandedArg, 1, 0, {A}}, 179 {tok::plus, MR_Hidden, 0, 0, {A}}, 180 {tok::identifier, MR_Hidden, 0, 1, {A}}, 181 }; 182 EXPECT_ATTRIBUTES(Result, Attributes); 183 } 184 185 } // namespace 186 } // namespace format 187 } // namespace clang 188