2019-07-12 00:04:18 +08:00
|
|
|
//===-- ASTTests.cpp --------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "AST.h"
|
[clangd] Untangle Hover from XRefs, move into own file.
Summary:
This is mostly mechanical, with a few exceptions:
- getDeducedType moved into AST.h where it belongs. It now takes
ASTContext instead of ParsedAST, and avoids using the preprocessor.
- hover now uses SelectionTree directly rather than via
getDeclAtPosition helper
- hover on 'auto' used to find the decl that contained the 'auto' and
use that to set Kind and documentation for the hover result.
Now we use targetDecl() to find the decl matching the deduced type instead.
This changes tests, e.g. 'variable' -> class for auto on lambdas.
I think this is better, but the motivation was to avoid depending on
the internals of DeducedTypeVisitor. This functionality is removed
from the visitor.
Reviewers: kadircet
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70357
2019-11-17 00:00:19 +08:00
|
|
|
|
|
|
|
#include "Annotations.h"
|
2019-10-30 16:04:10 +08:00
|
|
|
#include "ParsedAST.h"
|
[clangd] Untangle Hover from XRefs, move into own file.
Summary:
This is mostly mechanical, with a few exceptions:
- getDeducedType moved into AST.h where it belongs. It now takes
ASTContext instead of ParsedAST, and avoids using the preprocessor.
- hover now uses SelectionTree directly rather than via
getDeclAtPosition helper
- hover on 'auto' used to find the decl that contained the 'auto' and
use that to set Kind and documentation for the hover result.
Now we use targetDecl() to find the decl matching the deduced type instead.
This changes tests, e.g. 'variable' -> class for auto on lambdas.
I think this is better, but the motivation was to avoid depending on
the internals of DeducedTypeVisitor. This functionality is removed
from the visitor.
Reviewers: kadircet
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70357
2019-11-17 00:00:19 +08:00
|
|
|
#include "TestTU.h"
|
2019-10-30 16:04:10 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/AST/DeclBase.h"
|
[clangd] Untangle Hover from XRefs, move into own file.
Summary:
This is mostly mechanical, with a few exceptions:
- getDeducedType moved into AST.h where it belongs. It now takes
ASTContext instead of ParsedAST, and avoids using the preprocessor.
- hover now uses SelectionTree directly rather than via
getDeclAtPosition helper
- hover on 'auto' used to find the decl that contained the 'auto' and
use that to set Kind and documentation for the hover result.
Now we use targetDecl() to find the decl matching the deduced type instead.
This changes tests, e.g. 'variable' -> class for auto on lambdas.
I think this is better, but the motivation was to avoid depending on
the internals of DeducedTypeVisitor. This functionality is removed
from the visitor.
Reviewers: kadircet
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70357
2019-11-17 00:00:19 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2019-10-30 16:04:10 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2019-12-18 18:23:47 +08:00
|
|
|
#include "llvm/Support/Casting.h"
|
2019-10-30 16:04:10 +08:00
|
|
|
#include "gmock/gmock.h"
|
2019-07-12 00:04:18 +08:00
|
|
|
#include "gtest/gtest.h"
|
2019-10-30 16:04:10 +08:00
|
|
|
#include <cstddef>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2019-07-12 00:04:18 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
|
|
|
|
2020-12-15 23:31:25 +08:00
|
|
|
TEST(GetDeducedType, KwAutoKwDecltypeExpansion) {
|
[clangd] Untangle Hover from XRefs, move into own file.
Summary:
This is mostly mechanical, with a few exceptions:
- getDeducedType moved into AST.h where it belongs. It now takes
ASTContext instead of ParsedAST, and avoids using the preprocessor.
- hover now uses SelectionTree directly rather than via
getDeclAtPosition helper
- hover on 'auto' used to find the decl that contained the 'auto' and
use that to set Kind and documentation for the hover result.
Now we use targetDecl() to find the decl matching the deduced type instead.
This changes tests, e.g. 'variable' -> class for auto on lambdas.
I think this is better, but the motivation was to avoid depending on
the internals of DeducedTypeVisitor. This functionality is removed
from the visitor.
Reviewers: kadircet
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70357
2019-11-17 00:00:19 +08:00
|
|
|
struct Test {
|
|
|
|
StringRef AnnotatedCode;
|
|
|
|
const char *DeducedType;
|
|
|
|
} Tests[] = {
|
|
|
|
{"^auto i = 0;", "int"},
|
|
|
|
{"^auto f(){ return 1;};", "int"},
|
2020-12-15 23:31:25 +08:00
|
|
|
{
|
|
|
|
R"cpp( // auto on struct in a namespace
|
|
|
|
namespace ns1 { struct S {}; }
|
|
|
|
^auto v = ns1::S{};
|
|
|
|
)cpp",
|
|
|
|
"struct ns1::S",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // decltype on struct
|
|
|
|
namespace ns1 { struct S {}; }
|
|
|
|
ns1::S i;
|
|
|
|
^decltype(i) j;
|
|
|
|
)cpp",
|
|
|
|
"ns1::S",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp(// decltype(auto) on struct&
|
|
|
|
namespace ns1 {
|
|
|
|
struct S {};
|
|
|
|
} // namespace ns1
|
|
|
|
|
|
|
|
ns1::S i;
|
|
|
|
ns1::S& j = i;
|
|
|
|
^decltype(auto) k = j;
|
|
|
|
)cpp",
|
|
|
|
"struct ns1::S &",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // auto on template class
|
|
|
|
class X;
|
|
|
|
template<typename T> class Foo {};
|
|
|
|
^auto v = Foo<X>();
|
|
|
|
)cpp",
|
|
|
|
"class Foo<class X>",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // auto on initializer list.
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
template<class _E>
|
|
|
|
class [[initializer_list]] {};
|
|
|
|
}
|
|
|
|
|
|
|
|
^auto i = {1,2};
|
|
|
|
)cpp",
|
|
|
|
"class std::initializer_list<int>",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // auto in function return type with trailing return type
|
|
|
|
struct Foo {};
|
|
|
|
^auto test() -> decltype(Foo()) {
|
|
|
|
return Foo();
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"struct Foo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // decltype in trailing return type
|
|
|
|
struct Foo {};
|
|
|
|
auto test() -> ^decltype(Foo()) {
|
|
|
|
return Foo();
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"struct Foo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // auto in function return type
|
|
|
|
struct Foo {};
|
|
|
|
^auto test() {
|
|
|
|
return Foo();
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"struct Foo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // auto& in function return type
|
|
|
|
struct Foo {};
|
|
|
|
^auto& test() {
|
|
|
|
static Foo x;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"struct Foo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // auto* in function return type
|
|
|
|
struct Foo {};
|
|
|
|
^auto* test() {
|
|
|
|
Foo *x;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"struct Foo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // const auto& in function return type
|
|
|
|
struct Foo {};
|
|
|
|
const ^auto& test() {
|
|
|
|
static Foo x;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"struct Foo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // decltype(auto) in function return (value)
|
|
|
|
struct Foo {};
|
|
|
|
^decltype(auto) test() {
|
|
|
|
return Foo();
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"struct Foo",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // decltype(auto) in function return (ref)
|
|
|
|
struct Foo {};
|
|
|
|
^decltype(auto) test() {
|
|
|
|
static Foo x;
|
|
|
|
return (x);
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"struct Foo &",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // decltype(auto) in function return (const ref)
|
|
|
|
struct Foo {};
|
|
|
|
^decltype(auto) test() {
|
|
|
|
static const Foo x;
|
|
|
|
return (x);
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"const struct Foo &",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp( // auto on alias
|
|
|
|
struct Foo {};
|
|
|
|
using Bar = Foo;
|
|
|
|
^auto x = Bar();
|
|
|
|
)cpp",
|
|
|
|
// FIXME: it'd be nice if this resolved to the alias instead
|
|
|
|
"struct Foo",
|
|
|
|
},
|
[clangd] Untangle Hover from XRefs, move into own file.
Summary:
This is mostly mechanical, with a few exceptions:
- getDeducedType moved into AST.h where it belongs. It now takes
ASTContext instead of ParsedAST, and avoids using the preprocessor.
- hover now uses SelectionTree directly rather than via
getDeclAtPosition helper
- hover on 'auto' used to find the decl that contained the 'auto' and
use that to set Kind and documentation for the hover result.
Now we use targetDecl() to find the decl matching the deduced type instead.
This changes tests, e.g. 'variable' -> class for auto on lambdas.
I think this is better, but the motivation was to avoid depending on
the internals of DeducedTypeVisitor. This functionality is removed
from the visitor.
Reviewers: kadircet
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70357
2019-11-17 00:00:19 +08:00
|
|
|
};
|
|
|
|
for (Test T : Tests) {
|
|
|
|
Annotations File(T.AnnotatedCode);
|
|
|
|
auto AST = TestTU::withCode(File.code()).build();
|
|
|
|
SourceManagerForFile SM("foo.cpp", File.code());
|
|
|
|
|
2020-12-15 23:31:25 +08:00
|
|
|
SCOPED_TRACE(File.code());
|
|
|
|
EXPECT_FALSE(File.points().empty());
|
[clangd] Untangle Hover from XRefs, move into own file.
Summary:
This is mostly mechanical, with a few exceptions:
- getDeducedType moved into AST.h where it belongs. It now takes
ASTContext instead of ParsedAST, and avoids using the preprocessor.
- hover now uses SelectionTree directly rather than via
getDeclAtPosition helper
- hover on 'auto' used to find the decl that contained the 'auto' and
use that to set Kind and documentation for the hover result.
Now we use targetDecl() to find the decl matching the deduced type instead.
This changes tests, e.g. 'variable' -> class for auto on lambdas.
I think this is better, but the motivation was to avoid depending on
the internals of DeducedTypeVisitor. This functionality is removed
from the visitor.
Reviewers: kadircet
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70357
2019-11-17 00:00:19 +08:00
|
|
|
for (Position Pos : File.points()) {
|
|
|
|
auto Location = sourceLocationInMainFile(SM.get(), Pos);
|
|
|
|
ASSERT_TRUE(!!Location) << llvm::toString(Location.takeError());
|
|
|
|
auto DeducedType = getDeducedType(AST.getASTContext(), *Location);
|
2020-12-15 23:31:25 +08:00
|
|
|
ASSERT_TRUE(DeducedType);
|
[clangd] Untangle Hover from XRefs, move into own file.
Summary:
This is mostly mechanical, with a few exceptions:
- getDeducedType moved into AST.h where it belongs. It now takes
ASTContext instead of ParsedAST, and avoids using the preprocessor.
- hover now uses SelectionTree directly rather than via
getDeclAtPosition helper
- hover on 'auto' used to find the decl that contained the 'auto' and
use that to set Kind and documentation for the hover result.
Now we use targetDecl() to find the decl matching the deduced type instead.
This changes tests, e.g. 'variable' -> class for auto on lambdas.
I think this is better, but the motivation was to avoid depending on
the internals of DeducedTypeVisitor. This functionality is removed
from the visitor.
Reviewers: kadircet
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70357
2019-11-17 00:00:19 +08:00
|
|
|
EXPECT_EQ(DeducedType->getAsString(), T.DeducedType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-30 16:04:10 +08:00
|
|
|
TEST(ClangdAST, GetQualification) {
|
|
|
|
// Tries to insert the decl `Foo` into position of each decl named `insert`.
|
|
|
|
// This is done to get an appropriate DeclContext for the insertion location.
|
|
|
|
// Qualifications are the required nested name specifier to spell `Foo` at the
|
|
|
|
// `insert`ion location.
|
|
|
|
// VisibleNamespaces are assumed to be visible at every insertion location.
|
|
|
|
const struct {
|
|
|
|
llvm::StringRef Test;
|
|
|
|
std::vector<llvm::StringRef> Qualifications;
|
|
|
|
std::vector<std::string> VisibleNamespaces;
|
|
|
|
} Cases[] = {
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
namespace ns1 { namespace ns2 { class Foo {}; } }
|
|
|
|
void insert(); // ns1::ns2::Foo
|
|
|
|
namespace ns1 {
|
|
|
|
void insert(); // ns2::Foo
|
|
|
|
namespace ns2 {
|
|
|
|
void insert(); // Foo
|
|
|
|
}
|
|
|
|
using namespace ns2;
|
|
|
|
void insert(); // Foo
|
|
|
|
}
|
|
|
|
using namespace ns1;
|
|
|
|
void insert(); // ns2::Foo
|
|
|
|
using namespace ns2;
|
|
|
|
void insert(); // Foo
|
|
|
|
)cpp",
|
|
|
|
{"ns1::ns2::", "ns2::", "", "", "ns2::", ""},
|
|
|
|
{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
namespace ns1 { namespace ns2 { class Bar { void Foo(); }; } }
|
|
|
|
void insert(); // ns1::ns2::Bar::Foo
|
|
|
|
namespace ns1 {
|
|
|
|
void insert(); // ns2::Bar::Foo
|
|
|
|
namespace ns2 {
|
|
|
|
void insert(); // Bar::Foo
|
|
|
|
}
|
|
|
|
using namespace ns2;
|
|
|
|
void insert(); // Bar::Foo
|
|
|
|
}
|
|
|
|
using namespace ns1;
|
|
|
|
void insert(); // ns2::Bar::Foo
|
|
|
|
using namespace ns2;
|
|
|
|
void insert(); // Bar::Foo
|
|
|
|
)cpp",
|
|
|
|
{"ns1::ns2::Bar::", "ns2::Bar::", "Bar::", "Bar::", "ns2::Bar::",
|
|
|
|
"Bar::"},
|
|
|
|
{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
namespace ns1 { namespace ns2 { void Foo(); } }
|
|
|
|
void insert(); // ns2::Foo
|
|
|
|
namespace ns1 {
|
|
|
|
void insert(); // ns2::Foo
|
|
|
|
namespace ns2 {
|
|
|
|
void insert(); // Foo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
{"ns2::", "ns2::", ""},
|
|
|
|
{"ns1::"},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
for (const auto &Case : Cases) {
|
|
|
|
Annotations Test(Case.Test);
|
|
|
|
TestTU TU = TestTU::withCode(Test.code());
|
|
|
|
ParsedAST AST = TU.build();
|
|
|
|
std::vector<const Decl *> InsertionPoints;
|
|
|
|
const NamedDecl *TargetDecl;
|
|
|
|
findDecl(AST, [&](const NamedDecl &ND) {
|
|
|
|
if (ND.getNameAsString() == "Foo") {
|
|
|
|
TargetDecl = &ND;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ND.getNameAsString() == "insert")
|
|
|
|
InsertionPoints.push_back(&ND);
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
ASSERT_EQ(InsertionPoints.size(), Case.Qualifications.size());
|
|
|
|
for (size_t I = 0, E = InsertionPoints.size(); I != E; ++I) {
|
|
|
|
const Decl *D = InsertionPoints[I];
|
|
|
|
if (Case.VisibleNamespaces.empty()) {
|
|
|
|
EXPECT_EQ(getQualification(AST.getASTContext(),
|
|
|
|
D->getLexicalDeclContext(), D->getBeginLoc(),
|
|
|
|
TargetDecl),
|
|
|
|
Case.Qualifications[I]);
|
|
|
|
} else {
|
|
|
|
EXPECT_EQ(getQualification(AST.getASTContext(),
|
2019-12-18 18:23:47 +08:00
|
|
|
D->getLexicalDeclContext(), TargetDecl,
|
|
|
|
Case.VisibleNamespaces),
|
2019-10-30 16:04:10 +08:00
|
|
|
Case.Qualifications[I]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-18 18:23:47 +08:00
|
|
|
TEST(ClangdAST, PrintType) {
|
|
|
|
const struct {
|
|
|
|
llvm::StringRef Test;
|
|
|
|
std::vector<llvm::StringRef> Types;
|
|
|
|
} Cases[] = {
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
namespace ns1 { namespace ns2 { class Foo {}; } }
|
|
|
|
void insert(); // ns1::ns2::Foo
|
|
|
|
namespace ns1 {
|
|
|
|
void insert(); // ns2::Foo
|
|
|
|
namespace ns2 {
|
|
|
|
void insert(); // Foo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
{"ns1::ns2::Foo", "ns2::Foo", "Foo"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
namespace ns1 {
|
|
|
|
typedef int Foo;
|
|
|
|
}
|
|
|
|
void insert(); // ns1::Foo
|
|
|
|
namespace ns1 {
|
|
|
|
void insert(); // Foo
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
{"ns1::Foo", "Foo"},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
for (const auto &Case : Cases) {
|
|
|
|
Annotations Test(Case.Test);
|
|
|
|
TestTU TU = TestTU::withCode(Test.code());
|
|
|
|
ParsedAST AST = TU.build();
|
|
|
|
std::vector<const DeclContext *> InsertionPoints;
|
|
|
|
const TypeDecl *TargetDecl = nullptr;
|
|
|
|
findDecl(AST, [&](const NamedDecl &ND) {
|
|
|
|
if (ND.getNameAsString() == "Foo") {
|
|
|
|
if (const auto *TD = llvm::dyn_cast<TypeDecl>(&ND)) {
|
|
|
|
TargetDecl = TD;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else if (ND.getNameAsString() == "insert")
|
|
|
|
InsertionPoints.push_back(ND.getDeclContext());
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
ASSERT_EQ(InsertionPoints.size(), Case.Types.size());
|
|
|
|
for (size_t I = 0, E = InsertionPoints.size(); I != E; ++I) {
|
|
|
|
const auto *DC = InsertionPoints[I];
|
|
|
|
EXPECT_EQ(printType(AST.getASTContext().getTypeDeclType(TargetDecl), *DC),
|
|
|
|
Case.Types[I]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-04-22 22:08:48 +08:00
|
|
|
|
|
|
|
TEST(ClangdAST, IsDeeplyNested) {
|
|
|
|
Annotations Test(
|
|
|
|
R"cpp(
|
|
|
|
namespace ns {
|
|
|
|
class Foo {
|
|
|
|
void bar() {
|
|
|
|
class Bar {};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
})cpp");
|
|
|
|
TestTU TU = TestTU::withCode(Test.code());
|
|
|
|
ParsedAST AST = TU.build();
|
|
|
|
|
|
|
|
EXPECT_TRUE(isDeeplyNested(&findUnqualifiedDecl(AST, "Foo"), /*MaxDepth=*/1));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
isDeeplyNested(&findUnqualifiedDecl(AST, "Foo"), /*MaxDepth=*/2));
|
|
|
|
|
|
|
|
EXPECT_TRUE(isDeeplyNested(&findUnqualifiedDecl(AST, "bar"), /*MaxDepth=*/2));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
isDeeplyNested(&findUnqualifiedDecl(AST, "bar"), /*MaxDepth=*/3));
|
|
|
|
|
|
|
|
EXPECT_TRUE(isDeeplyNested(&findUnqualifiedDecl(AST, "Bar"), /*MaxDepth=*/3));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
isDeeplyNested(&findUnqualifiedDecl(AST, "Bar"), /*MaxDepth=*/4));
|
|
|
|
}
|
2019-07-12 00:04:18 +08:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|