xref: /llvm-project/clang-tools-extra/clangd/unittests/CollectMacrosTests.cpp (revision 7298bcf7f06145e2d4dfdb177b94dc42fc95dc55)
12054ed05SUtkarsh Saxena //===-- CollectMacrosTests.cpp ----------------------------------*- C++ -*-===//
22054ed05SUtkarsh Saxena //
32054ed05SUtkarsh Saxena // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42054ed05SUtkarsh Saxena // See https://llvm.org/LICENSE.txt for license information.
52054ed05SUtkarsh Saxena // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62054ed05SUtkarsh Saxena //
72054ed05SUtkarsh Saxena //===----------------------------------------------------------------------===//
84d006520SSam McCall #include "AST.h"
92054ed05SUtkarsh Saxena #include "Annotations.h"
102054ed05SUtkarsh Saxena #include "CollectMacros.h"
11002c4b7bSHaojian Wu #include "Matchers.h"
122054ed05SUtkarsh Saxena #include "SourceCode.h"
132054ed05SUtkarsh Saxena #include "TestTU.h"
142054ed05SUtkarsh Saxena #include "clang/Basic/SourceLocation.h"
152054ed05SUtkarsh Saxena #include "llvm/Support/ScopedPrinter.h"
162054ed05SUtkarsh Saxena #include "gmock/gmock.h"
172054ed05SUtkarsh Saxena #include "gtest/gtest.h"
18002c4b7bSHaojian Wu #include <vector>
192054ed05SUtkarsh Saxena 
202054ed05SUtkarsh Saxena namespace clang {
212054ed05SUtkarsh Saxena namespace clangd {
222054ed05SUtkarsh Saxena namespace {
232054ed05SUtkarsh Saxena 
242054ed05SUtkarsh Saxena using testing::UnorderedElementsAreArray;
252054ed05SUtkarsh Saxena 
26*7298bcf7SHaojian Wu MATCHER_P(rangeIs, R, "") {
27*7298bcf7SHaojian Wu   return arg.StartOffset == R.Begin && arg.EndOffset == R.End;
28*7298bcf7SHaojian Wu }
29002c4b7bSHaojian Wu MATCHER(isDef, "") { return arg.IsDefinition; }
30002c4b7bSHaojian Wu MATCHER(inConditionalDirective, "") { return arg.InConditionalDirective; }
31002c4b7bSHaojian Wu 
TEST(CollectMainFileMacros,SelectedMacros)322054ed05SUtkarsh Saxena TEST(CollectMainFileMacros, SelectedMacros) {
332054ed05SUtkarsh Saxena   // References of the same symbol must have the ranges with the same
342054ed05SUtkarsh Saxena   // name(integer). If there are N different symbols then they must be named
352054ed05SUtkarsh Saxena   // from 1 to N. Macros for which SymbolID cannot be computed must be named
36002c4b7bSHaojian Wu   // "Unknown". The payload of the annotation describes the extra bit
37002c4b7bSHaojian Wu   // information of the MacroOccurrence (e.g. $1(def) => IsDefinition).
382054ed05SUtkarsh Saxena   const char *Tests[] = {
392054ed05SUtkarsh Saxena       R"cpp(// Macros: Cursor on definition.
40002c4b7bSHaojian Wu         #define $1(def)[[FOO]](x,y) (x + y)
412054ed05SUtkarsh Saxena         int main() { int x = $1[[FOO]]($1[[FOO]](3, 4), $1[[FOO]](5, 6)); }
422054ed05SUtkarsh Saxena       )cpp",
432054ed05SUtkarsh Saxena       R"cpp(
44002c4b7bSHaojian Wu         #define $1(def)[[M]](X) X;
45002c4b7bSHaojian Wu         #define $2(def)[[abc]] 123
462054ed05SUtkarsh Saxena         int s = $1[[M]]($2[[abc]]);
472054ed05SUtkarsh Saxena       )cpp",
482054ed05SUtkarsh Saxena       // FIXME: Locating macro in duplicate definitions doesn't work. Enable
492054ed05SUtkarsh Saxena       // this once LocateMacro is fixed.
502054ed05SUtkarsh Saxena       // R"cpp(// Multiple definitions.
512054ed05SUtkarsh Saxena       //   #define $1[[abc]] 1
522054ed05SUtkarsh Saxena       //   int func1() { int a = $1[[abc]];}
532054ed05SUtkarsh Saxena       //   #undef $1[[abc]]
542054ed05SUtkarsh Saxena 
552054ed05SUtkarsh Saxena       //   #define $2[[abc]] 2
562054ed05SUtkarsh Saxena       //   int func2() { int a = $2[[abc]];}
572054ed05SUtkarsh Saxena       //   #undef $2[[abc]]
582054ed05SUtkarsh Saxena       // )cpp",
592054ed05SUtkarsh Saxena       R"cpp(
60002c4b7bSHaojian Wu         #ifdef $Unknown(condit)[[UNDEFINED]]
613ddfea07SHaojian Wu         #elifdef $Unknown(condit)[[UNDEFINED]]
623ddfea07SHaojian Wu         #endif
633ddfea07SHaojian Wu 
643ddfea07SHaojian Wu         #ifdef $Unknown(condit)[[UNDEFINED]]
653ddfea07SHaojian Wu         #elifndef $Unknown(condit)[[UNDEFINED]]
66002c4b7bSHaojian Wu         #endif
67002c4b7bSHaojian Wu 
68002c4b7bSHaojian Wu         #ifndef $Unknown(condit)[[UNDEFINED]]
69002c4b7bSHaojian Wu         #endif
70002c4b7bSHaojian Wu 
71002c4b7bSHaojian Wu         #if defined($Unknown(condit)[[UNDEFINED]])
722054ed05SUtkarsh Saxena         #endif
732054ed05SUtkarsh Saxena       )cpp",
742054ed05SUtkarsh Saxena       R"cpp(
75002c4b7bSHaojian Wu         #ifndef $Unknown(condit)[[abc]]
76002c4b7bSHaojian Wu         #define $1(def)[[abc]]
77002c4b7bSHaojian Wu         #ifdef $1(condit)[[abc]]
782054ed05SUtkarsh Saxena         #endif
792054ed05SUtkarsh Saxena         #endif
802054ed05SUtkarsh Saxena       )cpp",
812054ed05SUtkarsh Saxena       R"cpp(
822054ed05SUtkarsh Saxena         // Macros from token concatenations not included.
83002c4b7bSHaojian Wu         #define $1(def)[[CONCAT]](X) X##A()
84002c4b7bSHaojian Wu         #define $2(def)[[PREPEND]](X) MACRO##X()
85002c4b7bSHaojian Wu         #define $3(def)[[MACROA]]() 123
862054ed05SUtkarsh Saxena         int B = $1[[CONCAT]](MACRO);
87d3260bf5SSam McCall         int D = $2[[PREPEND]](A);
882054ed05SUtkarsh Saxena       )cpp",
892054ed05SUtkarsh Saxena       R"cpp(
90002c4b7bSHaojian Wu         #define $1(def)[[MACRO_ARGS2]](X, Y) X Y
91002c4b7bSHaojian Wu         #define $3(def)[[BAR]] 1
92002c4b7bSHaojian Wu         #define $2(def)[[FOO]] $3[[BAR]]
932054ed05SUtkarsh Saxena         int A = $2[[FOO]];
942054ed05SUtkarsh Saxena       )cpp"};
95*7298bcf7SHaojian Wu   auto ExpectedResults = [](const llvm::Annotations &T, StringRef Name) {
96002c4b7bSHaojian Wu     std::vector<Matcher<MacroOccurrence>> ExpectedLocations;
97002c4b7bSHaojian Wu     for (const auto &[R, Bits] : T.rangesWithPayload(Name)) {
98002c4b7bSHaojian Wu       if (Bits == "def")
99002c4b7bSHaojian Wu         ExpectedLocations.push_back(testing::AllOf(rangeIs(R), isDef()));
100002c4b7bSHaojian Wu       else if (Bits == "condit")
101002c4b7bSHaojian Wu         ExpectedLocations.push_back(
102002c4b7bSHaojian Wu             testing::AllOf(rangeIs(R), inConditionalDirective()));
103002c4b7bSHaojian Wu       else
104002c4b7bSHaojian Wu         ExpectedLocations.push_back(testing::AllOf(rangeIs(R)));
105002c4b7bSHaojian Wu     }
106002c4b7bSHaojian Wu     return ExpectedLocations;
107002c4b7bSHaojian Wu   };
108002c4b7bSHaojian Wu 
1092054ed05SUtkarsh Saxena   for (const char *Test : Tests) {
110*7298bcf7SHaojian Wu     llvm::Annotations T(Test);
1113ddfea07SHaojian Wu     auto Inputs = TestTU::withCode(T.code());
1123ddfea07SHaojian Wu     Inputs.ExtraArgs.push_back("-std=c++2b");
1133ddfea07SHaojian Wu     auto AST = Inputs.build();
1142054ed05SUtkarsh Saxena     auto ActualMacroRefs = AST.getMacros();
1152054ed05SUtkarsh Saxena     auto &SM = AST.getSourceManager();
1162054ed05SUtkarsh Saxena     auto &PP = AST.getPreprocessor();
117002c4b7bSHaojian Wu     for (const auto &[Name, Ranges] : T.all_ranges()) {
118002c4b7bSHaojian Wu       if (Name == "Unknown") {
119002c4b7bSHaojian Wu         EXPECT_THAT(ActualMacroRefs.UnknownMacros,
120002c4b7bSHaojian Wu                     UnorderedElementsAreArray(ExpectedResults(T, "Unknown")))
121002c4b7bSHaojian Wu             << "Unknown macros doesn't match in " << Test;
122002c4b7bSHaojian Wu         continue;
123002c4b7bSHaojian Wu       }
1242054ed05SUtkarsh Saxena 
125002c4b7bSHaojian Wu       auto Loc = sourceLocationInMainFile(
126002c4b7bSHaojian Wu           SM, offsetToPosition(T.code(), Ranges.front().Begin));
1272bb7774dSKadir Cetinkaya       ASSERT_TRUE(bool(Loc));
1283ae2fc7aSKadir Cetinkaya       const auto *Id = syntax::spelledIdentifierTouching(*Loc, AST.getTokens());
1293ae2fc7aSKadir Cetinkaya       ASSERT_TRUE(Id);
1303ae2fc7aSKadir Cetinkaya       auto Macro = locateMacroAt(*Id, PP);
1312054ed05SUtkarsh Saxena       assert(Macro);
1322054ed05SUtkarsh Saxena       auto SID = getSymbolID(Macro->Name, Macro->Info, SM);
1332054ed05SUtkarsh Saxena 
134002c4b7bSHaojian Wu       EXPECT_THAT(ActualMacroRefs.MacroRefs[SID],
135002c4b7bSHaojian Wu                   UnorderedElementsAreArray(ExpectedResults(T, Name)))
136002c4b7bSHaojian Wu           << "Annotation=" << Name << ", MacroName=" << Macro->Name
1372054ed05SUtkarsh Saxena           << ", Test = " << Test;
1382054ed05SUtkarsh Saxena     }
1392054ed05SUtkarsh Saxena   }
1402054ed05SUtkarsh Saxena }
1412054ed05SUtkarsh Saxena } // namespace
1422054ed05SUtkarsh Saxena } // namespace clangd
1432054ed05SUtkarsh Saxena } // namespace clang
144