146a6f5aeSKirill Bobyrev //===- unittest/Tooling/StandardLibrary.cpp -------------------------------===//
246a6f5aeSKirill Bobyrev //
346a6f5aeSKirill Bobyrev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446a6f5aeSKirill Bobyrev // See https://llvm.org/LICENSE.txt for license information.
546a6f5aeSKirill Bobyrev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646a6f5aeSKirill Bobyrev //
746a6f5aeSKirill Bobyrev //===----------------------------------------------------------------------===//
846a6f5aeSKirill Bobyrev
946a6f5aeSKirill Bobyrev #include "clang/Tooling/Inclusions/StandardLibrary.h"
10a7691deeSSam McCall #include "clang/AST/ASTContext.h"
1146a6f5aeSKirill Bobyrev #include "clang/AST/Decl.h"
1246a6f5aeSKirill Bobyrev #include "clang/AST/DeclarationName.h"
13a7691deeSSam McCall #include "clang/Testing/TestAST.h"
1446a6f5aeSKirill Bobyrev #include "llvm/ADT/StringRef.h"
1546a6f5aeSKirill Bobyrev #include "llvm/Support/Casting.h"
1646a6f5aeSKirill Bobyrev #include "llvm/Support/ScopedPrinter.h"
1746a6f5aeSKirill Bobyrev
1846a6f5aeSKirill Bobyrev #include "gmock/gmock.h"
1946a6f5aeSKirill Bobyrev #include "gtest/gtest.h"
2046a6f5aeSKirill Bobyrev
21e1aaa314SSam McCall using ::testing::Contains;
2246a6f5aeSKirill Bobyrev using ::testing::ElementsAre;
2346a6f5aeSKirill Bobyrev
2446a6f5aeSKirill Bobyrev namespace clang {
2546a6f5aeSKirill Bobyrev namespace tooling {
2646a6f5aeSKirill Bobyrev namespace {
2746a6f5aeSKirill Bobyrev
lookup(TestAST & AST,llvm::StringRef Name)28a7691deeSSam McCall const NamedDecl &lookup(TestAST &AST, llvm::StringRef Name) {
29a7691deeSSam McCall TranslationUnitDecl *TU = AST.context().getTranslationUnitDecl();
30a7691deeSSam McCall auto Result = TU->lookup(DeclarationName(&AST.context().Idents.get(Name)));
3146a6f5aeSKirill Bobyrev assert(!Result.empty() && "Lookup failed");
3246a6f5aeSKirill Bobyrev assert(Result.isSingleResult() && "Lookup returned multiple results");
3346a6f5aeSKirill Bobyrev return *Result.front();
3446a6f5aeSKirill Bobyrev }
3546a6f5aeSKirill Bobyrev
TEST(StdlibTest,All)3646a6f5aeSKirill Bobyrev TEST(StdlibTest, All) {
3746a6f5aeSKirill Bobyrev auto VectorH = stdlib::Header::named("<vector>");
3846a6f5aeSKirill Bobyrev EXPECT_TRUE(VectorH);
39e1aaa314SSam McCall EXPECT_EQ(VectorH->name(), "<vector>");
4046a6f5aeSKirill Bobyrev EXPECT_EQ(llvm::to_string(*VectorH), "<vector>");
4146a6f5aeSKirill Bobyrev EXPECT_FALSE(stdlib::Header::named("HeadersTests.cpp"));
4246a6f5aeSKirill Bobyrev
431285172cSViktoriia Bakalova EXPECT_TRUE(stdlib::Header::named("<vector>", stdlib::Lang::CXX));
441285172cSViktoriia Bakalova EXPECT_FALSE(stdlib::Header::named("<vector>", stdlib::Lang::C));
451285172cSViktoriia Bakalova
4646a6f5aeSKirill Bobyrev auto Vector = stdlib::Symbol::named("std::", "vector");
4746a6f5aeSKirill Bobyrev EXPECT_TRUE(Vector);
48e1aaa314SSam McCall EXPECT_EQ(Vector->scope(), "std::");
49e1aaa314SSam McCall EXPECT_EQ(Vector->name(), "vector");
50d46d44e3SHaojian Wu EXPECT_EQ(Vector->qualifiedName(), "std::vector");
5146a6f5aeSKirill Bobyrev EXPECT_EQ(llvm::to_string(*Vector), "std::vector");
5246a6f5aeSKirill Bobyrev EXPECT_FALSE(stdlib::Symbol::named("std::", "dongle"));
5346a6f5aeSKirill Bobyrev EXPECT_FALSE(stdlib::Symbol::named("clang::", "ASTContext"));
5446a6f5aeSKirill Bobyrev
551285172cSViktoriia Bakalova EXPECT_TRUE(stdlib::Symbol::named("std::", "vector", stdlib::Lang::CXX));
561285172cSViktoriia Bakalova EXPECT_FALSE(stdlib::Symbol::named("std::", "vector", stdlib::Lang::C));
571285172cSViktoriia Bakalova
5846a6f5aeSKirill Bobyrev EXPECT_EQ(Vector->header(), *VectorH);
5946a6f5aeSKirill Bobyrev EXPECT_THAT(Vector->headers(), ElementsAre(*VectorH));
60e1aaa314SSam McCall
615a623c2aSKadir Cetinkaya EXPECT_TRUE(stdlib::Symbol::named("std::", "get"));
625a623c2aSKadir Cetinkaya EXPECT_FALSE(stdlib::Symbol::named("std::", "get")->header());
635a623c2aSKadir Cetinkaya
643599cbd3SHaojian Wu EXPECT_THAT(stdlib::Symbol::named("std::", "basic_iostream")->headers(),
653599cbd3SHaojian Wu ElementsAre(stdlib::Header::named("<istream>"),
663599cbd3SHaojian Wu stdlib::Header::named("<iostream>"),
673599cbd3SHaojian Wu stdlib::Header::named("<iosfwd>")));
6811dcd885SHaojian Wu EXPECT_THAT(stdlib::Symbol::named("std::", "size_t")->headers(),
6911dcd885SHaojian Wu ElementsAre(stdlib::Header::named("<cstddef>"),
7011dcd885SHaojian Wu stdlib::Header::named("<cstdlib>"),
7111dcd885SHaojian Wu stdlib::Header::named("<cstring>"),
7211dcd885SHaojian Wu stdlib::Header::named("<cwchar>"),
7311dcd885SHaojian Wu stdlib::Header::named("<cuchar>"),
7411dcd885SHaojian Wu stdlib::Header::named("<ctime>"),
7511dcd885SHaojian Wu stdlib::Header::named("<cstdio>")));
7611dcd885SHaojian Wu EXPECT_EQ(stdlib::Symbol::named("std::", "size_t")->header(),
7711dcd885SHaojian Wu stdlib::Header::named("<cstddef>"));
783599cbd3SHaojian Wu
79e1aaa314SSam McCall EXPECT_THAT(stdlib::Header::all(), Contains(*VectorH));
80e1aaa314SSam McCall EXPECT_THAT(stdlib::Symbol::all(), Contains(*Vector));
81c812ab73SHaojian Wu EXPECT_TRUE(stdlib::Header::named("<stdint.h>", stdlib::Lang::CXX));
82c812ab73SHaojian Wu EXPECT_FALSE(stdlib::Header::named("<ios646.h>", stdlib::Lang::CXX));
83c812ab73SHaojian Wu }
841285172cSViktoriia Bakalova
TEST(StdlibTest,Experimental)85d4021ed3SYounan Zhang TEST(StdlibTest, Experimental) {
86d4021ed3SYounan Zhang EXPECT_FALSE(
87d4021ed3SYounan Zhang stdlib::Header::named("<experimental/filesystem>", stdlib::Lang::C));
88d4021ed3SYounan Zhang EXPECT_TRUE(
89d4021ed3SYounan Zhang stdlib::Header::named("<experimental/filesystem>", stdlib::Lang::CXX));
90d4021ed3SYounan Zhang
91d4021ed3SYounan Zhang auto Symbol = stdlib::Symbol::named("std::experimental::filesystem::",
92d4021ed3SYounan Zhang "system_complete");
93d4021ed3SYounan Zhang EXPECT_TRUE(Symbol);
94d4021ed3SYounan Zhang EXPECT_EQ(Symbol->scope(), "std::experimental::filesystem::");
95d4021ed3SYounan Zhang EXPECT_EQ(Symbol->name(), "system_complete");
96d4021ed3SYounan Zhang EXPECT_EQ(Symbol->header(),
97d4021ed3SYounan Zhang stdlib::Header::named("<experimental/filesystem>"));
98d4021ed3SYounan Zhang EXPECT_EQ(Symbol->qualifiedName(),
99d4021ed3SYounan Zhang "std::experimental::filesystem::system_complete");
100d4021ed3SYounan Zhang }
101d4021ed3SYounan Zhang
TEST(StdlibTest,CCompat)102c812ab73SHaojian Wu TEST(StdlibTest, CCompat) {
103c812ab73SHaojian Wu EXPECT_THAT(
104c812ab73SHaojian Wu stdlib::Symbol::named("", "int16_t", stdlib::Lang::CXX)->headers(),
105c812ab73SHaojian Wu ElementsAre(stdlib::Header::named("<cstdint>"),
106c812ab73SHaojian Wu stdlib::Header::named("<stdint.h>")));
107c812ab73SHaojian Wu EXPECT_THAT(
108c812ab73SHaojian Wu stdlib::Symbol::named("std::", "int16_t", stdlib::Lang::CXX)->headers(),
109c812ab73SHaojian Wu ElementsAre(stdlib::Header::named("<cstdint>")));
110c812ab73SHaojian Wu
111c812ab73SHaojian Wu EXPECT_TRUE(stdlib::Header::named("<stdint.h>", stdlib::Lang::C));
112c812ab73SHaojian Wu EXPECT_THAT(
113c812ab73SHaojian Wu stdlib::Symbol::named("", "int16_t", stdlib::Lang::C)->headers(),
114c812ab73SHaojian Wu ElementsAre(stdlib::Header::named("<stdint.h>", stdlib::Lang::C)));
115c812ab73SHaojian Wu EXPECT_FALSE(stdlib::Symbol::named("std::", "int16_t", stdlib::Lang::C));
11646a6f5aeSKirill Bobyrev }
11746a6f5aeSKirill Bobyrev
TEST(StdlibTest,Recognizer)11846a6f5aeSKirill Bobyrev TEST(StdlibTest, Recognizer) {
119a7691deeSSam McCall TestAST AST(R"cpp(
12046a6f5aeSKirill Bobyrev namespace std {
12146a6f5aeSKirill Bobyrev inline namespace inl {
12246a6f5aeSKirill Bobyrev
12346a6f5aeSKirill Bobyrev template <typename>
12446a6f5aeSKirill Bobyrev struct vector { class nested {}; };
12546a6f5aeSKirill Bobyrev
12646a6f5aeSKirill Bobyrev class secret {};
12746a6f5aeSKirill Bobyrev
12846a6f5aeSKirill Bobyrev } // inl
12946a6f5aeSKirill Bobyrev
13046a6f5aeSKirill Bobyrev inline namespace __1 {
13146a6f5aeSKirill Bobyrev namespace chrono {
13246a6f5aeSKirill Bobyrev inline namespace chrono_inl {
13346a6f5aeSKirill Bobyrev class system_clock {};
13446a6f5aeSKirill Bobyrev } // chrono_inl
13546a6f5aeSKirill Bobyrev } // chrono
13646a6f5aeSKirill Bobyrev } // __1
13746a6f5aeSKirill Bobyrev
13846a6f5aeSKirill Bobyrev } // std
13946a6f5aeSKirill Bobyrev
14046a6f5aeSKirill Bobyrev // C Standard Library structure defined in <stdlib.h>
14146a6f5aeSKirill Bobyrev struct div_t {};
14246a6f5aeSKirill Bobyrev
14346a6f5aeSKirill Bobyrev class vector {};
14446a6f5aeSKirill Bobyrev std::vector<int> vec;
14546a6f5aeSKirill Bobyrev std::vector<int>::nested nest;
14646a6f5aeSKirill Bobyrev std::secret sec;
14746a6f5aeSKirill Bobyrev std::chrono::system_clock clock;
14846a6f5aeSKirill Bobyrev
14946a6f5aeSKirill Bobyrev div_t div;
15046a6f5aeSKirill Bobyrev )cpp");
15146a6f5aeSKirill Bobyrev
152a7691deeSSam McCall auto &VectorNonstd = lookup(AST, "vector");
153a7691deeSSam McCall auto *Vec = cast<VarDecl>(lookup(AST, "vec")).getType()->getAsCXXRecordDecl();
15446a6f5aeSKirill Bobyrev auto *Nest =
155a7691deeSSam McCall cast<VarDecl>(lookup(AST, "nest")).getType()->getAsCXXRecordDecl();
15646a6f5aeSKirill Bobyrev auto *Clock =
157a7691deeSSam McCall cast<VarDecl>(lookup(AST, "clock")).getType()->getAsCXXRecordDecl();
158a7691deeSSam McCall auto *Sec = cast<VarDecl>(lookup(AST, "sec")).getType()->getAsCXXRecordDecl();
15946a6f5aeSKirill Bobyrev auto *CDivT =
160a7691deeSSam McCall cast<VarDecl>(lookup(AST, "div")).getType()->getAsCXXRecordDecl();
16146a6f5aeSKirill Bobyrev
16246a6f5aeSKirill Bobyrev stdlib::Recognizer Recognizer;
16346a6f5aeSKirill Bobyrev
164a41fbb1fSKazu Hirata EXPECT_EQ(Recognizer(&VectorNonstd), std::nullopt);
16546a6f5aeSKirill Bobyrev EXPECT_EQ(Recognizer(Vec), stdlib::Symbol::named("std::", "vector"));
1661285172cSViktoriia Bakalova EXPECT_EQ(Recognizer(Vec),
1671285172cSViktoriia Bakalova stdlib::Symbol::named("std::", "vector", stdlib::Lang::CXX));
16846a6f5aeSKirill Bobyrev EXPECT_EQ(Recognizer(Nest), stdlib::Symbol::named("std::", "vector"));
16946a6f5aeSKirill Bobyrev EXPECT_EQ(Recognizer(Clock),
17046a6f5aeSKirill Bobyrev stdlib::Symbol::named("std::chrono::", "system_clock"));
171c812ab73SHaojian Wu auto DivT = stdlib::Symbol::named("", "div_t", stdlib::Lang::CXX);
172c812ab73SHaojian Wu EXPECT_TRUE(DivT);
173c812ab73SHaojian Wu EXPECT_EQ(Recognizer(CDivT), DivT);
174a41fbb1fSKazu Hirata EXPECT_EQ(Recognizer(Sec), std::nullopt);
17546a6f5aeSKirill Bobyrev }
17646a6f5aeSKirill Bobyrev
TEST(StdlibTest,RecognizerForC99)177e93cbd18SHaojian Wu TEST(StdlibTest, RecognizerForC99) {
178e93cbd18SHaojian Wu TestInputs Input("typedef char uint8_t;");
179e93cbd18SHaojian Wu Input.Language = TestLanguage::Lang_C99;
180e93cbd18SHaojian Wu TestAST AST(Input);
181e93cbd18SHaojian Wu
182e93cbd18SHaojian Wu auto &Uint8T = lookup(AST, "uint8_t");
183e93cbd18SHaojian Wu stdlib::Recognizer Recognizer;
184e93cbd18SHaojian Wu EXPECT_EQ(Recognizer(&Uint8T),
185e93cbd18SHaojian Wu stdlib::Symbol::named("", "uint8_t", stdlib::Lang::C));
186e93cbd18SHaojian Wu }
187e93cbd18SHaojian Wu
TEST(StdlibTest,SpecialCMappings)188*756c2056Skadir çetinkaya TEST(StdlibTest, SpecialCMappings) {
189*756c2056Skadir çetinkaya TestInputs Input("typedef char size_t;");
190*756c2056Skadir çetinkaya Input.Language = TestLanguage::Lang_C99;
191*756c2056Skadir çetinkaya TestAST AST(Input);
192*756c2056Skadir çetinkaya
193*756c2056Skadir çetinkaya auto &SizeT = lookup(AST, "size_t");
194*756c2056Skadir çetinkaya stdlib::Recognizer Recognizer;
195*756c2056Skadir çetinkaya auto ActualSym = Recognizer(&SizeT);
196*756c2056Skadir çetinkaya assert(ActualSym);
197*756c2056Skadir çetinkaya EXPECT_EQ(ActualSym, stdlib::Symbol::named("", "size_t", stdlib::Lang::C));
198*756c2056Skadir çetinkaya EXPECT_EQ(ActualSym->header()->name(), "<stddef.h>");
199*756c2056Skadir çetinkaya }
200*756c2056Skadir çetinkaya
20146a6f5aeSKirill Bobyrev } // namespace
20246a6f5aeSKirill Bobyrev } // namespace tooling
20346a6f5aeSKirill Bobyrev } // namespace clang
204