1083 lines · cpp
1#include "../clang-tidy/utils/FixItHintUtils.h"2#include "ClangTidyDiagnosticConsumer.h"3#include "ClangTidyTest.h"4#include "clang/ASTMatchers/ASTMatchFinder.h"5#include "clang/ASTMatchers/ASTMatchers.h"6#include "clang/Tooling/Tooling.h"7#include "gtest/gtest.h"8#include <optional>9 10namespace clang {11namespace tidy {12 13namespace {14using namespace clang::ast_matchers;15using namespace utils::fixit;16 17template <QualifierTarget CT, QualifierPolicy CP>18class ConstTransform : public ClangTidyCheck {19public:20 ConstTransform(StringRef CheckName, ClangTidyContext *Context)21 : ClangTidyCheck(CheckName, Context) {}22 23 void registerMatchers(MatchFinder *Finder) override {24 Finder->addMatcher(varDecl(hasName("target")).bind("var"), this);25 }26 27 void check(const MatchFinder::MatchResult &Result) override {28 const auto *D = Result.Nodes.getNodeAs<VarDecl>("var");29 using utils::fixit::addQualifierToVarDecl;30 std::optional<FixItHint> Fix =31 addQualifierToVarDecl(*D, *Result.Context, Qualifiers::Const, CT, CP);32 auto Diag = diag(D->getBeginLoc(), "doing const transformation");33 if (Fix)34 Diag << *Fix;35 }36};37} // namespace38 39namespace test {40using PointeeLTransform =41 ConstTransform<QualifierTarget::Pointee, QualifierPolicy::Left>;42using PointeeRTransform =43 ConstTransform<QualifierTarget::Pointee, QualifierPolicy::Right>;44 45using ValueLTransform =46 ConstTransform<QualifierTarget::Value, QualifierPolicy::Left>;47using ValueRTransform =48 ConstTransform<QualifierTarget::Value, QualifierPolicy::Right>;49 50// ----------------------------------------------------------------------------51// Test Value-like types. Everything with indirection is done later.52// ----------------------------------------------------------------------------53 54TEST(Values, Builtin) {55 StringRef Snippet = "int target = 0;";56 57 EXPECT_EQ("const int target = 0;", runCheckOnCode<ValueLTransform>(Snippet));58 EXPECT_EQ("const int target = 0;",59 runCheckOnCode<PointeeLTransform>(Snippet));60 61 EXPECT_EQ("int const target = 0;", runCheckOnCode<ValueRTransform>(Snippet));62 EXPECT_EQ("int const target = 0;",63 runCheckOnCode<PointeeRTransform>(Snippet));64}65TEST(Values, TypedefBuiltin) {66 StringRef T = "typedef int MyInt;";67 StringRef S = "MyInt target = 0;";68 auto Cat = [&T](StringRef S) { return (T + S).str(); };69 70 EXPECT_EQ(Cat("const MyInt target = 0;"),71 runCheckOnCode<ValueLTransform>(Cat(S)));72 EXPECT_EQ(Cat("const MyInt target = 0;"),73 runCheckOnCode<PointeeLTransform>(Cat(S)));74 75 EXPECT_EQ(Cat("MyInt const target = 0;"),76 runCheckOnCode<ValueRTransform>(Cat(S)));77 EXPECT_EQ(Cat("MyInt const target = 0;"),78 runCheckOnCode<PointeeRTransform>(Cat(S)));79}80TEST(Values, TypedefBuiltinPointer) {81 StringRef T = "typedef int* MyInt;";82 StringRef S = "MyInt target = nullptr;";83 auto Cat = [&T](StringRef S) { return (T + S).str(); };84 85 EXPECT_EQ(Cat("const MyInt target = nullptr;"),86 runCheckOnCode<ValueLTransform>(Cat(S)));87 EXPECT_EQ(Cat("const MyInt target = nullptr;"),88 runCheckOnCode<PointeeLTransform>(Cat(S)));89 90 EXPECT_EQ(Cat("MyInt const target = nullptr;"),91 runCheckOnCode<ValueRTransform>(Cat(S)));92 EXPECT_EQ(Cat("MyInt const target = nullptr;"),93 runCheckOnCode<PointeeRTransform>(Cat(S)));94}95TEST(Values, UsingBuiltin) {96 StringRef T = "using MyInt = int;";97 StringRef S = "MyInt target = 0;";98 auto Cat = [&T](StringRef S) { return (T + S).str(); };99 100 EXPECT_EQ(Cat("const MyInt target = 0;"),101 runCheckOnCode<ValueLTransform>(Cat(S)));102 EXPECT_EQ(Cat("const MyInt target = 0;"),103 runCheckOnCode<PointeeLTransform>(Cat(S)));104 105 EXPECT_EQ(Cat("MyInt const target = 0;"),106 runCheckOnCode<ValueRTransform>(Cat(S)));107 EXPECT_EQ(Cat("MyInt const target = 0;"),108 runCheckOnCode<PointeeRTransform>(Cat(S)));109}110TEST(Values, UsingBuiltinPointer) {111 StringRef T = "using MyInt = int*;";112 StringRef S = "MyInt target = nullptr;";113 auto Cat = [&T](StringRef S) { return (T + S).str(); };114 115 EXPECT_EQ(Cat("const MyInt target = nullptr;"),116 runCheckOnCode<ValueLTransform>(Cat(S)));117 EXPECT_EQ(Cat("const MyInt target = nullptr;"),118 runCheckOnCode<PointeeLTransform>(Cat(S)));119 120 EXPECT_EQ(Cat("MyInt const target = nullptr;"),121 runCheckOnCode<ValueRTransform>(Cat(S)));122 EXPECT_EQ(Cat("MyInt const target = nullptr;"),123 runCheckOnCode<PointeeRTransform>(Cat(S)));124}125TEST(Values, AutoValue) {126 StringRef T = "int f() { return 42; }\n";127 StringRef S = "auto target = f();";128 auto Cat = [&T](StringRef S) { return (T + S).str(); };129 130 EXPECT_EQ(Cat("const auto target = f();"),131 runCheckOnCode<ValueLTransform>(Cat(S)));132 EXPECT_EQ(Cat("const auto target = f();"),133 runCheckOnCode<PointeeLTransform>(Cat(S)));134 135 EXPECT_EQ(Cat("auto const target = f();"),136 runCheckOnCode<ValueRTransform>(Cat(S)));137 EXPECT_EQ(Cat("auto const target = f();"),138 runCheckOnCode<PointeeRTransform>(Cat(S)));139}140TEST(Values, AutoPointer) {141 StringRef T = "int* f() { return nullptr; }\n";142 StringRef S = "auto target = f();";143 auto Cat = [&T](StringRef S) { return (T + S).str(); };144 145 EXPECT_EQ(Cat("const auto target = f();"),146 runCheckOnCode<ValueLTransform>(Cat(S)));147 EXPECT_EQ(Cat("const auto target = f();"),148 runCheckOnCode<PointeeLTransform>(Cat(S)));149 150 EXPECT_EQ(Cat("auto const target = f();"),151 runCheckOnCode<ValueRTransform>(Cat(S)));152 EXPECT_EQ(Cat("auto const target = f();"),153 runCheckOnCode<PointeeRTransform>(Cat(S)));154}155TEST(Values, AutoReference) {156 StringRef T = "static int global = 42; int& f() { return global; }\n";157 StringRef S = "auto target = f();";158 auto Cat = [&T](StringRef S) { return (T + S).str(); };159 160 EXPECT_EQ(Cat("const auto target = f();"),161 runCheckOnCode<ValueLTransform>(Cat(S)));162 EXPECT_EQ(Cat("const auto target = f();"),163 runCheckOnCode<PointeeLTransform>(Cat(S)));164 165 EXPECT_EQ(Cat("auto const target = f();"),166 runCheckOnCode<ValueRTransform>(Cat(S)));167 EXPECT_EQ(Cat("auto const target = f();"),168 runCheckOnCode<PointeeRTransform>(Cat(S)));169}170TEST(Values, DeclTypeValue) {171 StringRef T = "int f() { return 42; }\n";172 StringRef S = "decltype(f()) target = f();";173 auto Cat = [&T](StringRef S) { return (T + S).str(); };174 175 EXPECT_EQ(Cat("const decltype(f()) target = f();"),176 runCheckOnCode<ValueLTransform>(Cat(S)));177 EXPECT_EQ(Cat("const decltype(f()) target = f();"),178 runCheckOnCode<PointeeLTransform>(Cat(S)));179 180 EXPECT_EQ(Cat("decltype(f()) const target = f();"),181 runCheckOnCode<ValueRTransform>(Cat(S)));182 EXPECT_EQ(Cat("decltype(f()) const target = f();"),183 runCheckOnCode<PointeeRTransform>(Cat(S)));184}185TEST(Values, DeclTypePointer) {186 // The pointer itself will be changed to 'const'. There is no187 // way to make the pointee 'const' with this syntax.188 StringRef T = "int* f() { return nullptr; }\n";189 StringRef S = "decltype(f()) target = f();";190 auto Cat = [&T](StringRef S) { return (T + S).str(); };191 192 EXPECT_EQ(Cat("const decltype(f()) target = f();"),193 runCheckOnCode<ValueLTransform>(Cat(S)));194 EXPECT_EQ(Cat("const decltype(f()) target = f();"),195 runCheckOnCode<PointeeLTransform>(Cat(S)));196 197 EXPECT_EQ(Cat("decltype(f()) const target = f();"),198 runCheckOnCode<ValueRTransform>(Cat(S)));199 EXPECT_EQ(Cat("decltype(f()) const target = f();"),200 runCheckOnCode<PointeeRTransform>(Cat(S)));201}202TEST(Values, DeclTypeReference) {203 // Same as pointer, but the reference itself will be marked 'const'.204 // This has no effect and will result in a warning afterwards. The205 // transformation itself is still correct.206 StringRef T = "static int global = 42; int& f() { return global; }\n";207 StringRef S = "decltype(f()) target = f();";208 auto Cat = [&T](StringRef S) { return (T + S).str(); };209 210 EXPECT_EQ(Cat("const decltype(f()) target = f();"),211 runCheckOnCode<ValueLTransform>(Cat(S)));212 EXPECT_EQ(Cat("const decltype(f()) target = f();"),213 runCheckOnCode<PointeeLTransform>(Cat(S)));214 215 EXPECT_EQ(Cat("decltype(f()) const target = f();"),216 runCheckOnCode<ValueRTransform>(Cat(S)));217 EXPECT_EQ(Cat("decltype(f()) const target = f();"),218 runCheckOnCode<PointeeRTransform>(Cat(S)));219}220TEST(Values, Parens) {221 StringRef Snippet = "int ((target)) = 0;";222 223 EXPECT_EQ("const int ((target)) = 0;",224 runCheckOnCode<ValueLTransform>(Snippet));225 EXPECT_EQ("const int ((target)) = 0;",226 runCheckOnCode<PointeeLTransform>(Snippet));227 228 EXPECT_EQ("int const ((target)) = 0;",229 runCheckOnCode<ValueRTransform>(Snippet));230 EXPECT_EQ("int const ((target)) = 0;",231 runCheckOnCode<PointeeRTransform>(Snippet));232}233 234// ----------------------------------------------------------------------------235// Test builtin-arrays236// ----------------------------------------------------------------------------237 238TEST(Arrays, Builtin) {239 StringRef Snippet = "int target[][1] = {{1}, {2}, {3}};";240 241 EXPECT_EQ("const int target[][1] = {{1}, {2}, {3}};",242 runCheckOnCode<PointeeLTransform>(Snippet));243 EXPECT_EQ("const int target[][1] = {{1}, {2}, {3}};",244 runCheckOnCode<ValueLTransform>(Snippet));245 246 EXPECT_EQ("int const target[][1] = {{1}, {2}, {3}};",247 runCheckOnCode<PointeeRTransform>(Snippet));248 EXPECT_EQ("int const target[][1] = {{1}, {2}, {3}};",249 runCheckOnCode<ValueRTransform>(Snippet));250}251TEST(Arrays, BuiltinParens) {252 StringRef Snippet = "int ((target))[][1] = {{1}, {2}, {3}};";253 254 EXPECT_EQ("const int ((target))[][1] = {{1}, {2}, {3}};",255 runCheckOnCode<PointeeLTransform>(Snippet));256 EXPECT_EQ("const int ((target))[][1] = {{1}, {2}, {3}};",257 runCheckOnCode<ValueLTransform>(Snippet));258 259 EXPECT_EQ("int const ((target))[][1] = {{1}, {2}, {3}};",260 runCheckOnCode<PointeeRTransform>(Snippet));261 EXPECT_EQ("int const ((target))[][1] = {{1}, {2}, {3}};",262 runCheckOnCode<ValueRTransform>(Snippet));263}264TEST(Arrays, Pointers) {265 StringRef Snippet = "int x; int* target[] = {&x, &x, &x};";266 267 EXPECT_EQ("int x; const int* target[] = {&x, &x, &x};",268 runCheckOnCode<PointeeLTransform>(Snippet));269 EXPECT_EQ("int x; int const* target[] = {&x, &x, &x};",270 runCheckOnCode<PointeeRTransform>(Snippet));271 272 EXPECT_EQ("int x; int* const target[] = {&x, &x, &x};",273 runCheckOnCode<ValueLTransform>(Snippet));274 EXPECT_EQ("int x; int* const target[] = {&x, &x, &x};",275 runCheckOnCode<ValueRTransform>(Snippet));276}277TEST(Arrays, PointerPointers) {278 StringRef Snippet = "int* x = nullptr; int** target[] = {&x, &x, &x};";279 280 EXPECT_EQ("int* x = nullptr; int* const* target[] = {&x, &x, &x};",281 runCheckOnCode<PointeeLTransform>(Snippet));282 EXPECT_EQ("int* x = nullptr; int** const target[] = {&x, &x, &x};",283 runCheckOnCode<ValueLTransform>(Snippet));284 285 EXPECT_EQ("int* x = nullptr; int* const* target[] = {&x, &x, &x};",286 runCheckOnCode<PointeeRTransform>(Snippet));287 EXPECT_EQ("int* x = nullptr; int** const target[] = {&x, &x, &x};",288 runCheckOnCode<ValueRTransform>(Snippet));289}290TEST(Arrays, PointersParens) {291 StringRef Snippet = "int x; int* (target)[] = {&x, &x, &x};";292 293 EXPECT_EQ("int x; const int* (target)[] = {&x, &x, &x};",294 runCheckOnCode<PointeeLTransform>(Snippet));295 EXPECT_EQ("int x; int const* (target)[] = {&x, &x, &x};",296 runCheckOnCode<PointeeRTransform>(Snippet));297 298 EXPECT_EQ("int x; int* const (target)[] = {&x, &x, &x};",299 runCheckOnCode<ValueLTransform>(Snippet));300 EXPECT_EQ("int x; int* const (target)[] = {&x, &x, &x};",301 runCheckOnCode<ValueRTransform>(Snippet));302}303 304// ----------------------------------------------------------------------------305// Test reference types. This does not include pointers and arrays.306// ----------------------------------------------------------------------------307 308TEST(Reference, LValueBuiltin) {309 StringRef Snippet = "int x = 42; int& target = x;";310 311 EXPECT_EQ("int x = 42; const int& target = x;",312 runCheckOnCode<ValueLTransform>(Snippet));313 EXPECT_EQ("int x = 42; const int& target = x;",314 runCheckOnCode<PointeeLTransform>(Snippet));315 316 EXPECT_EQ("int x = 42; int const& target = x;",317 runCheckOnCode<ValueRTransform>(Snippet));318 EXPECT_EQ("int x = 42; int const& target = x;",319 runCheckOnCode<PointeeRTransform>(Snippet));320}321TEST(Reference, RValueBuiltin) {322 StringRef Snippet = "int&& target = 42;";323 EXPECT_EQ("const int&& target = 42;",324 runCheckOnCode<ValueLTransform>(Snippet));325 EXPECT_EQ("const int&& target = 42;",326 runCheckOnCode<PointeeLTransform>(Snippet));327 328 EXPECT_EQ("int const&& target = 42;",329 runCheckOnCode<ValueRTransform>(Snippet));330 EXPECT_EQ("int const&& target = 42;",331 runCheckOnCode<PointeeRTransform>(Snippet));332}333TEST(Reference, LValueToPointer) {334 StringRef Snippet = "int* p; int *& target = p;";335 EXPECT_EQ("int* p; int * const& target = p;",336 runCheckOnCode<ValueLTransform>(Snippet));337 EXPECT_EQ("int* p; int * const& target = p;",338 runCheckOnCode<PointeeLTransform>(Snippet));339 340 EXPECT_EQ("int* p; int * const& target = p;",341 runCheckOnCode<ValueRTransform>(Snippet));342 EXPECT_EQ("int* p; int * const& target = p;",343 runCheckOnCode<PointeeRTransform>(Snippet));344}345TEST(Reference, LValueParens) {346 StringRef Snippet = "int x = 42; int ((& target)) = x;";347 348 EXPECT_EQ("int x = 42; const int ((& target)) = x;",349 runCheckOnCode<ValueLTransform>(Snippet));350 EXPECT_EQ("int x = 42; const int ((& target)) = x;",351 runCheckOnCode<PointeeLTransform>(Snippet));352 353 EXPECT_EQ("int x = 42; int const((& target)) = x;",354 runCheckOnCode<ValueRTransform>(Snippet));355 EXPECT_EQ("int x = 42; int const((& target)) = x;",356 runCheckOnCode<PointeeRTransform>(Snippet));357}358TEST(Reference, ToArray) {359 StringRef ArraySnippet = "int a[4] = {1, 2, 3, 4};";360 StringRef Snippet = "int (&target)[4] = a;";361 auto Cat = [&ArraySnippet](StringRef S) { return (ArraySnippet + S).str(); };362 363 EXPECT_EQ(Cat("const int (&target)[4] = a;"),364 runCheckOnCode<ValueLTransform>(Cat(Snippet)));365 EXPECT_EQ(Cat("const int (&target)[4] = a;"),366 runCheckOnCode<PointeeLTransform>(Cat(Snippet)));367 368 EXPECT_EQ(Cat("int const(&target)[4] = a;"),369 runCheckOnCode<ValueRTransform>(Cat(Snippet)));370 EXPECT_EQ(Cat("int const(&target)[4] = a;"),371 runCheckOnCode<PointeeRTransform>(Cat(Snippet)));372}373TEST(Reference, Auto) {374 StringRef T = "static int global = 42; int& f() { return global; }\n";375 StringRef S = "auto& target = f();";376 auto Cat = [&T](StringRef S) { return (T + S).str(); };377 378 EXPECT_EQ(Cat("const auto& target = f();"),379 runCheckOnCode<ValueLTransform>(Cat(S)));380 EXPECT_EQ(Cat("auto const& target = f();"),381 runCheckOnCode<ValueRTransform>(Cat(S)));382 383 EXPECT_EQ(Cat("const auto& target = f();"),384 runCheckOnCode<PointeeLTransform>(Cat(S)));385 EXPECT_EQ(Cat("auto const& target = f();"),386 runCheckOnCode<PointeeRTransform>(Cat(S)));387}388 389// ----------------------------------------------------------------------------390// Test pointers types.391// ----------------------------------------------------------------------------392 393TEST(Pointers, SingleBuiltin) {394 StringRef Snippet = "int* target = nullptr;";395 396 EXPECT_EQ("int* const target = nullptr;",397 runCheckOnCode<ValueLTransform>(Snippet));398 EXPECT_EQ("int* const target = nullptr;",399 runCheckOnCode<ValueRTransform>(Snippet));400 401 EXPECT_EQ("const int* target = nullptr;",402 runCheckOnCode<PointeeLTransform>(Snippet));403 EXPECT_EQ("int const* target = nullptr;",404 runCheckOnCode<PointeeRTransform>(Snippet));405}406TEST(Pointers, MultiBuiltin) {407 StringRef Snippet = "int** target = nullptr;";408 409 EXPECT_EQ("int** const target = nullptr;",410 runCheckOnCode<ValueLTransform>(Snippet));411 EXPECT_EQ("int** const target = nullptr;",412 runCheckOnCode<ValueRTransform>(Snippet));413 414 EXPECT_EQ("int* const* target = nullptr;",415 runCheckOnCode<PointeeLTransform>(Snippet));416 EXPECT_EQ("int* const* target = nullptr;",417 runCheckOnCode<PointeeRTransform>(Snippet));418}419TEST(Pointers, ToArray) {420 StringRef ArraySnippet = "int a[4] = {1, 2, 3, 4};";421 StringRef Snippet = "int (*target)[4] = &a;";422 auto Cat = [&ArraySnippet](StringRef S) { return (ArraySnippet + S).str(); };423 424 EXPECT_EQ(Cat("int (*const target)[4] = &a;"),425 runCheckOnCode<ValueLTransform>(Cat(Snippet)));426 EXPECT_EQ(Cat("const int (*target)[4] = &a;"),427 runCheckOnCode<PointeeLTransform>(Cat(Snippet)));428 429 EXPECT_EQ(Cat("int (*const target)[4] = &a;"),430 runCheckOnCode<ValueRTransform>(Cat(Snippet)));431 EXPECT_EQ(Cat("int const(*target)[4] = &a;"),432 runCheckOnCode<PointeeRTransform>(Cat(Snippet)));433}434TEST(Pointers, Parens) {435 StringRef Snippet = "int ((**target)) = nullptr;";436 437 EXPECT_EQ("int ((**const target)) = nullptr;",438 runCheckOnCode<ValueLTransform>(Snippet));439 EXPECT_EQ("int ((**const target)) = nullptr;",440 runCheckOnCode<ValueRTransform>(Snippet));441 442 EXPECT_EQ("int ((* const*target)) = nullptr;",443 runCheckOnCode<PointeeLTransform>(Snippet));444 EXPECT_EQ("int ((* const*target)) = nullptr;",445 runCheckOnCode<PointeeRTransform>(Snippet));446}447TEST(Pointers, Auto) {448 StringRef T = "int* f() { return nullptr; }\n";449 StringRef S = "auto* target = f();";450 auto Cat = [&T](StringRef S) { return (T + S).str(); };451 452 EXPECT_EQ(Cat("auto* const target = f();"),453 runCheckOnCode<ValueLTransform>(Cat(S)));454 EXPECT_EQ(Cat("auto* const target = f();"),455 runCheckOnCode<ValueRTransform>(Cat(S)));456 457 EXPECT_EQ(Cat("const auto* target = f();"),458 runCheckOnCode<PointeeLTransform>(Cat(S)));459 EXPECT_EQ(Cat("auto const* target = f();"),460 runCheckOnCode<PointeeRTransform>(Cat(S)));461}462TEST(Pointers, AutoParens) {463 StringRef T = "int* f() { return nullptr; }\n";464 StringRef S = "auto (((* target))) = f();";465 auto Cat = [&T](StringRef S) { return (T + S).str(); };466 467 EXPECT_EQ(Cat("auto (((* const target))) = f();"),468 runCheckOnCode<ValueLTransform>(Cat(S)));469 EXPECT_EQ(Cat("auto (((* const target))) = f();"),470 runCheckOnCode<ValueRTransform>(Cat(S)));471 472 EXPECT_EQ(Cat("const auto (((* target))) = f();"),473 runCheckOnCode<PointeeLTransform>(Cat(S)));474 EXPECT_EQ(Cat("auto const(((* target))) = f();"),475 runCheckOnCode<PointeeRTransform>(Cat(S)));476}477TEST(Pointers, FunctionPointer) {478 StringRef S = "int (*target)(float, int, double) = nullptr;";479 480 EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",481 runCheckOnCode<ValueLTransform>(S));482 EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",483 runCheckOnCode<ValueRTransform>(S));484 485 EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",486 runCheckOnCode<PointeeLTransform>(S));487 EXPECT_EQ("int (*const target)(float, int, double) = nullptr;",488 runCheckOnCode<PointeeRTransform>(S));489 490 S = "int (((*target)))(float, int, double) = nullptr;";491 EXPECT_EQ("int (((*const target)))(float, int, double) = nullptr;",492 runCheckOnCode<PointeeRTransform>(S));493}494TEST(Pointers, MemberFunctionPointer) {495 StringRef T = "struct A { int f() { return 1; } };";496 StringRef S = "int (A::*target)() = &A::f;";497 auto Cat = [&T](StringRef S) { return (T + S).str(); };498 499 EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),500 runCheckOnCode<ValueLTransform>(Cat(S)));501 EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),502 runCheckOnCode<ValueRTransform>(Cat(S)));503 504 EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),505 runCheckOnCode<PointeeLTransform>(Cat(S)));506 EXPECT_EQ(Cat("int (A::*const target)() = &A::f;"),507 runCheckOnCode<PointeeRTransform>(Cat(S)));508 509 S = "int (A::*((target)))() = &A::f;";510 EXPECT_EQ(Cat("int (A::*const ((target)))() = &A::f;"),511 runCheckOnCode<ValueLTransform>(Cat(S)));512}513TEST(Pointers, MemberDataPointer) {514 StringRef T = "struct A { int member = 0; };";515 StringRef S = "int A::*target = &A::member;";516 auto Cat = [&T](StringRef S) { return (T + S).str(); };517 518 EXPECT_EQ(Cat("int A::*const target = &A::member;"),519 runCheckOnCode<ValueLTransform>(Cat(S)));520 EXPECT_EQ(Cat("int A::*const target = &A::member;"),521 runCheckOnCode<ValueRTransform>(Cat(S)));522 523 EXPECT_EQ(Cat("int A::*const target = &A::member;"),524 runCheckOnCode<PointeeLTransform>(Cat(S)));525 EXPECT_EQ(Cat("int A::*const target = &A::member;"),526 runCheckOnCode<PointeeRTransform>(Cat(S)));527 528 S = "int A::*((target)) = &A::member;";529 EXPECT_EQ(Cat("int A::*const ((target)) = &A::member;"),530 runCheckOnCode<PointeeRTransform>(Cat(S)));531}532 533// ----------------------------------------------------------------------------534// Test TagTypes (struct, class, unions, enums)535// ----------------------------------------------------------------------------536 537TEST(TagTypes, Struct) {538 StringRef T = "struct Foo { int data; int method(); };\n";539 StringRef S = "struct Foo target{0};";540 auto Cat = [&T](StringRef S) { return (T + S).str(); };541 542 EXPECT_EQ(Cat("const struct Foo target{0};"),543 runCheckOnCode<ValueLTransform>(Cat(S)));544 EXPECT_EQ(Cat("const struct Foo target{0};"),545 runCheckOnCode<PointeeLTransform>(Cat(S)));546 547 EXPECT_EQ(Cat("struct Foo const target{0};"),548 runCheckOnCode<ValueRTransform>(Cat(S)));549 EXPECT_EQ(Cat("struct Foo const target{0};"),550 runCheckOnCode<PointeeRTransform>(Cat(S)));551 552 S = "Foo target{0};";553 EXPECT_EQ(Cat("const Foo target{0};"),554 runCheckOnCode<ValueLTransform>(Cat(S)));555 EXPECT_EQ(Cat("const Foo target{0};"),556 runCheckOnCode<PointeeLTransform>(Cat(S)));557 558 EXPECT_EQ(Cat("Foo const target{0};"),559 runCheckOnCode<ValueRTransform>(Cat(S)));560 EXPECT_EQ(Cat("Foo const target{0};"),561 runCheckOnCode<PointeeRTransform>(Cat(S)));562 563 S = "Foo (target){0};";564 EXPECT_EQ(Cat("const Foo (target){0};"),565 runCheckOnCode<ValueLTransform>(Cat(S)));566 EXPECT_EQ(Cat("const Foo (target){0};"),567 runCheckOnCode<PointeeLTransform>(Cat(S)));568 569 EXPECT_EQ(Cat("Foo const (target){0};"),570 runCheckOnCode<ValueRTransform>(Cat(S)));571 EXPECT_EQ(Cat("Foo const (target){0};"),572 runCheckOnCode<PointeeRTransform>(Cat(S)));573 574 S = "struct S { int i; } target = { 0 };";575 EXPECT_EQ("const struct S { int i; } target = { 0 };",576 runCheckOnCode<ValueLTransform>(S));577 EXPECT_EQ("const struct S { int i; } target = { 0 };",578 runCheckOnCode<PointeeLTransform>(S));579 580 EXPECT_EQ("struct S { int i; } const target = { 0 };",581 runCheckOnCode<PointeeRTransform>(S));582 EXPECT_EQ("struct S { int i; } const target = { 0 };",583 runCheckOnCode<PointeeRTransform>(S));584 585 S = "struct { int i; } target = { 0 };";586 EXPECT_EQ("const struct { int i; } target = { 0 };",587 runCheckOnCode<ValueLTransform>(S));588 EXPECT_EQ("const struct { int i; } target = { 0 };",589 runCheckOnCode<PointeeLTransform>(S));590 591 EXPECT_EQ("struct { int i; } const target = { 0 };",592 runCheckOnCode<PointeeRTransform>(S));593 EXPECT_EQ("struct { int i; } const target = { 0 };",594 runCheckOnCode<PointeeRTransform>(S));595}596TEST(TagTypes, Class) {597 StringRef T = "class Foo { int data; int method(); };\n";598 StringRef S = "class Foo target;";599 auto Cat = [&T](StringRef S) { return (T + S).str(); };600 601 EXPECT_EQ(Cat("const class Foo target;"),602 runCheckOnCode<ValueLTransform>(Cat(S)));603 EXPECT_EQ(Cat("const class Foo target;"),604 runCheckOnCode<PointeeLTransform>(Cat(S)));605 606 EXPECT_EQ(Cat("class Foo const target;"),607 runCheckOnCode<ValueRTransform>(Cat(S)));608 EXPECT_EQ(Cat("class Foo const target;"),609 runCheckOnCode<PointeeRTransform>(Cat(S)));610 611 S = "Foo target;";612 EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode<ValueLTransform>(Cat(S)));613 EXPECT_EQ(Cat("const Foo target;"),614 runCheckOnCode<PointeeLTransform>(Cat(S)));615 616 EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode<ValueRTransform>(Cat(S)));617 EXPECT_EQ(Cat("Foo const target;"),618 runCheckOnCode<PointeeRTransform>(Cat(S)));619 620 S = "Foo (target);";621 EXPECT_EQ(Cat("const Foo (target);"),622 runCheckOnCode<ValueLTransform>(Cat(S)));623 EXPECT_EQ(Cat("const Foo (target);"),624 runCheckOnCode<PointeeLTransform>(Cat(S)));625 626 EXPECT_EQ(Cat("Foo const (target);"),627 runCheckOnCode<ValueRTransform>(Cat(S)));628 EXPECT_EQ(Cat("Foo const (target);"),629 runCheckOnCode<PointeeRTransform>(Cat(S)));630}631TEST(TagTypes, Enum) {632 StringRef T = "enum Foo { N_ONE, N_TWO, N_THREE };\n";633 StringRef S = "enum Foo target;";634 auto Cat = [&T](StringRef S) { return (T + S).str(); };635 636 EXPECT_EQ(Cat("const enum Foo target;"),637 runCheckOnCode<ValueLTransform>(Cat(S)));638 EXPECT_EQ(Cat("const enum Foo target;"),639 runCheckOnCode<PointeeLTransform>(Cat(S)));640 641 EXPECT_EQ(Cat("enum Foo const target;"),642 runCheckOnCode<ValueRTransform>(Cat(S)));643 EXPECT_EQ(Cat("enum Foo const target;"),644 runCheckOnCode<PointeeRTransform>(Cat(S)));645 646 S = "Foo target;";647 EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode<ValueLTransform>(Cat(S)));648 EXPECT_EQ(Cat("const Foo target;"),649 runCheckOnCode<PointeeLTransform>(Cat(S)));650 651 EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode<ValueRTransform>(Cat(S)));652 EXPECT_EQ(Cat("Foo const target;"),653 runCheckOnCode<PointeeRTransform>(Cat(S)));654 655 S = "Foo (target);";656 EXPECT_EQ(Cat("const Foo (target);"),657 runCheckOnCode<ValueLTransform>(Cat(S)));658 EXPECT_EQ(Cat("const Foo (target);"),659 runCheckOnCode<PointeeLTransform>(Cat(S)));660 661 EXPECT_EQ(Cat("Foo const (target);"),662 runCheckOnCode<ValueRTransform>(Cat(S)));663 EXPECT_EQ(Cat("Foo const (target);"),664 runCheckOnCode<PointeeRTransform>(Cat(S)));665}666TEST(TagTypes, Union) {667 StringRef T = "union Foo { int yay; float nej; };\n";668 StringRef S = "union Foo target;";669 auto Cat = [&T](StringRef S) { return (T + S).str(); };670 671 EXPECT_EQ(Cat("const union Foo target;"),672 runCheckOnCode<ValueLTransform>(Cat(S)));673 EXPECT_EQ(Cat("const union Foo target;"),674 runCheckOnCode<PointeeLTransform>(Cat(S)));675 676 EXPECT_EQ(Cat("union Foo const target;"),677 runCheckOnCode<ValueRTransform>(Cat(S)));678 EXPECT_EQ(Cat("union Foo const target;"),679 runCheckOnCode<PointeeRTransform>(Cat(S)));680 681 S = "Foo target;";682 EXPECT_EQ(Cat("const Foo target;"), runCheckOnCode<ValueLTransform>(Cat(S)));683 EXPECT_EQ(Cat("const Foo target;"),684 runCheckOnCode<PointeeLTransform>(Cat(S)));685 686 EXPECT_EQ(Cat("Foo const target;"), runCheckOnCode<ValueRTransform>(Cat(S)));687 EXPECT_EQ(Cat("Foo const target;"),688 runCheckOnCode<PointeeRTransform>(Cat(S)));689 690 S = "Foo (target);";691 EXPECT_EQ(Cat("const Foo (target);"),692 runCheckOnCode<ValueLTransform>(Cat(S)));693 EXPECT_EQ(Cat("const Foo (target);"),694 runCheckOnCode<PointeeLTransform>(Cat(S)));695 696 EXPECT_EQ(Cat("Foo const (target);"),697 runCheckOnCode<ValueRTransform>(Cat(S)));698 EXPECT_EQ(Cat("Foo const (target);"),699 runCheckOnCode<PointeeRTransform>(Cat(S)));700}701 702// ----------------------------------------------------------------------------703// Test Macro expansions.704// ----------------------------------------------------------------------------705 706TEST(Macro, AllInMacro) {707 StringRef T = "#define DEFINE_VARIABLE int target = 42\n";708 StringRef S = "DEFINE_VARIABLE;";709 auto Cat = [&T](StringRef S) { return (T + S).str(); };710 711 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<ValueLTransform>(Cat(S)));712 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<ValueRTransform>(Cat(S)));713 714 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<PointeeLTransform>(Cat(S)));715 EXPECT_EQ(Cat("DEFINE_VARIABLE;"), runCheckOnCode<PointeeRTransform>(Cat(S)));716}717TEST(Macro, MacroParameter) {718 StringRef T = "#define DEFINE_VARIABLE(X) int X = 42\n";719 StringRef S = "DEFINE_VARIABLE(target);";720 auto Cat = [&T](StringRef S) { return (T + S).str(); };721 722 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),723 runCheckOnCode<ValueLTransform>(Cat(S)));724 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),725 runCheckOnCode<ValueRTransform>(Cat(S)));726 727 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),728 runCheckOnCode<PointeeLTransform>(Cat(S)));729 EXPECT_EQ(Cat("DEFINE_VARIABLE(target);"),730 runCheckOnCode<PointeeRTransform>(Cat(S)));731}732TEST(Macro, MacroTypeValue) {733 StringRef T = "#define BAD_TYPEDEF int\n";734 StringRef S = "BAD_TYPEDEF target = 42;";735 auto Cat = [&T](StringRef S) { return (T + S).str(); };736 737 EXPECT_EQ(Cat("BAD_TYPEDEF target = 42;"),738 runCheckOnCode<ValueLTransform>(Cat(S)));739 EXPECT_EQ(Cat("BAD_TYPEDEF target = 42;"),740 runCheckOnCode<PointeeLTransform>(Cat(S)));741 742 EXPECT_EQ(Cat("BAD_TYPEDEF const target = 42;"),743 runCheckOnCode<PointeeRTransform>(Cat(S)));744 EXPECT_EQ(Cat("BAD_TYPEDEF const target = 42;"),745 runCheckOnCode<ValueRTransform>(Cat(S)));746}747TEST(Macro, MacroTypePointer) {748 StringRef T = "#define BAD_TYPEDEF int *\n";749 StringRef S = "BAD_TYPEDEF target = nullptr;";750 auto Cat = [&T](StringRef S) { return (T + S).str(); };751 752 EXPECT_EQ(Cat("BAD_TYPEDEF const target = nullptr;"),753 runCheckOnCode<ValueLTransform>(Cat(S)));754 EXPECT_EQ(Cat("BAD_TYPEDEF const target = nullptr;"),755 runCheckOnCode<ValueRTransform>(Cat(S)));756 757 // FIXME: Failing even all parts seem to bail-out in for isMacroID()758 // The macro itself is changed here and below which is not intended.759 EXPECT_NE(Cat("BAD_TYPEDEF target = nullptr;"),760 runCheckOnCode<PointeeRTransform>(Cat(S)));761 EXPECT_EQ(Cat("BAD_TYPEDEF target = nullptr;"),762 runCheckOnCode<PointeeLTransform>(Cat(S)));763}764TEST(Macro, MacroTypeReference) {765 StringRef T = "static int g = 42;\n#define BAD_TYPEDEF int&\n";766 StringRef S = "BAD_TYPEDEF target = g;";767 auto Cat = [&T](StringRef S) { return (T + S).str(); };768 769 EXPECT_EQ(Cat("BAD_TYPEDEF target = g;"),770 runCheckOnCode<ValueLTransform>(Cat(S)));771 // FIXME: Failing even all parts seem to bail-out in for isMacroID()772 EXPECT_NE(Cat("BAD_TYPEDEF target = g;"),773 runCheckOnCode<ValueRTransform>(Cat(S)));774 775 EXPECT_EQ(Cat("BAD_TYPEDEF target = g;"),776 runCheckOnCode<PointeeLTransform>(Cat(S)));777 // FIXME: Failing even all parts seem to bail-out in for isMacroID()778 EXPECT_NE(Cat("BAD_TYPEDEF target = g;"),779 runCheckOnCode<PointeeRTransform>(Cat(S)));780}781// This failed in LLVM.782TEST(Macro, Variable) {783 StringRef M = "#define DEBUG(X) do { if (1) { X; } } while (0)\n";784 StringRef F = "void foo() ";785 StringRef V = "{ DEBUG(int target = 42;); }";786 787 auto Cat = [&](StringRef S) { return (M + F + V).str(); };788 789 EXPECT_EQ(Cat("{ DEBUG(const int target = 42;); }"),790 runCheckOnCode<ValueLTransform>(Cat(V)));791 EXPECT_EQ(Cat("{ DEBUG(int const target = 42;); }"),792 runCheckOnCode<ValueRTransform>(Cat(V)));793}794TEST(Macro, RangeLoop) {795 StringRef M = "#define DEBUG(X) do { if (1) { X; }} while (false)\n";796 StringRef F = "void foo() { char array[] = {'a', 'b', 'c'}; ";797 StringRef V = "DEBUG( for(auto& target: array) 10 + target; );";798 StringRef E = "}";799 800 auto Cat = [&](StringRef S) { return (M + F + V + E).str(); };801 802 EXPECT_EQ(Cat("DEBUG( for(const auto& target: array); );"),803 runCheckOnCode<ValueLTransform>(Cat(V)));804 EXPECT_EQ(Cat("DEBUG( for(auto const& target: array); );"),805 runCheckOnCode<ValueRTransform>(Cat(V)));806}807 808// ----------------------------------------------------------------------------809// Test template code.810// ----------------------------------------------------------------------------811 812TEST(Template, TemplateVariable) {813 StringRef T = "template <typename T> T target = 3.1415;";814 815 EXPECT_EQ("template <typename T> const T target = 3.1415;",816 runCheckOnCode<ValueLTransform>(T));817 EXPECT_EQ("template <typename T> T const target = 3.1415;",818 runCheckOnCode<ValueRTransform>(T));819 820 EXPECT_EQ("template <typename T> const T target = 3.1415;",821 runCheckOnCode<PointeeLTransform>(T));822 EXPECT_EQ("template <typename T> T const target = 3.1415;",823 runCheckOnCode<PointeeRTransform>(T));824}825TEST(Template, FunctionValue) {826 StringRef T = "template <typename T> void f(T v) \n";827 StringRef S = "{ T target = v; }";828 auto Cat = [&T](StringRef S) { return (T + S).str(); };829 830 EXPECT_EQ(Cat("{ const T target = v; }"),831 runCheckOnCode<ValueLTransform>(Cat(S)));832 EXPECT_EQ(Cat("{ T const target = v; }"),833 runCheckOnCode<ValueRTransform>(Cat(S)));834 835 EXPECT_EQ(Cat("{ const T target = v; }"),836 runCheckOnCode<PointeeLTransform>(Cat(S)));837 EXPECT_EQ(Cat("{ T const target = v; }"),838 runCheckOnCode<PointeeRTransform>(Cat(S)));839}840TEST(Template, FunctionPointer) {841 StringRef T = "template <typename T> void f(T* v) \n";842 StringRef S = "{ T* target = v; }";843 auto Cat = [&T](StringRef S) { return (T + S).str(); };844 845 EXPECT_EQ(Cat("{ T* const target = v; }"),846 runCheckOnCode<ValueLTransform>(Cat(S)));847 EXPECT_EQ(Cat("{ T* const target = v; }"),848 runCheckOnCode<ValueRTransform>(Cat(S)));849 850 EXPECT_EQ(Cat("{ const T* target = v; }"),851 runCheckOnCode<PointeeLTransform>(Cat(S)));852 EXPECT_EQ(Cat("{ T const* target = v; }"),853 runCheckOnCode<PointeeRTransform>(Cat(S)));854}855TEST(Template, FunctionReference) {856 StringRef T = "template <typename T> void f(T& v) \n";857 StringRef S = "{ T& target = v; }";858 auto Cat = [&T](StringRef S) { return (T + S).str(); };859 860 EXPECT_EQ(Cat("{ const T& target = v; }"),861 runCheckOnCode<ValueLTransform>(Cat(S)));862 EXPECT_EQ(Cat("{ T const& target = v; }"),863 runCheckOnCode<ValueRTransform>(Cat(S)));864 865 EXPECT_EQ(Cat("{ const T& target = v; }"),866 runCheckOnCode<PointeeLTransform>(Cat(S)));867 EXPECT_EQ(Cat("{ T const& target = v; }"),868 runCheckOnCode<PointeeRTransform>(Cat(S)));869}870TEST(Template, MultiInstantiationsFunction) {871 StringRef T = "template <typename T> void f(T v) \n";872 StringRef S = "{ T target = v; }";873 StringRef InstantStart = "void calls() {\n";874 StringRef InstValue = "f<int>(42);\n";875 StringRef InstConstValue = "f<const int>(42);\n";876 StringRef InstPointer = "f<int*>(nullptr);\n";877 StringRef InstPointerConst = "f<int* const>(nullptr);\n";878 StringRef InstConstPointer = "f<const int*>(nullptr);\n";879 StringRef InstConstPointerConst = "f<const int* const>(nullptr);\n";880 StringRef InstRef = "int i = 42;\nf<int&>(i);\n";881 StringRef InstConstRef = "f<const int&>(i);\n";882 StringRef InstantEnd = "}";883 auto Cat = [&](StringRef Target) {884 return (T + Target + InstantStart + InstValue + InstConstValue +885 InstPointer + InstPointerConst + InstConstPointer +886 InstConstPointerConst + InstRef + InstConstRef + InstantEnd)887 .str();888 };889 890 EXPECT_EQ(Cat("{ const T target = v; }"),891 runCheckOnCode<ValueLTransform>(Cat(S)));892 EXPECT_EQ(Cat("{ T const target = v; }"),893 runCheckOnCode<ValueRTransform>(Cat(S)));894 895 EXPECT_EQ(Cat("{ const T target = v; }"),896 runCheckOnCode<PointeeLTransform>(Cat(S)));897 EXPECT_EQ(Cat("{ T const target = v; }"),898 runCheckOnCode<PointeeRTransform>(Cat(S)));899}900 901TEST(Template, StructValue) {902 StringRef T = "template <typename T> struct S { void f(T& v) \n";903 StringRef S = "{ T target = v; }";904 StringRef End = "\n};";905 auto Cat = [&T, &End](StringRef S) { return (T + S + End).str(); };906 907 EXPECT_EQ(Cat("{ const T target = v; }"),908 runCheckOnCode<ValueLTransform>(Cat(S)));909 EXPECT_EQ(Cat("{ T const target = v; }"),910 runCheckOnCode<ValueRTransform>(Cat(S)));911 912 EXPECT_EQ(Cat("{ const T target = v; }"),913 runCheckOnCode<PointeeLTransform>(Cat(S)));914 EXPECT_EQ(Cat("{ T const target = v; }"),915 runCheckOnCode<PointeeRTransform>(Cat(S)));916}917TEST(Template, StructPointer) {918 StringRef T = "template <typename T> struct S { void f(T* v) \n";919 StringRef S = "{ T* target = v; }";920 StringRef End = "\n};";921 auto Cat = [&T, &End](StringRef S) { return (T + S + End).str(); };922 923 EXPECT_EQ(Cat("{ T* const target = v; }"),924 runCheckOnCode<ValueLTransform>(Cat(S)));925 EXPECT_EQ(Cat("{ T* const target = v; }"),926 runCheckOnCode<ValueRTransform>(Cat(S)));927 928 EXPECT_EQ(Cat("{ const T* target = v; }"),929 runCheckOnCode<PointeeLTransform>(Cat(S)));930 EXPECT_EQ(Cat("{ T const* target = v; }"),931 runCheckOnCode<PointeeRTransform>(Cat(S)));932}933TEST(Template, StructReference) {934 StringRef T = "template <typename T> struct S { void f(T& v) \n";935 StringRef S = "{ T& target = v; }";936 StringRef End = "\n};";937 auto Cat = [&T, &End](StringRef S) { return (T + S + End).str(); };938 939 EXPECT_EQ(Cat("{ const T& target = v; }"),940 runCheckOnCode<ValueLTransform>(Cat(S)));941 EXPECT_EQ(Cat("{ T const& target = v; }"),942 runCheckOnCode<ValueRTransform>(Cat(S)));943 944 EXPECT_EQ(Cat("{ const T& target = v; }"),945 runCheckOnCode<PointeeLTransform>(Cat(S)));946 EXPECT_EQ(Cat("{ T const& target = v; }"),947 runCheckOnCode<PointeeRTransform>(Cat(S)));948}949TEST(Template, DependentReturnFunction) {950 StringRef TS = "template <typename T> struct TS { using value_type = T; };";951 StringRef T = "template <typename T> void foo() ";952 StringRef S = "{ typename T::value_type target; }";953 auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };954 955 EXPECT_EQ(Cat("{ const typename T::value_type target; }"),956 runCheckOnCode<ValueLTransform>(Cat(S)));957 EXPECT_EQ(Cat("{ typename T::value_type const target; }"),958 runCheckOnCode<ValueRTransform>(Cat(S)));959 960 EXPECT_EQ(Cat("{ const typename T::value_type target; }"),961 runCheckOnCode<PointeeLTransform>(Cat(S)));962 EXPECT_EQ(Cat("{ typename T::value_type const target; }"),963 runCheckOnCode<PointeeRTransform>(Cat(S)));964}965TEST(Template, DependentReturnPointerFunction) {966 StringRef TS = "template <typename T> struct TS { using value_type = T; };";967 StringRef T = "template <typename T> void foo() ";968 StringRef S = "{ typename T::value_type *target; }";969 auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };970 971 EXPECT_EQ(Cat("{ typename T::value_type *const target; }"),972 runCheckOnCode<ValueLTransform>(Cat(S)));973 EXPECT_EQ(Cat("{ typename T::value_type *const target; }"),974 runCheckOnCode<ValueRTransform>(Cat(S)));975 976 EXPECT_EQ(Cat("{ const typename T::value_type *target; }"),977 runCheckOnCode<PointeeLTransform>(Cat(S)));978 EXPECT_EQ(Cat("{ typename T::value_type const*target; }"),979 runCheckOnCode<PointeeRTransform>(Cat(S)));980}981TEST(Template, DependentReturnReferenceFunction) {982 StringRef TS = "template <typename T> struct TS { using value_type = T; };";983 StringRef T = "template <typename T> void foo(T& f) ";984 StringRef S = "{ typename T::value_type &target = f; }";985 auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };986 987 EXPECT_EQ(Cat("{ const typename T::value_type &target = f; }"),988 runCheckOnCode<ValueLTransform>(Cat(S)));989 EXPECT_EQ(Cat("{ typename T::value_type const&target = f; }"),990 runCheckOnCode<ValueRTransform>(Cat(S)));991 992 EXPECT_EQ(Cat("{ const typename T::value_type &target = f; }"),993 runCheckOnCode<PointeeLTransform>(Cat(S)));994 EXPECT_EQ(Cat("{ typename T::value_type const&target = f; }"),995 runCheckOnCode<PointeeRTransform>(Cat(S)));996}997TEST(Template, VectorLikeType) {998 StringRef TS = "template <typename T> struct TS { TS(const T&) {} }; ";999 StringRef T = "void foo() ";1000 StringRef S = "{ TS<int> target(42); }";1001 auto Cat = [&TS, &T](StringRef S) { return (TS + T + S).str(); };1002 1003 EXPECT_EQ(Cat("{ const TS<int> target(42); }"),1004 runCheckOnCode<ValueLTransform>(Cat(S)));1005 EXPECT_EQ(Cat("{ TS<int> const target(42); }"),1006 runCheckOnCode<ValueRTransform>(Cat(S)));1007 1008 EXPECT_EQ(Cat("{ const TS<int> target(42); }"),1009 runCheckOnCode<PointeeLTransform>(Cat(S)));1010 EXPECT_EQ(Cat("{ TS<int> const target(42); }"),1011 runCheckOnCode<PointeeRTransform>(Cat(S)));1012}1013TEST(Template, SpecializedTemplate) {1014 StringRef TS = "template <typename T = int> struct TS { TS(const T&) {} }; ";1015 StringRef TS2 = "template <> struct TS<double> { TS(const double&) {} }; ";1016 StringRef T = "void foo() ";1017 StringRef S = "{ TS<double> target(42.42); }";1018 auto Cat = [&](StringRef S) { return (TS + TS2 + T + S).str(); };1019 1020 EXPECT_EQ(Cat("{ const TS<double> target(42.42); }"),1021 runCheckOnCode<ValueLTransform>(Cat(S)));1022 EXPECT_EQ(Cat("{ TS<double> const target(42.42); }"),1023 runCheckOnCode<ValueRTransform>(Cat(S)));1024 1025 EXPECT_EQ(Cat("{ const TS<double> target(42.42); }"),1026 runCheckOnCode<PointeeLTransform>(Cat(S)));1027 EXPECT_EQ(Cat("{ TS<double> const target(42.42); }"),1028 runCheckOnCode<PointeeRTransform>(Cat(S)));1029}1030 1031// -----------------------------------------------------------------------------1032// ObjC Pointers1033// -----------------------------------------------------------------------------1034 1035TEST(ObjC, SimplePointers) {1036 StringRef S = "int * target = 0;";1037 EXPECT_EQ(runCheckOnCode<PointeeLTransform>(S, nullptr, "input.m"),1038 "const int * target = 0;");1039 EXPECT_EQ(runCheckOnCode<PointeeRTransform>(S, nullptr, "input.m"),1040 "int const* target = 0;");1041 EXPECT_EQ(runCheckOnCode<ValueLTransform>(S, nullptr, "input.m"),1042 "int * const target = 0;");1043 EXPECT_EQ(runCheckOnCode<ValueRTransform>(S, nullptr, "input.m"),1044 "int * const target = 0;");1045}1046TEST(ObjC, ClassPointer) {1047 StringRef TB = "@class Object;\nint main() {\n";1048 StringRef S = "Object *target;";1049 StringRef TE = "\n}";1050 auto Cat = [&](StringRef S) { return (TB + S + TE).str(); };1051 1052 // FIXME: Not done properly for some reason.1053 EXPECT_NE(runCheckOnCode<PointeeLTransform>(Cat(S), nullptr, "input.m"),1054 Cat("const Object *target;"));1055 EXPECT_NE(runCheckOnCode<PointeeRTransform>(Cat(S), nullptr, "input.m"),1056 Cat("Object const*target;"));1057 EXPECT_NE(runCheckOnCode<ValueLTransform>(Cat(S), nullptr, "input.m"),1058 Cat("Object *const target;"));1059 EXPECT_NE(runCheckOnCode<ValueRTransform>(Cat(S), nullptr, "input.m"),1060 Cat("Object *const target;"));1061}1062TEST(ObjC, InterfacePointer) {1063 StringRef TB = "@interface I\n";1064 StringRef S = "- (void) foo: (int *) target;";1065 StringRef TE = "\n@end";1066 auto Cat = [&](StringRef S) { return (TB + S + TE).str(); };1067 1068 EXPECT_EQ(runCheckOnCode<PointeeLTransform>(Cat(S), nullptr, "input.m"),1069 Cat("- (void) foo: (const int *) target;"));1070 EXPECT_EQ(runCheckOnCode<PointeeRTransform>(Cat(S), nullptr, "input.m"),1071 Cat("- (void) foo: (int const*) target;"));1072 // FIXME: These transformations are incorrect. ObjC seems to need1073 // RParenSkipping which is not implemented.1074 EXPECT_NE(runCheckOnCode<ValueLTransform>(Cat(S), nullptr, "input.m"),1075 Cat("- (void) foo: (int * const) target;"));1076 EXPECT_NE(runCheckOnCode<ValueRTransform>(Cat(S), nullptr, "input.m"),1077 Cat("- (void) foo: (int * const) target;"));1078}1079 1080} // namespace test1081} // namespace tidy1082} // namespace clang1083