xref: /llvm-project/clang/unittests/Analysis/MacroExpansionContextTest.cpp (revision 3116d60494f219bfcb284d05d9ebed5b6c196ca5)
16e307100SBalazs Benics //===- unittests/Analysis/MacroExpansionContextTest.cpp - -----------------===//
26e307100SBalazs Benics //
36e307100SBalazs Benics // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46e307100SBalazs Benics // See https://llvm.org/LICENSE.txt for license information.
56e307100SBalazs Benics // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66e307100SBalazs Benics //
76e307100SBalazs Benics //===----------------------------------------------------------------------===//
86e307100SBalazs Benics 
96e307100SBalazs Benics #include "clang/Analysis/MacroExpansionContext.h"
106e307100SBalazs Benics #include "clang/AST/ASTConsumer.h"
116e307100SBalazs Benics #include "clang/AST/ASTContext.h"
126e307100SBalazs Benics #include "clang/Basic/Diagnostic.h"
136e307100SBalazs Benics #include "clang/Basic/DiagnosticOptions.h"
146e307100SBalazs Benics #include "clang/Basic/FileManager.h"
156e307100SBalazs Benics #include "clang/Basic/LangOptions.h"
166e307100SBalazs Benics #include "clang/Basic/SourceManager.h"
176e307100SBalazs Benics #include "clang/Basic/TargetInfo.h"
186e307100SBalazs Benics #include "clang/Basic/TargetOptions.h"
196e307100SBalazs Benics #include "clang/Lex/HeaderSearch.h"
206e307100SBalazs Benics #include "clang/Lex/HeaderSearchOptions.h"
216e307100SBalazs Benics #include "clang/Lex/Preprocessor.h"
226e307100SBalazs Benics #include "clang/Lex/PreprocessorOptions.h"
236e307100SBalazs Benics #include "clang/Parse/Parser.h"
246e307100SBalazs Benics #include "llvm/ADT/SmallString.h"
256e307100SBalazs Benics #include "gtest/gtest.h"
266e307100SBalazs Benics 
276e307100SBalazs Benics // static bool HACK_EnableDebugInUnitTest = (::llvm::DebugFlag = true);
286e307100SBalazs Benics 
296e307100SBalazs Benics namespace clang {
306e307100SBalazs Benics namespace analysis {
316e307100SBalazs Benics namespace {
326e307100SBalazs Benics 
336e307100SBalazs Benics class MacroExpansionContextTest : public ::testing::Test {
346e307100SBalazs Benics protected:
MacroExpansionContextTest()356e307100SBalazs Benics   MacroExpansionContextTest()
366e307100SBalazs Benics       : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
376e307100SBalazs Benics         FileMgr(FileSystemOptions(), InMemoryFileSystem),
386e307100SBalazs Benics         DiagID(new DiagnosticIDs()), DiagOpts(new DiagnosticOptions()),
396e307100SBalazs Benics         Diags(DiagID, DiagOpts.get(), new IgnoringDiagConsumer()),
406e307100SBalazs Benics         SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions()) {
416e307100SBalazs Benics     TargetOpts->Triple = "x86_64-pc-linux-unknown";
426e307100SBalazs Benics     Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
436e307100SBalazs Benics     LangOpts.CPlusPlus20 = 1; // For __VA_OPT__
446e307100SBalazs Benics   }
456e307100SBalazs Benics 
466e307100SBalazs Benics   IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
476e307100SBalazs Benics   FileManager FileMgr;
486e307100SBalazs Benics   IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
496e307100SBalazs Benics   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
506e307100SBalazs Benics   DiagnosticsEngine Diags;
516e307100SBalazs Benics   SourceManager SourceMgr;
526e307100SBalazs Benics   LangOptions LangOpts;
536e307100SBalazs Benics   std::shared_ptr<TargetOptions> TargetOpts;
546e307100SBalazs Benics   IntrusiveRefCntPtr<TargetInfo> Target;
556e307100SBalazs Benics 
566e307100SBalazs Benics   std::unique_ptr<MacroExpansionContext>
getMacroExpansionContextFor(StringRef SourceText)576e307100SBalazs Benics   getMacroExpansionContextFor(StringRef SourceText) {
586e307100SBalazs Benics     std::unique_ptr<llvm::MemoryBuffer> Buf =
596e307100SBalazs Benics         llvm::MemoryBuffer::getMemBuffer(SourceText);
606e307100SBalazs Benics     SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
616e307100SBalazs Benics     TrivialModuleLoader ModLoader;
626e307100SBalazs Benics     HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
636e307100SBalazs Benics                             Diags, LangOpts, Target.get());
646e307100SBalazs Benics     Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
656e307100SBalazs Benics                     SourceMgr, HeaderInfo, ModLoader,
666e307100SBalazs Benics                     /*IILookup =*/nullptr,
676e307100SBalazs Benics                     /*OwnsHeaderSearch =*/false);
686e307100SBalazs Benics 
696e307100SBalazs Benics     PP.Initialize(*Target);
706e307100SBalazs Benics     auto Ctx = std::make_unique<MacroExpansionContext>(LangOpts);
716e307100SBalazs Benics     Ctx->registerForPreprocessor(PP);
726e307100SBalazs Benics 
736e307100SBalazs Benics     // Lex source text.
746e307100SBalazs Benics     PP.EnterMainSourceFile();
756e307100SBalazs Benics 
76*3116d604SJonas Hahnfeld     PP.LexTokensUntilEOF();
776e307100SBalazs Benics 
786e307100SBalazs Benics     // Callbacks have been executed at this point.
796e307100SBalazs Benics     return Ctx;
806e307100SBalazs Benics   }
816e307100SBalazs Benics 
826e307100SBalazs Benics   /// Returns the expansion location to main file at the given row and column.
at(unsigned row,unsigned col) const836e307100SBalazs Benics   SourceLocation at(unsigned row, unsigned col) const {
846e307100SBalazs Benics     SourceLocation Loc =
856e307100SBalazs Benics         SourceMgr.translateLineCol(SourceMgr.getMainFileID(), row, col);
866e307100SBalazs Benics     return SourceMgr.getExpansionLoc(Loc);
876e307100SBalazs Benics   }
886e307100SBalazs Benics 
dumpExpandedTexts(const MacroExpansionContext & Ctx)896e307100SBalazs Benics   static std::string dumpExpandedTexts(const MacroExpansionContext &Ctx) {
906e307100SBalazs Benics     std::string Buf;
916e307100SBalazs Benics     llvm::raw_string_ostream OS{Buf};
926e307100SBalazs Benics     Ctx.dumpExpandedTextsToStream(OS);
9308eb614eSLogan Smith     return Buf;
946e307100SBalazs Benics   }
956e307100SBalazs Benics 
dumpExpansionRanges(const MacroExpansionContext & Ctx)966e307100SBalazs Benics   static std::string dumpExpansionRanges(const MacroExpansionContext &Ctx) {
976e307100SBalazs Benics     std::string Buf;
986e307100SBalazs Benics     llvm::raw_string_ostream OS{Buf};
996e307100SBalazs Benics     Ctx.dumpExpansionRangesToStream(OS);
10008eb614eSLogan Smith     return Buf;
1016e307100SBalazs Benics   }
1026e307100SBalazs Benics };
1036e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,IgnoresPragmas)1046e307100SBalazs Benics TEST_F(MacroExpansionContextTest, IgnoresPragmas) {
1056e307100SBalazs Benics   // No-crash during lexing.
1066e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
1076e307100SBalazs Benics   _Pragma("pack(push, 1)")
1086e307100SBalazs Benics   _Pragma("pack(pop, 1)")
1096e307100SBalazs Benics       )code");
1106e307100SBalazs Benics   // After preprocessing:
1116e307100SBalazs Benics   // #pragma pack(push, 1)
1126e307100SBalazs Benics   // #pragma pack(pop, 1)
1136e307100SBalazs Benics 
1146e307100SBalazs Benics   EXPECT_EQ("\n=============== ExpandedTokens ===============\n",
1156e307100SBalazs Benics             dumpExpandedTexts(*Ctx));
1166e307100SBalazs Benics   EXPECT_EQ("\n=============== ExpansionRanges ===============\n",
1176e307100SBalazs Benics             dumpExpansionRanges(*Ctx));
1186e307100SBalazs Benics 
11953daa177SKazu Hirata   EXPECT_FALSE(Ctx->getExpandedText(at(2, 1)).has_value());
12053daa177SKazu Hirata   EXPECT_FALSE(Ctx->getOriginalText(at(2, 1)).has_value());
1216e307100SBalazs Benics 
12253daa177SKazu Hirata   EXPECT_FALSE(Ctx->getExpandedText(at(2, 3)).has_value());
12353daa177SKazu Hirata   EXPECT_FALSE(Ctx->getOriginalText(at(2, 3)).has_value());
1246e307100SBalazs Benics 
12553daa177SKazu Hirata   EXPECT_FALSE(Ctx->getExpandedText(at(3, 3)).has_value());
12653daa177SKazu Hirata   EXPECT_FALSE(Ctx->getOriginalText(at(3, 3)).has_value());
1276e307100SBalazs Benics }
1286e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,NoneForNonExpansionLocations)1296e307100SBalazs Benics TEST_F(MacroExpansionContextTest, NoneForNonExpansionLocations) {
1306e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
1316e307100SBalazs Benics   #define EMPTY
1326e307100SBalazs Benics   A b cd EMPTY ef EMPTY gh
1336e307100SBalazs Benics EMPTY zz
1346e307100SBalazs Benics       )code");
1356e307100SBalazs Benics   // After preprocessing:
1366e307100SBalazs Benics   //  A b cd ef gh
1376e307100SBalazs Benics   //      zz
1386e307100SBalazs Benics 
1396e307100SBalazs Benics   // That's the beginning of the definition of EMPTY.
14053daa177SKazu Hirata   EXPECT_FALSE(Ctx->getExpandedText(at(2, 11)).has_value());
14153daa177SKazu Hirata   EXPECT_FALSE(Ctx->getOriginalText(at(2, 11)).has_value());
1426e307100SBalazs Benics 
1436e307100SBalazs Benics   // The space before the first expansion of EMPTY.
14453daa177SKazu Hirata   EXPECT_FALSE(Ctx->getExpandedText(at(3, 9)).has_value());
14553daa177SKazu Hirata   EXPECT_FALSE(Ctx->getOriginalText(at(3, 9)).has_value());
1466e307100SBalazs Benics 
1476e307100SBalazs Benics   // The beginning of the first expansion of EMPTY.
14853daa177SKazu Hirata   EXPECT_TRUE(Ctx->getExpandedText(at(3, 10)).has_value());
14953daa177SKazu Hirata   EXPECT_TRUE(Ctx->getOriginalText(at(3, 10)).has_value());
1506e307100SBalazs Benics 
1516e307100SBalazs Benics   // Pointing inside of the token EMPTY, but not at the beginning.
1526e307100SBalazs Benics   // FIXME: We only deal with begin locations.
15353daa177SKazu Hirata   EXPECT_FALSE(Ctx->getExpandedText(at(3, 11)).has_value());
15453daa177SKazu Hirata   EXPECT_FALSE(Ctx->getOriginalText(at(3, 11)).has_value());
1556e307100SBalazs Benics 
1566e307100SBalazs Benics   // Same here.
15753daa177SKazu Hirata   EXPECT_FALSE(Ctx->getExpandedText(at(3, 12)).has_value());
15853daa177SKazu Hirata   EXPECT_FALSE(Ctx->getOriginalText(at(3, 12)).has_value());
1596e307100SBalazs Benics 
1606e307100SBalazs Benics   // The beginning of the last expansion of EMPTY.
16153daa177SKazu Hirata   EXPECT_TRUE(Ctx->getExpandedText(at(4, 1)).has_value());
16253daa177SKazu Hirata   EXPECT_TRUE(Ctx->getOriginalText(at(4, 1)).has_value());
1636e307100SBalazs Benics 
1646e307100SBalazs Benics   // Same as for the 3:11 case.
16553daa177SKazu Hirata   EXPECT_FALSE(Ctx->getExpandedText(at(4, 2)).has_value());
16653daa177SKazu Hirata   EXPECT_FALSE(Ctx->getOriginalText(at(4, 2)).has_value());
1676e307100SBalazs Benics }
1686e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,EmptyExpansions)1696e307100SBalazs Benics TEST_F(MacroExpansionContextTest, EmptyExpansions) {
1706e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
1716e307100SBalazs Benics   #define EMPTY
1726e307100SBalazs Benics   A b cd EMPTY ef EMPTY gh
1736e307100SBalazs Benics EMPTY zz
1746e307100SBalazs Benics       )code");
1756e307100SBalazs Benics   // After preprocessing:
1766e307100SBalazs Benics   //  A b cd ef gh
1776e307100SBalazs Benics   //      zz
1786e307100SBalazs Benics 
179d1f47534SFangrui Song   EXPECT_EQ("", *Ctx->getExpandedText(at(3, 10)));
180d1f47534SFangrui Song   EXPECT_EQ("EMPTY", *Ctx->getOriginalText(at(3, 10)));
1816e307100SBalazs Benics 
182d1f47534SFangrui Song   EXPECT_EQ("", *Ctx->getExpandedText(at(3, 19)));
183d1f47534SFangrui Song   EXPECT_EQ("EMPTY", *Ctx->getOriginalText(at(3, 19)));
1846e307100SBalazs Benics 
185d1f47534SFangrui Song   EXPECT_EQ("", *Ctx->getExpandedText(at(4, 1)));
186d1f47534SFangrui Song   EXPECT_EQ("EMPTY", *Ctx->getOriginalText(at(4, 1)));
1876e307100SBalazs Benics }
1886e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,TransitiveExpansions)1896e307100SBalazs Benics TEST_F(MacroExpansionContextTest, TransitiveExpansions) {
1906e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
1916e307100SBalazs Benics   #define EMPTY
1926e307100SBalazs Benics   #define WOOF EMPTY ) EMPTY   1
1936e307100SBalazs Benics   A b cd WOOF ef EMPTY gh
1946e307100SBalazs Benics       )code");
1956e307100SBalazs Benics   // After preprocessing:
1966e307100SBalazs Benics   //  A b cd ) 1 ef gh
1976e307100SBalazs Benics 
198d1f47534SFangrui Song   EXPECT_EQ("WOOF", *Ctx->getOriginalText(at(4, 10)));
1996e307100SBalazs Benics 
200d1f47534SFangrui Song   EXPECT_EQ("", *Ctx->getExpandedText(at(4, 18)));
201d1f47534SFangrui Song   EXPECT_EQ("EMPTY", *Ctx->getOriginalText(at(4, 18)));
2026e307100SBalazs Benics }
2036e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,MacroFunctions)2046e307100SBalazs Benics TEST_F(MacroExpansionContextTest, MacroFunctions) {
2056e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
2066e307100SBalazs Benics   #define EMPTY
2076e307100SBalazs Benics   #define WOOF(x) x(EMPTY ) )  ) EMPTY   1
2086e307100SBalazs Benics   A b cd WOOF($$ ef) EMPTY gh
2096e307100SBalazs Benics   WOOF(WOOF)
2106e307100SBalazs Benics   WOOF(WOOF(bar barr))),,),')
2116e307100SBalazs Benics       )code");
2126e307100SBalazs Benics   // After preprocessing:
2136e307100SBalazs Benics   //  A b cd $$ ef( ) ) ) 1 gh
2146e307100SBalazs Benics   //  WOOF( ) ) ) 1
2156e307100SBalazs Benics   //  bar barr( ) ) ) 1( ) ) ) 1),,),')
2166e307100SBalazs Benics 
217d1f47534SFangrui Song   EXPECT_EQ("$$ ef ()))1", *Ctx->getExpandedText(at(4, 10)));
218d1f47534SFangrui Song   EXPECT_EQ("WOOF($$ ef)", *Ctx->getOriginalText(at(4, 10)));
2196e307100SBalazs Benics 
220d1f47534SFangrui Song   EXPECT_EQ("", *Ctx->getExpandedText(at(4, 22)));
221d1f47534SFangrui Song   EXPECT_EQ("EMPTY", *Ctx->getOriginalText(at(4, 22)));
2226e307100SBalazs Benics 
223d1f47534SFangrui Song   EXPECT_EQ("WOOF ()))1", *Ctx->getExpandedText(at(5, 3)));
224d1f47534SFangrui Song   EXPECT_EQ("WOOF(WOOF)", *Ctx->getOriginalText(at(5, 3)));
2256e307100SBalazs Benics 
226d1f47534SFangrui Song   EXPECT_EQ("bar barr ()))1()))1", *Ctx->getExpandedText(at(6, 3)));
227d1f47534SFangrui Song   EXPECT_EQ("WOOF(WOOF(bar barr))", *Ctx->getOriginalText(at(6, 3)));
2286e307100SBalazs Benics }
2296e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,VariadicMacros)2306e307100SBalazs Benics TEST_F(MacroExpansionContextTest, VariadicMacros) {
2316e307100SBalazs Benics   // From the GCC website.
2326e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
2336e307100SBalazs Benics   #define eprintf(format, ...) fprintf (stderr, format, __VA_ARGS__)
2346e307100SBalazs Benics   eprintf("success!\n", );
2356e307100SBalazs Benics   eprintf("success!\n");
2366e307100SBalazs Benics 
2376e307100SBalazs Benics   #define eprintf2(format, ...) \
2386e307100SBalazs Benics     fprintf (stderr, format __VA_OPT__(,) __VA_ARGS__)
2396e307100SBalazs Benics   eprintf2("success!\n", );
2406e307100SBalazs Benics   eprintf2("success!\n");
2416e307100SBalazs Benics       )code");
2426e307100SBalazs Benics   // After preprocessing:
2436e307100SBalazs Benics   //  fprintf (stderr, "success!\n", );
2446e307100SBalazs Benics   //  fprintf (stderr, "success!\n", );
2456e307100SBalazs Benics   //  fprintf (stderr, "success!\n" );
2466e307100SBalazs Benics   //  fprintf (stderr, "success!\n" );
2476e307100SBalazs Benics 
2486e307100SBalazs Benics   EXPECT_EQ(R"(fprintf (stderr ,"success!\n",))",
249d1f47534SFangrui Song             *Ctx->getExpandedText(at(3, 3)));
250d1f47534SFangrui Song   EXPECT_EQ(R"(eprintf("success!\n", ))", *Ctx->getOriginalText(at(3, 3)));
2516e307100SBalazs Benics 
2526e307100SBalazs Benics   EXPECT_EQ(R"(fprintf (stderr ,"success!\n",))",
253d1f47534SFangrui Song             *Ctx->getExpandedText(at(4, 3)));
254d1f47534SFangrui Song   EXPECT_EQ(R"(eprintf("success!\n"))", *Ctx->getOriginalText(at(4, 3)));
2556e307100SBalazs Benics 
2566e307100SBalazs Benics   EXPECT_EQ(R"(fprintf (stderr ,"success!\n"))",
257d1f47534SFangrui Song             *Ctx->getExpandedText(at(8, 3)));
258d1f47534SFangrui Song   EXPECT_EQ(R"(eprintf2("success!\n", ))", *Ctx->getOriginalText(at(8, 3)));
2596e307100SBalazs Benics 
2606e307100SBalazs Benics   EXPECT_EQ(R"(fprintf (stderr ,"success!\n"))",
261d1f47534SFangrui Song             *Ctx->getExpandedText(at(9, 3)));
262d1f47534SFangrui Song   EXPECT_EQ(R"(eprintf2("success!\n"))", *Ctx->getOriginalText(at(9, 3)));
2636e307100SBalazs Benics }
2646e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,ConcatenationMacros)2656e307100SBalazs Benics TEST_F(MacroExpansionContextTest, ConcatenationMacros) {
2666e307100SBalazs Benics   // From the GCC website.
2676e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
2686e307100SBalazs Benics   #define COMMAND(NAME)  { #NAME, NAME ## _command }
2696e307100SBalazs Benics   struct command commands[] = {
2706e307100SBalazs Benics     COMMAND(quit),
2716e307100SBalazs Benics     COMMAND(help),
2726e307100SBalazs Benics   };)code");
2736e307100SBalazs Benics   // After preprocessing:
2746e307100SBalazs Benics   //  struct command commands[] = {
2756e307100SBalazs Benics   //    { "quit", quit_command },
2766e307100SBalazs Benics   //    { "help", help_command },
2776e307100SBalazs Benics   //  };
2786e307100SBalazs Benics 
279d1f47534SFangrui Song   EXPECT_EQ(R"({"quit",quit_command })", *Ctx->getExpandedText(at(4, 5)));
280d1f47534SFangrui Song   EXPECT_EQ("COMMAND(quit)", *Ctx->getOriginalText(at(4, 5)));
2816e307100SBalazs Benics 
282d1f47534SFangrui Song   EXPECT_EQ(R"({"help",help_command })", *Ctx->getExpandedText(at(5, 5)));
283d1f47534SFangrui Song   EXPECT_EQ("COMMAND(help)", *Ctx->getOriginalText(at(5, 5)));
2846e307100SBalazs Benics }
2856e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,StringizingMacros)2866e307100SBalazs Benics TEST_F(MacroExpansionContextTest, StringizingMacros) {
2876e307100SBalazs Benics   // From the GCC website.
2886e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
2896e307100SBalazs Benics   #define WARN_IF(EXP) \
2906e307100SBalazs Benics   do { if (EXP) \
2916e307100SBalazs Benics           fprintf (stderr, "Warning: " #EXP "\n"); } \
2926e307100SBalazs Benics   while (0)
2936e307100SBalazs Benics   WARN_IF (x == 0);
2946e307100SBalazs Benics 
2956e307100SBalazs Benics   #define xstr(s) str(s)
2966e307100SBalazs Benics   #define str(s) #s
2976e307100SBalazs Benics   #define foo 4
2986e307100SBalazs Benics   str (foo)
2996e307100SBalazs Benics   xstr (foo)
3006e307100SBalazs Benics       )code");
3016e307100SBalazs Benics   // After preprocessing:
3026e307100SBalazs Benics   //  do { if (x == 0) fprintf (stderr, "Warning: " "x == 0" "\n"); } while (0);
3036e307100SBalazs Benics   //  "foo"
3046e307100SBalazs Benics   //  "4"
3056e307100SBalazs Benics 
3066e307100SBalazs Benics   EXPECT_EQ(
3076e307100SBalazs Benics       R"(do {if (x ==0)fprintf (stderr ,"Warning: ""x == 0""\n");}while (0))",
308d1f47534SFangrui Song       *Ctx->getExpandedText(at(6, 3)));
309d1f47534SFangrui Song   EXPECT_EQ("WARN_IF (x == 0)", *Ctx->getOriginalText(at(6, 3)));
3106e307100SBalazs Benics 
311d1f47534SFangrui Song   EXPECT_EQ(R"("foo")", *Ctx->getExpandedText(at(11, 3)));
312d1f47534SFangrui Song   EXPECT_EQ("str (foo)", *Ctx->getOriginalText(at(11, 3)));
3136e307100SBalazs Benics 
314d1f47534SFangrui Song   EXPECT_EQ(R"("4")", *Ctx->getExpandedText(at(12, 3)));
315d1f47534SFangrui Song   EXPECT_EQ("xstr (foo)", *Ctx->getOriginalText(at(12, 3)));
3166e307100SBalazs Benics }
3176e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,StringizingVariadicMacros)3186e307100SBalazs Benics TEST_F(MacroExpansionContextTest, StringizingVariadicMacros) {
3196e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
3206e307100SBalazs Benics   #define xstr(...) str(__VA_ARGS__)
3216e307100SBalazs Benics   #define str(...) #__VA_ARGS__
3226e307100SBalazs Benics   #define RParen2x ) )
3236e307100SBalazs Benics   #define EMPTY
3246e307100SBalazs Benics   #define f(x, ...) __VA_ARGS__ ! x * x
3256e307100SBalazs Benics   #define g(...) zz EMPTY f(__VA_ARGS__ ! x) f() * y
3266e307100SBalazs Benics   #define h(x, G) G(x) G(x ## x RParen2x
3276e307100SBalazs Benics   #define q(G) h(apple, G(apple)) RParen2x
3286e307100SBalazs Benics 
3296e307100SBalazs Benics   q(g)
3306e307100SBalazs Benics   q(xstr)
3316e307100SBalazs Benics   g(RParen2x)
3326e307100SBalazs Benics   f( RParen2x )s
3336e307100SBalazs Benics       )code");
3346e307100SBalazs Benics   // clang-format off
3356e307100SBalazs Benics   // After preprocessing:
3366e307100SBalazs Benics   //  zz ! apple ! x * apple ! x ! * * y(apple) zz ! apple ! x * apple ! x ! * * y(appleapple ) ) ) )
3376e307100SBalazs Benics   //  "apple"(apple) "apple"(appleapple ) ) ) )
3386e307100SBalazs Benics   //  zz ! * ) ! x) ! * * y
3396e307100SBalazs Benics   //  ! ) ) * ) )
3406e307100SBalazs Benics   // clang-format on
3416e307100SBalazs Benics 
3426e307100SBalazs Benics   EXPECT_EQ("zz !apple !x *apple !x !**y (apple )zz !apple !x *apple !x !**y "
3436e307100SBalazs Benics             "(appleapple ))))",
344d1f47534SFangrui Song             *Ctx->getExpandedText(at(11, 3)));
345d1f47534SFangrui Song   EXPECT_EQ("q(g)", *Ctx->getOriginalText(at(11, 3)));
3466e307100SBalazs Benics 
3476e307100SBalazs Benics   EXPECT_EQ(R"res("apple"(apple )"apple"(appleapple )))))res",
348d1f47534SFangrui Song             *Ctx->getExpandedText(at(12, 3)));
349d1f47534SFangrui Song   EXPECT_EQ("q(xstr)", *Ctx->getOriginalText(at(12, 3)));
3506e307100SBalazs Benics 
351d1f47534SFangrui Song   EXPECT_EQ("zz !*)!x )!**y ", *Ctx->getExpandedText(at(13, 3)));
352d1f47534SFangrui Song   EXPECT_EQ("g(RParen2x)", *Ctx->getOriginalText(at(13, 3)));
3536e307100SBalazs Benics 
354d1f47534SFangrui Song   EXPECT_EQ("!))*))", *Ctx->getExpandedText(at(14, 3)));
355d1f47534SFangrui Song   EXPECT_EQ("f( RParen2x )", *Ctx->getOriginalText(at(14, 3)));
3566e307100SBalazs Benics }
3576e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,RedefUndef)3586e307100SBalazs Benics TEST_F(MacroExpansionContextTest, RedefUndef) {
3596e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
3606e307100SBalazs Benics   #define Hi(x) Welcome x
3616e307100SBalazs Benics   Hi(Adam)
3626e307100SBalazs Benics   #define Hi Willkommen
3636e307100SBalazs Benics   Hi Hans
3646e307100SBalazs Benics   #undef Hi
3656e307100SBalazs Benics   Hi(Hi)
3666e307100SBalazs Benics       )code");
3676e307100SBalazs Benics   // After preprocessing:
3686e307100SBalazs Benics   //  Welcome Adam
3696e307100SBalazs Benics   //  Willkommen Hans
3706e307100SBalazs Benics   //  Hi(Hi)
3716e307100SBalazs Benics 
3726e307100SBalazs Benics   // FIXME: Extra space follows every identifier.
373d1f47534SFangrui Song   EXPECT_EQ("Welcome Adam ", *Ctx->getExpandedText(at(3, 3)));
374d1f47534SFangrui Song   EXPECT_EQ("Hi(Adam)", *Ctx->getOriginalText(at(3, 3)));
3756e307100SBalazs Benics 
376d1f47534SFangrui Song   EXPECT_EQ("Willkommen ", *Ctx->getExpandedText(at(5, 3)));
377d1f47534SFangrui Song   EXPECT_EQ("Hi", *Ctx->getOriginalText(at(5, 3)));
3786e307100SBalazs Benics 
3796e307100SBalazs Benics   // There was no macro expansion at 7:3, we should expect None.
38053daa177SKazu Hirata   EXPECT_FALSE(Ctx->getExpandedText(at(7, 3)).has_value());
38153daa177SKazu Hirata   EXPECT_FALSE(Ctx->getOriginalText(at(7, 3)).has_value());
3826e307100SBalazs Benics }
3836e307100SBalazs Benics 
TEST_F(MacroExpansionContextTest,UnbalacedParenthesis)3846e307100SBalazs Benics TEST_F(MacroExpansionContextTest, UnbalacedParenthesis) {
3856e307100SBalazs Benics   const auto Ctx = getMacroExpansionContextFor(R"code(
3866e307100SBalazs Benics   #define retArg(x) x
3876e307100SBalazs Benics   #define retArgUnclosed retArg(fun()
3886e307100SBalazs Benics   #define BB CC
3896e307100SBalazs Benics   #define applyInt BB(int)
3906e307100SBalazs Benics   #define CC(x) retArgUnclosed
3916e307100SBalazs Benics 
3926e307100SBalazs Benics   applyInt );
3936e307100SBalazs Benics 
3946e307100SBalazs Benics   #define expandArgUnclosedCommaExpr(x) (x, fun(), 1
3956e307100SBalazs Benics   #define f expandArgUnclosedCommaExpr
3966e307100SBalazs Benics 
3976e307100SBalazs Benics   int x =  f(f(1))  ));
3986e307100SBalazs Benics       )code");
3996e307100SBalazs Benics   // After preprocessing:
4006e307100SBalazs Benics   //  fun();
4016e307100SBalazs Benics   //  int x = ((1, fun(), 1, fun(), 1 ));
4026e307100SBalazs Benics 
403d1f47534SFangrui Song   EXPECT_EQ("fun ()", *Ctx->getExpandedText(at(8, 3)));
404d1f47534SFangrui Song   EXPECT_EQ("applyInt )", *Ctx->getOriginalText(at(8, 3)));
4056e307100SBalazs Benics 
406d1f47534SFangrui Song   EXPECT_EQ("((1,fun (),1,fun (),1", *Ctx->getExpandedText(at(13, 12)));
407d1f47534SFangrui Song   EXPECT_EQ("f(f(1))", *Ctx->getOriginalText(at(13, 12)));
4086e307100SBalazs Benics }
4096e307100SBalazs Benics 
4106e307100SBalazs Benics } // namespace
4116e307100SBalazs Benics } // namespace analysis
4126e307100SBalazs Benics } // namespace clang
413