blob: 31a444f2e4ec9ca7a74cbe6b982aa36dfb671779 [file] [log] [blame]
#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