2019-02-01 05:30:05 +08:00
|
|
|
//===-- TweakTests.cpp ------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
2019-02-06 17:08:26 +08:00
|
|
|
// 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
|
2019-02-01 05:30:05 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Annotations.h"
|
|
|
|
#include "SourceCode.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include "TestFS.h"
|
2019-02-01 05:30:05 +08:00
|
|
|
#include "TestTU.h"
|
2019-08-02 17:12:39 +08:00
|
|
|
#include "TweakTesting.h"
|
2019-02-01 05:30:05 +08:00
|
|
|
#include "refactor/Tweak.h"
|
|
|
|
#include "clang/AST/Expr.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
|
|
|
#include "clang/Basic/DiagnosticIDs.h"
|
|
|
|
#include "clang/Basic/DiagnosticOptions.h"
|
|
|
|
#include "clang/Basic/FileManager.h"
|
|
|
|
#include "clang/Basic/FileSystemOptions.h"
|
2019-07-12 00:04:18 +08:00
|
|
|
#include "clang/Basic/LLVM.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
2019-02-01 05:30:05 +08:00
|
|
|
#include "clang/Rewrite/Core/Rewriter.h"
|
|
|
|
#include "clang/Tooling/Core/Replacement.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
2019-10-28 14:21:04 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2019-09-06 15:49:40 +08:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2019-02-01 05:30:05 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Support/Error.h"
|
2019-09-09 20:28:44 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
#include "llvm/Support/VirtualFileSystem.h"
|
2019-02-01 05:30:05 +08:00
|
|
|
#include "llvm/Testing/Support/Error.h"
|
2019-07-17 18:17:47 +08:00
|
|
|
#include "gmock/gmock-matchers.h"
|
2019-02-01 05:30:05 +08:00
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include <cassert>
|
2019-10-28 14:21:04 +08:00
|
|
|
#include <string>
|
2019-09-06 15:49:40 +08:00
|
|
|
#include <utility>
|
2019-10-28 14:21:04 +08:00
|
|
|
#include <vector>
|
2019-02-01 05:30:05 +08:00
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
using ::testing::AllOf;
|
2019-10-14 18:02:24 +08:00
|
|
|
using ::testing::ElementsAre;
|
2019-08-02 17:12:39 +08:00
|
|
|
using ::testing::HasSubstr;
|
|
|
|
using ::testing::StartsWith;
|
2019-02-01 05:30:05 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
|
|
|
|
2019-09-06 15:49:40 +08:00
|
|
|
MATCHER_P2(FileWithContents, FileName, Contents, "") {
|
|
|
|
return arg.first() == FileName && arg.second == Contents;
|
|
|
|
}
|
|
|
|
|
2019-09-09 20:28:44 +08:00
|
|
|
TEST(FileEdits, AbsolutePath) {
|
|
|
|
auto RelPaths = {"a.h", "foo.cpp", "test/test.cpp"};
|
|
|
|
|
|
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> MemFS(
|
|
|
|
new llvm::vfs::InMemoryFileSystem);
|
|
|
|
MemFS->setCurrentWorkingDirectory(testRoot());
|
|
|
|
for (auto Path : RelPaths)
|
|
|
|
MemFS->addFile(Path, 0, llvm::MemoryBuffer::getMemBuffer("", Path));
|
|
|
|
FileManager FM(FileSystemOptions(), MemFS);
|
|
|
|
DiagnosticsEngine DE(new DiagnosticIDs, new DiagnosticOptions);
|
|
|
|
SourceManager SM(DE, FM);
|
|
|
|
|
|
|
|
for (auto Path : RelPaths) {
|
|
|
|
auto FID = SM.createFileID(*FM.getFile(Path), SourceLocation(),
|
|
|
|
clang::SrcMgr::C_User);
|
|
|
|
auto Res = Tweak::Effect::fileEdit(SM, FID, tooling::Replacements());
|
|
|
|
ASSERT_THAT_EXPECTED(Res, llvm::Succeeded());
|
|
|
|
EXPECT_EQ(Res->first, testPath(Path));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
TWEAK_TEST(SwapIfBranches);
|
|
|
|
TEST_F(SwapIfBranchesTest, Test) {
|
|
|
|
Context = Function;
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_EQ(apply("^if (true) {return;} else {(void)0;}"),
|
|
|
|
"if (true) {(void)0;} else {return;}");
|
|
|
|
EXPECT_EQ(apply("^if (/*error-ok*/) {return;} else {(void)0;}"),
|
|
|
|
"if (/*error-ok*/) {(void)0;} else {return;}")
|
2019-10-16 17:53:59 +08:00
|
|
|
<< "broken condition";
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return; } ^e^l^s^e^ { return; }");
|
|
|
|
EXPECT_UNAVAILABLE("if (true) {^return ^;^ } else { ^return^;^ }");
|
2019-08-02 17:12:39 +08:00
|
|
|
// Available in subexpressions of the condition;
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_THAT("if(2 + [[2]] + 2) { return; } else {return;}", isAvailable());
|
2019-02-01 23:09:47 +08:00
|
|
|
// But not as part of the branches.
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_THAT("if(2 + 2 + 2) { [[return]]; } else { return; }",
|
2019-08-02 17:12:39 +08:00
|
|
|
Not(isAvailable()));
|
2019-02-01 23:09:47 +08:00
|
|
|
// Range covers the "else" token, so available.
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_THAT("if(2 + 2 + 2) { return[[; } else {return;]]}", isAvailable());
|
2019-02-01 23:09:47 +08:00
|
|
|
// Not available in compound statements in condition.
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_THAT("if([]{return [[true]];}()) { return; } else { return; }",
|
|
|
|
Not(isAvailable()));
|
2019-02-01 23:09:47 +08:00
|
|
|
// Not available if both sides aren't braced.
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_THAT("^if (1) return; else { return; }", Not(isAvailable()));
|
2019-02-01 23:09:47 +08:00
|
|
|
// Only one if statement is supported!
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_THAT("[[if(1){}else{}if(2){}else{}]]", Not(isAvailable()));
|
2019-02-01 05:30:05 +08:00
|
|
|
}
|
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
TWEAK_TEST(RawStringLiteral);
|
|
|
|
TEST_F(RawStringLiteralTest, Test) {
|
|
|
|
Context = Expression;
|
|
|
|
EXPECT_AVAILABLE(R"cpp(^"^f^o^o^\^n^")cpp");
|
|
|
|
EXPECT_AVAILABLE(R"cpp(R"(multi )" ^"token " "str\ning")cpp");
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(^"f^o^o^o")cpp"); // no chars need escaping
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro
|
2019-10-16 17:53:59 +08:00
|
|
|
EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char
|
2019-08-02 17:12:39 +08:00
|
|
|
|
|
|
|
const char *Input = R"cpp(R"(multi
|
|
|
|
token)" "\nst^ring\n" "literal")cpp";
|
|
|
|
const char *Output = R"cpp(R"(multi
|
2019-05-21 21:04:24 +08:00
|
|
|
token
|
|
|
|
string
|
2019-08-02 17:12:39 +08:00
|
|
|
literal)")cpp";
|
|
|
|
EXPECT_EQ(apply(Input), Output);
|
2019-05-21 21:04:24 +08:00
|
|
|
}
|
|
|
|
|
2019-12-05 08:58:12 +08:00
|
|
|
TWEAK_TEST(ObjCLocalizeStringLiteral);
|
|
|
|
TEST_F(ObjCLocalizeStringLiteralTest, Test) {
|
|
|
|
ExtraArgs.push_back("-x");
|
|
|
|
ExtraArgs.push_back("objective-c");
|
|
|
|
|
2020-01-03 02:41:43 +08:00
|
|
|
// Ensure the action can be initiated in the string literal.
|
2019-12-05 08:58:12 +08:00
|
|
|
EXPECT_AVAILABLE(R"(id x = ^[[@[[^"^t^est^"]]]];)");
|
|
|
|
|
|
|
|
// Ensure that the action can't be initiated in other places.
|
|
|
|
EXPECT_UNAVAILABLE(R"([[i^d ^[[x]] ^= @"test";^]])");
|
|
|
|
|
|
|
|
// Ensure that the action is not available for regular C strings.
|
|
|
|
EXPECT_UNAVAILABLE(R"(const char * x= "^test";)");
|
|
|
|
|
|
|
|
const char *Input = R"(id x = [[@"test"]];)";
|
|
|
|
const char *Output = R"(id x = NSLocalizedString(@"test", @"");)";
|
|
|
|
EXPECT_EQ(apply(Input), Output);
|
|
|
|
}
|
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
TWEAK_TEST(DumpAST);
|
|
|
|
TEST_F(DumpASTTest, Test) {
|
|
|
|
EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }");
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_UNAVAILABLE("/*c^omment*/ int foo() { return 2 ^ + 2; }");
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_THAT(apply("int x = 2 ^+ 2;"),
|
|
|
|
AllOf(StartsWith("message:"), HasSubstr("BinaryOperator"),
|
|
|
|
HasSubstr("'+'"), HasSubstr("|-IntegerLiteral"),
|
|
|
|
HasSubstr("<col:9> 'int' 2\n`-IntegerLiteral"),
|
|
|
|
HasSubstr("<col:13> 'int' 2")));
|
2019-06-18 21:37:54 +08:00
|
|
|
}
|
|
|
|
|
2019-10-28 23:27:42 +08:00
|
|
|
TWEAK_TEST(DumpSymbol);
|
|
|
|
TEST_F(DumpSymbolTest, Test) {
|
|
|
|
std::string ID = R"("id":"CA2EBE44A1D76D2A")";
|
|
|
|
std::string USR = R"("usr":"c:@F@foo#")";
|
|
|
|
EXPECT_THAT(apply("void f^oo();"),
|
|
|
|
AllOf(StartsWith("message:"), testing::HasSubstr(ID),
|
|
|
|
testing::HasSubstr(USR)));
|
|
|
|
}
|
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
TWEAK_TEST(ShowSelectionTree);
|
|
|
|
TEST_F(ShowSelectionTreeTest, Test) {
|
|
|
|
EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }");
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_AVAILABLE("/*c^omment*/ int foo() { return 2 ^ + 2; }");
|
2019-06-18 21:37:54 +08:00
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
const char *Output = R"(message:
|
|
|
|
TranslationUnitDecl
|
[clangd] SelectionTree treats TranslationUnitDecl (mostly) consistently with other containers.
Summary:
Previously TranslationUnitDecl would never be selected.
This means root() is never null, and returns a reference.
commonAncestor() is in principle never null also, but returning TUDecl
here requires tweaks to be careful not to traverse it (this was already
possible when selecting multiple top-level decls, and there are associated bugs!)
Instead, never allow commonAncestor() to return TUDecl, return null instead.
Reviewers: hokein
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D65101
llvm-svn: 366893
2019-07-24 20:14:56 +08:00
|
|
|
VarDecl int x = fcall(2 + 2)
|
|
|
|
.CallExpr fcall(2 + 2)
|
|
|
|
ImplicitCastExpr fcall
|
|
|
|
.DeclRefExpr fcall
|
|
|
|
.BinaryOperator 2 + 2
|
|
|
|
*IntegerLiteral 2
|
2019-06-18 21:37:54 +08:00
|
|
|
)";
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_EQ(apply("int fcall(int); int x = fca[[ll(2 +]]2);"), Output);
|
2019-06-18 21:37:54 +08:00
|
|
|
}
|
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
TWEAK_TEST(DumpRecordLayout);
|
|
|
|
TEST_F(DumpRecordLayoutTest, Test) {
|
|
|
|
EXPECT_AVAILABLE("^s^truct ^X ^{ int x; ^};");
|
|
|
|
EXPECT_THAT("struct X { int ^a; };", Not(isAvailable()));
|
|
|
|
EXPECT_THAT("struct ^X;", Not(isAvailable()));
|
|
|
|
EXPECT_THAT("template <typename T> struct ^X { T t; };", Not(isAvailable()));
|
|
|
|
EXPECT_THAT("enum ^X {};", Not(isAvailable()));
|
2019-06-18 21:37:54 +08:00
|
|
|
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_THAT(apply("struct ^X { int x; int y; };"),
|
2019-08-02 17:12:39 +08:00
|
|
|
AllOf(StartsWith("message:"), HasSubstr("0 | int x")));
|
2019-06-18 21:37:54 +08:00
|
|
|
}
|
2019-07-24 13:42:55 +08:00
|
|
|
|
2019-08-29 16:20:48 +08:00
|
|
|
TWEAK_TEST(ExtractVariable);
|
|
|
|
TEST_F(ExtractVariableTest, Test) {
|
|
|
|
const char *AvailableCases = R"cpp(
|
2019-07-24 13:42:55 +08:00
|
|
|
int xyz(int a = 1) {
|
|
|
|
struct T {
|
|
|
|
int bar(int a = 1);
|
|
|
|
int z;
|
|
|
|
} t;
|
2019-07-09 18:12:26 +08:00
|
|
|
// return statement
|
2019-07-24 13:42:55 +08:00
|
|
|
return [[[[t.b[[a]]r]](t.z)]];
|
2019-07-09 18:12:26 +08:00
|
|
|
}
|
|
|
|
void f() {
|
2019-07-18 23:38:03 +08:00
|
|
|
int a = [[5 +]] [[4 * [[[[xyz]]()]]]];
|
2019-07-09 18:12:26 +08:00
|
|
|
// multivariable initialization
|
|
|
|
if(1)
|
2019-07-24 13:42:55 +08:00
|
|
|
int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
|
2019-07-09 18:12:26 +08:00
|
|
|
// if without else
|
2019-07-18 23:38:03 +08:00
|
|
|
if([[1]])
|
|
|
|
a = [[1]];
|
2019-07-09 18:12:26 +08:00
|
|
|
// if with else
|
2019-07-18 23:38:03 +08:00
|
|
|
if(a < [[3]])
|
|
|
|
if(a == [[4]])
|
|
|
|
a = [[5]];
|
2019-07-09 18:12:26 +08:00
|
|
|
else
|
2019-07-18 23:38:03 +08:00
|
|
|
a = [[5]];
|
|
|
|
else if (a < [[4]])
|
|
|
|
a = [[4]];
|
2019-07-09 18:12:26 +08:00
|
|
|
else
|
2019-07-18 23:38:03 +08:00
|
|
|
a = [[5]];
|
2019-07-24 13:42:55 +08:00
|
|
|
// for loop
|
2019-07-18 23:38:03 +08:00
|
|
|
for(a = [[1]]; a > [[[[3]] + [[4]]]]; a++)
|
|
|
|
a = [[2]];
|
2019-07-24 13:42:55 +08:00
|
|
|
// while
|
2019-07-18 23:38:03 +08:00
|
|
|
while(a < [[1]])
|
2019-08-10 07:40:54 +08:00
|
|
|
a = [[1]];
|
2019-07-24 13:42:55 +08:00
|
|
|
// do while
|
2019-07-09 18:12:26 +08:00
|
|
|
do
|
2019-07-18 23:38:03 +08:00
|
|
|
a = [[1]];
|
|
|
|
while(a < [[3]]);
|
2019-07-09 18:12:26 +08:00
|
|
|
}
|
2019-08-29 16:20:48 +08:00
|
|
|
)cpp";
|
|
|
|
EXPECT_AVAILABLE(AvailableCases);
|
|
|
|
|
2020-02-24 23:38:57 +08:00
|
|
|
ExtraArgs = {"-xc"};
|
|
|
|
const char *AvailableButC = R"cpp(
|
|
|
|
void foo() {
|
|
|
|
int x = [[1]];
|
|
|
|
})cpp";
|
|
|
|
EXPECT_UNAVAILABLE(AvailableButC);
|
|
|
|
ExtraArgs = {};
|
|
|
|
|
2019-08-29 16:20:48 +08:00
|
|
|
const char *NoCrashCases = R"cpp(
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
// error-ok: broken code, but shouldn't crash
|
2019-07-11 20:29:01 +08:00
|
|
|
template<typename T, typename ...Args>
|
|
|
|
struct Test<T, Args...> {
|
2019-07-24 13:42:55 +08:00
|
|
|
Test(const T &v) :val[[(^]]) {}
|
2019-07-11 20:29:01 +08:00
|
|
|
T val;
|
|
|
|
};
|
2019-08-29 16:20:48 +08:00
|
|
|
)cpp";
|
|
|
|
EXPECT_UNAVAILABLE(NoCrashCases);
|
|
|
|
|
|
|
|
const char *UnavailableCases = R"cpp(
|
2019-07-18 23:38:03 +08:00
|
|
|
int xyz(int a = [[1]]) {
|
2019-07-24 13:42:55 +08:00
|
|
|
struct T {
|
|
|
|
int bar(int a = [[1]]);
|
|
|
|
int z = [[1]];
|
|
|
|
} t;
|
|
|
|
return [[t]].bar([[[[t]].z]]);
|
2019-07-09 18:12:26 +08:00
|
|
|
}
|
2019-07-24 13:42:55 +08:00
|
|
|
void v() { return; }
|
2019-07-09 18:12:26 +08:00
|
|
|
// function default argument
|
2019-07-18 23:38:03 +08:00
|
|
|
void f(int b = [[1]]) {
|
|
|
|
// empty selection
|
|
|
|
int a = ^1 ^+ ^2;
|
2019-07-09 18:12:26 +08:00
|
|
|
// void expressions
|
|
|
|
auto i = new int, j = new int;
|
2019-07-18 23:38:03 +08:00
|
|
|
[[[[delete i]], delete j]];
|
2019-07-24 13:42:55 +08:00
|
|
|
[[v]]();
|
2019-07-09 18:12:26 +08:00
|
|
|
// if
|
|
|
|
if(1)
|
2019-07-18 23:38:03 +08:00
|
|
|
int x = 1, y = a + 1, a = 1, z = [[a + 1]];
|
2019-07-09 18:12:26 +08:00
|
|
|
if(int a = 1)
|
2019-07-24 13:42:55 +08:00
|
|
|
if([[a + 1]] == 4)
|
2019-07-18 23:38:03 +08:00
|
|
|
a = [[[[a]] +]] 1;
|
2019-07-24 13:42:55 +08:00
|
|
|
// for loop
|
|
|
|
for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
|
2019-07-18 23:38:03 +08:00
|
|
|
a = [[a + 1]];
|
2019-07-24 13:42:55 +08:00
|
|
|
// lambda
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;};
|
2020-01-04 23:28:41 +08:00
|
|
|
// assignment
|
2019-08-10 07:40:54 +08:00
|
|
|
xyz([[a = 5]]);
|
|
|
|
xyz([[a *= 5]]);
|
2019-07-24 13:42:55 +08:00
|
|
|
// Variable DeclRefExpr
|
|
|
|
a = [[b]];
|
2019-08-10 07:40:54 +08:00
|
|
|
// statement expression
|
|
|
|
[[xyz()]];
|
|
|
|
while (a)
|
|
|
|
[[++a]];
|
2019-07-24 13:42:55 +08:00
|
|
|
// label statement
|
|
|
|
goto label;
|
|
|
|
label:
|
|
|
|
a = [[1]];
|
2019-07-09 18:12:26 +08:00
|
|
|
}
|
2019-08-29 16:20:48 +08:00
|
|
|
)cpp";
|
|
|
|
EXPECT_UNAVAILABLE(UnavailableCases);
|
|
|
|
|
2019-07-09 18:12:26 +08:00
|
|
|
// vector of pairs of input and output strings
|
2019-12-03 23:59:52 +08:00
|
|
|
const std::vector<std::pair<std::string, std::string>>
|
2019-07-09 18:12:26 +08:00
|
|
|
InputOutputs = {
|
|
|
|
// extraction from variable declaration/assignment
|
|
|
|
{R"cpp(void varDecl() {
|
|
|
|
int a = 5 * (4 + (3 [[- 1)]]);
|
|
|
|
})cpp",
|
|
|
|
R"cpp(void varDecl() {
|
|
|
|
auto dummy = (3 - 1); int a = 5 * (4 + dummy);
|
|
|
|
})cpp"},
|
|
|
|
// FIXME: extraction from switch case
|
|
|
|
/*{R"cpp(void f(int a) {
|
|
|
|
if(1)
|
|
|
|
while(a < 1)
|
|
|
|
switch (1) {
|
|
|
|
case 1:
|
|
|
|
a = [[1 + 2]];
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
})cpp",
|
|
|
|
R"cpp(void f(int a) {
|
|
|
|
auto dummy = 1 + 2; if(1)
|
|
|
|
while(a < 1)
|
|
|
|
switch (1) {
|
|
|
|
case 1:
|
|
|
|
a = dummy;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
})cpp"},*/
|
2019-07-24 13:42:55 +08:00
|
|
|
// Macros
|
|
|
|
{R"cpp(#define PLUS(x) x++
|
|
|
|
void f(int a) {
|
2019-08-10 07:40:54 +08:00
|
|
|
int y = PLUS([[1+a]]);
|
2019-07-24 13:42:55 +08:00
|
|
|
})cpp",
|
2019-10-16 17:53:59 +08:00
|
|
|
/*FIXME: It should be extracted like this.
|
|
|
|
R"cpp(#define PLUS(x) x++
|
|
|
|
void f(int a) {
|
|
|
|
auto dummy = 1+a; int y = PLUS(dummy);
|
|
|
|
})cpp"},*/
|
2019-07-24 13:42:55 +08:00
|
|
|
R"cpp(#define PLUS(x) x++
|
|
|
|
void f(int a) {
|
2019-08-10 07:40:54 +08:00
|
|
|
auto dummy = PLUS(1+a); int y = dummy;
|
2019-07-24 13:42:55 +08:00
|
|
|
})cpp"},
|
2019-07-09 18:12:26 +08:00
|
|
|
// ensure InsertionPoint isn't inside a macro
|
2019-07-19 20:11:04 +08:00
|
|
|
{R"cpp(#define LOOP(x) while (1) {a = x;}
|
2019-07-09 18:12:26 +08:00
|
|
|
void f(int a) {
|
|
|
|
if(1)
|
2019-07-18 23:38:03 +08:00
|
|
|
LOOP(5 + [[3]])
|
2019-07-09 18:12:26 +08:00
|
|
|
})cpp",
|
2019-10-16 17:53:59 +08:00
|
|
|
R"cpp(#define LOOP(x) while (1) {a = x;}
|
2019-07-19 19:41:02 +08:00
|
|
|
void f(int a) {
|
2019-12-03 23:59:52 +08:00
|
|
|
auto dummy = 3; if(1)
|
|
|
|
LOOP(5 + dummy)
|
2019-07-19 20:11:04 +08:00
|
|
|
})cpp"},
|
2019-07-19 19:41:02 +08:00
|
|
|
{R"cpp(#define LOOP(x) do {x;} while(1);
|
|
|
|
void f(int a) {
|
|
|
|
if(1)
|
|
|
|
LOOP(5 + [[3]])
|
|
|
|
})cpp",
|
|
|
|
R"cpp(#define LOOP(x) do {x;} while(1);
|
2019-07-09 18:12:26 +08:00
|
|
|
void f(int a) {
|
|
|
|
auto dummy = 3; if(1)
|
|
|
|
LOOP(5 + dummy)
|
|
|
|
})cpp"},
|
2019-07-24 13:42:55 +08:00
|
|
|
// attribute testing
|
2019-07-09 18:12:26 +08:00
|
|
|
{R"cpp(void f(int a) {
|
2019-07-24 13:42:55 +08:00
|
|
|
[ [gsl::suppress("type")] ] for (;;) a = [[1]];
|
2019-07-09 18:12:26 +08:00
|
|
|
})cpp",
|
|
|
|
R"cpp(void f(int a) {
|
2019-07-24 13:42:55 +08:00
|
|
|
auto dummy = 1; [ [gsl::suppress("type")] ] for (;;) a = dummy;
|
2019-07-09 18:12:26 +08:00
|
|
|
})cpp"},
|
2019-07-24 13:42:55 +08:00
|
|
|
// MemberExpr
|
|
|
|
{R"cpp(class T {
|
|
|
|
T f() {
|
|
|
|
return [[T().f()]].f();
|
|
|
|
}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(class T {
|
|
|
|
T f() {
|
|
|
|
auto dummy = T().f(); return dummy.f();
|
|
|
|
}
|
|
|
|
};)cpp"},
|
|
|
|
// Function DeclRefExpr
|
|
|
|
{R"cpp(int f() {
|
|
|
|
return [[f]]();
|
2019-07-09 18:12:26 +08:00
|
|
|
})cpp",
|
2019-07-24 13:42:55 +08:00
|
|
|
R"cpp(int f() {
|
|
|
|
auto dummy = f(); return dummy;
|
2019-07-19 20:11:04 +08:00
|
|
|
})cpp"},
|
2019-07-24 13:42:55 +08:00
|
|
|
// FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = [[1]];
|
|
|
|
// since the attr is inside the DeclStmt and the bounds of
|
|
|
|
// DeclStmt don't cover the attribute.
|
2019-07-26 23:29:52 +08:00
|
|
|
|
|
|
|
// Binary subexpressions
|
|
|
|
{R"cpp(void f() {
|
|
|
|
int x = 1 + [[2 + 3 + 4]] + 5;
|
|
|
|
})cpp",
|
|
|
|
R"cpp(void f() {
|
|
|
|
auto dummy = 2 + 3 + 4; int x = 1 + dummy + 5;
|
|
|
|
})cpp"},
|
|
|
|
{R"cpp(void f() {
|
|
|
|
int x = [[1 + 2 + 3]] + 4 + 5;
|
|
|
|
})cpp",
|
|
|
|
R"cpp(void f() {
|
|
|
|
auto dummy = 1 + 2 + 3; int x = dummy + 4 + 5;
|
|
|
|
})cpp"},
|
|
|
|
{R"cpp(void f() {
|
|
|
|
int x = 1 + 2 + [[3 + 4 + 5]];
|
|
|
|
})cpp",
|
|
|
|
R"cpp(void f() {
|
|
|
|
auto dummy = 3 + 4 + 5; int x = 1 + 2 + dummy;
|
|
|
|
})cpp"},
|
|
|
|
// Non-associative operations have no special support
|
|
|
|
{R"cpp(void f() {
|
|
|
|
int x = 1 - [[2 - 3 - 4]] - 5;
|
|
|
|
})cpp",
|
|
|
|
R"cpp(void f() {
|
|
|
|
auto dummy = 1 - 2 - 3 - 4; int x = dummy - 5;
|
|
|
|
})cpp"},
|
|
|
|
// A mix of associative operators isn't associative.
|
|
|
|
{R"cpp(void f() {
|
|
|
|
int x = 0 + 1 * [[2 + 3]] * 4 + 5;
|
|
|
|
})cpp",
|
|
|
|
R"cpp(void f() {
|
|
|
|
auto dummy = 1 * 2 + 3 * 4; int x = 0 + dummy + 5;
|
|
|
|
})cpp"},
|
|
|
|
// Overloaded operators are supported, we assume associativity
|
|
|
|
// as if they were built-in.
|
|
|
|
{R"cpp(struct S {
|
|
|
|
S(int);
|
|
|
|
};
|
|
|
|
S operator+(S, S);
|
|
|
|
|
|
|
|
void f() {
|
|
|
|
S x = S(1) + [[S(2) + S(3) + S(4)]] + S(5);
|
|
|
|
})cpp",
|
|
|
|
R"cpp(struct S {
|
|
|
|
S(int);
|
|
|
|
};
|
|
|
|
S operator+(S, S);
|
|
|
|
|
|
|
|
void f() {
|
|
|
|
auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5);
|
|
|
|
})cpp"},
|
2019-10-16 17:53:59 +08:00
|
|
|
// Don't try to analyze across macro boundaries
|
|
|
|
// FIXME: it'd be nice to do this someday (in a safe way)
|
2019-07-26 23:29:52 +08:00
|
|
|
{R"cpp(#define ECHO(X) X
|
|
|
|
void f() {
|
|
|
|
int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
|
|
|
|
})cpp",
|
|
|
|
R"cpp(#define ECHO(X) X
|
|
|
|
void f() {
|
|
|
|
auto dummy = 1 + ECHO(2 + 3) + 4; int x = dummy + 5;
|
|
|
|
})cpp"},
|
|
|
|
{R"cpp(#define ECHO(X) X
|
|
|
|
void f() {
|
|
|
|
int x = 1 + [[ECHO(2) + ECHO(3) + 4]] + 5;
|
|
|
|
})cpp",
|
|
|
|
R"cpp(#define ECHO(X) X
|
|
|
|
void f() {
|
|
|
|
auto dummy = 1 + ECHO(2) + ECHO(3) + 4; int x = dummy + 5;
|
|
|
|
})cpp"},
|
2019-07-09 18:12:26 +08:00
|
|
|
};
|
|
|
|
for (const auto &IO : InputOutputs) {
|
2019-08-29 16:20:48 +08:00
|
|
|
EXPECT_EQ(IO.second, apply(IO.first)) << IO.first;
|
2019-07-09 18:12:26 +08:00
|
|
|
}
|
|
|
|
}
|
2019-06-18 21:37:54 +08:00
|
|
|
|
2019-08-29 16:20:48 +08:00
|
|
|
TWEAK_TEST(AnnotateHighlightings);
|
|
|
|
TEST_F(AnnotateHighlightingsTest, Test) {
|
|
|
|
EXPECT_AVAILABLE("^vo^id^ ^f(^) {^}^"); // available everywhere.
|
|
|
|
EXPECT_AVAILABLE("[[int a; int b;]]");
|
2019-10-28 18:31:06 +08:00
|
|
|
EXPECT_EQ("void /* entity.name.function.cpp */f() {}", apply("void ^f() {}"));
|
2019-08-29 16:20:48 +08:00
|
|
|
|
|
|
|
EXPECT_EQ(apply("[[void f1(); void f2();]]"),
|
2019-10-28 18:31:06 +08:00
|
|
|
"void /* entity.name.function.cpp */f1(); "
|
|
|
|
"void /* entity.name.function.cpp */f2();");
|
2019-08-29 16:20:48 +08:00
|
|
|
|
|
|
|
EXPECT_EQ(apply("void f1(); void f2() {^}"),
|
|
|
|
"void f1(); "
|
2019-10-28 18:31:06 +08:00
|
|
|
"void /* entity.name.function.cpp */f2() {}");
|
2019-07-04 18:49:32 +08:00
|
|
|
}
|
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
TWEAK_TEST(ExpandMacro);
|
|
|
|
TEST_F(ExpandMacroTest, Test) {
|
|
|
|
Header = R"cpp(
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
// error-ok: not real c++, just token manipulation
|
2019-08-02 17:12:39 +08:00
|
|
|
#define FOO 1 2 3
|
|
|
|
#define FUNC(X) X+X+X
|
|
|
|
#define EMPTY
|
|
|
|
#define EMPTY_FN(X)
|
|
|
|
)cpp";
|
2019-07-08 23:25:16 +08:00
|
|
|
|
|
|
|
// Available on macro names, not available anywhere else.
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_AVAILABLE("^F^O^O^ BAR ^F^O^O^");
|
|
|
|
EXPECT_AVAILABLE("^F^U^N^C^(1)");
|
|
|
|
EXPECT_UNAVAILABLE("^#^d^efine^ ^XY^Z 1 ^2 ^3^");
|
|
|
|
EXPECT_UNAVAILABLE("FOO ^B^A^R^ FOO ^");
|
|
|
|
EXPECT_UNAVAILABLE("FUNC(^1^)^");
|
2019-07-08 23:25:16 +08:00
|
|
|
|
|
|
|
// Works as expected on object-like macros.
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_EQ(apply("^FOO BAR FOO"), "1 2 3 BAR FOO");
|
|
|
|
EXPECT_EQ(apply("FOO BAR ^FOO"), "FOO BAR 1 2 3");
|
2019-07-08 23:25:16 +08:00
|
|
|
// And function-like macros.
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_EQ(apply("F^UNC(2)"), "2 + 2 + 2");
|
2019-07-08 23:25:16 +08:00
|
|
|
|
|
|
|
// Works on empty macros.
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_EQ(apply("int a ^EMPTY;"), "int a ;");
|
|
|
|
EXPECT_EQ(apply("int a ^EMPTY_FN(1 2 3);"), "int a ;");
|
|
|
|
EXPECT_EQ(apply("int a = 123 ^EMPTY EMPTY_FN(1);"),
|
|
|
|
"int a = 123 EMPTY_FN(1);");
|
|
|
|
EXPECT_EQ(apply("int a = 123 ^EMPTY_FN(1) EMPTY;"), "int a = 123 EMPTY;");
|
|
|
|
EXPECT_EQ(apply("int a = 123 EMPTY_FN(1) ^EMPTY;"),
|
|
|
|
"int a = 123 EMPTY_FN(1) ;");
|
2019-07-08 23:25:16 +08:00
|
|
|
}
|
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
TWEAK_TEST(ExpandAutoType);
|
|
|
|
TEST_F(ExpandAutoTypeTest, Test) {
|
2019-10-13 21:15:27 +08:00
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
Header = R"cpp(
|
|
|
|
namespace ns {
|
|
|
|
struct Class {
|
|
|
|
struct Nested {};
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
};
|
2019-08-02 17:12:39 +08:00
|
|
|
void Func();
|
2019-07-12 00:04:18 +08:00
|
|
|
}
|
2019-08-02 17:12:39 +08:00
|
|
|
inline namespace inl_ns {
|
|
|
|
namespace {
|
|
|
|
struct Visible {};
|
|
|
|
}
|
2019-07-12 00:04:18 +08:00
|
|
|
}
|
|
|
|
)cpp";
|
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_AVAILABLE("^a^u^t^o^ i = 0;");
|
|
|
|
EXPECT_UNAVAILABLE("auto ^i^ ^=^ ^0^;^");
|
2019-07-12 00:04:18 +08:00
|
|
|
|
2019-08-02 17:12:39 +08:00
|
|
|
// check primitive type
|
|
|
|
EXPECT_EQ(apply("[[auto]] i = 0;"), "int i = 0;");
|
|
|
|
EXPECT_EQ(apply("au^to i = 0;"), "int i = 0;");
|
|
|
|
// check classes and namespaces
|
|
|
|
EXPECT_EQ(apply("^auto C = ns::Class::Nested();"),
|
|
|
|
"ns::Class::Nested C = ns::Class::Nested();");
|
|
|
|
// check that namespaces are shortened
|
|
|
|
EXPECT_EQ(apply("namespace ns { void f() { ^auto C = Class(); } }"),
|
|
|
|
"namespace ns { void f() { Class C = Class(); } }");
|
2019-07-12 00:04:18 +08:00
|
|
|
// undefined functions should not be replaced
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_THAT(apply("au^to x = doesnt_exist(); // error-ok"),
|
2019-08-02 17:12:39 +08:00
|
|
|
StartsWith("fail: Could not deduce type for 'auto' type"));
|
2019-07-12 00:04:18 +08:00
|
|
|
// function pointers should not be replaced
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_THAT(apply("au^to x = &ns::Func;"),
|
|
|
|
StartsWith("fail: Could not expand type of function pointer"));
|
2019-07-12 00:04:18 +08:00
|
|
|
// lambda types are not replaced
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_THAT(apply("au^to x = []{};"),
|
|
|
|
StartsWith("fail: Could not expand type of lambda expression"));
|
2019-07-12 00:04:18 +08:00
|
|
|
// inline namespaces
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
|
2019-10-16 17:53:59 +08:00
|
|
|
"Visible x = inl_ns::Visible();");
|
2019-07-12 00:04:18 +08:00
|
|
|
// local class
|
2019-08-02 17:12:39 +08:00
|
|
|
EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
|
|
|
|
"namespace x { void y() { struct S{}; S z = S(); } }");
|
2019-07-12 00:04:18 +08:00
|
|
|
// replace array types
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
EXPECT_EQ(apply(R"cpp(au^to x = "test";)cpp"),
|
|
|
|
R"cpp(const char * x = "test";)cpp");
|
2019-10-08 22:03:45 +08:00
|
|
|
|
|
|
|
EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;");
|
2019-10-13 21:15:27 +08:00
|
|
|
|
|
|
|
// FIXME: Auto-completion in a template requires disabling delayed template
|
|
|
|
// parsing.
|
|
|
|
ExtraArgs.push_back("-fno-delayed-template-parsing");
|
|
|
|
// unknown types in a template should not be replaced
|
|
|
|
EXPECT_THAT(apply("template <typename T> void x() { ^auto y = T::z(); }"),
|
|
|
|
StartsWith("fail: Could not deduce type for 'auto' type"));
|
2019-07-12 00:04:18 +08:00
|
|
|
}
|
|
|
|
|
2019-08-29 03:34:17 +08:00
|
|
|
TWEAK_TEST(ExtractFunction);
|
|
|
|
TEST_F(ExtractFunctionTest, FunctionTest) {
|
|
|
|
Context = Function;
|
|
|
|
|
|
|
|
// Root statements should have common parent.
|
|
|
|
EXPECT_EQ(apply("for(;;) [[1+2; 1+2;]]"), "unavailable");
|
|
|
|
// Expressions aren't extracted.
|
|
|
|
EXPECT_EQ(apply("int x = 0; [[x++;]]"), "unavailable");
|
|
|
|
// We don't support extraction from lambdas.
|
|
|
|
EXPECT_EQ(apply("auto lam = [](){ [[int x;]] }; "), "unavailable");
|
2019-10-02 18:01:53 +08:00
|
|
|
// Partial statements aren't extracted.
|
|
|
|
EXPECT_THAT(apply("int [[x = 0]];"), "unavailable");
|
2019-08-29 03:34:17 +08:00
|
|
|
|
|
|
|
// Ensure that end of Zone and Beginning of PostZone being adjacent doesn't
|
|
|
|
// lead to break being included in the extraction zone.
|
|
|
|
EXPECT_THAT(apply("for(;;) { [[int x;]]break; }"), HasSubstr("extracted"));
|
|
|
|
// FIXME: ExtractFunction should be unavailable inside loop construct
|
|
|
|
// initalizer/condition.
|
|
|
|
EXPECT_THAT(apply(" for([[int i = 0;]];);"), HasSubstr("extracted"));
|
|
|
|
// Don't extract because needs hoisting.
|
|
|
|
EXPECT_THAT(apply(" [[int a = 5;]] a++; "), StartsWith("fail"));
|
2019-11-22 06:14:01 +08:00
|
|
|
// Extract certain return
|
|
|
|
EXPECT_THAT(apply(" if(true) [[{ return; }]] "), HasSubstr("extracted"));
|
|
|
|
// Don't extract uncertain return
|
|
|
|
EXPECT_THAT(apply(" if(true) [[if (false) return;]] "), StartsWith("fail"));
|
2019-08-29 03:34:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ExtractFunctionTest, FileTest) {
|
|
|
|
// Check all parameters are in order
|
|
|
|
std::string ParameterCheckInput = R"cpp(
|
|
|
|
struct Foo {
|
|
|
|
int x;
|
|
|
|
};
|
|
|
|
void f(int a) {
|
|
|
|
int b;
|
|
|
|
int *ptr = &a;
|
|
|
|
Foo foo;
|
|
|
|
[[a += foo.x + b;
|
|
|
|
*ptr++;]]
|
|
|
|
})cpp";
|
|
|
|
std::string ParameterCheckOutput = R"cpp(
|
|
|
|
struct Foo {
|
|
|
|
int x;
|
|
|
|
};
|
|
|
|
void extracted(int &a, int &b, int * &ptr, Foo &foo) {
|
|
|
|
a += foo.x + b;
|
|
|
|
*ptr++;
|
|
|
|
}
|
|
|
|
void f(int a) {
|
|
|
|
int b;
|
|
|
|
int *ptr = &a;
|
|
|
|
Foo foo;
|
|
|
|
extracted(a, b, ptr, foo);
|
|
|
|
})cpp";
|
|
|
|
EXPECT_EQ(apply(ParameterCheckInput), ParameterCheckOutput);
|
|
|
|
|
|
|
|
// Check const qualifier
|
|
|
|
std::string ConstCheckInput = R"cpp(
|
|
|
|
void f(const int c) {
|
|
|
|
[[while(c) {}]]
|
|
|
|
})cpp";
|
|
|
|
std::string ConstCheckOutput = R"cpp(
|
|
|
|
void extracted(const int &c) {
|
|
|
|
while(c) {}
|
|
|
|
}
|
|
|
|
void f(const int c) {
|
|
|
|
extracted(c);
|
|
|
|
})cpp";
|
|
|
|
EXPECT_EQ(apply(ConstCheckInput), ConstCheckOutput);
|
|
|
|
|
|
|
|
// Don't extract when we need to make a function as a parameter.
|
|
|
|
EXPECT_THAT(apply("void f() { [[int a; f();]] }"), StartsWith("fail"));
|
|
|
|
|
|
|
|
// We don't extract from methods for now since they may involve multi-file
|
|
|
|
// edits
|
|
|
|
std::string MethodFailInput = R"cpp(
|
|
|
|
class T {
|
|
|
|
void f() {
|
|
|
|
[[int x;]]
|
|
|
|
}
|
|
|
|
};
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(MethodFailInput), "unavailable");
|
|
|
|
|
|
|
|
// We don't extract from templated functions for now as templates are hard
|
|
|
|
// to deal with.
|
|
|
|
std::string TemplateFailInput = R"cpp(
|
|
|
|
template<typename T>
|
|
|
|
void f() {
|
|
|
|
[[int x;]]
|
|
|
|
}
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(TemplateFailInput), "unavailable");
|
|
|
|
|
2019-12-03 23:59:52 +08:00
|
|
|
std::string MacroInput = R"cpp(
|
2019-08-29 03:34:17 +08:00
|
|
|
#define F(BODY) void f() { BODY }
|
|
|
|
F ([[int x = 0;]])
|
|
|
|
)cpp";
|
2019-12-03 23:59:52 +08:00
|
|
|
std::string MacroOutput = R"cpp(
|
|
|
|
#define F(BODY) void f() { BODY }
|
|
|
|
void extracted() {
|
|
|
|
int x = 0;
|
|
|
|
}
|
|
|
|
F (extracted();)
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(MacroInput), MacroOutput);
|
2019-10-02 21:51:06 +08:00
|
|
|
|
|
|
|
// Shouldn't crash.
|
|
|
|
EXPECT_EQ(apply("void f([[int a]]);"), "unavailable");
|
2019-10-02 21:52:14 +08:00
|
|
|
// Don't extract if we select the entire function body (CompoundStmt).
|
|
|
|
std::string CompoundFailInput = R"cpp(
|
|
|
|
void f() [[{
|
|
|
|
int a;
|
|
|
|
}]]
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(CompoundFailInput), "unavailable");
|
2019-08-29 03:34:17 +08:00
|
|
|
}
|
|
|
|
|
2019-08-30 17:57:56 +08:00
|
|
|
TEST_F(ExtractFunctionTest, ControlFlow) {
|
|
|
|
Context = Function;
|
|
|
|
// We should be able to extract break/continue with a parent loop/switch.
|
|
|
|
EXPECT_THAT(apply(" [[for(;;) if(1) break;]] "), HasSubstr("extracted"));
|
|
|
|
EXPECT_THAT(apply(" for(;;) [[while(1) break;]] "), HasSubstr("extracted"));
|
|
|
|
EXPECT_THAT(apply(" [[switch(1) { break; }]]"), HasSubstr("extracted"));
|
|
|
|
EXPECT_THAT(apply(" [[while(1) switch(1) { continue; }]]"),
|
|
|
|
HasSubstr("extracted"));
|
|
|
|
// Don't extract break and continue without a loop/switch parent.
|
|
|
|
EXPECT_THAT(apply(" for(;;) [[if(1) continue;]] "), StartsWith("fail"));
|
|
|
|
EXPECT_THAT(apply(" while(1) [[if(1) break;]] "), StartsWith("fail"));
|
|
|
|
EXPECT_THAT(apply(" switch(1) { [[break;]] }"), StartsWith("fail"));
|
|
|
|
EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"),
|
|
|
|
StartsWith("fail"));
|
|
|
|
}
|
2019-10-16 17:53:59 +08:00
|
|
|
|
2019-11-22 06:14:01 +08:00
|
|
|
TEST_F(ExtractFunctionTest, ExistingReturnStatement) {
|
|
|
|
Context = File;
|
|
|
|
const char* Before = R"cpp(
|
|
|
|
bool lucky(int N);
|
|
|
|
int getNum(bool Superstitious, int Min, int Max) {
|
|
|
|
if (Superstitious) [[{
|
|
|
|
for (int I = Min; I <= Max; ++I)
|
|
|
|
if (lucky(I))
|
|
|
|
return I;
|
|
|
|
return -1;
|
|
|
|
}]] else {
|
|
|
|
return (Min + Max) / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)cpp";
|
|
|
|
// FIXME: min/max should be by value.
|
|
|
|
// FIXME: avoid emitting redundant braces
|
|
|
|
const char* After = R"cpp(
|
|
|
|
bool lucky(int N);
|
|
|
|
int extracted(int &Min, int &Max) {
|
|
|
|
{
|
|
|
|
for (int I = Min; I <= Max; ++I)
|
|
|
|
if (lucky(I))
|
|
|
|
return I;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int getNum(bool Superstitious, int Min, int Max) {
|
|
|
|
if (Superstitious) return extracted(Min, Max); else {
|
|
|
|
return (Min + Max) / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Before), After);
|
|
|
|
}
|
|
|
|
|
2019-10-16 17:53:59 +08:00
|
|
|
TWEAK_TEST(RemoveUsingNamespace);
|
|
|
|
TEST_F(RemoveUsingNamespaceTest, All) {
|
|
|
|
std::pair<llvm::StringRef /*Input*/, llvm::StringRef /*Expected*/> Cases[] = {
|
|
|
|
{// Remove all occurrences of ns. Qualify only unqualified.
|
|
|
|
R"cpp(
|
|
|
|
namespace ns1 { struct vector {}; }
|
|
|
|
namespace ns2 { struct map {}; }
|
|
|
|
using namespace n^s1;
|
|
|
|
using namespace ns2;
|
|
|
|
using namespace ns1;
|
|
|
|
int main() {
|
|
|
|
ns1::vector v1;
|
|
|
|
vector v2;
|
|
|
|
map m1;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace ns1 { struct vector {}; }
|
|
|
|
namespace ns2 { struct map {}; }
|
|
|
|
|
|
|
|
using namespace ns2;
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
ns1::vector v1;
|
|
|
|
ns1::vector v2;
|
|
|
|
map m1;
|
|
|
|
}
|
|
|
|
)cpp"},
|
|
|
|
{// Ident to be qualified is a macro arg.
|
|
|
|
R"cpp(
|
|
|
|
#define DECLARE(x, y) x y
|
|
|
|
namespace ns { struct vector {}; }
|
|
|
|
using namespace n^s;
|
|
|
|
int main() {
|
|
|
|
DECLARE(ns::vector, v1);
|
|
|
|
DECLARE(vector, v2);
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define DECLARE(x, y) x y
|
|
|
|
namespace ns { struct vector {}; }
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
DECLARE(ns::vector, v1);
|
|
|
|
DECLARE(ns::vector, v2);
|
|
|
|
}
|
|
|
|
)cpp"},
|
|
|
|
{// Nested namespace: Fully qualify ident from inner ns.
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
using namespace aa::b^b;
|
|
|
|
int main() {
|
|
|
|
map m;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
aa::bb::map m;
|
|
|
|
}
|
|
|
|
)cpp"},
|
|
|
|
{// Nested namespace: Fully qualify ident from inner ns.
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
using namespace a^a;
|
|
|
|
int main() {
|
|
|
|
bb::map m;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
aa::bb::map m;
|
|
|
|
}
|
|
|
|
)cpp"},
|
|
|
|
{// Typedef.
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
using namespace a^a;
|
|
|
|
typedef bb::map map;
|
|
|
|
int main() { map M; }
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
|
|
|
|
typedef aa::bb::map map;
|
|
|
|
int main() { map M; }
|
|
|
|
)cpp"},
|
|
|
|
{// FIXME: Nested namespaces: Not aware of using ns decl of outer ns.
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
using name[[space aa::b]]b;
|
|
|
|
using namespace aa;
|
|
|
|
int main() {
|
|
|
|
map m;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
|
|
|
|
using namespace aa;
|
|
|
|
int main() {
|
|
|
|
aa::bb::map m;
|
|
|
|
}
|
|
|
|
)cpp"},
|
|
|
|
{// Does not qualify ident from inner namespace.
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
using namespace aa::bb;
|
|
|
|
using namespace a^a;
|
|
|
|
int main() {
|
|
|
|
map m;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace aa { namespace bb { struct map {}; }}
|
|
|
|
using namespace aa::bb;
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
map m;
|
|
|
|
}
|
|
|
|
)cpp"},
|
|
|
|
{// Available only for top level namespace decl.
|
|
|
|
R"cpp(
|
|
|
|
namespace aa {
|
|
|
|
namespace bb { struct map {}; }
|
|
|
|
using namespace b^b;
|
|
|
|
}
|
|
|
|
int main() { aa::map m; }
|
|
|
|
)cpp",
|
|
|
|
"unavailable"},
|
|
|
|
{// FIXME: Unavailable for namespaces containing using-namespace decl.
|
|
|
|
R"cpp(
|
|
|
|
namespace aa {
|
|
|
|
namespace bb { struct map {}; }
|
|
|
|
using namespace bb;
|
|
|
|
}
|
|
|
|
using namespace a^a;
|
|
|
|
int main() {
|
|
|
|
map m;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
"unavailable"},
|
|
|
|
{R"cpp(
|
|
|
|
namespace a::b { struct Foo {}; }
|
|
|
|
using namespace a;
|
|
|
|
using namespace a::[[b]];
|
|
|
|
using namespace b;
|
|
|
|
int main() { Foo F;}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace a::b { struct Foo {}; }
|
|
|
|
using namespace a;
|
|
|
|
|
|
|
|
|
|
|
|
int main() { a::b::Foo F;}
|
|
|
|
)cpp"},
|
|
|
|
{R"cpp(
|
|
|
|
namespace a::b { struct Foo {}; }
|
|
|
|
using namespace a;
|
|
|
|
using namespace a::b;
|
|
|
|
using namespace [[b]];
|
|
|
|
int main() { Foo F;}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace a::b { struct Foo {}; }
|
|
|
|
using namespace a;
|
|
|
|
|
|
|
|
|
|
|
|
int main() { b::Foo F;}
|
|
|
|
)cpp"},
|
|
|
|
{// Enumerators.
|
|
|
|
R"cpp(
|
|
|
|
namespace tokens {
|
|
|
|
enum Token {
|
|
|
|
comma, identifier, numeric
|
|
|
|
};
|
|
|
|
}
|
|
|
|
using namespace tok^ens;
|
|
|
|
int main() {
|
|
|
|
auto x = comma;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace tokens {
|
|
|
|
enum Token {
|
|
|
|
comma, identifier, numeric
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
auto x = tokens::comma;
|
|
|
|
}
|
|
|
|
)cpp"},
|
|
|
|
{// inline namespaces.
|
|
|
|
R"cpp(
|
|
|
|
namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}}
|
|
|
|
using namespace st^d;
|
|
|
|
int main() {
|
|
|
|
vector V;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace std { inline namespace ns1 { inline namespace ns2 { struct vector {}; }}}
|
|
|
|
|
|
|
|
int main() {
|
|
|
|
std::vector V;
|
|
|
|
}
|
|
|
|
)cpp"}};
|
|
|
|
for (auto C : Cases)
|
|
|
|
EXPECT_EQ(C.second, apply(C.first)) << C.first;
|
|
|
|
}
|
|
|
|
|
2019-10-28 14:21:04 +08:00
|
|
|
TWEAK_TEST(DefineInline);
|
|
|
|
TEST_F(DefineInlineTest, TriggersOnFunctionDecl) {
|
|
|
|
// Basic check for function body and signature.
|
|
|
|
EXPECT_AVAILABLE(R"cpp(
|
|
|
|
class Bar {
|
|
|
|
void baz();
|
|
|
|
};
|
|
|
|
|
|
|
|
[[void [[Bar::[[b^a^z]]]]() [[{
|
|
|
|
return;
|
|
|
|
}]]]]
|
|
|
|
|
|
|
|
void foo();
|
|
|
|
[[void [[f^o^o]]() [[{
|
|
|
|
return;
|
|
|
|
}]]]]
|
|
|
|
)cpp");
|
|
|
|
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
// Not a definition
|
|
|
|
vo^i[[d^ ^f]]^oo();
|
|
|
|
|
|
|
|
[[vo^id ]]foo[[()]] {[[
|
|
|
|
[[(void)(5+3);
|
|
|
|
return;]]
|
|
|
|
}]]
|
2019-11-12 02:00:44 +08:00
|
|
|
|
|
|
|
// Definition with no body.
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
class Bar { Bar() = def^ault; };
|
2019-10-28 14:21:04 +08:00
|
|
|
)cpp");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, NoForwardDecl) {
|
|
|
|
Header = "void bar();";
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
void bar() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// FIXME: Generate a decl in the header.
|
|
|
|
void fo^o() {
|
|
|
|
return;
|
|
|
|
})cpp");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, ReferencedDecls) {
|
|
|
|
EXPECT_AVAILABLE(R"cpp(
|
|
|
|
void bar();
|
|
|
|
void foo(int test);
|
|
|
|
|
|
|
|
void fo^o(int baz) {
|
|
|
|
int x = 10;
|
|
|
|
bar();
|
|
|
|
})cpp");
|
|
|
|
|
|
|
|
// Internal symbol usage.
|
|
|
|
Header = "void foo(int test);";
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
void bar();
|
|
|
|
void fo^o(int baz) {
|
|
|
|
int x = 10;
|
|
|
|
bar();
|
|
|
|
})cpp");
|
|
|
|
|
|
|
|
// Becomes available after making symbol visible.
|
|
|
|
Header = "void bar();" + Header;
|
|
|
|
EXPECT_AVAILABLE(R"cpp(
|
|
|
|
void fo^o(int baz) {
|
|
|
|
int x = 10;
|
|
|
|
bar();
|
|
|
|
})cpp");
|
|
|
|
|
|
|
|
// FIXME: Move declaration below bar to make it visible.
|
|
|
|
Header.clear();
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
void foo();
|
|
|
|
void bar();
|
|
|
|
|
|
|
|
void fo^o() {
|
|
|
|
bar();
|
|
|
|
})cpp");
|
|
|
|
|
|
|
|
// Order doesn't matter within a class.
|
|
|
|
EXPECT_AVAILABLE(R"cpp(
|
|
|
|
class Bar {
|
|
|
|
void foo();
|
|
|
|
void bar();
|
|
|
|
};
|
|
|
|
|
|
|
|
void Bar::fo^o() {
|
|
|
|
bar();
|
|
|
|
})cpp");
|
|
|
|
|
|
|
|
// FIXME: Perform include insertion to make symbol visible.
|
|
|
|
ExtraFiles["a.h"] = "void bar();";
|
|
|
|
Header = "void foo(int test);";
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
#include "a.h"
|
|
|
|
void fo^o(int baz) {
|
|
|
|
int x = 10;
|
|
|
|
bar();
|
|
|
|
})cpp");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TemplateSpec) {
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
template <typename T> void foo();
|
|
|
|
template<> void foo<char>();
|
|
|
|
|
|
|
|
template<> void f^oo<int>() {
|
|
|
|
})cpp");
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
template <typename T> void foo();
|
|
|
|
|
|
|
|
template<> void f^oo<int>() {
|
|
|
|
})cpp");
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
template <typename T> struct Foo { void foo(); };
|
|
|
|
|
|
|
|
template <typename T> void Foo<T>::f^oo() {
|
|
|
|
})cpp");
|
|
|
|
EXPECT_AVAILABLE(R"cpp(
|
|
|
|
template <typename T> void foo();
|
|
|
|
void bar();
|
|
|
|
template <> void foo<int>();
|
|
|
|
|
|
|
|
template<> void f^oo<int>() {
|
|
|
|
bar();
|
|
|
|
})cpp");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, CheckForCanonDecl) {
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
void foo();
|
|
|
|
|
|
|
|
void bar() {}
|
|
|
|
void f^oo() {
|
|
|
|
// This bar normally refers to the definition just above, but it is not
|
|
|
|
// visible from the forward declaration of foo.
|
|
|
|
bar();
|
|
|
|
})cpp");
|
|
|
|
// Make it available with a forward decl.
|
|
|
|
EXPECT_AVAILABLE(R"cpp(
|
|
|
|
void bar();
|
|
|
|
void foo();
|
|
|
|
|
|
|
|
void bar() {}
|
|
|
|
void f^oo() {
|
|
|
|
bar();
|
|
|
|
})cpp");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, UsingShadowDecls) {
|
|
|
|
// Template body is not parsed until instantiation time on windows, which
|
|
|
|
// results in arbitrary failures as function body becomes NULL.
|
|
|
|
ExtraArgs.push_back("-fno-delayed-template-parsing");
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
namespace ns1 { void foo(int); }
|
|
|
|
namespace ns2 { void foo(int*); }
|
|
|
|
template <typename T>
|
|
|
|
void bar();
|
|
|
|
|
|
|
|
using ns1::foo;
|
|
|
|
using ns2::foo;
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void b^ar() {
|
|
|
|
foo(T());
|
|
|
|
})cpp");
|
|
|
|
}
|
|
|
|
|
2019-09-06 15:49:40 +08:00
|
|
|
TEST_F(DefineInlineTest, TransformNestedNamespaces) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
void bar();
|
|
|
|
namespace b {
|
|
|
|
void baz();
|
|
|
|
namespace c {
|
|
|
|
void aux();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo();
|
|
|
|
using namespace a;
|
|
|
|
using namespace b;
|
|
|
|
using namespace c;
|
|
|
|
void f^oo() {
|
|
|
|
bar();
|
|
|
|
a::bar();
|
|
|
|
|
|
|
|
baz();
|
|
|
|
b::baz();
|
|
|
|
a::b::baz();
|
|
|
|
|
|
|
|
aux();
|
|
|
|
c::aux();
|
|
|
|
b::c::aux();
|
|
|
|
a::b::c::aux();
|
|
|
|
})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
void bar();
|
|
|
|
namespace b {
|
|
|
|
void baz();
|
|
|
|
namespace c {
|
|
|
|
void aux();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo(){
|
|
|
|
a::bar();
|
|
|
|
a::bar();
|
|
|
|
|
|
|
|
a::b::baz();
|
|
|
|
a::b::baz();
|
|
|
|
a::b::baz();
|
|
|
|
|
|
|
|
a::b::c::aux();
|
|
|
|
a::b::c::aux();
|
|
|
|
a::b::c::aux();
|
|
|
|
a::b::c::aux();
|
|
|
|
}
|
|
|
|
using namespace a;
|
|
|
|
using namespace b;
|
|
|
|
using namespace c;
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TransformUsings) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
namespace a { namespace b { namespace c { void aux(); } } }
|
|
|
|
|
|
|
|
void foo();
|
|
|
|
void f^oo() {
|
|
|
|
using namespace a;
|
|
|
|
using namespace b;
|
|
|
|
using namespace c;
|
|
|
|
using c::aux;
|
|
|
|
namespace d = c;
|
|
|
|
})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
namespace a { namespace b { namespace c { void aux(); } } }
|
|
|
|
|
|
|
|
void foo(){
|
|
|
|
using namespace a;
|
|
|
|
using namespace a::b;
|
|
|
|
using namespace a::b::c;
|
|
|
|
using a::b::c::aux;
|
|
|
|
namespace d = a::b::c;
|
|
|
|
}
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TransformDecls) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
void foo();
|
|
|
|
void f^oo() {
|
|
|
|
class Foo {
|
|
|
|
public:
|
|
|
|
void foo();
|
|
|
|
int x;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum En { Zero, One };
|
|
|
|
En x = Zero;
|
|
|
|
|
|
|
|
enum class EnClass { Zero, One };
|
|
|
|
EnClass y = EnClass::Zero;
|
|
|
|
})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
void foo(){
|
|
|
|
class Foo {
|
|
|
|
public:
|
|
|
|
void foo();
|
|
|
|
int x;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum En { Zero, One };
|
|
|
|
En x = Zero;
|
|
|
|
|
|
|
|
enum class EnClass { Zero, One };
|
|
|
|
EnClass y = EnClass::Zero;
|
|
|
|
}
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TransformTemplDecls) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
template <typename T> class Bar {
|
|
|
|
public:
|
|
|
|
void bar();
|
|
|
|
};
|
|
|
|
template <typename T> T bar;
|
|
|
|
template <typename T> void aux() {}
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo();
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
void f^oo() {
|
|
|
|
bar<Bar<int>>.bar();
|
|
|
|
aux<Bar<int>>();
|
|
|
|
})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
template <typename T> class Bar {
|
|
|
|
public:
|
|
|
|
void bar();
|
|
|
|
};
|
|
|
|
template <typename T> T bar;
|
|
|
|
template <typename T> void aux() {}
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo(){
|
|
|
|
a::bar<a::Bar<int>>.bar();
|
|
|
|
a::aux<a::Bar<int>>();
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TransformMembers) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
class Foo {
|
|
|
|
void foo();
|
|
|
|
};
|
|
|
|
|
|
|
|
void Foo::f^oo() {
|
|
|
|
return;
|
|
|
|
})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
class Foo {
|
|
|
|
void foo(){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
|
|
|
|
ExtraFiles["a.h"] = R"cpp(
|
|
|
|
class Foo {
|
|
|
|
void foo();
|
|
|
|
};)cpp";
|
|
|
|
|
|
|
|
llvm::StringMap<std::string> EditedFiles;
|
|
|
|
Test = R"cpp(
|
|
|
|
#include "a.h"
|
|
|
|
void Foo::f^oo() {
|
|
|
|
return;
|
|
|
|
})cpp";
|
|
|
|
Expected = R"cpp(
|
|
|
|
#include "a.h"
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test, &EditedFiles), Expected);
|
|
|
|
|
|
|
|
Expected = R"cpp(
|
|
|
|
class Foo {
|
|
|
|
void foo(){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};)cpp";
|
|
|
|
EXPECT_THAT(EditedFiles,
|
|
|
|
ElementsAre(FileWithContents(testPath("a.h"), Expected)));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TransformDependentTypes) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
template <typename T> class Bar {};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void foo();
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
template <typename T>
|
|
|
|
void f^oo() {
|
|
|
|
Bar<T> B;
|
|
|
|
Bar<Bar<T>> q;
|
|
|
|
})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
template <typename T> class Bar {};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void foo(){
|
|
|
|
a::Bar<T> B;
|
|
|
|
a::Bar<a::Bar<T>> q;
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
)cpp";
|
|
|
|
|
|
|
|
// Template body is not parsed until instantiation time on windows, which
|
|
|
|
// results in arbitrary failures as function body becomes NULL.
|
|
|
|
ExtraArgs.push_back("-fno-delayed-template-parsing");
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TransformFunctionTempls) {
|
|
|
|
// Check we select correct specialization decl.
|
|
|
|
std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
|
|
|
|
{R"cpp(
|
|
|
|
template <typename T>
|
|
|
|
void foo(T p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<int>(int p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<char>(char p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void fo^o<int>(int p) {
|
|
|
|
return;
|
|
|
|
})cpp",
|
|
|
|
R"cpp(
|
|
|
|
template <typename T>
|
|
|
|
void foo(T p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<int>(int p){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<char>(char p);
|
|
|
|
|
|
|
|
)cpp"},
|
|
|
|
{// Make sure we are not selecting the first specialization all the time.
|
|
|
|
R"cpp(
|
|
|
|
template <typename T>
|
|
|
|
void foo(T p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<int>(int p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<char>(char p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void fo^o<char>(char p) {
|
|
|
|
return;
|
|
|
|
})cpp",
|
|
|
|
R"cpp(
|
|
|
|
template <typename T>
|
|
|
|
void foo(T p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<int>(int p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<char>(char p){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
)cpp"},
|
|
|
|
{R"cpp(
|
|
|
|
template <typename T>
|
|
|
|
void foo(T p);
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<int>(int p);
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void fo^o(T p) {
|
|
|
|
return;
|
|
|
|
})cpp",
|
|
|
|
R"cpp(
|
|
|
|
template <typename T>
|
|
|
|
void foo(T p){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
void foo<int>(int p);
|
|
|
|
|
|
|
|
)cpp"},
|
|
|
|
};
|
|
|
|
// Template body is not parsed until instantiation time on windows, which
|
|
|
|
// results in arbitrary failures as function body becomes NULL.
|
|
|
|
ExtraArgs.push_back("-fno-delayed-template-parsing");
|
2019-10-14 18:02:24 +08:00
|
|
|
for (const auto &Case : Cases)
|
2019-09-06 15:49:40 +08:00
|
|
|
EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TransformTypeLocs) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
template <typename T> class Bar {
|
|
|
|
public:
|
|
|
|
template <typename Q> class Baz {};
|
|
|
|
};
|
|
|
|
class Foo{};
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo();
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
void f^oo() {
|
|
|
|
Bar<int> B;
|
|
|
|
Foo foo;
|
|
|
|
a::Bar<Bar<int>>::Baz<Bar<int>> q;
|
|
|
|
})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
template <typename T> class Bar {
|
|
|
|
public:
|
|
|
|
template <typename Q> class Baz {};
|
|
|
|
};
|
|
|
|
class Foo{};
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo(){
|
|
|
|
a::Bar<int> B;
|
|
|
|
a::Foo foo;
|
|
|
|
a::Bar<a::Bar<int>>::Baz<a::Bar<int>> q;
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TransformDeclRefs) {
|
2019-10-14 18:02:24 +08:00
|
|
|
auto Test = R"cpp(
|
2019-09-06 15:49:40 +08:00
|
|
|
namespace a {
|
|
|
|
template <typename T> class Bar {
|
|
|
|
public:
|
|
|
|
void foo();
|
|
|
|
static void bar();
|
|
|
|
int x;
|
|
|
|
static int y;
|
|
|
|
};
|
|
|
|
void bar();
|
|
|
|
void test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo();
|
|
|
|
using namespace a;
|
|
|
|
void f^oo() {
|
|
|
|
a::Bar<int> B;
|
|
|
|
B.foo();
|
|
|
|
a::bar();
|
|
|
|
Bar<Bar<int>>::bar();
|
|
|
|
a::Bar<int>::bar();
|
|
|
|
B.x = Bar<int>::y;
|
|
|
|
Bar<int>::y = 3;
|
|
|
|
bar();
|
|
|
|
a::test();
|
|
|
|
})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
template <typename T> class Bar {
|
|
|
|
public:
|
|
|
|
void foo();
|
|
|
|
static void bar();
|
|
|
|
int x;
|
|
|
|
static int y;
|
|
|
|
};
|
|
|
|
void bar();
|
|
|
|
void test();
|
|
|
|
}
|
|
|
|
|
|
|
|
void foo(){
|
|
|
|
a::Bar<int> B;
|
|
|
|
B.foo();
|
|
|
|
a::bar();
|
|
|
|
a::Bar<a::Bar<int>>::bar();
|
|
|
|
a::Bar<int>::bar();
|
|
|
|
B.x = a::Bar<int>::y;
|
|
|
|
a::Bar<int>::y = 3;
|
|
|
|
a::bar();
|
|
|
|
a::test();
|
|
|
|
}
|
|
|
|
using namespace a;
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, StaticMembers) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
namespace ns { class X { static void foo(); void bar(); }; }
|
|
|
|
void ns::X::b^ar() {
|
|
|
|
foo();
|
|
|
|
})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
namespace ns { class X { static void foo(); void bar(){
|
|
|
|
foo();
|
|
|
|
} }; }
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
2019-10-14 18:02:24 +08:00
|
|
|
TEST_F(DefineInlineTest, TransformParamNames) {
|
|
|
|
std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
|
|
|
|
{R"cpp(
|
|
|
|
void foo(int, bool b, int T\
|
|
|
|
est);
|
|
|
|
void ^foo(int f, bool x, int z) {})cpp",
|
|
|
|
R"cpp(
|
|
|
|
void foo(int f, bool x, int z){}
|
|
|
|
)cpp"},
|
|
|
|
{R"cpp(
|
|
|
|
#define PARAM int Z
|
|
|
|
void foo(PARAM);
|
|
|
|
|
|
|
|
void ^foo(int X) {})cpp",
|
|
|
|
"fail: Cant rename parameter inside macro body."},
|
|
|
|
{R"cpp(
|
|
|
|
#define TYPE int
|
|
|
|
#define PARAM TYPE Z
|
|
|
|
#define BODY(x) 5 * (x) + 2
|
|
|
|
template <int P>
|
|
|
|
void foo(PARAM, TYPE Q, TYPE, TYPE W = BODY(P));
|
|
|
|
template <int x>
|
|
|
|
void ^foo(int Z, int b, int c, int d) {})cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define TYPE int
|
|
|
|
#define PARAM TYPE Z
|
|
|
|
#define BODY(x) 5 * (x) + 2
|
|
|
|
template <int x>
|
|
|
|
void foo(PARAM, TYPE b, TYPE c, TYPE d = BODY(x)){}
|
|
|
|
)cpp"},
|
|
|
|
};
|
2019-10-31 20:22:20 +08:00
|
|
|
ExtraArgs.push_back("-fno-delayed-template-parsing");
|
2019-10-14 18:02:24 +08:00
|
|
|
for (const auto &Case : Cases)
|
|
|
|
EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TransformTemplParamNames) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
struct Foo {
|
|
|
|
struct Bar {
|
|
|
|
template <class, class X,
|
|
|
|
template<typename> class, template<typename> class Y,
|
|
|
|
int, int Z>
|
|
|
|
void foo(X, Y<X>, int W = 5 * Z + 2);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T, class U,
|
|
|
|
template<typename> class V, template<typename> class W,
|
|
|
|
int X, int Y>
|
|
|
|
void Foo::Bar::f^oo(U, W<U>, int Q) {})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
struct Foo {
|
|
|
|
struct Bar {
|
|
|
|
template <class T, class U,
|
|
|
|
template<typename> class V, template<typename> class W,
|
|
|
|
int X, int Y>
|
|
|
|
void foo(U, W<U>, int Q = 5 * Y + 2){}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
)cpp";
|
2019-10-31 20:22:20 +08:00
|
|
|
ExtraArgs.push_back("-fno-delayed-template-parsing");
|
2019-10-14 18:02:24 +08:00
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
2019-09-06 15:49:40 +08:00
|
|
|
TEST_F(DefineInlineTest, TransformInlineNamespaces) {
|
|
|
|
auto Test = R"cpp(
|
|
|
|
namespace a { inline namespace b { namespace { struct Foo{}; } } }
|
|
|
|
void foo();
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
void ^foo() {Foo foo;})cpp";
|
|
|
|
auto Expected = R"cpp(
|
|
|
|
namespace a { inline namespace b { namespace { struct Foo{}; } } }
|
|
|
|
void foo(){a::Foo foo;}
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, TokensBeforeSemicolon) {
|
|
|
|
std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
|
|
|
|
{R"cpp(
|
|
|
|
void foo() /*Comment -_-*/ /*Com 2*/ ;
|
|
|
|
void fo^o() { return ; })cpp",
|
|
|
|
R"cpp(
|
|
|
|
void foo() /*Comment -_-*/ /*Com 2*/ { return ; }
|
|
|
|
)cpp"},
|
|
|
|
|
|
|
|
{R"cpp(
|
|
|
|
void foo();
|
|
|
|
void fo^o() { return ; })cpp",
|
|
|
|
R"cpp(
|
|
|
|
void foo(){ return ; }
|
|
|
|
)cpp"},
|
|
|
|
|
|
|
|
{R"cpp(
|
|
|
|
#define SEMI ;
|
|
|
|
void foo() SEMI
|
|
|
|
void fo^o() { return ; })cpp",
|
|
|
|
"fail: Couldn't find semicolon for target declaration."},
|
|
|
|
};
|
2019-10-14 18:02:24 +08:00
|
|
|
for (const auto &Case : Cases)
|
2019-09-06 15:49:40 +08:00
|
|
|
EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, HandleMacros) {
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
#define BODY { return; }
|
|
|
|
void foo();
|
|
|
|
void f^oo()BODY)cpp");
|
|
|
|
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
#define BODY void foo(){ return; }
|
|
|
|
void foo();
|
|
|
|
[[BODY]])cpp");
|
|
|
|
|
|
|
|
std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
|
|
|
|
// We don't qualify declarations coming from macros.
|
|
|
|
{R"cpp(
|
|
|
|
#define BODY Foo
|
|
|
|
namespace a { class Foo{}; }
|
|
|
|
void foo();
|
|
|
|
using namespace a;
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
void f^oo(){BODY();})cpp",
|
2019-09-06 15:49:40 +08:00
|
|
|
R"cpp(
|
|
|
|
#define BODY Foo
|
|
|
|
namespace a { class Foo{}; }
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
void foo(){BODY();}
|
2019-09-06 15:49:40 +08:00
|
|
|
using namespace a;
|
|
|
|
)cpp"},
|
|
|
|
|
|
|
|
// Macro is not visible at declaration location, but we proceed.
|
|
|
|
{R"cpp(
|
|
|
|
void foo();
|
|
|
|
#define BODY return;
|
|
|
|
void f^oo(){BODY})cpp",
|
|
|
|
R"cpp(
|
|
|
|
void foo(){BODY}
|
|
|
|
#define BODY return;
|
|
|
|
)cpp"},
|
|
|
|
|
|
|
|
{R"cpp(
|
|
|
|
#define TARGET void foo()
|
|
|
|
TARGET;
|
|
|
|
void f^oo(){ return; })cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define TARGET void foo()
|
|
|
|
TARGET{ return; }
|
|
|
|
)cpp"},
|
|
|
|
|
|
|
|
{R"cpp(
|
|
|
|
#define TARGET foo
|
|
|
|
void TARGET();
|
|
|
|
void f^oo(){ return; })cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define TARGET foo
|
|
|
|
void TARGET(){ return; }
|
|
|
|
)cpp"},
|
|
|
|
};
|
2019-10-14 18:02:24 +08:00
|
|
|
for (const auto &Case : Cases)
|
2019-09-06 15:49:40 +08:00
|
|
|
EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
|
|
|
|
}
|
|
|
|
|
2019-10-01 16:58:35 +08:00
|
|
|
TEST_F(DefineInlineTest, DropCommonNameSpecifiers) {
|
|
|
|
struct {
|
|
|
|
llvm::StringRef Test;
|
|
|
|
llvm::StringRef Expected;
|
|
|
|
} Cases[] = {
|
|
|
|
{R"cpp(
|
|
|
|
namespace a { namespace b { void aux(); } }
|
|
|
|
namespace ns1 {
|
|
|
|
void foo();
|
|
|
|
namespace qq { void test(); }
|
|
|
|
namespace ns2 {
|
|
|
|
void bar();
|
|
|
|
namespace ns3 { void baz(); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
using namespace a::b;
|
|
|
|
using namespace ns1::qq;
|
|
|
|
void ns1::ns2::ns3::b^az() {
|
|
|
|
foo();
|
|
|
|
bar();
|
|
|
|
baz();
|
|
|
|
ns1::ns2::ns3::baz();
|
|
|
|
aux();
|
|
|
|
test();
|
|
|
|
})cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace a { namespace b { void aux(); } }
|
|
|
|
namespace ns1 {
|
|
|
|
void foo();
|
|
|
|
namespace qq { void test(); }
|
|
|
|
namespace ns2 {
|
|
|
|
void bar();
|
|
|
|
namespace ns3 { void baz(){
|
|
|
|
foo();
|
|
|
|
bar();
|
|
|
|
baz();
|
|
|
|
ns1::ns2::ns3::baz();
|
|
|
|
a::b::aux();
|
|
|
|
qq::test();
|
|
|
|
} }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace a;
|
|
|
|
using namespace a::b;
|
|
|
|
using namespace ns1::qq;
|
|
|
|
)cpp"},
|
|
|
|
{R"cpp(
|
|
|
|
namespace ns1 {
|
|
|
|
namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; }
|
|
|
|
namespace ns2 { void baz(); }
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace ns1::qq;
|
|
|
|
void ns1::ns2::b^az() { Foo f; B b; })cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace ns1 {
|
|
|
|
namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; }
|
|
|
|
namespace ns2 { void baz(){ qq::Foo f; qq::B b; } }
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace ns1::qq;
|
|
|
|
)cpp"},
|
|
|
|
{R"cpp(
|
|
|
|
namespace ns1 {
|
|
|
|
namespace qq {
|
|
|
|
template<class T> struct Foo { template <class U> struct Bar {}; };
|
|
|
|
template<class T, class U>
|
|
|
|
using B = typename Foo<T>::template Bar<U>;
|
|
|
|
}
|
|
|
|
namespace ns2 { void baz(); }
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace ns1::qq;
|
|
|
|
void ns1::ns2::b^az() { B<int, bool> b; })cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace ns1 {
|
|
|
|
namespace qq {
|
|
|
|
template<class T> struct Foo { template <class U> struct Bar {}; };
|
|
|
|
template<class T, class U>
|
|
|
|
using B = typename Foo<T>::template Bar<U>;
|
|
|
|
}
|
|
|
|
namespace ns2 { void baz(){ qq::B<int, bool> b; } }
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace ns1::qq;
|
|
|
|
)cpp"},
|
|
|
|
};
|
|
|
|
for (const auto &Case : Cases)
|
|
|
|
EXPECT_EQ(apply(Case.Test), Case.Expected) << Case.Test;
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineInlineTest, QualifyWithUsingDirectives) {
|
|
|
|
llvm::StringRef Test = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
void bar();
|
|
|
|
namespace b { struct Foo{}; void aux(); }
|
|
|
|
namespace c { void cux(); }
|
|
|
|
}
|
|
|
|
using namespace a;
|
|
|
|
using X = b::Foo;
|
|
|
|
void foo();
|
|
|
|
|
|
|
|
using namespace b;
|
|
|
|
using namespace c;
|
|
|
|
void ^foo() {
|
|
|
|
cux();
|
|
|
|
bar();
|
|
|
|
X x;
|
|
|
|
aux();
|
|
|
|
using namespace c;
|
|
|
|
// FIXME: The last reference to cux() in body of foo should not be
|
|
|
|
// qualified, since there is a using directive inside the function body.
|
|
|
|
cux();
|
|
|
|
})cpp";
|
|
|
|
llvm::StringRef Expected = R"cpp(
|
|
|
|
namespace a {
|
|
|
|
void bar();
|
|
|
|
namespace b { struct Foo{}; void aux(); }
|
|
|
|
namespace c { void cux(); }
|
|
|
|
}
|
|
|
|
using namespace a;
|
|
|
|
using X = b::Foo;
|
|
|
|
void foo(){
|
|
|
|
c::cux();
|
|
|
|
bar();
|
|
|
|
X x;
|
|
|
|
b::aux();
|
|
|
|
using namespace c;
|
|
|
|
// FIXME: The last reference to cux() in body of foo should not be
|
|
|
|
// qualified, since there is a using directive inside the function body.
|
|
|
|
c::cux();
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace b;
|
|
|
|
using namespace c;
|
|
|
|
)cpp";
|
|
|
|
EXPECT_EQ(apply(Test), Expected) << Test;
|
|
|
|
}
|
|
|
|
|
2019-10-01 16:39:14 +08:00
|
|
|
TEST_F(DefineInlineTest, AddInline) {
|
2019-12-13 17:29:39 +08:00
|
|
|
ExtraArgs.push_back("-fno-delayed-template-parsing");
|
2019-10-01 16:39:14 +08:00
|
|
|
llvm::StringMap<std::string> EditedFiles;
|
|
|
|
ExtraFiles["a.h"] = "void foo();";
|
|
|
|
apply(R"cpp(#include "a.h"
|
2019-12-13 17:29:39 +08:00
|
|
|
void fo^o() {})cpp",
|
|
|
|
&EditedFiles);
|
2019-10-01 16:39:14 +08:00
|
|
|
EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
|
|
|
|
testPath("a.h"), "inline void foo(){}")));
|
|
|
|
|
|
|
|
// Check we put inline before cv-qualifiers.
|
|
|
|
ExtraFiles["a.h"] = "const int foo();";
|
|
|
|
apply(R"cpp(#include "a.h"
|
2019-12-13 17:29:39 +08:00
|
|
|
const int fo^o() {})cpp",
|
|
|
|
&EditedFiles);
|
2019-10-01 16:39:14 +08:00
|
|
|
EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
|
|
|
|
testPath("a.h"), "inline const int foo(){}")));
|
|
|
|
|
|
|
|
// No double inline.
|
|
|
|
ExtraFiles["a.h"] = "inline void foo();";
|
|
|
|
apply(R"cpp(#include "a.h"
|
2019-12-13 17:29:39 +08:00
|
|
|
inline void fo^o() {})cpp",
|
|
|
|
&EditedFiles);
|
2019-10-01 16:39:14 +08:00
|
|
|
EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
|
|
|
|
testPath("a.h"), "inline void foo(){}")));
|
|
|
|
|
|
|
|
// Constexprs don't need "inline".
|
|
|
|
ExtraFiles["a.h"] = "constexpr void foo();";
|
|
|
|
apply(R"cpp(#include "a.h"
|
2019-12-13 17:29:39 +08:00
|
|
|
constexpr void fo^o() {})cpp",
|
|
|
|
&EditedFiles);
|
2019-10-01 16:39:14 +08:00
|
|
|
EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
|
|
|
|
testPath("a.h"), "constexpr void foo(){}")));
|
|
|
|
|
|
|
|
// Class members don't need "inline".
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
ExtraFiles["a.h"] = "struct Foo { void foo(); };";
|
2019-10-01 16:39:14 +08:00
|
|
|
apply(R"cpp(#include "a.h"
|
2019-12-13 17:29:39 +08:00
|
|
|
void Foo::fo^o() {})cpp",
|
|
|
|
&EditedFiles);
|
2019-10-01 16:39:14 +08:00
|
|
|
EXPECT_THAT(EditedFiles,
|
|
|
|
testing::ElementsAre(FileWithContents(
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
testPath("a.h"), "struct Foo { void foo(){} };")));
|
2019-10-01 16:39:14 +08:00
|
|
|
|
|
|
|
// Function template doesn't need to be "inline"d.
|
|
|
|
ExtraFiles["a.h"] = "template <typename T> void foo();";
|
|
|
|
apply(R"cpp(#include "a.h"
|
|
|
|
template <typename T>
|
2019-12-13 17:29:39 +08:00
|
|
|
void fo^o() {})cpp",
|
|
|
|
&EditedFiles);
|
2019-10-01 16:39:14 +08:00
|
|
|
EXPECT_THAT(EditedFiles,
|
|
|
|
testing::ElementsAre(FileWithContents(
|
|
|
|
testPath("a.h"), "template <typename T> void foo(){}")));
|
|
|
|
|
|
|
|
// Specializations needs to be marked "inline".
|
|
|
|
ExtraFiles["a.h"] = R"cpp(
|
|
|
|
template <typename T> void foo();
|
|
|
|
template <> void foo<int>();)cpp";
|
|
|
|
apply(R"cpp(#include "a.h"
|
|
|
|
template <>
|
2019-12-13 17:29:39 +08:00
|
|
|
void fo^o<int>() {})cpp",
|
|
|
|
&EditedFiles);
|
2019-10-01 16:39:14 +08:00
|
|
|
EXPECT_THAT(EditedFiles,
|
|
|
|
testing::ElementsAre(FileWithContents(testPath("a.h"),
|
|
|
|
R"cpp(
|
|
|
|
template <typename T> void foo();
|
|
|
|
template <> inline void foo<int>(){})cpp")));
|
|
|
|
}
|
|
|
|
|
2019-10-22 00:03:38 +08:00
|
|
|
TWEAK_TEST(DefineOutline);
|
|
|
|
TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) {
|
|
|
|
FileName = "Test.cpp";
|
|
|
|
// Not available unless in a header file.
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
[[void [[f^o^o]]() [[{
|
|
|
|
return;
|
|
|
|
}]]]])cpp");
|
|
|
|
|
|
|
|
FileName = "Test.hpp";
|
|
|
|
// Not available unless function name or fully body is selected.
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
// Not a definition
|
|
|
|
vo^i[[d^ ^f]]^oo();
|
|
|
|
|
|
|
|
[[vo^id ]]foo[[()]] {[[
|
|
|
|
[[(void)(5+3);
|
|
|
|
return;]]
|
|
|
|
}]])cpp");
|
|
|
|
|
|
|
|
// Available even if there are no implementation files.
|
|
|
|
EXPECT_AVAILABLE(R"cpp(
|
|
|
|
[[void [[f^o^o]]() [[{
|
|
|
|
return;
|
|
|
|
}]]]])cpp");
|
|
|
|
|
|
|
|
// Not available for out-of-line methods.
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
class Bar {
|
|
|
|
void baz();
|
|
|
|
};
|
|
|
|
|
|
|
|
[[void [[Bar::[[b^a^z]]]]() [[{
|
|
|
|
return;
|
|
|
|
}]]]])cpp");
|
|
|
|
|
|
|
|
// Basic check for function body and signature.
|
|
|
|
EXPECT_AVAILABLE(R"cpp(
|
|
|
|
class Bar {
|
2020-02-24 03:03:00 +08:00
|
|
|
[[void [[f^o^o^]]() [[{ return; }]]]]
|
2019-10-22 00:03:38 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
void foo();
|
|
|
|
[[void [[f^o^o]]() [[{
|
|
|
|
return;
|
|
|
|
}]]]])cpp");
|
|
|
|
|
|
|
|
// Not available on defaulted/deleted members.
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
class Foo {
|
|
|
|
Fo^o() = default;
|
|
|
|
F^oo(const Foo&) = delete;
|
|
|
|
};)cpp");
|
|
|
|
|
|
|
|
// Not available within templated classes, as it is hard to spell class name
|
|
|
|
// out-of-line in such cases.
|
|
|
|
EXPECT_UNAVAILABLE(R"cpp(
|
|
|
|
template <typename> struct Foo { void fo^o(){} };
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
)cpp");
|
2019-10-22 00:03:38 +08:00
|
|
|
}
|
|
|
|
|
2019-10-22 00:16:40 +08:00
|
|
|
TEST_F(DefineOutlineTest, FailsWithoutSource) {
|
|
|
|
FileName = "Test.hpp";
|
|
|
|
llvm::StringRef Test = "void fo^o() { return; }";
|
|
|
|
llvm::StringRef Expected =
|
|
|
|
"fail: Couldn't find a suitable implementation file.";
|
|
|
|
EXPECT_EQ(apply(Test), Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineOutlineTest, ApplyTest) {
|
|
|
|
llvm::StringMap<std::string> EditedFiles;
|
|
|
|
ExtraFiles["Test.cpp"] = "";
|
|
|
|
FileName = "Test.hpp";
|
2019-12-04 19:19:08 +08:00
|
|
|
// Template body is not parsed until instantiation time on windows, which
|
|
|
|
// results in arbitrary failures as function body becomes NULL.
|
|
|
|
ExtraArgs.push_back("-fno-delayed-template-parsing");
|
2019-10-22 00:16:40 +08:00
|
|
|
|
|
|
|
struct {
|
|
|
|
llvm::StringRef Test;
|
|
|
|
llvm::StringRef ExpectedHeader;
|
|
|
|
llvm::StringRef ExpectedSource;
|
|
|
|
} Cases[] = {
|
|
|
|
// Simple check
|
|
|
|
{
|
|
|
|
"void fo^o() { return; }",
|
|
|
|
"void foo() ;",
|
|
|
|
"void foo() { return; }",
|
|
|
|
},
|
|
|
|
// Templated function.
|
|
|
|
{
|
|
|
|
"template <typename T> void fo^o(T, T x) { return; }",
|
|
|
|
"template <typename T> void foo(T, T x) ;",
|
|
|
|
"template <typename T> void foo(T, T x) { return; }",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"template <typename> void fo^o() { return; }",
|
|
|
|
"template <typename> void foo() ;",
|
|
|
|
"template <typename> void foo() { return; }",
|
|
|
|
},
|
|
|
|
// Template specialization.
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
template <typename> void foo();
|
|
|
|
template <> void fo^o<int>() { return; })cpp",
|
|
|
|
R"cpp(
|
|
|
|
template <typename> void foo();
|
|
|
|
template <> void foo<int>() ;)cpp",
|
|
|
|
"template <> void foo<int>() { return; }",
|
|
|
|
},
|
2019-12-09 17:38:36 +08:00
|
|
|
// Default args.
|
|
|
|
{
|
|
|
|
"void fo^o(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) {}",
|
|
|
|
"void foo(int x, int y = 5, int = 2, int (*foo)(int) = nullptr) ;",
|
|
|
|
"void foo(int x, int y , int , int (*foo)(int) ) {}",
|
|
|
|
},
|
2019-12-09 18:54:21 +08:00
|
|
|
// Ctor initializers.
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
class Foo {
|
|
|
|
int y = 2;
|
|
|
|
F^oo(int z) __attribute__((weak)) : bar(2){}
|
|
|
|
int bar;
|
|
|
|
int z = 2;
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(
|
|
|
|
class Foo {
|
|
|
|
int y = 2;
|
|
|
|
Foo(int z) __attribute__((weak)) ;
|
|
|
|
int bar;
|
|
|
|
int z = 2;
|
|
|
|
};)cpp",
|
|
|
|
"Foo::Foo(int z) __attribute__((weak)) : bar(2){}\n",
|
|
|
|
},
|
2020-03-03 17:58:14 +08:00
|
|
|
// Virt specifiers.
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void f^oo() {}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() ;
|
|
|
|
};)cpp",
|
|
|
|
" void A::foo() {}\n",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual virtual void virtual f^oo() {}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual virtual void virtual foo() ;
|
|
|
|
};)cpp",
|
|
|
|
" void A::foo() {}\n",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() = 0;
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void fo^o() override {}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() = 0;
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void foo() override ;
|
|
|
|
};)cpp",
|
|
|
|
"void B::foo() {}\n",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() = 0;
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void fo^o() final {}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() = 0;
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void foo() final ;
|
|
|
|
};)cpp",
|
|
|
|
"void B::foo() {}\n",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() = 0;
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void fo^o() final override {}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() = 0;
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void foo() final override ;
|
|
|
|
};)cpp",
|
|
|
|
"void B::foo() {}\n",
|
|
|
|
},
|
2019-10-22 00:16:40 +08:00
|
|
|
};
|
|
|
|
for (const auto &Case : Cases) {
|
|
|
|
SCOPED_TRACE(Case.Test);
|
|
|
|
EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
|
|
|
|
EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
|
|
|
|
testPath("Test.cpp"), Case.ExpectedSource)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(DefineOutlineTest, HandleMacros) {
|
|
|
|
llvm::StringMap<std::string> EditedFiles;
|
|
|
|
ExtraFiles["Test.cpp"] = "";
|
|
|
|
FileName = "Test.hpp";
|
2020-03-03 17:58:14 +08:00
|
|
|
ExtraArgs.push_back("-DVIRTUAL=virtual");
|
|
|
|
ExtraArgs.push_back("-DOVER=override");
|
2019-10-22 00:16:40 +08:00
|
|
|
|
|
|
|
struct {
|
|
|
|
llvm::StringRef Test;
|
|
|
|
llvm::StringRef ExpectedHeader;
|
|
|
|
llvm::StringRef ExpectedSource;
|
|
|
|
} Cases[] = {
|
|
|
|
{R"cpp(
|
|
|
|
#define BODY { return; }
|
|
|
|
void f^oo()BODY)cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define BODY { return; }
|
|
|
|
void foo();)cpp",
|
|
|
|
"void foo()BODY"},
|
|
|
|
|
|
|
|
{R"cpp(
|
|
|
|
#define BODY return;
|
|
|
|
void f^oo(){BODY})cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define BODY return;
|
|
|
|
void foo();)cpp",
|
|
|
|
"void foo(){BODY}"},
|
|
|
|
|
|
|
|
{R"cpp(
|
|
|
|
#define TARGET void foo()
|
|
|
|
[[TARGET]]{ return; })cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define TARGET void foo()
|
|
|
|
TARGET;)cpp",
|
|
|
|
"TARGET{ return; }"},
|
|
|
|
|
|
|
|
{R"cpp(
|
|
|
|
#define TARGET foo
|
|
|
|
void [[TARGET]](){ return; })cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define TARGET foo
|
|
|
|
void TARGET();)cpp",
|
|
|
|
"void TARGET(){ return; }"},
|
2020-03-03 17:58:14 +08:00
|
|
|
{R"cpp(#define VIRT virtual
|
|
|
|
struct A {
|
|
|
|
VIRT void f^oo() {}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(#define VIRT virtual
|
|
|
|
struct A {
|
|
|
|
VIRT void foo() ;
|
|
|
|
};)cpp",
|
|
|
|
" void A::foo() {}\n"},
|
|
|
|
{R"cpp(
|
|
|
|
struct A {
|
|
|
|
VIRTUAL void f^oo() {}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
VIRTUAL void foo() ;
|
|
|
|
};)cpp",
|
|
|
|
" void A::foo() {}\n"},
|
|
|
|
{R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() = 0;
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void fo^o() OVER {}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() = 0;
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void foo() OVER ;
|
|
|
|
};)cpp",
|
|
|
|
"void B::foo() {}\n"},
|
|
|
|
{R"cpp(#define STUPID_MACRO(X) virtual
|
|
|
|
struct A {
|
|
|
|
STUPID_MACRO(sizeof sizeof int) void f^oo() {}
|
|
|
|
};)cpp",
|
|
|
|
R"cpp(#define STUPID_MACRO(X) virtual
|
|
|
|
struct A {
|
|
|
|
STUPID_MACRO(sizeof sizeof int) void foo() ;
|
|
|
|
};)cpp",
|
|
|
|
" void A::foo() {}\n"},
|
2019-10-22 00:16:40 +08:00
|
|
|
};
|
|
|
|
for (const auto &Case : Cases) {
|
|
|
|
SCOPED_TRACE(Case.Test);
|
|
|
|
EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
|
|
|
|
EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
|
|
|
|
testPath("Test.cpp"), Case.ExpectedSource)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-22 23:02:29 +08:00
|
|
|
TEST_F(DefineOutlineTest, QualifyReturnValue) {
|
|
|
|
FileName = "Test.hpp";
|
|
|
|
ExtraFiles["Test.cpp"] = "";
|
|
|
|
|
|
|
|
struct {
|
|
|
|
llvm::StringRef Test;
|
|
|
|
llvm::StringRef ExpectedHeader;
|
|
|
|
llvm::StringRef ExpectedSource;
|
|
|
|
} Cases[] = {
|
|
|
|
{R"cpp(
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
namespace a { class Foo{}; }
|
2019-10-22 23:02:29 +08:00
|
|
|
using namespace a;
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
Foo fo^o() { return {}; })cpp",
|
2019-10-22 23:02:29 +08:00
|
|
|
R"cpp(
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
namespace a { class Foo{}; }
|
2019-10-22 23:02:29 +08:00
|
|
|
using namespace a;
|
|
|
|
Foo foo() ;)cpp",
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
"a::Foo foo() { return {}; }"},
|
2019-10-22 23:02:29 +08:00
|
|
|
{R"cpp(
|
|
|
|
namespace a {
|
|
|
|
class Foo {
|
|
|
|
class Bar {};
|
|
|
|
Bar fo^o() { return {}; }
|
|
|
|
};
|
|
|
|
})cpp",
|
|
|
|
R"cpp(
|
|
|
|
namespace a {
|
|
|
|
class Foo {
|
|
|
|
class Bar {};
|
|
|
|
Bar foo() ;
|
|
|
|
};
|
|
|
|
})cpp",
|
2019-11-22 20:56:02 +08:00
|
|
|
"a::Foo::Bar a::Foo::foo() { return {}; }\n"},
|
2019-10-22 23:02:29 +08:00
|
|
|
{R"cpp(
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
class Foo {};
|
|
|
|
Foo fo^o() { return {}; })cpp",
|
2019-10-22 23:02:29 +08:00
|
|
|
R"cpp(
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
class Foo {};
|
2019-10-22 23:02:29 +08:00
|
|
|
Foo foo() ;)cpp",
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
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
2020-01-22 23:38:41 +08:00
|
|
|
"Foo foo() { return {}; }"},
|
2019-10-22 23:02:29 +08:00
|
|
|
};
|
|
|
|
llvm::StringMap<std::string> EditedFiles;
|
|
|
|
for (auto &Case : Cases) {
|
|
|
|
apply(Case.Test, &EditedFiles);
|
|
|
|
EXPECT_EQ(apply(Case.Test, &EditedFiles), Case.ExpectedHeader);
|
|
|
|
EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
|
|
|
|
testPath("Test.cpp"), Case.ExpectedSource)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-22 20:56:02 +08:00
|
|
|
TEST_F(DefineOutlineTest, QualifyFunctionName) {
|
|
|
|
FileName = "Test.hpp";
|
|
|
|
struct {
|
|
|
|
llvm::StringRef TestHeader;
|
|
|
|
llvm::StringRef TestSource;
|
|
|
|
llvm::StringRef ExpectedHeader;
|
|
|
|
llvm::StringRef ExpectedSource;
|
|
|
|
} Cases[] = {
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
namespace a {
|
|
|
|
namespace b {
|
|
|
|
class Foo {
|
|
|
|
void fo^o() {}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
})cpp",
|
|
|
|
"",
|
|
|
|
R"cpp(
|
|
|
|
namespace a {
|
|
|
|
namespace b {
|
|
|
|
class Foo {
|
|
|
|
void foo() ;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
})cpp",
|
|
|
|
"void a::b::Foo::foo() {}\n",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"namespace a { namespace b { void f^oo() {} } }",
|
|
|
|
"namespace a{}",
|
|
|
|
"namespace a { namespace b { void foo() ; } }",
|
|
|
|
"namespace a{void b::foo() {} }",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"namespace a { namespace b { void f^oo() {} } }",
|
|
|
|
"using namespace a;",
|
|
|
|
"namespace a { namespace b { void foo() ; } }",
|
|
|
|
// FIXME: Take using namespace directives in the source file into
|
|
|
|
// account. This can be spelled as b::foo instead.
|
|
|
|
"using namespace a;void a::b::foo() {} ",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
llvm::StringMap<std::string> EditedFiles;
|
|
|
|
for (auto &Case : Cases) {
|
2020-01-29 03:23:46 +08:00
|
|
|
ExtraFiles["Test.cpp"] = std::string(Case.TestSource);
|
2019-11-22 20:56:02 +08:00
|
|
|
EXPECT_EQ(apply(Case.TestHeader, &EditedFiles), Case.ExpectedHeader);
|
|
|
|
EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
|
|
|
|
testPath("Test.cpp"), Case.ExpectedSource)))
|
|
|
|
<< Case.TestHeader;
|
|
|
|
}
|
|
|
|
}
|
2020-03-03 17:58:14 +08:00
|
|
|
|
|
|
|
TEST_F(DefineOutlineTest, FailsMacroSpecifier) {
|
|
|
|
FileName = "Test.hpp";
|
|
|
|
ExtraFiles["Test.cpp"] = "";
|
|
|
|
ExtraArgs.push_back("-DFINALOVER=final override");
|
|
|
|
|
|
|
|
std::pair<StringRef, StringRef> Cases[] = {
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
#define VIRT virtual void
|
|
|
|
struct A {
|
|
|
|
VIRT fo^o() {}
|
|
|
|
};)cpp",
|
|
|
|
"fail: define outline: Can't move out of line as function has a "
|
|
|
|
"macro `virtual` specifier."},
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
#define OVERFINAL final override
|
|
|
|
struct A {
|
|
|
|
virtual void foo() {}
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void fo^o() OVERFINAL {}
|
|
|
|
};)cpp",
|
|
|
|
"fail: define outline: Can't move out of line as function has a "
|
|
|
|
"macro `override` specifier.\ndefine outline: Can't move out of line "
|
|
|
|
"as function has a macro `final` specifier."},
|
|
|
|
{
|
|
|
|
R"cpp(
|
|
|
|
struct A {
|
|
|
|
virtual void foo() {}
|
|
|
|
};
|
|
|
|
struct B : A {
|
|
|
|
void fo^o() FINALOVER {}
|
|
|
|
};)cpp",
|
|
|
|
"fail: define outline: Can't move out of line as function has a "
|
|
|
|
"macro `override` specifier.\ndefine outline: Can't move out of line "
|
|
|
|
"as function has a macro `final` specifier."},
|
|
|
|
};
|
|
|
|
for (const auto &Case : Cases) {
|
|
|
|
EXPECT_EQ(apply(Case.first), Case.second);
|
|
|
|
}
|
|
|
|
}
|
2019-02-01 05:30:05 +08:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|