1 //===- unittest/Tooling/StandardLibrary.cpp -------------------------------===//
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 
9 #include "clang/Tooling/Inclusions/StandardLibrary.h"
10 #include "clang/AST/Decl.h"
11 #include "clang/AST/DeclarationName.h"
12 #include "clang/Frontend/ASTUnit.h"
13 #include "clang/Tooling/Tooling.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/Casting.h"
16 #include "llvm/Support/ScopedPrinter.h"
17 
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
20 
21 using ::testing::ElementsAre;
22 
23 namespace clang {
24 namespace tooling {
25 namespace {
26 
27 const NamedDecl &lookup(ASTUnit &AST, llvm::StringRef Name) {
28   auto &Ctx = AST.getASTContext();
29   TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
30   auto Result = TU->lookup(DeclarationName(&Ctx.Idents.get(Name)));
31   assert(!Result.empty() && "Lookup failed");
32   assert(Result.isSingleResult() && "Lookup returned multiple results");
33   return *Result.front();
34 }
35 
36 TEST(StdlibTest, All) {
37   auto VectorH = stdlib::Header::named("<vector>");
38   EXPECT_TRUE(VectorH);
39   EXPECT_EQ(llvm::to_string(*VectorH), "<vector>");
40   EXPECT_FALSE(stdlib::Header::named("HeadersTests.cpp"));
41 
42   auto Vector = stdlib::Symbol::named("std::", "vector");
43   EXPECT_TRUE(Vector);
44   EXPECT_EQ(llvm::to_string(*Vector), "std::vector");
45   EXPECT_FALSE(stdlib::Symbol::named("std::", "dongle"));
46   EXPECT_FALSE(stdlib::Symbol::named("clang::", "ASTContext"));
47 
48   EXPECT_EQ(Vector->header(), *VectorH);
49   EXPECT_THAT(Vector->headers(), ElementsAre(*VectorH));
50 }
51 
52 TEST(StdlibTest, Recognizer) {
53   std::unique_ptr<ASTUnit> AST = buildASTFromCode(R"cpp(
54     namespace std {
55     inline namespace inl {
56 
57     template <typename>
58     struct vector { class nested {}; };
59 
60     class secret {};
61 
62     } // inl
63 
64     inline namespace __1 {
65       namespace chrono {
66         inline namespace chrono_inl {
67         class system_clock {};
68         } // chrono_inl
69       } // chrono
70     } // __1
71 
72     } // std
73 
74     // C Standard Library structure defined in <stdlib.h>
75     struct div_t {};
76 
77     class vector {};
78     std::vector<int> vec;
79     std::vector<int>::nested nest;
80     std::secret sec;
81     std::chrono::system_clock clock;
82 
83     div_t div;
84   )cpp");
85 
86   auto &VectorNonstd = lookup(*AST, "vector");
87   auto *Vec =
88       cast<VarDecl>(lookup(*AST, "vec")).getType()->getAsCXXRecordDecl();
89   auto *Nest =
90       cast<VarDecl>(lookup(*AST, "nest")).getType()->getAsCXXRecordDecl();
91   auto *Clock =
92       cast<VarDecl>(lookup(*AST, "clock")).getType()->getAsCXXRecordDecl();
93   auto *Sec =
94       cast<VarDecl>(lookup(*AST, "sec")).getType()->getAsCXXRecordDecl();
95   auto *CDivT =
96       cast<VarDecl>(lookup(*AST, "div")).getType()->getAsCXXRecordDecl();
97 
98   stdlib::Recognizer Recognizer;
99 
100   EXPECT_EQ(Recognizer(&VectorNonstd), llvm::None);
101   EXPECT_EQ(Recognizer(Vec), stdlib::Symbol::named("std::", "vector"));
102   EXPECT_EQ(Recognizer(Nest), stdlib::Symbol::named("std::", "vector"));
103   EXPECT_EQ(Recognizer(Clock),
104             stdlib::Symbol::named("std::chrono::", "system_clock"));
105   EXPECT_EQ(Recognizer(CDivT), stdlib::Symbol::named("", "div_t"));
106   EXPECT_EQ(Recognizer(Sec), llvm::None);
107 }
108 
109 } // namespace
110 } // namespace tooling
111 } // namespace clang
112