22 #include "clang/AST/DeclTemplate.h" 23 #include "clang/Basic/TokenKinds.h" 24 #include "clang/Tooling/Syntax/Tokens.h" 25 #include "llvm/Support/ScopedPrinter.h" 26 #include "gmock/gmock-matchers.h" 27 #include "gmock/gmock.h" 28 #include "gtest/gtest.h" 34 using ::testing::AllOf;
35 using ::testing::ElementsAre;
36 using ::testing::ElementsAreArray;
39 if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
40 if (ND->getName() ==
Name)
42 if (
auto *Stream = result_listener->stream()) {
43 llvm::raw_os_ostream OS(*Stream);
51 MATCHER_P(WithTemplateArgs, ArgName,
"") {
52 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(arg)) {
53 if (
const auto *Args = FD->getTemplateSpecializationArgs()) {
54 std::string SpecializationArgs;
57 PrintingPolicy Policy(LO);
58 Policy.adjustForCPlusPlus();
59 for (
const auto &Arg : Args->asArray()) {
60 if (SpecializationArgs.size() > 0)
61 SpecializationArgs +=
",";
62 SpecializationArgs += Arg.getAsType().getAsString(Policy);
64 if (Args->size() == 0)
65 return ArgName == SpecializationArgs;
66 return ArgName ==
"<" + SpecializationArgs +
">";
69 if (
const NamedDecl *ND = dyn_cast<NamedDecl>(arg))
74 TEST(ParsedASTTest, TopLevelDecls) {
80 TU.Code = "int main();";
81 auto AST = TU.
build();
85 TEST(ParsedASTTest, DoesNotGetIncludedTopDecls) {
87 TU.HeaderCode = R
"cpp( 88 #define LL void foo(){} 101 auto AST = TU.
build();
105 TEST(ParsedASTTest, DoesNotGetImplicitTemplateTopDecls) {
115 auto AST = TU.
build();
117 ElementsAre(DeclNamed(
"f"), DeclNamed(
"s")));
121 GetsExplicitInstantiationAndSpecializationTemplateTopDecls) {
124 template <typename T> 128 template void f(double); 140 double d = foo<double>; 149 TU.ExtraArgs.push_back(
"-fno-delayed-template-parsing");
151 auto AST = TU.
build();
154 ElementsAreArray({AllOf(DeclNamed(
"f"), WithTemplateArgs(
"")),
155 AllOf(DeclNamed(
"f"), WithTemplateArgs(
"<bool>")),
156 AllOf(DeclNamed(
"f"), WithTemplateArgs(
"<double>")),
157 AllOf(DeclNamed(
"V"), WithTemplateArgs(
"")),
158 AllOf(DeclNamed(
"V"), WithTemplateArgs(
"<T *>")),
159 AllOf(DeclNamed(
"V"), WithTemplateArgs(
"<bool>")),
160 AllOf(DeclNamed(
"foo"), WithTemplateArgs(
"")),
161 AllOf(DeclNamed(
"i"), WithTemplateArgs(
"")),
162 AllOf(DeclNamed(
"d"), WithTemplateArgs(
"")),
163 AllOf(DeclNamed(
"foo"), WithTemplateArgs(
"<T *>")),
164 AllOf(DeclNamed(
"foo"), WithTemplateArgs(
"<bool>"))}));
167 TEST(ParsedASTTest, TokensAfterPreamble) {
169 TU.AdditionalFiles[
"foo.h"] = R
"( 179 auto AST = TU.
build();
180 const syntax::TokenBuffer &T = AST.
getTokens();
183 ASSERT_GT(T.expandedTokens().size(), 2u);
185 EXPECT_EQ(T.expandedTokens().front().text(SM),
"first_token");
187 EXPECT_EQ(T.expandedTokens().back().kind(), tok::eof);
189 EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM),
"last_token");
192 auto Spelled = T.spelledTokens(SM.getMainFileID());
193 ASSERT_FALSE(Spelled.empty());
194 EXPECT_EQ(Spelled.front().kind(), tok::hash);
195 EXPECT_EQ(Spelled.back().text(SM),
"last_token");
198 TEST(ParsedASTTest, NoCrashOnTokensWithTidyCheck) {
202 TU.ClangTidyChecks =
"modernize-use-trailing-return-type";
203 TU.Code =
"inline int foo() {}";
205 auto AST = TU.
build();
206 const syntax::TokenBuffer &T = AST.
getTokens();
209 ASSERT_GT(T.expandedTokens().size(), 7u);
211 EXPECT_EQ(T.expandedTokens().front().text(SM),
"inline");
213 EXPECT_EQ(T.expandedTokens().back().kind(), tok::eof);
215 EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM),
"}");
218 TEST(ParsedASTTest, CanBuildInvocationWithUnknownArgs) {
222 Inputs.CompileCommand.CommandLine = {
"clang",
"-fsome-unknown-flag",
228 Inputs.CompileCommand.CommandLine = {
229 "clang",
"-Xclang",
"-fsome-unknown-flag",
testPath(
"foo.cpp")};
233 TEST(ParsedASTTest, CollectsMainFileMacroExpansions) {
234 Annotations TestCase(R
"cpp( 235 #define ^MACRO_ARGS(X, Y) X Y 238 // Macro arguments included. 239 ^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), A), ^ID(= 2)); 241 // Macro names inside other macros not included. 242 #define ^MACRO_ARGS2(X, Y) X Y 247 // Macros from token concatenations not included. 248 #define ^CONCAT(X) X##A() 249 #define ^PREPEND(X) MACRO##X() 250 #define ^MACROA() 123 251 int B = ^CONCAT(MACRO); 254 // Macros included not from preamble not included. 257 #define ^assert(COND) if (!(COND)) { printf("%s", #COND); exit(0); } 260 // Includes macro expansions in arguments that are expressions 267 #define ^MULTIPLE_DEFINITION 1 268 #undef ^MULTIPLE_DEFINITION 270 #define ^MULTIPLE_DEFINITION 2 271 #undef ^MULTIPLE_DEFINITION 276 #define MACRO_EXP(X) ID(X) 279 TU.AdditionalFiles["foo.inc"] = R
"cpp( 284 ParsedAST AST = TU.build(); 285 std::vector<Position> MacroExpansionPositions; 286 for (
const auto &SIDToRefs : AST.getMacros().MacroRefs) {
287 for (
const auto &R : SIDToRefs.second)
288 MacroExpansionPositions.push_back(R.start);
290 for (
const auto &R : AST.getMacros().UnknownMacros)
291 MacroExpansionPositions.push_back(R.start);
292 EXPECT_THAT(MacroExpansionPositions,
293 testing::UnorderedElementsAreArray(TestCase.points()));
ArrayRef< Decl * > getLocalTopLevelDecls()
This function returns top-level decls present in the main file of the AST.
std::string printTemplateSpecializationArgs(const NamedDecl &ND)
Prints template arguments of a decl as written in the source code, including enclosing '<' and '>'...
const syntax::TokenBuffer & getTokens() const
Tokens recorded while parsing the main file.
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > buildTestFS(llvm::StringMap< std::string > const &Files, llvm::StringMap< time_t > const &Timestamps)
TEST(BackgroundQueueTest, Priority)
std::string testPath(PathRef File)
static constexpr llvm::StringLiteral Name
static TestTU withCode(llvm::StringRef Code)
SourceManager & getSourceManager()
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector< std::string > *CC1Args)
Builds compiler invocation that could be used to build AST or preamble.
static llvm::Optional< ParsedAST > build(std::unique_ptr< clang::CompilerInvocation > CI, llvm::ArrayRef< Diag > CompilerInvocationDiags, std::shared_ptr< const PreambleData > Preamble, std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, const SymbolIndex *Index, const ParseOptions &Opts)
Attempts to run Clang and store parsed AST.