2019-11-07 19:14:38 +08:00
|
|
|
//===-- CollectMacrosTests.cpp ----------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Annotations.h"
|
|
|
|
#include "CollectMacros.h"
|
|
|
|
#include "Matchers.h"
|
|
|
|
#include "SourceCode.h"
|
|
|
|
#include "TestTU.h"
|
|
|
|
#include "index/SymbolID.h"
|
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
|
|
#include "llvm/Support/ScopedPrinter.h"
|
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
using testing::UnorderedElementsAreArray;
|
|
|
|
|
|
|
|
TEST(CollectMainFileMacros, SelectedMacros) {
|
|
|
|
// References of the same symbol must have the ranges with the same
|
|
|
|
// name(integer). If there are N different symbols then they must be named
|
|
|
|
// from 1 to N. Macros for which SymbolID cannot be computed must be named
|
|
|
|
// "Unknown".
|
|
|
|
const char *Tests[] = {
|
|
|
|
R"cpp(// Macros: Cursor on definition.
|
|
|
|
#define $1[[FOO]](x,y) (x + y)
|
|
|
|
int main() { int x = $1[[FOO]]($1[[FOO]](3, 4), $1[[FOO]](5, 6)); }
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
#define $1[[M]](X) X;
|
|
|
|
#define $2[[abc]] 123
|
|
|
|
int s = $1[[M]]($2[[abc]]);
|
|
|
|
)cpp",
|
|
|
|
// FIXME: Locating macro in duplicate definitions doesn't work. Enable
|
|
|
|
// this once LocateMacro is fixed.
|
|
|
|
// R"cpp(// Multiple definitions.
|
|
|
|
// #define $1[[abc]] 1
|
|
|
|
// int func1() { int a = $1[[abc]];}
|
|
|
|
// #undef $1[[abc]]
|
|
|
|
|
|
|
|
// #define $2[[abc]] 2
|
|
|
|
// int func2() { int a = $2[[abc]];}
|
|
|
|
// #undef $2[[abc]]
|
|
|
|
// )cpp",
|
|
|
|
R"cpp(
|
|
|
|
#ifdef $Unknown[[UNDEFINED]]
|
|
|
|
#endif
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
#ifndef $Unknown[[abc]]
|
|
|
|
#define $1[[abc]]
|
|
|
|
#ifdef $1[[abc]]
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
// Macros from token concatenations not included.
|
|
|
|
#define $1[[CONCAT]](X) X##A()
|
|
|
|
#define $2[[PREPEND]](X) MACRO##X()
|
|
|
|
#define $3[[MACROA]]() 123
|
|
|
|
int B = $1[[CONCAT]](MACRO);
|
[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
|
|
|
int D = $2[[PREPEND]](A);
|
2019-11-07 19:14:38 +08:00
|
|
|
)cpp",
|
|
|
|
R"cpp(
|
|
|
|
// FIXME: Macro names in a definition are not detected.
|
|
|
|
#define $1[[MACRO_ARGS2]](X, Y) X Y
|
|
|
|
#define $2[[FOO]] BAR
|
|
|
|
#define $3[[BAR]] 1
|
|
|
|
int A = $2[[FOO]];
|
|
|
|
)cpp"};
|
|
|
|
for (const char *Test : Tests) {
|
|
|
|
Annotations T(Test);
|
|
|
|
auto AST = TestTU::withCode(T.code()).build();
|
|
|
|
auto ActualMacroRefs = AST.getMacros();
|
|
|
|
auto &SM = AST.getSourceManager();
|
|
|
|
auto &PP = AST.getPreprocessor();
|
|
|
|
|
|
|
|
// Known macros.
|
|
|
|
for (int I = 1;; I++) {
|
|
|
|
const auto ExpectedRefs = T.ranges(llvm::to_string(I));
|
|
|
|
if (ExpectedRefs.empty())
|
|
|
|
break;
|
|
|
|
|
2020-02-26 22:23:40 +08:00
|
|
|
auto Loc = sourceLocationInMainFile(SM, ExpectedRefs.begin()->start);
|
|
|
|
ASSERT_TRUE(bool(Loc));
|
2020-02-28 16:25:40 +08:00
|
|
|
const auto *Id = syntax::spelledIdentifierTouching(*Loc, AST.getTokens());
|
|
|
|
ASSERT_TRUE(Id);
|
|
|
|
auto Macro = locateMacroAt(*Id, PP);
|
2019-11-07 19:14:38 +08:00
|
|
|
assert(Macro);
|
|
|
|
auto SID = getSymbolID(Macro->Name, Macro->Info, SM);
|
|
|
|
|
|
|
|
EXPECT_THAT(ExpectedRefs,
|
|
|
|
UnorderedElementsAreArray(ActualMacroRefs.MacroRefs[*SID]))
|
|
|
|
<< "Annotation=" << I << ", MacroName=" << Macro->Name
|
|
|
|
<< ", Test = " << Test;
|
|
|
|
}
|
|
|
|
// Unkown macros.
|
|
|
|
EXPECT_THAT(AST.getMacros().UnknownMacros,
|
|
|
|
UnorderedElementsAreArray(T.ranges("Unknown")))
|
|
|
|
<< "Unknown macros doesn't match in " << Test;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|