brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · 91b2d3e Raw
144 lines · cpp
1//===-- CollectMacrosTests.cpp ----------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#include "AST.h"9#include "Annotations.h"10#include "CollectMacros.h"11#include "Matchers.h"12#include "SourceCode.h"13#include "TestTU.h"14#include "clang/Basic/SourceLocation.h"15#include "llvm/Support/ScopedPrinter.h"16#include "gmock/gmock.h"17#include "gtest/gtest.h"18#include <vector>19 20namespace clang {21namespace clangd {22namespace {23 24using testing::UnorderedElementsAreArray;25 26MATCHER_P(rangeIs, R, "") {27  return arg.StartOffset == R.Begin && arg.EndOffset == R.End;28}29MATCHER(isDef, "") { return arg.IsDefinition; }30MATCHER(inConditionalDirective, "") { return arg.InConditionalDirective; }31 32TEST(CollectMainFileMacros, SelectedMacros) {33  // References of the same symbol must have the ranges with the same34  // name(integer). If there are N different symbols then they must be named35  // from 1 to N. Macros for which SymbolID cannot be computed must be named36  // "Unknown". The payload of the annotation describes the extra bit37  // information of the MacroOccurrence (e.g. $1(def) => IsDefinition).38  const char *Tests[] = {39      R"cpp(// Macros: Cursor on definition.40        #define $1(def)[[FOO]](x,y) (x + y)41        int main() { int x = $1[[FOO]]($1[[FOO]](3, 4), $1[[FOO]](5, 6)); }42      )cpp",43      R"cpp(44        #define $1(def)[[M]](X) X;45        #define $2(def)[[abc]] 12346        int s = $1[[M]]($2[[abc]]);47      )cpp",48      // FIXME: Locating macro in duplicate definitions doesn't work. Enable49      // this once LocateMacro is fixed.50      // R"cpp(// Multiple definitions.51      //   #define $1[[abc]] 152      //   int func1() { int a = $1[[abc]];}53      //   #undef $1[[abc]]54 55      //   #define $2[[abc]] 256      //   int func2() { int a = $2[[abc]];}57      //   #undef $2[[abc]]58      // )cpp",59      R"cpp(60        #ifdef $Unknown(condit)[[UNDEFINED]]61        #elifdef $Unknown(condit)[[UNDEFINED]]62        #endif63 64        #ifdef $Unknown(condit)[[UNDEFINED]]65        #elifndef $Unknown(condit)[[UNDEFINED]]66        #endif67 68        #ifndef $Unknown(condit)[[UNDEFINED]]69        #endif70 71        #if defined($Unknown(condit)[[UNDEFINED]])72        #endif73      )cpp",74      R"cpp(75        #ifndef $Unknown(condit)[[abc]]76        #define $1(def)[[abc]]77        #ifdef $1(condit)[[abc]]78        #endif79        #endif80      )cpp",81      R"cpp(82        // Macros from token concatenations not included.83        #define $1(def)[[CONCAT]](X) X##A()84        #define $2(def)[[PREPEND]](X) MACRO##X()85        #define $3(def)[[MACROA]]() 12386        int B = $1[[CONCAT]](MACRO);87        int D = $2[[PREPEND]](A);88      )cpp",89      R"cpp(90        #define $1(def)[[MACRO_ARGS2]](X, Y) X Y91        #define $3(def)[[BAR]] 192        #define $2(def)[[FOO]] $3[[BAR]]93        int A = $2[[FOO]];94      )cpp"};95  auto ExpectedResults = [](const llvm::Annotations &T, StringRef Name) {96    std::vector<Matcher<MacroOccurrence>> ExpectedLocations;97    for (const auto &[R, Bits] : T.rangesWithPayload(Name)) {98      if (Bits == "def")99        ExpectedLocations.push_back(testing::AllOf(rangeIs(R), isDef()));100      else if (Bits == "condit")101        ExpectedLocations.push_back(102            testing::AllOf(rangeIs(R), inConditionalDirective()));103      else104        ExpectedLocations.push_back(testing::AllOf(rangeIs(R)));105    }106    return ExpectedLocations;107  };108 109  for (const char *Test : Tests) {110    llvm::Annotations T(Test);111    auto Inputs = TestTU::withCode(T.code());112    Inputs.ExtraArgs.push_back("-std=c++2b");113    auto AST = Inputs.build();114    auto ActualMacroRefs = AST.getMacros();115    auto &SM = AST.getSourceManager();116    auto &PP = AST.getPreprocessor();117    for (const auto &[Name, Ranges] : T.all_ranges()) {118      if (Name == "Unknown") {119        EXPECT_THAT(ActualMacroRefs.UnknownMacros,120                    UnorderedElementsAreArray(ExpectedResults(T, "Unknown")))121            << "Unknown macros doesn't match in " << Test;122        continue;123      }124 125      auto Loc = sourceLocationInMainFile(126          SM, offsetToPosition(T.code(), Ranges.front().Begin));127      ASSERT_TRUE(bool(Loc));128      const auto *Id = syntax::spelledIdentifierTouching(*Loc, AST.getTokens());129      ASSERT_TRUE(Id);130      auto Macro = locateMacroAt(*Id, PP);131      assert(Macro);132      auto SID = getSymbolID(Macro->Name, Macro->Info, SM);133 134      EXPECT_THAT(ActualMacroRefs.MacroRefs[SID],135                  UnorderedElementsAreArray(ExpectedResults(T, Name)))136          << "Annotation=" << Name << ", MacroName=" << Macro->Name137          << ", Test = " << Test;138    }139  }140}141} // namespace142} // namespace clangd143} // namespace clang144