forked from OSchip/llvm-project
1082 lines
43 KiB
C++
1082 lines
43 KiB
C++
|
#include "../clang-tidy/utils/FixItHintUtils.h"
|
||
|
#include "ClangTidyDiagnosticConsumer.h"
|
||
|
#include "ClangTidyTest.h"
|
||
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
||
|
#include "clang/Tooling/Tooling.h"
|
||
|
#include "gtest/gtest.h"
|
||
|
|
||
|
namespace clang {
|
||
|
namespace tidy {
|
||
|
|
||
|
namespace {
|
||
|
using namespace clang::ast_matchers;
|
||
|
using namespace utils::fixit;
|
||
|
|
||
|
template <QualifierTarget CT, QualifierPolicy CP>
|
||
|
class ConstTransform : public ClangTidyCheck {
|
||
|
public:
|
||
|
ConstTransform(StringRef CheckName, ClangTidyContext *Context)
|
||
|
: ClangTidyCheck(CheckName, Context) {}
|
||
|
|
||
|
void registerMatchers(MatchFinder *Finder) override {
|
||
|
Finder->addMatcher(varDecl(hasName("target")).bind("var"), this);
|
||
|
}
|
||
|
|
||
|
void check(const MatchFinder::MatchResult &Result) override {
|
||
|
const auto *D = Result.Nodes.getNodeAs<VarDecl>("var");
|
||
|
using utils::fixit::addQualifierToVarDecl;
|
||
|
Optional<FixItHint> Fix = addQualifierToVarDecl(
|
||
|
*D, *Result.Context, DeclSpec::TQ::TQ_const, CT, CP);
|
||
|
auto Diag = diag(D->getBeginLoc(), "doing const transformation");
|
||
|
if (Fix)
|
||
|
Diag << *Fix;
|
||
|
}
|
||
|
};
|
||
|
} // namespace
|
||
|
|
||
|
namespace test {
|
||
|
using PointeeLTransform =
|
||
|
ConstTransform<QualifierTarget::Pointee, QualifierPolicy::Left>;
|
||
|
using PointeeRTransform =
|
||
|
ConstTransform<QualifierTarget::Pointee, QualifierPolicy::Right>;
|
||
|
|
||
|
using ValueLTransform =
|
||
|
ConstTransform<QualifierTarget::Value, QualifierPolicy::Left>;
|
||
|
using ValueRTransform =
|
||
|
ConstTransform<QualifierTarget::Value, QualifierPolicy::Right>;
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// Test Value-like types. Everything with indirection is done later.
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
TEST(Values, Builtin) {
|
||
|
StringRef Snippet = "int target = 0;";
|
||
|
|
||
|
EXPECT_EQ("const int target = 0;", runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("const int target = 0;",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int const target = 0;", runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
EXPECT_EQ("int const target = 0;",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Values, TypedefBuiltin) {
|
||
|
StringRef T = "typedef int MyInt;";
|
||
|
StringRef S = "MyInt target = 0;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const MyInt target = 0;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const MyInt target = 0;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("MyInt const target = 0;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("MyInt const target = 0;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, TypedefBuiltinPointer) {
|
||
|
StringRef T = "typedef int* MyInt;";
|
||
|
StringRef S = "MyInt target = nullptr;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const MyInt target = nullptr;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const MyInt target = nullptr;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("MyInt const target = nullptr;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("MyInt const target = nullptr;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, UsingBuiltin) {
|
||
|
StringRef T = "using MyInt = int;";
|
||
|
StringRef S = "MyInt target = 0;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const MyInt target = 0;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const MyInt target = 0;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("MyInt const target = 0;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("MyInt const target = 0;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, UsingBuiltinPointer) {
|
||
|
StringRef T = "using MyInt = int*;";
|
||
|
StringRef S = "MyInt target = nullptr;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const MyInt target = nullptr;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const MyInt target = nullptr;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("MyInt const target = nullptr;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("MyInt const target = nullptr;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, AutoValue) {
|
||
|
StringRef T = "int f() { return 42; }\n";
|
||
|
StringRef S = "auto target = f();";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const auto target = f();"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const auto target = f();"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("auto const target = f();"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("auto const target = f();"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, AutoPointer) {
|
||
|
StringRef T = "int* f() { return nullptr; }\n";
|
||
|
StringRef S = "auto target = f();";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const auto target = f();"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const auto target = f();"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("auto const target = f();"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("auto const target = f();"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, AutoReference) {
|
||
|
StringRef T = "static int global = 42; int& f() { return global; }\n";
|
||
|
StringRef S = "auto target = f();";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const auto target = f();"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const auto target = f();"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("auto const target = f();"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("auto const target = f();"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, DeclTypeValue) {
|
||
|
StringRef T = "int f() { return 42; }\n";
|
||
|
StringRef S = "decltype(f()) target = f();";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const decltype(f()) target = f();"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const decltype(f()) target = f();"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("decltype(f()) const target = f();"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("decltype(f()) const target = f();"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, DeclTypePointer) {
|
||
|
// The pointer itself will be changed to 'const'. There is no
|
||
|
// way to make the pointee 'const' with this syntax.
|
||
|
StringRef T = "int* f() { return nullptr; }\n";
|
||
|
StringRef S = "decltype(f()) target = f();";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const decltype(f()) target = f();"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const decltype(f()) target = f();"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("decltype(f()) const target = f();"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("decltype(f()) const target = f();"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, DeclTypeReference) {
|
||
|
// Same as pointer, but the reference itself will be marked 'const'.
|
||
|
// This has no effect and will result in a warning afterwards. The
|
||
|
// transformation itself is still correct.
|
||
|
StringRef T = "static int global = 42; int& f() { return global; }\n";
|
||
|
StringRef S = "decltype(f()) target = f();";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const decltype(f()) target = f();"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const decltype(f()) target = f();"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("decltype(f()) const target = f();"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("decltype(f()) const target = f();"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Values, Parens) {
|
||
|
StringRef Snippet = "int ((target)) = 0;";
|
||
|
|
||
|
EXPECT_EQ("const int ((target)) = 0;",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("const int ((target)) = 0;",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int const ((target)) = 0;",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
EXPECT_EQ("int const ((target)) = 0;",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// Test builtin-arrays
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
TEST(Arrays, Builtin) {
|
||
|
StringRef Snippet = "int target[][1] = {{1}, {2}, {3}};";
|
||
|
|
||
|
EXPECT_EQ("const int target[][1] = {{1}, {2}, {3}};",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
EXPECT_EQ("const int target[][1] = {{1}, {2}, {3}};",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int const target[][1] = {{1}, {2}, {3}};",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
EXPECT_EQ("int const target[][1] = {{1}, {2}, {3}};",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Arrays, BuiltinParens) {
|
||
|
StringRef Snippet = "int ((target))[][1] = {{1}, {2}, {3}};";
|
||
|
|
||
|
EXPECT_EQ("const int ((target))[][1] = {{1}, {2}, {3}};",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
EXPECT_EQ("const int ((target))[][1] = {{1}, {2}, {3}};",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int const ((target))[][1] = {{1}, {2}, {3}};",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
EXPECT_EQ("int const ((target))[][1] = {{1}, {2}, {3}};",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Arrays, Pointers) {
|
||
|
StringRef Snippet = "int x; int* target[] = {&x, &x, &x};";
|
||
|
|
||
|
EXPECT_EQ("int x; const int* target[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
EXPECT_EQ("int x; int const* target[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int x; int* const target[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("int x; int* const target[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Arrays, PointerPointers) {
|
||
|
StringRef Snippet = "int* x = nullptr; int** target[] = {&x, &x, &x};";
|
||
|
|
||
|
EXPECT_EQ("int* x = nullptr; int* const* target[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
EXPECT_EQ("int* x = nullptr; int** const target[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int* x = nullptr; int* const* target[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
EXPECT_EQ("int* x = nullptr; int** const target[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Arrays, PointersParens) {
|
||
|
StringRef Snippet = "int x; int* (target)[] = {&x, &x, &x};";
|
||
|
|
||
|
EXPECT_EQ("int x; const int* (target)[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
EXPECT_EQ("int x; int const* (target)[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int x; int* const (target)[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("int x; int* const (target)[] = {&x, &x, &x};",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// Test reference types. This does not include pointers and arrays.
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
TEST(Reference, LValueBuiltin) {
|
||
|
StringRef Snippet = "int x = 42; int& target = x;";
|
||
|
|
||
|
EXPECT_EQ("int x = 42; const int& target = x;",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("int x = 42; const int& target = x;",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int x = 42; int const& target = x;",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
EXPECT_EQ("int x = 42; int const& target = x;",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Reference, RValueBuiltin) {
|
||
|
StringRef Snippet = "int&& target = 42;";
|
||
|
EXPECT_EQ("const int&& target = 42;",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("const int&& target = 42;",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int const&& target = 42;",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
EXPECT_EQ("int const&& target = 42;",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Reference, LValueToPointer) {
|
||
|
StringRef Snippet = "int* p; int *& target = p;";
|
||
|
EXPECT_EQ("int* p; int * const& target = p;",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("int* p; int * const& target = p;",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int* p; int * const& target = p;",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
EXPECT_EQ("int* p; int * const& target = p;",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Reference, LValueParens) {
|
||
|
StringRef Snippet = "int x = 42; int ((& target)) = x;";
|
||
|
|
||
|
EXPECT_EQ("int x = 42; const int ((& target)) = x;",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("int x = 42; const int ((& target)) = x;",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int x = 42; int const((& target)) = x;",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
EXPECT_EQ("int x = 42; int const((& target)) = x;",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Reference, ToArray) {
|
||
|
StringRef ArraySnippet = "int a[4] = {1, 2, 3, 4};";
|
||
|
StringRef Snippet = "int (&target)[4] = a;";
|
||
|
auto Cat = [&ArraySnippet](StringRef S) { return (ArraySnippet + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const int (&target)[4] = a;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(Snippet)));
|
||
|
EXPECT_EQ(Cat("const int (&target)[4] = a;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(Snippet)));
|
||
|
|
||
|
EXPECT_EQ(Cat("int const(&target)[4] = a;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(Snippet)));
|
||
|
EXPECT_EQ(Cat("int const(&target)[4] = a;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(Snippet)));
|
||
|
}
|
||
|
TEST(Reference, Auto) {
|
||
|
StringRef T = "static int global = 42; int& f() { return global; }\n";
|
||
|
StringRef S = "auto& target = f();";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const auto& target = f();"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("auto const& target = f();"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("const auto& target = f();"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("auto const& target = f();"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// Test pointers types.
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
TEST(Pointers, SingleBuiltin) {
|
||
|
StringRef Snippet = "int* target = nullptr;";
|
||
|
|
||
|
EXPECT_EQ("int* const target = nullptr;",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("int* const target = nullptr;",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("const int* target = nullptr;",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
EXPECT_EQ("int const* target = nullptr;",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Pointers, MultiBuiltin) {
|
||
|
StringRef Snippet = "int** target = nullptr;";
|
||
|
|
||
|
EXPECT_EQ("int** const target = nullptr;",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("int** const target = nullptr;",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int* const* target = nullptr;",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
EXPECT_EQ("int* const* target = nullptr;",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Pointers, ToArray) {
|
||
|
StringRef ArraySnippet = "int a[4] = {1, 2, 3, 4};";
|
||
|
StringRef Snippet = "int (*target)[4] = &a;";
|
||
|
auto Cat = [&ArraySnippet](StringRef S) { return (ArraySnippet + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("int (*const target)[4] = &a;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(Snippet)));
|
||
|
EXPECT_EQ(Cat("const int (*target)[4] = &a;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(Snippet)));
|
||
|
|
||
|
EXPECT_EQ(Cat("int (*const target)[4] = &a;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(Snippet)));
|
||
|
EXPECT_EQ(Cat("int const(*target)[4] = &a;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(Snippet)));
|
||
|
}
|
||
|
TEST(Pointers, Parens) {
|
||
|
StringRef Snippet = "int ((**target)) = nullptr;";
|
||
|
|
||
|
EXPECT_EQ("int ((**const target)) = nullptr;",
|
||
|
runCheckOnCode<ValueLTransform>(Snippet));
|
||
|
EXPECT_EQ("int ((**const target)) = nullptr;",
|
||
|
runCheckOnCode<ValueRTransform>(Snippet));
|
||
|
|
||
|
EXPECT_EQ("int ((* const*target)) = nullptr;",
|
||
|
runCheckOnCode<PointeeLTransform>(Snippet));
|
||
|
EXPECT_EQ("int ((* const*target)) = nullptr;",
|
||
|
runCheckOnCode<PointeeRTransform>(Snippet));
|
||
|
}
|
||
|
TEST(Pointers, Auto) {
|
||
|
StringRef T = "int* f() { return nullptr; }\n";
|
||
|
StringRef S = "auto* target = f();";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("auto* const target = f();"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("auto* const target = f();"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("const auto* target = f();"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("auto const* target = f();"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Pointers, AutoParens) {
|
||
|
StringRef T = "int* f() { return nullptr; }\n";
|
||
|
StringRef S = "auto (((* target))) = f();";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("auto (((* const target))) = f();"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("auto (((* const target))) = f();"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("const auto (((* target))) = f();"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("auto const(((* target))) = f();"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Pointers, FunctionPointer) {
|
||
|
StringRef S = "int (*target)(float, int, double) = nullptr;";
|
||
|
|
||
|
EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",
|
||
|
runCheckOnCode<ValueLTransform>(S));
|
||
|
EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",
|
||
|
runCheckOnCode<ValueRTransform>(S));
|
||
|
|
||
|
EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",
|
||
|
runCheckOnCode<PointeeLTransform>(S));
|
||
|
EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",
|
||
|
runCheckOnCode<PointeeRTransform>(S));
|
||
|
|
||
|
S = "int (((*target)))(float, int, double) = nullptr;";
|
||
|
EXPECT_EQ("int (((*const target)))(float, int, double) = nullptr;",
|
||
|
runCheckOnCode<PointeeRTransform>(S));
|
||
|
}
|
||
|
TEST(Pointers, MemberFunctionPointer) {
|
||
|
StringRef T = "struct A { int f() { return 1; } };";
|
||
|
StringRef S = "int (A::*target)() = &A::f;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "int (A::*((target)))() = &A::f;";
|
||
|
EXPECT_EQ(Cat("int (A::*const ((target)))() = &A::f;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Pointers, MemberDataPointer) {
|
||
|
StringRef T = "struct A { int member = 0; };";
|
||
|
StringRef S = "int A::*target = &A::member;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("int A::*const target = &A::member;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("int A::*const target = &A::member;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("int A::*const target = &A::member;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("int A::*const target = &A::member;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "int A::*((target)) = &A::member;";
|
||
|
EXPECT_EQ(Cat("int A::*const ((target)) = &A::member;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// Test TagTypes (struct, class, unions, enums)
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
TEST(TagTypes, Struct) {
|
||
|
StringRef T = "struct Foo { int data; int method(); };\n";
|
||
|
StringRef S = "struct Foo target{0};";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const struct Foo target{0};"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const struct Foo target{0};"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("struct Foo const target{0};"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("struct Foo const target{0};"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "Foo target{0};";
|
||
|
EXPECT_EQ(Cat("const Foo target{0};"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const Foo target{0};"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("Foo const target{0};"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("Foo const target{0};"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "Foo (target){0};";
|
||
|
EXPECT_EQ(Cat("const Foo (target){0};"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const Foo (target){0};"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("Foo const (target){0};"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("Foo const (target){0};"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "struct S { int i; } target = { 0 };";
|
||
|
EXPECT_EQ("const struct S { int i; } target = { 0 };",
|
||
|
runCheckOnCode<ValueLTransform>(S));
|
||
|
EXPECT_EQ("const struct S { int i; } target = { 0 };",
|
||
|
runCheckOnCode<PointeeLTransform>(S));
|
||
|
|
||
|
EXPECT_EQ("struct S { int i; } const target = { 0 };",
|
||
|
runCheckOnCode<PointeeRTransform>(S));
|
||
|
EXPECT_EQ("struct S { int i; } const target = { 0 };",
|
||
|
runCheckOnCode<PointeeRTransform>(S));
|
||
|
|
||
|
S = "struct { int i; } target = { 0 };";
|
||
|
EXPECT_EQ("const struct { int i; } target = { 0 };",
|
||
|
runCheckOnCode<ValueLTransform>(S));
|
||
|
EXPECT_EQ("const struct { int i; } target = { 0 };",
|
||
|
runCheckOnCode<PointeeLTransform>(S));
|
||
|
|
||
|
EXPECT_EQ("struct { int i; } const target = { 0 };",
|
||
|
runCheckOnCode<PointeeRTransform>(S));
|
||
|
EXPECT_EQ("struct { int i; } const target = { 0 };",
|
||
|
runCheckOnCode<PointeeRTransform>(S));
|
||
|
}
|
||
|
TEST(TagTypes, Class) {
|
||
|
StringRef T = "class Foo { int data; int method(); };\n";
|
||
|
StringRef S = "class Foo target;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const class Foo target;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const class Foo target;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("class Foo const target;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("class Foo const target;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "Foo target;";
|
||
|
EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const Foo target;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("Foo const target;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "Foo (target);";
|
||
|
EXPECT_EQ(Cat("const Foo (target);"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const Foo (target);"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("Foo const (target);"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("Foo const (target);"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(TagTypes, Enum) {
|
||
|
StringRef T = "enum Foo { N_ONE, N_TWO, N_THREE };\n";
|
||
|
StringRef S = "enum Foo target;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const enum Foo target;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const enum Foo target;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("enum Foo const target;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("enum Foo const target;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "Foo target;";
|
||
|
EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const Foo target;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("Foo const target;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "Foo (target);";
|
||
|
EXPECT_EQ(Cat("const Foo (target);"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const Foo (target);"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("Foo const (target);"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("Foo const (target);"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(TagTypes, Union) {
|
||
|
StringRef T = "union Foo { int yay; float nej; };\n";
|
||
|
StringRef S = "union Foo target;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("const union Foo target;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const union Foo target;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("union Foo const target;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("union Foo const target;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "Foo target;";
|
||
|
EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const Foo target;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("Foo const target;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
|
||
|
S = "Foo (target);";
|
||
|
EXPECT_EQ(Cat("const Foo (target);"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("const Foo (target);"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("Foo const (target);"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("Foo const (target);"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// Test Macro expansions.
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
TEST(Macro, AllInMacro) {
|
||
|
StringRef T = "#define DEFINE_VARIABLE int target = 42\n";
|
||
|
StringRef S = "DEFINE_VARIABLE;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Macro, MacroParameter) {
|
||
|
StringRef T = "#define DEFINE_VARIABLE(X) int X = 42\n";
|
||
|
StringRef S = "DEFINE_VARIABLE(target);";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Macro, MacroTypeValue) {
|
||
|
StringRef T = "#define BAD_TYPEDEF int\n";
|
||
|
StringRef S = "BAD_TYPEDEF target = 42;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("BAD_TYPEDEF target = 42;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("BAD_TYPEDEF target = 42;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("BAD_TYPEDEF const target = 42;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("BAD_TYPEDEF const target = 42;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Macro, MacroTypePointer) {
|
||
|
StringRef T = "#define BAD_TYPEDEF int *\n";
|
||
|
StringRef S = "BAD_TYPEDEF target = nullptr;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("BAD_TYPEDEF const target = nullptr;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("BAD_TYPEDEF const target = nullptr;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
// FIXME: Failing even all parts seem to bail-out in for isMacroID()
|
||
|
// The macro itself is changed here and below which is not intended.
|
||
|
EXPECT_NE(Cat("BAD_TYPEDEF target = nullptr;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("BAD_TYPEDEF target = nullptr;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Macro, MacroTypeReference) {
|
||
|
StringRef T = "static int g = 42;\n#define BAD_TYPEDEF int&\n";
|
||
|
StringRef S = "BAD_TYPEDEF target = g;";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("BAD_TYPEDEF target = g;"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
// FIXME: Failing even all parts seem to bail-out in for isMacroID()
|
||
|
EXPECT_NE(Cat("BAD_TYPEDEF target = g;"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("BAD_TYPEDEF target = g;"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
// FIXME: Failing even all parts seem to bail-out in for isMacroID()
|
||
|
EXPECT_NE(Cat("BAD_TYPEDEF target = g;"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
// This failed in LLVM.
|
||
|
TEST(Macro, Variable) {
|
||
|
StringRef M = "#define DEBUG(X) do { if (1) { X; } } while (0)\n";
|
||
|
StringRef F = "void foo() ";
|
||
|
StringRef V = "{ DEBUG(int target = 42;); }";
|
||
|
|
||
|
auto Cat = [&](StringRef S) { return (M + F + V).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ DEBUG(const int target = 42;); }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(V)));
|
||
|
EXPECT_EQ(Cat("{ DEBUG(int const target = 42;); }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(V)));
|
||
|
}
|
||
|
TEST(Macro, RangeLoop) {
|
||
|
StringRef M = "#define DEBUG(X) do { if (1) { X; }} while (false)\n";
|
||
|
StringRef F = "void foo() { char array[] = {'a', 'b', 'c'}; ";
|
||
|
StringRef V = "DEBUG( for(auto& target: array) 10 + target; );";
|
||
|
StringRef E = "}";
|
||
|
|
||
|
auto Cat = [&](StringRef S) { return (M + F + V + E).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("DEBUG( for(const auto& target: array); );"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(V)));
|
||
|
EXPECT_EQ(Cat("DEBUG( for(auto const& target: array); );"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(V)));
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// Test template code.
|
||
|
// ----------------------------------------------------------------------------
|
||
|
|
||
|
TEST(Template, TemplateVariable) {
|
||
|
StringRef T = "template <typename T> T target = 3.1415;";
|
||
|
|
||
|
EXPECT_EQ("template <typename T> const T target = 3.1415;",
|
||
|
runCheckOnCode<ValueLTransform>(T));
|
||
|
EXPECT_EQ("template <typename T> T const target = 3.1415;",
|
||
|
runCheckOnCode<ValueRTransform>(T));
|
||
|
|
||
|
EXPECT_EQ("template <typename T> const T target = 3.1415;",
|
||
|
runCheckOnCode<PointeeLTransform>(T));
|
||
|
EXPECT_EQ("template <typename T> T const target = 3.1415;",
|
||
|
runCheckOnCode<PointeeRTransform>(T));
|
||
|
}
|
||
|
TEST(Template, FunctionValue) {
|
||
|
StringRef T = "template <typename T> void f(T v) \n";
|
||
|
StringRef S = "{ T target = v; }";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T target = v; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const target = v; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T target = v; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const target = v; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, FunctionPointer) {
|
||
|
StringRef T = "template <typename T> void f(T* v) \n";
|
||
|
StringRef S = "{ T* target = v; }";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ T* const target = v; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T* const target = v; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T* target = v; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const* target = v; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, FunctionReference) {
|
||
|
StringRef T = "template <typename T> void f(T& v) \n";
|
||
|
StringRef S = "{ T& target = v; }";
|
||
|
auto Cat = [&T](StringRef S) { return (T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T& target = v; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const& target = v; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T& target = v; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const& target = v; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, MultiInstantiationsFunction) {
|
||
|
StringRef T = "template <typename T> void f(T v) \n";
|
||
|
StringRef S = "{ T target = v; }";
|
||
|
StringRef InstantStart = "void calls() {\n";
|
||
|
StringRef InstValue = "f<int>(42);\n";
|
||
|
StringRef InstConstValue = "f<const int>(42);\n";
|
||
|
StringRef InstPointer = "f<int*>(nullptr);\n";
|
||
|
StringRef InstPointerConst = "f<int* const>(nullptr);\n";
|
||
|
StringRef InstConstPointer = "f<const int*>(nullptr);\n";
|
||
|
StringRef InstConstPointerConst = "f<const int* const>(nullptr);\n";
|
||
|
StringRef InstRef = "int i = 42;\nf<int&>(i);\n";
|
||
|
StringRef InstConstRef = "f<const int&>(i);\n";
|
||
|
StringRef InstantEnd = "}";
|
||
|
auto Cat = [&](StringRef Target) {
|
||
|
return (T + Target + InstantStart + InstValue + InstConstValue +
|
||
|
InstPointer + InstPointerConst + InstConstPointer +
|
||
|
InstConstPointerConst + InstRef + InstConstRef + InstantEnd)
|
||
|
.str();
|
||
|
};
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T target = v; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const target = v; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T target = v; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const target = v; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
|
||
|
TEST(Template, StructValue) {
|
||
|
StringRef T = "template <typename T> struct S { void f(T& v) \n";
|
||
|
StringRef S = "{ T target = v; }";
|
||
|
StringRef End = "\n};";
|
||
|
auto Cat = [&T, &End](StringRef S) { return (T + S + End).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T target = v; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const target = v; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T target = v; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const target = v; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, StructPointer) {
|
||
|
StringRef T = "template <typename T> struct S { void f(T* v) \n";
|
||
|
StringRef S = "{ T* target = v; }";
|
||
|
StringRef End = "\n};";
|
||
|
auto Cat = [&T, &End](StringRef S) { return (T + S + End).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ T* const target = v; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T* const target = v; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T* target = v; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const* target = v; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, StructReference) {
|
||
|
StringRef T = "template <typename T> struct S { void f(T& v) \n";
|
||
|
StringRef S = "{ T& target = v; }";
|
||
|
StringRef End = "\n};";
|
||
|
auto Cat = [&T, &End](StringRef S) { return (T + S + End).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T& target = v; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const& target = v; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const T& target = v; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ T const& target = v; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, DependentReturnFunction) {
|
||
|
StringRef TS = "template <typename T> struct TS { using value_type = T; };";
|
||
|
StringRef T = "template <typename T> void foo() ";
|
||
|
StringRef S = "{ typename T::value_type target; }";
|
||
|
auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const typename T::value_type target; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ typename T::value_type const target; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const typename T::value_type target; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ typename T::value_type const target; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, DependentReturnPointerFunction) {
|
||
|
StringRef TS = "template <typename T> struct TS { using value_type = T; };";
|
||
|
StringRef T = "template <typename T> void foo() ";
|
||
|
StringRef S = "{ typename T::value_type *target; }";
|
||
|
auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ typename T::value_type *const target; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ typename T::value_type *const target; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const typename T::value_type *target; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ typename T::value_type const*target; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, DependentReturnReferenceFunction) {
|
||
|
StringRef TS = "template <typename T> struct TS { using value_type = T; };";
|
||
|
StringRef T = "template <typename T> void foo(T& f) ";
|
||
|
StringRef S = "{ typename T::value_type &target = f; }";
|
||
|
auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const typename T::value_type &target = f; }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ typename T::value_type const&target = f; }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const typename T::value_type &target = f; }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ typename T::value_type const&target = f; }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, VectorLikeType) {
|
||
|
StringRef TS = "template <typename T> struct TS { TS(const T&) {} }; ";
|
||
|
StringRef T = "void foo() ";
|
||
|
StringRef S = "{ TS<int> target(42); }";
|
||
|
auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const TS<int> target(42); }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ TS<int> const target(42); }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const TS<int> target(42); }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ TS<int> const target(42); }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
TEST(Template, SpecializedTemplate) {
|
||
|
StringRef TS = "template <typename T = int> struct TS { TS(const T&) {} }; ";
|
||
|
StringRef TS2 = "template <> struct TS<double> { TS(const double&) {} }; ";
|
||
|
StringRef T = "void foo() ";
|
||
|
StringRef S = "{ TS<double> target(42.42); }";
|
||
|
auto Cat = [&](StringRef S) { return (TS + TS2 + T + S).str(); };
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const TS<double> target(42.42); }"),
|
||
|
runCheckOnCode<ValueLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ TS<double> const target(42.42); }"),
|
||
|
runCheckOnCode<ValueRTransform>(Cat(S)));
|
||
|
|
||
|
EXPECT_EQ(Cat("{ const TS<double> target(42.42); }"),
|
||
|
runCheckOnCode<PointeeLTransform>(Cat(S)));
|
||
|
EXPECT_EQ(Cat("{ TS<double> const target(42.42); }"),
|
||
|
runCheckOnCode<PointeeRTransform>(Cat(S)));
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// ObjC Pointers
|
||
|
// -----------------------------------------------------------------------------
|
||
|
|
||
|
TEST(ObjC, SimplePointers) {
|
||
|
StringRef S = "int * target = 0;";
|
||
|
EXPECT_EQ(runCheckOnCode<PointeeLTransform>(S, nullptr, "input.m"),
|
||
|
"const int * target = 0;");
|
||
|
EXPECT_EQ(runCheckOnCode<PointeeRTransform>(S, nullptr, "input.m"),
|
||
|
"int const* target = 0;");
|
||
|
EXPECT_EQ(runCheckOnCode<ValueLTransform>(S, nullptr, "input.m"),
|
||
|
"int * const target = 0;");
|
||
|
EXPECT_EQ(runCheckOnCode<ValueRTransform>(S, nullptr, "input.m"),
|
||
|
"int * const target = 0;");
|
||
|
}
|
||
|
TEST(ObjC, ClassPointer) {
|
||
|
StringRef TB = "@class Object;\nint main() {\n";
|
||
|
StringRef S = "Object *target;";
|
||
|
StringRef TE = "\n}";
|
||
|
auto Cat = [&](StringRef S) { return (TB + S + TE).str(); };
|
||
|
|
||
|
// FIXME: Not done properly for some reason.
|
||
|
EXPECT_NE(runCheckOnCode<PointeeLTransform>(Cat(S), nullptr, "input.m"),
|
||
|
Cat("const Object *target;"));
|
||
|
EXPECT_NE(runCheckOnCode<PointeeRTransform>(Cat(S), nullptr, "input.m"),
|
||
|
Cat("Object const*target;"));
|
||
|
EXPECT_NE(runCheckOnCode<ValueLTransform>(Cat(S), nullptr, "input.m"),
|
||
|
Cat("Object *const target;"));
|
||
|
EXPECT_NE(runCheckOnCode<ValueRTransform>(Cat(S), nullptr, "input.m"),
|
||
|
Cat("Object *const target;"));
|
||
|
}
|
||
|
TEST(ObjC, InterfacePointer) {
|
||
|
StringRef TB = "@interface I\n";
|
||
|
StringRef S = "- (void) foo: (int *) target;";
|
||
|
StringRef TE = "\n@end";
|
||
|
auto Cat = [&](StringRef S) { return (TB + S + TE).str(); };
|
||
|
|
||
|
EXPECT_EQ(runCheckOnCode<PointeeLTransform>(Cat(S), nullptr, "input.m"),
|
||
|
Cat("- (void) foo: (const int *) target;"));
|
||
|
EXPECT_EQ(runCheckOnCode<PointeeRTransform>(Cat(S), nullptr, "input.m"),
|
||
|
Cat("- (void) foo: (int const*) target;"));
|
||
|
// FIXME: These transformations are incorrect. ObjC seems to need
|
||
|
// RParenSkipping which is not implemented.
|
||
|
EXPECT_NE(runCheckOnCode<ValueLTransform>(Cat(S), nullptr, "input.m"),
|
||
|
Cat("- (void) foo: (int * const) target;"));
|
||
|
EXPECT_NE(runCheckOnCode<ValueRTransform>(Cat(S), nullptr, "input.m"),
|
||
|
Cat("- (void) foo: (int * const) target;"));
|
||
|
}
|
||
|
|
||
|
} // namespace test
|
||
|
} // namespace tidy
|
||
|
} // namespace clang
|