mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 19:45:40 -04:00

Summary: The historic behavior of TestTU is to gather diagnostics and otherwise ignore them. So if a test has a syntax error, and doesn't assert diagnostics, it silently misbehaves. This can be annoying when developing tests, as evidenced by various tests gaining "assert no diagnostics" where that's not really the point of the test. This patch aims to make that default behavior. For the first error (not warning), TestTU will call ADD_FAILURE(). This can be suppressed with a comment containing "error-ok". For now that will suppress any errors in the TU. We can make this stricter later -verify style. (-verify itself is hard to reuse because of DiagnosticConsumer interfaces...) A magic-comment was chosen over a TestTU option because of table-driven tests. In addition to the behavior change, this patch: - adds //error-ok where we're knowingly testing invalid code (e.g. for diagnostics, crash-resilience, or token-level tests) - fixes a bunch of errors in the checked-in tests, mostly trivial (missing ;) - removes a bunch of now-redundant instances of "assert no diagnostics" Reviewers: kadircet Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D73199
343 lines
10 KiB
C++
343 lines
10 KiB
C++
//===-- SymbolInfoTests.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 "Annotations.h"
|
|
#include "Compiler.h"
|
|
#include "Matchers.h"
|
|
#include "ParsedAST.h"
|
|
#include "SyncAPI.h"
|
|
#include "TestFS.h"
|
|
#include "TestTU.h"
|
|
#include "XRefs.h"
|
|
#include "index/FileIndex.h"
|
|
#include "index/SymbolCollector.h"
|
|
#include "clang/Index/IndexingAction.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace clang {
|
|
namespace clangd {
|
|
namespace {
|
|
|
|
using ::testing::UnorderedElementsAreArray;
|
|
|
|
auto CreateExpectedSymbolDetails = [](const std::string &name,
|
|
const std::string &container,
|
|
const std::string &USR) {
|
|
return SymbolDetails{name, container, USR, SymbolID(USR)};
|
|
};
|
|
|
|
TEST(SymbolInfoTests, All) {
|
|
std::pair<const char *, std::vector<SymbolDetails>>
|
|
TestInputExpectedOutput[] = {
|
|
{
|
|
R"cpp( // Simple function reference - declaration
|
|
void foo();
|
|
int bar() {
|
|
fo^o();
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
|
|
{
|
|
R"cpp( // Simple function reference - definition
|
|
void foo() {}
|
|
int bar() {
|
|
fo^o();
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
|
|
{
|
|
R"cpp( // Function in namespace reference
|
|
namespace bar {
|
|
void foo();
|
|
int baz() {
|
|
fo^o();
|
|
}
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
|
|
{
|
|
R"cpp( // Function in different namespace reference
|
|
namespace bar {
|
|
void foo();
|
|
}
|
|
namespace barbar {
|
|
int baz() {
|
|
bar::fo^o();
|
|
}
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}},
|
|
{
|
|
R"cpp( // Function in global namespace reference
|
|
void foo();
|
|
namespace Nbar {
|
|
namespace Nbaz {
|
|
int baz() {
|
|
::fo^o();
|
|
}
|
|
}
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}},
|
|
{
|
|
R"cpp( // Function in anonymous namespace reference
|
|
namespace {
|
|
void foo();
|
|
}
|
|
namespace barbar {
|
|
int baz() {
|
|
fo^o();
|
|
}
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "(anonymous)",
|
|
"c:TestTU.cpp@aN@F@foo#")}},
|
|
{
|
|
R"cpp( // Function reference - ADL
|
|
namespace bar {
|
|
struct BarType {};
|
|
void foo(const BarType&);
|
|
}
|
|
namespace barbar {
|
|
int baz() {
|
|
bar::BarType b;
|
|
fo^o(b);
|
|
}
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails(
|
|
"foo", "bar::", "c:@N@bar@F@foo#&1$@N@bar@S@BarType#")}},
|
|
{
|
|
R"cpp( // Global value reference
|
|
int value;
|
|
void foo(int) { }
|
|
void bar() {
|
|
foo(val^ue);
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("value", "", "c:@value")}},
|
|
{
|
|
R"cpp( // Local value reference
|
|
void foo() { int aaa; int bbb = aa^a; }
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("aaa", "foo",
|
|
"c:TestTU.cpp@49@F@foo#@aaa")}},
|
|
{
|
|
R"cpp( // Function param
|
|
void bar(int aaa) {
|
|
int bbb = a^aa;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("aaa", "bar",
|
|
"c:TestTU.cpp@38@F@bar#I#@aaa")}},
|
|
{
|
|
R"cpp( // Lambda capture
|
|
void foo() {
|
|
int ii;
|
|
auto lam = [ii]() {
|
|
return i^i;
|
|
};
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("ii", "foo",
|
|
"c:TestTU.cpp@54@F@foo#@ii")}},
|
|
{
|
|
R"cpp( // Macro reference
|
|
#define MACRO 5\nint i = MAC^RO;
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("MACRO", "",
|
|
"c:TestTU.cpp@38@macro@MACRO")}},
|
|
{
|
|
R"cpp( // Macro reference
|
|
#define MACRO 5\nint i = MACRO^;
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("MACRO", "",
|
|
"c:TestTU.cpp@38@macro@MACRO")}},
|
|
{
|
|
R"cpp( // Multiple symbols returned - using overloaded function name
|
|
void foo() {}
|
|
void foo(bool) {}
|
|
void foo(int) {}
|
|
namespace bar {
|
|
using ::fo^o;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:@F@foo#"),
|
|
CreateExpectedSymbolDetails("foo", "", "c:@F@foo#b#"),
|
|
CreateExpectedSymbolDetails("foo", "", "c:@F@foo#I#"),
|
|
CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@UD@foo")}},
|
|
{
|
|
R"cpp( // Multiple symbols returned - implicit conversion
|
|
struct foo {};
|
|
struct bar {
|
|
bar(const foo&) {}
|
|
};
|
|
void func_baz1(bar) {}
|
|
void func_baz2() {
|
|
foo ff;
|
|
func_baz1(f^f);
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails(
|
|
"ff", "func_baz2", "c:TestTU.cpp@218@F@func_baz2#@ff")}},
|
|
{
|
|
R"cpp( // Type reference - declaration
|
|
struct foo;
|
|
void bar(fo^o*);
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}},
|
|
{
|
|
R"cpp( // Type reference - definition
|
|
struct foo {};
|
|
void bar(fo^o*);
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}},
|
|
{
|
|
R"cpp( // Type Reference - template argumen
|
|
struct foo {};
|
|
template<class T> struct bar {};
|
|
void baz() {
|
|
bar<fo^o> b;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}},
|
|
{
|
|
R"cpp( // Template parameter reference - type param
|
|
template<class TT> struct bar {
|
|
T^T t;
|
|
};
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("TT", "bar::", "c:TestTU.cpp@65")}},
|
|
{
|
|
R"cpp( // Template parameter reference - type param
|
|
template<int NN> struct bar {
|
|
int a = N^N;
|
|
};
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("NN", "bar::", "c:TestTU.cpp@65")}},
|
|
{
|
|
R"cpp( // Class member reference - objec
|
|
struct foo {
|
|
int aa;
|
|
};
|
|
void bar() {
|
|
foo f;
|
|
f.a^a;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}},
|
|
{
|
|
R"cpp( // Class member reference - pointer
|
|
struct foo {
|
|
int aa;
|
|
};
|
|
void bar() {
|
|
&foo::a^a;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}},
|
|
{
|
|
R"cpp( // Class method reference - objec
|
|
struct foo {
|
|
void aa() {}
|
|
};
|
|
void bar() {
|
|
foo f;
|
|
f.a^a();
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}},
|
|
{
|
|
R"cpp( // Class method reference - pointer
|
|
struct foo {
|
|
void aa() {}
|
|
};
|
|
void bar() {
|
|
&foo::a^a;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}},
|
|
{
|
|
R"cpp( // Typedef
|
|
typedef int foo;
|
|
void bar() {
|
|
fo^o a;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:TestTU.cpp@T@foo")}},
|
|
{
|
|
R"cpp( // Type alias
|
|
using foo = int;
|
|
void bar() {
|
|
fo^o a;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:@foo")}},
|
|
{
|
|
R"cpp( // Namespace reference
|
|
namespace foo {}
|
|
using namespace fo^o;
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("foo", "", "c:@N@foo")}},
|
|
{
|
|
R"cpp( // Enum value reference
|
|
enum foo { bar, baz };
|
|
void f() {
|
|
foo fff = ba^r;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("bar", "foo", "c:@E@foo@bar")}},
|
|
{
|
|
R"cpp( // Enum class value reference
|
|
enum class foo { bar, baz };
|
|
void f() {
|
|
foo fff = foo::ba^r;
|
|
}
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("bar", "foo::", "c:@E@foo@bar")}},
|
|
{
|
|
R"cpp( // Parameters in declarations
|
|
void foo(int ba^r);
|
|
)cpp",
|
|
{CreateExpectedSymbolDetails("bar", "foo",
|
|
"c:TestTU.cpp@50@F@foo#I#@bar")}},
|
|
{
|
|
R"cpp( // Type inference with auto keyword
|
|
struct foo {};
|
|
foo getfoo() { return foo{}; }
|
|
void f() {
|
|
au^to a = getfoo();
|
|
}
|
|
)cpp",
|
|
{/* not implemented */}},
|
|
{
|
|
R"cpp( // decltype
|
|
struct foo {};
|
|
void f() {
|
|
foo f;
|
|
declt^ype(f);
|
|
}
|
|
)cpp",
|
|
{/* not implemented */}},
|
|
};
|
|
|
|
for (const auto &T : TestInputExpectedOutput) {
|
|
Annotations TestInput(T.first);
|
|
auto AST = TestTU::withCode(TestInput.code()).build();
|
|
|
|
EXPECT_THAT(getSymbolInfo(AST, TestInput.point()),
|
|
UnorderedElementsAreArray(T.second))
|
|
<< T.first;
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace clangd
|
|
} // namespace clang
|