brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.3 KiB · e001c98 Raw
219 lines · cpp
1#include "../../lib/Format/Macros.h"2#include "TestLexer.h"3#include "clang/Basic/FileManager.h"4 5#include "gtest/gtest.h"6 7namespace clang {8namespace format {9 10namespace {11 12class MacroExpanderTest : public testing::Test {13public: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);20  }21 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), {}));26  }27 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)));33  }34 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;40  }41 42  struct MacroAttributes {43    tok::TokenKind Kind;44    MacroRole Role;45    unsigned Start;46    unsigned End;47    SmallVector<FormatToken *, 1> ExpandedFrom;48  };49 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;71    }72  }73 74protected:75  llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;76  std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;77  TestLexer Lex;78};79 80#define EXPECT_ATTRIBUTES(Tokens, Attributes)                                  \81  expectAttributes(Tokens, Attributes, __FILE__, __LINE__)82 83TEST_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;88}89 90TEST_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", {}));105}106 107TEST_F(MacroExpanderTest, ExpandsWithArguments) {108  auto Macros = create({109      "A(x)",110      "B(x, y)=x + y",111  });112  EXPECT_EQ("", expand(*Macros, "A", {"a"}));113  EXPECT_EQ("b1+b2+b3", expand(*Macros, "B", {"b1", "b2 + b3"}));114}115 116TEST_F(MacroExpanderTest, AttributizesTokens) {117  auto Macros = create({118      "A(x, y)={ x + y; }",119      "B(x, y)=x + 3 + y",120  });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}},138  };139  EXPECT_ATTRIBUTES(Result, Attributes);140 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}},153  };154  EXPECT_ATTRIBUTES(Result, Attributes);155}156 157TEST_F(MacroExpanderTest, RecursiveExpansion) {158  auto Macros = create({159      "A(x)=x",160      "B(x)=x",161      "C(x)=x",162  });163 164  auto *A = Lex.id("A");165  auto *B = Lex.id("B");166  auto *C = Lex.id("C");167 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));172 173  std::vector<MacroAttributes> Attributes = {174      {tok::identifier, MR_ExpandedArg, 3, 3, {C, B, A}},175  };176  EXPECT_ATTRIBUTES(AResult, Attributes);177}178 179TEST_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}},188  };189  EXPECT_ATTRIBUTES(Result, Attributes);190}191 192TEST_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}},204  };205  EXPECT_ATTRIBUTES(Result, Attributes);206}207 208TEST_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"}));214}215 216} // namespace217} // namespace format218} // namespace clang219