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