clang-tools  14.0.0git
CollectMacrosTests.cpp
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "Annotations.h"
9 #include "CollectMacros.h"
10 #include "Matchers.h"
11 #include "SourceCode.h"
12 #include "TestTU.h"
13 #include "index/SymbolID.h"
14 #include "clang/Basic/SourceLocation.h"
15 #include "llvm/Support/ScopedPrinter.h"
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
18 
19 namespace clang {
20 namespace clangd {
21 namespace {
22 
23 using testing::UnorderedElementsAreArray;
24 
25 TEST(CollectMainFileMacros, SelectedMacros) {
26  // References of the same symbol must have the ranges with the same
27  // name(integer). If there are N different symbols then they must be named
28  // from 1 to N. Macros for which SymbolID cannot be computed must be named
29  // "Unknown".
30  const char *Tests[] = {
31  R"cpp(// Macros: Cursor on definition.
32  #define $1[[FOO]](x,y) (x + y)
33  int main() { int x = $1[[FOO]]($1[[FOO]](3, 4), $1[[FOO]](5, 6)); }
34  )cpp",
35  R"cpp(
36  #define $1[[M]](X) X;
37  #define $2[[abc]] 123
38  int s = $1[[M]]($2[[abc]]);
39  )cpp",
40  // FIXME: Locating macro in duplicate definitions doesn't work. Enable
41  // this once LocateMacro is fixed.
42  // R"cpp(// Multiple definitions.
43  // #define $1[[abc]] 1
44  // int func1() { int a = $1[[abc]];}
45  // #undef $1[[abc]]
46 
47  // #define $2[[abc]] 2
48  // int func2() { int a = $2[[abc]];}
49  // #undef $2[[abc]]
50  // )cpp",
51  R"cpp(
52  #ifdef $Unknown[[UNDEFINED]]
53  #endif
54  )cpp",
55  R"cpp(
56  #ifndef $Unknown[[abc]]
57  #define $1[[abc]]
58  #ifdef $1[[abc]]
59  #endif
60  #endif
61  )cpp",
62  R"cpp(
63  // Macros from token concatenations not included.
64  #define $1[[CONCAT]](X) X##A()
65  #define $2[[PREPEND]](X) MACRO##X()
66  #define $3[[MACROA]]() 123
67  int B = $1[[CONCAT]](MACRO);
68  int D = $2[[PREPEND]](A);
69  )cpp",
70  R"cpp(
71  // FIXME: Macro names in a definition are not detected.
72  #define $1[[MACRO_ARGS2]](X, Y) X Y
73  #define $2[[FOO]] BAR
74  #define $3[[BAR]] 1
75  int A = $2[[FOO]];
76  )cpp"};
77  for (const char *Test : Tests) {
78  Annotations T(Test);
79  auto AST = TestTU::withCode(T.code()).build();
80  auto ActualMacroRefs = AST.getMacros();
81  auto &SM = AST.getSourceManager();
82  auto &PP = AST.getPreprocessor();
83 
84  // Known macros.
85  for (int I = 1;; I++) {
86  const auto ExpectedRefs = T.ranges(llvm::to_string(I));
87  if (ExpectedRefs.empty())
88  break;
89 
90  auto Loc = sourceLocationInMainFile(SM, ExpectedRefs.begin()->start);
91  ASSERT_TRUE(bool(Loc));
92  const auto *Id = syntax::spelledIdentifierTouching(*Loc, AST.getTokens());
93  ASSERT_TRUE(Id);
94  auto Macro = locateMacroAt(*Id, PP);
95  assert(Macro);
96  auto SID = getSymbolID(Macro->Name, Macro->Info, SM);
97 
98  std::vector<Range> Ranges;
99  for (const auto &Ref : ActualMacroRefs.MacroRefs[SID])
100  Ranges.push_back(Ref.Rng);
101  EXPECT_THAT(ExpectedRefs, UnorderedElementsAreArray(Ranges))
102  << "Annotation=" << I << ", MacroName=" << Macro->Name
103  << ", Test = " << Test;
104  }
105  // Unknown macros.
106  std::vector<Range> Ranges;
107  for (const auto &Ref : AST.getMacros().UnknownMacros)
108  Ranges.push_back(Ref.Rng);
109  EXPECT_THAT(Ranges, UnorderedElementsAreArray(T.ranges("Unknown")))
110  << "Unknown macros doesn't match in " << Test;
111  }
112 }
113 } // namespace
114 } // namespace clangd
115 } // namespace clang
Loc
SourceLocation Loc
Definition: KernelNameRestrictionCheck.cpp:45
SymbolID.h
clang::clangd::TEST
TEST(BackgroundQueueTest, Priority)
Definition: BackgroundIndexTests.cpp:751
clang::clangd::locateMacroAt
llvm::Optional< DefinedMacro > locateMacroAt(const syntax::Token &SpelledTok, Preprocessor &PP)
Gets the macro referenced by SpelledTok.
Definition: SourceCode.cpp:976
clang::clangd::TestTU::build
ParsedAST build() const
Definition: TestTU.cpp:109
TestTU.h
clang::clangd::HighlightingKind::Macro
@ Macro
CollectMacros.h
clang::clangd::TestTU::withCode
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:37
Annotations.h
clang::clangd::ParsedAST::getPreprocessor
Preprocessor & getPreprocessor()
Definition: ParsedAST.cpp:545
clang::tidy::bugprone::PP
static Preprocessor * PP
Definition: BadSignalToKillThreadCheck.cpp:29
clang::clangd::getSymbolID
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
Definition: AST.cpp:337
SourceCode.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::ParsedAST::getTokens
const syntax::TokenBuffer & getTokens() const
Tokens recorded while parsing the main file.
Definition: ParsedAST.h:108
SM
const SourceManager & SM
Definition: IncludeCleaner.cpp:108
clang::clangd::MainFileMacros::UnknownMacros
std::vector< MacroOccurrence > UnknownMacros
Definition: CollectMacros.h:37
clang::clangd::ParsedAST::getSourceManager
SourceManager & getSourceManager()
Definition: ParsedAST.h:75
Matchers.h
clang::clangd::sourceLocationInMainFile
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
Definition: SourceCode.cpp:456
clang::clangd::ParsedAST::getMacros
const MainFileMacros & getMacros() const
Gets all macro references (definition, expansions) present in the main file, including those in the p...
Definition: ParsedAST.cpp:559