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