xref: /llvm-project/clang-tools-extra/clangd/unittests/tweaks/DefineInlineTests.cpp (revision 4d006520b8c0cc3a52913b4665bf741c737e5592)
15934a791SAdam Czachorowski //===-- DefineInlineTests.cpp -----------------------------------*- C++ -*-===//
25934a791SAdam Czachorowski //
35934a791SAdam Czachorowski // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45934a791SAdam Czachorowski // See https://llvm.org/LICENSE.txt for license information.
55934a791SAdam Czachorowski // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65934a791SAdam Czachorowski //
75934a791SAdam Czachorowski //===----------------------------------------------------------------------===//
85934a791SAdam Czachorowski 
95934a791SAdam Czachorowski #include "TweakTesting.h"
10*4d006520SSam McCall #include "TestFS.h"
115934a791SAdam Czachorowski #include "gmock/gmock.h"
125934a791SAdam Czachorowski #include "gtest/gtest.h"
135934a791SAdam Czachorowski 
145934a791SAdam Czachorowski using ::testing::ElementsAre;
155934a791SAdam Czachorowski 
165934a791SAdam Czachorowski namespace clang {
175934a791SAdam Czachorowski namespace clangd {
185934a791SAdam Czachorowski namespace {
195934a791SAdam Czachorowski 
205934a791SAdam Czachorowski TWEAK_TEST(DefineInline);
215934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TriggersOnFunctionDecl)225934a791SAdam Czachorowski TEST_F(DefineInlineTest, TriggersOnFunctionDecl) {
235934a791SAdam Czachorowski   // Basic check for function body and signature.
245934a791SAdam Czachorowski   EXPECT_AVAILABLE(R"cpp(
255934a791SAdam Czachorowski   class Bar {
265934a791SAdam Czachorowski     void baz();
275934a791SAdam Czachorowski   };
285934a791SAdam Czachorowski 
295934a791SAdam Czachorowski   [[void [[Bar::[[b^a^z]]]]() [[{
305934a791SAdam Czachorowski     return;
315934a791SAdam Czachorowski   }]]]]
325934a791SAdam Czachorowski 
335934a791SAdam Czachorowski   void foo();
345934a791SAdam Czachorowski   [[void [[f^o^o]]() [[{
355934a791SAdam Czachorowski     return;
365934a791SAdam Czachorowski   }]]]]
375934a791SAdam Czachorowski   )cpp");
385934a791SAdam Czachorowski 
395934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
405934a791SAdam Czachorowski   // Not a definition
415934a791SAdam Czachorowski   vo^i[[d^ ^f]]^oo();
425934a791SAdam Czachorowski 
435934a791SAdam Czachorowski   [[vo^id ]]foo[[()]] {[[
445934a791SAdam Czachorowski     [[(void)(5+3);
455934a791SAdam Czachorowski     return;]]
465934a791SAdam Czachorowski   }]]
475934a791SAdam Czachorowski 
485934a791SAdam Czachorowski   // Definition with no body.
495934a791SAdam Czachorowski   class Bar { Bar() = def^ault; };
505934a791SAdam Czachorowski   )cpp");
515934a791SAdam Czachorowski }
525934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,NoForwardDecl)535934a791SAdam Czachorowski TEST_F(DefineInlineTest, NoForwardDecl) {
545934a791SAdam Czachorowski   Header = "void bar();";
555934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
565934a791SAdam Czachorowski   void bar() {
575934a791SAdam Czachorowski     return;
585934a791SAdam Czachorowski   }
595934a791SAdam Czachorowski   // FIXME: Generate a decl in the header.
605934a791SAdam Czachorowski   void fo^o() {
615934a791SAdam Czachorowski     return;
625934a791SAdam Czachorowski   })cpp");
635934a791SAdam Czachorowski }
645934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,ReferencedDecls)655934a791SAdam Czachorowski TEST_F(DefineInlineTest, ReferencedDecls) {
665934a791SAdam Czachorowski   EXPECT_AVAILABLE(R"cpp(
675934a791SAdam Czachorowski     void bar();
685934a791SAdam Czachorowski     void foo(int test);
695934a791SAdam Czachorowski 
705934a791SAdam Czachorowski     void fo^o(int baz) {
715934a791SAdam Czachorowski       int x = 10;
725934a791SAdam Czachorowski       bar();
735934a791SAdam Czachorowski     })cpp");
745934a791SAdam Czachorowski 
755934a791SAdam Czachorowski   // Internal symbol usage.
765934a791SAdam Czachorowski   Header = "void foo(int test);";
775934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
785934a791SAdam Czachorowski     void bar();
795934a791SAdam Czachorowski     void fo^o(int baz) {
805934a791SAdam Czachorowski       int x = 10;
815934a791SAdam Czachorowski       bar();
825934a791SAdam Czachorowski     })cpp");
835934a791SAdam Czachorowski 
845934a791SAdam Czachorowski   // Becomes available after making symbol visible.
855934a791SAdam Czachorowski   Header = "void bar();" + Header;
865934a791SAdam Czachorowski   EXPECT_AVAILABLE(R"cpp(
875934a791SAdam Czachorowski     void fo^o(int baz) {
885934a791SAdam Czachorowski       int x = 10;
895934a791SAdam Czachorowski       bar();
905934a791SAdam Czachorowski     })cpp");
915934a791SAdam Czachorowski 
925934a791SAdam Czachorowski   // FIXME: Move declaration below bar to make it visible.
935934a791SAdam Czachorowski   Header.clear();
945934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
955934a791SAdam Czachorowski     void foo();
965934a791SAdam Czachorowski     void bar();
975934a791SAdam Czachorowski 
985934a791SAdam Czachorowski     void fo^o() {
995934a791SAdam Czachorowski       bar();
1005934a791SAdam Czachorowski     })cpp");
1015934a791SAdam Czachorowski 
1025934a791SAdam Czachorowski   // Order doesn't matter within a class.
1035934a791SAdam Czachorowski   EXPECT_AVAILABLE(R"cpp(
1045934a791SAdam Czachorowski     class Bar {
1055934a791SAdam Czachorowski       void foo();
1065934a791SAdam Czachorowski       void bar();
1075934a791SAdam Czachorowski     };
1085934a791SAdam Czachorowski 
1095934a791SAdam Czachorowski     void Bar::fo^o() {
1105934a791SAdam Czachorowski       bar();
1115934a791SAdam Czachorowski     })cpp");
1125934a791SAdam Czachorowski 
1135934a791SAdam Czachorowski   // FIXME: Perform include insertion to make symbol visible.
1145934a791SAdam Czachorowski   ExtraFiles["a.h"] = "void bar();";
1155934a791SAdam Czachorowski   Header = "void foo(int test);";
1165934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
1175934a791SAdam Czachorowski     #include "a.h"
1185934a791SAdam Czachorowski     void fo^o(int baz) {
1195934a791SAdam Czachorowski       int x = 10;
1205934a791SAdam Czachorowski       bar();
1215934a791SAdam Czachorowski     })cpp");
1225934a791SAdam Czachorowski }
1235934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TemplateSpec)1245934a791SAdam Czachorowski TEST_F(DefineInlineTest, TemplateSpec) {
1255934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
1265934a791SAdam Czachorowski     template <typename T> void foo();
1275934a791SAdam Czachorowski     template<> void foo<char>();
1285934a791SAdam Czachorowski 
1295934a791SAdam Czachorowski     template<> void f^oo<int>() {
1305934a791SAdam Czachorowski     })cpp");
1315934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
1325934a791SAdam Czachorowski     template <typename T> void foo();
1335934a791SAdam Czachorowski 
1345934a791SAdam Czachorowski     template<> void f^oo<int>() {
1355934a791SAdam Czachorowski     })cpp");
1365934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
1375934a791SAdam Czachorowski     template <typename T> struct Foo { void foo(); };
1385934a791SAdam Czachorowski 
1395934a791SAdam Czachorowski     template <typename T> void Foo<T>::f^oo() {
1405934a791SAdam Czachorowski     })cpp");
1415934a791SAdam Czachorowski   EXPECT_AVAILABLE(R"cpp(
1425934a791SAdam Czachorowski     template <typename T> void foo();
1435934a791SAdam Czachorowski     void bar();
1445934a791SAdam Czachorowski     template <> void foo<int>();
1455934a791SAdam Czachorowski 
1465934a791SAdam Czachorowski     template<> void f^oo<int>() {
1475934a791SAdam Czachorowski       bar();
1485934a791SAdam Czachorowski     })cpp");
1495934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
1505934a791SAdam Czachorowski     namespace bar {
1515934a791SAdam Czachorowski       template <typename T> void f^oo() {}
1525934a791SAdam Czachorowski       template void foo<int>();
1535934a791SAdam Czachorowski     })cpp");
1545934a791SAdam Czachorowski }
1555934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,CheckForCanonDecl)1565934a791SAdam Czachorowski TEST_F(DefineInlineTest, CheckForCanonDecl) {
1575934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
1585934a791SAdam Czachorowski     void foo();
1595934a791SAdam Czachorowski 
1605934a791SAdam Czachorowski     void bar() {}
1615934a791SAdam Czachorowski     void f^oo() {
1625934a791SAdam Czachorowski       // This bar normally refers to the definition just above, but it is not
1635934a791SAdam Czachorowski       // visible from the forward declaration of foo.
1645934a791SAdam Czachorowski       bar();
1655934a791SAdam Czachorowski     })cpp");
1665934a791SAdam Czachorowski   // Make it available with a forward decl.
1675934a791SAdam Czachorowski   EXPECT_AVAILABLE(R"cpp(
1685934a791SAdam Czachorowski     void bar();
1695934a791SAdam Czachorowski     void foo();
1705934a791SAdam Czachorowski 
1715934a791SAdam Czachorowski     void bar() {}
1725934a791SAdam Czachorowski     void f^oo() {
1735934a791SAdam Czachorowski       bar();
1745934a791SAdam Czachorowski     })cpp");
1755934a791SAdam Czachorowski }
1765934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,UsingShadowDecls)1775934a791SAdam Czachorowski TEST_F(DefineInlineTest, UsingShadowDecls) {
1785934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
1795934a791SAdam Czachorowski   namespace ns1 { void foo(int); }
1805934a791SAdam Czachorowski   namespace ns2 { void foo(int*); }
1815934a791SAdam Czachorowski   template <typename T>
1825934a791SAdam Czachorowski   void bar();
1835934a791SAdam Czachorowski 
1845934a791SAdam Czachorowski   using ns1::foo;
1855934a791SAdam Czachorowski   using ns2::foo;
1865934a791SAdam Czachorowski 
1875934a791SAdam Czachorowski   template <typename T>
1885934a791SAdam Czachorowski   void b^ar() {
1895934a791SAdam Czachorowski     foo(T());
1905934a791SAdam Czachorowski   })cpp");
1915934a791SAdam Czachorowski }
1925934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformNestedNamespaces)1935934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformNestedNamespaces) {
194c0e3c893SChristian Kühnel   auto *Test = R"cpp(
1955934a791SAdam Czachorowski     namespace a {
1965934a791SAdam Czachorowski       void bar();
1975934a791SAdam Czachorowski       namespace b {
1985934a791SAdam Czachorowski         void baz();
1995934a791SAdam Czachorowski         namespace c {
2005934a791SAdam Czachorowski           void aux();
2015934a791SAdam Czachorowski         }
2025934a791SAdam Czachorowski       }
2035934a791SAdam Czachorowski     }
2045934a791SAdam Czachorowski 
2055934a791SAdam Czachorowski     void foo();
2065934a791SAdam Czachorowski     using namespace a;
2075934a791SAdam Czachorowski     using namespace b;
2085934a791SAdam Czachorowski     using namespace c;
2095934a791SAdam Czachorowski     void f^oo() {
2105934a791SAdam Czachorowski       bar();
2115934a791SAdam Czachorowski       a::bar();
2125934a791SAdam Czachorowski 
2135934a791SAdam Czachorowski       baz();
2145934a791SAdam Czachorowski       b::baz();
2155934a791SAdam Czachorowski       a::b::baz();
2165934a791SAdam Czachorowski 
2175934a791SAdam Czachorowski       aux();
2185934a791SAdam Czachorowski       c::aux();
2195934a791SAdam Czachorowski       b::c::aux();
2205934a791SAdam Czachorowski       a::b::c::aux();
2215934a791SAdam Czachorowski     })cpp";
222c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
2235934a791SAdam Czachorowski     namespace a {
2245934a791SAdam Czachorowski       void bar();
2255934a791SAdam Czachorowski       namespace b {
2265934a791SAdam Czachorowski         void baz();
2275934a791SAdam Czachorowski         namespace c {
2285934a791SAdam Czachorowski           void aux();
2295934a791SAdam Czachorowski         }
2305934a791SAdam Czachorowski       }
2315934a791SAdam Czachorowski     }
2325934a791SAdam Czachorowski 
2335934a791SAdam Czachorowski     void foo(){
2345934a791SAdam Czachorowski       a::bar();
2355934a791SAdam Czachorowski       a::bar();
2365934a791SAdam Czachorowski 
2375934a791SAdam Czachorowski       a::b::baz();
2385934a791SAdam Czachorowski       a::b::baz();
2395934a791SAdam Czachorowski       a::b::baz();
2405934a791SAdam Czachorowski 
2415934a791SAdam Czachorowski       a::b::c::aux();
2425934a791SAdam Czachorowski       a::b::c::aux();
2435934a791SAdam Czachorowski       a::b::c::aux();
2445934a791SAdam Czachorowski       a::b::c::aux();
2455934a791SAdam Czachorowski     }
2465934a791SAdam Czachorowski     using namespace a;
2475934a791SAdam Czachorowski     using namespace b;
2485934a791SAdam Czachorowski     using namespace c;
2495934a791SAdam Czachorowski     )cpp";
2505934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
2515934a791SAdam Czachorowski }
2525934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformUsings)2535934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformUsings) {
254c0e3c893SChristian Kühnel   auto *Test = R"cpp(
2555934a791SAdam Czachorowski     namespace a { namespace b { namespace c { void aux(); } } }
2565934a791SAdam Czachorowski 
2575934a791SAdam Czachorowski     void foo();
2585934a791SAdam Czachorowski     void f^oo() {
2595934a791SAdam Czachorowski       using namespace a;
2605934a791SAdam Czachorowski       using namespace b;
2615934a791SAdam Czachorowski       using namespace c;
2625934a791SAdam Czachorowski       using c::aux;
2635934a791SAdam Czachorowski       namespace d = c;
2645934a791SAdam Czachorowski     })cpp";
265c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
2665934a791SAdam Czachorowski     namespace a { namespace b { namespace c { void aux(); } } }
2675934a791SAdam Czachorowski 
2685934a791SAdam Czachorowski     void foo(){
2695934a791SAdam Czachorowski       using namespace a;
2705934a791SAdam Czachorowski       using namespace a::b;
2715934a791SAdam Czachorowski       using namespace a::b::c;
2725934a791SAdam Czachorowski       using a::b::c::aux;
2735934a791SAdam Czachorowski       namespace d = a::b::c;
2745934a791SAdam Czachorowski     }
2755934a791SAdam Czachorowski     )cpp";
2765934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
2775934a791SAdam Czachorowski }
2785934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformDecls)2795934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformDecls) {
280c0e3c893SChristian Kühnel   auto *Test = R"cpp(
2815934a791SAdam Czachorowski     void foo();
2825934a791SAdam Czachorowski     void f^oo() {
2835934a791SAdam Czachorowski       class Foo {
2845934a791SAdam Czachorowski       public:
2855934a791SAdam Czachorowski         void foo();
2865934a791SAdam Czachorowski         int x;
2875934a791SAdam Czachorowski       };
2885934a791SAdam Czachorowski 
2895934a791SAdam Czachorowski       enum En { Zero, One };
2905934a791SAdam Czachorowski       En x = Zero;
2915934a791SAdam Czachorowski 
2925934a791SAdam Czachorowski       enum class EnClass { Zero, One };
2935934a791SAdam Czachorowski       EnClass y = EnClass::Zero;
2945934a791SAdam Czachorowski     })cpp";
295c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
2965934a791SAdam Czachorowski     void foo(){
2975934a791SAdam Czachorowski       class Foo {
2985934a791SAdam Czachorowski       public:
2995934a791SAdam Czachorowski         void foo();
3005934a791SAdam Czachorowski         int x;
3015934a791SAdam Czachorowski       };
3025934a791SAdam Czachorowski 
3035934a791SAdam Czachorowski       enum En { Zero, One };
3045934a791SAdam Czachorowski       En x = Zero;
3055934a791SAdam Czachorowski 
3065934a791SAdam Czachorowski       enum class EnClass { Zero, One };
3075934a791SAdam Czachorowski       EnClass y = EnClass::Zero;
3085934a791SAdam Czachorowski     }
3095934a791SAdam Czachorowski     )cpp";
3105934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
3115934a791SAdam Czachorowski }
3125934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformTemplDecls)3135934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformTemplDecls) {
314c0e3c893SChristian Kühnel   auto *Test = R"cpp(
3155934a791SAdam Czachorowski     namespace a {
3165934a791SAdam Czachorowski       template <typename T> class Bar {
3175934a791SAdam Czachorowski       public:
3185934a791SAdam Czachorowski         void bar();
3195934a791SAdam Czachorowski       };
3205934a791SAdam Czachorowski       template <typename T> T bar;
3215934a791SAdam Czachorowski       template <typename T> void aux() {}
3225934a791SAdam Czachorowski     }
3235934a791SAdam Czachorowski 
3245934a791SAdam Czachorowski     void foo();
3255934a791SAdam Czachorowski 
3265934a791SAdam Czachorowski     using namespace a;
3275934a791SAdam Czachorowski     void f^oo() {
3285934a791SAdam Czachorowski       bar<Bar<int>>.bar();
3295934a791SAdam Czachorowski       aux<Bar<int>>();
3305934a791SAdam Czachorowski     })cpp";
331c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
3325934a791SAdam Czachorowski     namespace a {
3335934a791SAdam Czachorowski       template <typename T> class Bar {
3345934a791SAdam Czachorowski       public:
3355934a791SAdam Czachorowski         void bar();
3365934a791SAdam Czachorowski       };
3375934a791SAdam Czachorowski       template <typename T> T bar;
3385934a791SAdam Czachorowski       template <typename T> void aux() {}
3395934a791SAdam Czachorowski     }
3405934a791SAdam Czachorowski 
3415934a791SAdam Czachorowski     void foo(){
3425934a791SAdam Czachorowski       a::bar<a::Bar<int>>.bar();
3435934a791SAdam Czachorowski       a::aux<a::Bar<int>>();
3445934a791SAdam Czachorowski     }
3455934a791SAdam Czachorowski 
3465934a791SAdam Czachorowski     using namespace a;
3475934a791SAdam Czachorowski     )cpp";
3485934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
3495934a791SAdam Czachorowski }
3505934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformMembers)3515934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformMembers) {
352c0e3c893SChristian Kühnel   auto *Test = R"cpp(
3535934a791SAdam Czachorowski     class Foo {
3545934a791SAdam Czachorowski       void foo();
3555934a791SAdam Czachorowski     };
3565934a791SAdam Czachorowski 
3575934a791SAdam Czachorowski     void Foo::f^oo() {
3585934a791SAdam Czachorowski       return;
3595934a791SAdam Czachorowski     })cpp";
360c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
3615934a791SAdam Czachorowski     class Foo {
3625934a791SAdam Czachorowski       void foo(){
3635934a791SAdam Czachorowski       return;
3645934a791SAdam Czachorowski     }
3655934a791SAdam Czachorowski     };
3665934a791SAdam Czachorowski 
3675934a791SAdam Czachorowski     )cpp";
3685934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
3695934a791SAdam Czachorowski 
3705934a791SAdam Czachorowski   ExtraFiles["a.h"] = R"cpp(
3715934a791SAdam Czachorowski     class Foo {
3725934a791SAdam Czachorowski       void foo();
3735934a791SAdam Czachorowski     };)cpp";
3745934a791SAdam Czachorowski 
3755934a791SAdam Czachorowski   llvm::StringMap<std::string> EditedFiles;
3765934a791SAdam Czachorowski   Test = R"cpp(
3775934a791SAdam Czachorowski     #include "a.h"
3785934a791SAdam Czachorowski     void Foo::f^oo() {
3795934a791SAdam Czachorowski       return;
3805934a791SAdam Czachorowski     })cpp";
3815934a791SAdam Czachorowski   Expected = R"cpp(
3825934a791SAdam Czachorowski     #include "a.h"
3835934a791SAdam Czachorowski     )cpp";
3845934a791SAdam Czachorowski   EXPECT_EQ(apply(Test, &EditedFiles), Expected);
3855934a791SAdam Czachorowski 
3865934a791SAdam Czachorowski   Expected = R"cpp(
3875934a791SAdam Czachorowski     class Foo {
3885934a791SAdam Czachorowski       void foo(){
3895934a791SAdam Czachorowski       return;
3905934a791SAdam Czachorowski     }
3915934a791SAdam Czachorowski     };)cpp";
3925934a791SAdam Czachorowski   EXPECT_THAT(EditedFiles,
3935934a791SAdam Czachorowski               ElementsAre(FileWithContents(testPath("a.h"), Expected)));
3945934a791SAdam Czachorowski }
3955934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformDependentTypes)3965934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformDependentTypes) {
397c0e3c893SChristian Kühnel   auto *Test = R"cpp(
3985934a791SAdam Czachorowski     namespace a {
3995934a791SAdam Czachorowski       template <typename T> class Bar {};
4005934a791SAdam Czachorowski     }
4015934a791SAdam Czachorowski 
4025934a791SAdam Czachorowski     template <typename T>
4035934a791SAdam Czachorowski     void foo();
4045934a791SAdam Czachorowski 
4055934a791SAdam Czachorowski     using namespace a;
4065934a791SAdam Czachorowski     template <typename T>
4075934a791SAdam Czachorowski     void f^oo() {
4085934a791SAdam Czachorowski       Bar<T> B;
4095934a791SAdam Czachorowski       Bar<Bar<T>> q;
4105934a791SAdam Czachorowski     })cpp";
411c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
4125934a791SAdam Czachorowski     namespace a {
4135934a791SAdam Czachorowski       template <typename T> class Bar {};
4145934a791SAdam Czachorowski     }
4155934a791SAdam Czachorowski 
4165934a791SAdam Czachorowski     template <typename T>
4175934a791SAdam Czachorowski     void foo(){
4185934a791SAdam Czachorowski       a::Bar<T> B;
4195934a791SAdam Czachorowski       a::Bar<a::Bar<T>> q;
4205934a791SAdam Czachorowski     }
4215934a791SAdam Czachorowski 
4225934a791SAdam Czachorowski     using namespace a;
4235934a791SAdam Czachorowski     )cpp";
4245934a791SAdam Czachorowski 
4255934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
4265934a791SAdam Czachorowski }
4275934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformFunctionTempls)4285934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformFunctionTempls) {
4295934a791SAdam Czachorowski   // Check we select correct specialization decl.
4305934a791SAdam Czachorowski   std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
4315934a791SAdam Czachorowski       {R"cpp(
4325934a791SAdam Czachorowski           template <typename T>
4335934a791SAdam Czachorowski           void foo(T p);
4345934a791SAdam Czachorowski 
4355934a791SAdam Czachorowski           template <>
4365934a791SAdam Czachorowski           void foo<int>(int p);
4375934a791SAdam Czachorowski 
4385934a791SAdam Czachorowski           template <>
4395934a791SAdam Czachorowski           void foo<char>(char p);
4405934a791SAdam Czachorowski 
4415934a791SAdam Czachorowski           template <>
4425934a791SAdam Czachorowski           void fo^o<int>(int p) {
4435934a791SAdam Czachorowski             return;
4445934a791SAdam Czachorowski           })cpp",
4455934a791SAdam Czachorowski        R"cpp(
4465934a791SAdam Czachorowski           template <typename T>
4475934a791SAdam Czachorowski           void foo(T p);
4485934a791SAdam Czachorowski 
4495934a791SAdam Czachorowski           template <>
4505934a791SAdam Czachorowski           void foo<int>(int p){
4515934a791SAdam Czachorowski             return;
4525934a791SAdam Czachorowski           }
4535934a791SAdam Czachorowski 
4545934a791SAdam Czachorowski           template <>
4555934a791SAdam Czachorowski           void foo<char>(char p);
4565934a791SAdam Czachorowski 
4575934a791SAdam Czachorowski           )cpp"},
4585934a791SAdam Czachorowski       {// Make sure we are not selecting the first specialization all the time.
4595934a791SAdam Czachorowski        R"cpp(
4605934a791SAdam Czachorowski           template <typename T>
4615934a791SAdam Czachorowski           void foo(T p);
4625934a791SAdam Czachorowski 
4635934a791SAdam Czachorowski           template <>
4645934a791SAdam Czachorowski           void foo<int>(int p);
4655934a791SAdam Czachorowski 
4665934a791SAdam Czachorowski           template <>
4675934a791SAdam Czachorowski           void foo<char>(char p);
4685934a791SAdam Czachorowski 
4695934a791SAdam Czachorowski           template <>
4705934a791SAdam Czachorowski           void fo^o<char>(char p) {
4715934a791SAdam Czachorowski             return;
4725934a791SAdam Czachorowski           })cpp",
4735934a791SAdam Czachorowski        R"cpp(
4745934a791SAdam Czachorowski           template <typename T>
4755934a791SAdam Czachorowski           void foo(T p);
4765934a791SAdam Czachorowski 
4775934a791SAdam Czachorowski           template <>
4785934a791SAdam Czachorowski           void foo<int>(int p);
4795934a791SAdam Czachorowski 
4805934a791SAdam Czachorowski           template <>
4815934a791SAdam Czachorowski           void foo<char>(char p){
4825934a791SAdam Czachorowski             return;
4835934a791SAdam Czachorowski           }
4845934a791SAdam Czachorowski 
4855934a791SAdam Czachorowski           )cpp"},
4865934a791SAdam Czachorowski       {R"cpp(
4875934a791SAdam Czachorowski           template <typename T>
4885934a791SAdam Czachorowski           void foo(T p);
4895934a791SAdam Czachorowski 
4905934a791SAdam Czachorowski           template <>
4915934a791SAdam Czachorowski           void foo<int>(int p);
4925934a791SAdam Czachorowski 
4935934a791SAdam Czachorowski           template <typename T>
4945934a791SAdam Czachorowski           void fo^o(T p) {
4955934a791SAdam Czachorowski             return;
4965934a791SAdam Czachorowski           })cpp",
4975934a791SAdam Czachorowski        R"cpp(
4985934a791SAdam Czachorowski           template <typename T>
4995934a791SAdam Czachorowski           void foo(T p){
5005934a791SAdam Czachorowski             return;
5015934a791SAdam Czachorowski           }
5025934a791SAdam Czachorowski 
5035934a791SAdam Czachorowski           template <>
5045934a791SAdam Czachorowski           void foo<int>(int p);
5055934a791SAdam Czachorowski 
5065934a791SAdam Czachorowski           )cpp"},
5075934a791SAdam Czachorowski   };
5085934a791SAdam Czachorowski   for (const auto &Case : Cases)
5095934a791SAdam Czachorowski     EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
5105934a791SAdam Czachorowski }
5115934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformTypeLocs)5125934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformTypeLocs) {
513c0e3c893SChristian Kühnel   auto *Test = R"cpp(
5145934a791SAdam Czachorowski     namespace a {
5155934a791SAdam Czachorowski       template <typename T> class Bar {
5165934a791SAdam Czachorowski       public:
5175934a791SAdam Czachorowski         template <typename Q> class Baz {};
5185934a791SAdam Czachorowski       };
5195934a791SAdam Czachorowski       class Foo{};
5205934a791SAdam Czachorowski     }
5215934a791SAdam Czachorowski 
5225934a791SAdam Czachorowski     void foo();
5235934a791SAdam Czachorowski 
5245934a791SAdam Czachorowski     using namespace a;
5255934a791SAdam Czachorowski     void f^oo() {
5265934a791SAdam Czachorowski       Bar<int> B;
5275934a791SAdam Czachorowski       Foo foo;
5285934a791SAdam Czachorowski       a::Bar<Bar<int>>::Baz<Bar<int>> q;
5295934a791SAdam Czachorowski     })cpp";
530c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
5315934a791SAdam Czachorowski     namespace a {
5325934a791SAdam Czachorowski       template <typename T> class Bar {
5335934a791SAdam Czachorowski       public:
5345934a791SAdam Czachorowski         template <typename Q> class Baz {};
5355934a791SAdam Czachorowski       };
5365934a791SAdam Czachorowski       class Foo{};
5375934a791SAdam Czachorowski     }
5385934a791SAdam Czachorowski 
5395934a791SAdam Czachorowski     void foo(){
5405934a791SAdam Czachorowski       a::Bar<int> B;
5415934a791SAdam Czachorowski       a::Foo foo;
5425934a791SAdam Czachorowski       a::Bar<a::Bar<int>>::Baz<a::Bar<int>> q;
5435934a791SAdam Czachorowski     }
5445934a791SAdam Czachorowski 
5455934a791SAdam Czachorowski     using namespace a;
5465934a791SAdam Czachorowski     )cpp";
5475934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
5485934a791SAdam Czachorowski }
5495934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformDeclRefs)5505934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformDeclRefs) {
551c0e3c893SChristian Kühnel   auto *Test = R"cpp(
5525934a791SAdam Czachorowski     namespace a {
5535934a791SAdam Czachorowski       template <typename T> class Bar {
5545934a791SAdam Czachorowski       public:
5555934a791SAdam Czachorowski         void foo();
5565934a791SAdam Czachorowski         static void bar();
5575934a791SAdam Czachorowski         int x;
5585934a791SAdam Czachorowski         static int y;
5595934a791SAdam Czachorowski       };
5605934a791SAdam Czachorowski       void bar();
5615934a791SAdam Czachorowski       void test();
5625934a791SAdam Czachorowski     }
5635934a791SAdam Czachorowski 
5645934a791SAdam Czachorowski     void foo();
5655934a791SAdam Czachorowski     using namespace a;
5665934a791SAdam Czachorowski     void f^oo() {
5675934a791SAdam Czachorowski       a::Bar<int> B;
5685934a791SAdam Czachorowski       B.foo();
5695934a791SAdam Czachorowski       a::bar();
5705934a791SAdam Czachorowski       Bar<Bar<int>>::bar();
5715934a791SAdam Czachorowski       a::Bar<int>::bar();
5725934a791SAdam Czachorowski       B.x = Bar<int>::y;
5735934a791SAdam Czachorowski       Bar<int>::y = 3;
5745934a791SAdam Czachorowski       bar();
5755934a791SAdam Czachorowski       a::test();
5765934a791SAdam Czachorowski     })cpp";
577c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
5785934a791SAdam Czachorowski     namespace a {
5795934a791SAdam Czachorowski       template <typename T> class Bar {
5805934a791SAdam Czachorowski       public:
5815934a791SAdam Czachorowski         void foo();
5825934a791SAdam Czachorowski         static void bar();
5835934a791SAdam Czachorowski         int x;
5845934a791SAdam Czachorowski         static int y;
5855934a791SAdam Czachorowski       };
5865934a791SAdam Czachorowski       void bar();
5875934a791SAdam Czachorowski       void test();
5885934a791SAdam Czachorowski     }
5895934a791SAdam Czachorowski 
5905934a791SAdam Czachorowski     void foo(){
5915934a791SAdam Czachorowski       a::Bar<int> B;
5925934a791SAdam Czachorowski       B.foo();
5935934a791SAdam Czachorowski       a::bar();
5945934a791SAdam Czachorowski       a::Bar<a::Bar<int>>::bar();
5955934a791SAdam Czachorowski       a::Bar<int>::bar();
5965934a791SAdam Czachorowski       B.x = a::Bar<int>::y;
5975934a791SAdam Czachorowski       a::Bar<int>::y = 3;
5985934a791SAdam Czachorowski       a::bar();
5995934a791SAdam Czachorowski       a::test();
6005934a791SAdam Czachorowski     }
6015934a791SAdam Czachorowski     using namespace a;
6025934a791SAdam Czachorowski     )cpp";
6035934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
6045934a791SAdam Czachorowski }
6055934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,StaticMembers)6065934a791SAdam Czachorowski TEST_F(DefineInlineTest, StaticMembers) {
607c0e3c893SChristian Kühnel   auto *Test = R"cpp(
6085934a791SAdam Czachorowski     namespace ns { class X { static void foo(); void bar(); }; }
6095934a791SAdam Czachorowski     void ns::X::b^ar() {
6105934a791SAdam Czachorowski       foo();
6115934a791SAdam Czachorowski     })cpp";
612c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
6135934a791SAdam Czachorowski     namespace ns { class X { static void foo(); void bar(){
6145934a791SAdam Czachorowski       foo();
6155934a791SAdam Czachorowski     } }; }
6165934a791SAdam Czachorowski     )cpp";
6175934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
6185934a791SAdam Czachorowski }
6195934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformParamNames)6205934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformParamNames) {
6215934a791SAdam Czachorowski   std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
6225934a791SAdam Czachorowski       {R"cpp(
6235934a791SAdam Czachorowski         void foo(int, bool b, int T\
6245934a791SAdam Czachorowski est);
6255934a791SAdam Czachorowski         void ^foo(int f, bool x, int z) {})cpp",
6265934a791SAdam Czachorowski        R"cpp(
6275934a791SAdam Czachorowski         void foo(int f, bool x, int z){}
6285934a791SAdam Czachorowski         )cpp"},
6295934a791SAdam Czachorowski       {R"cpp(
6305934a791SAdam Czachorowski         #define PARAM int Z
6315934a791SAdam Czachorowski         void foo(PARAM);
6325934a791SAdam Czachorowski 
6335934a791SAdam Czachorowski         void ^foo(int X) {})cpp",
6345934a791SAdam Czachorowski        "fail: Cant rename parameter inside macro body."},
6355934a791SAdam Czachorowski       {R"cpp(
6365934a791SAdam Czachorowski         #define TYPE int
6375934a791SAdam Czachorowski         #define PARAM TYPE Z
6385934a791SAdam Czachorowski         #define BODY(x) 5 * (x) + 2
6395934a791SAdam Czachorowski         template <int P>
6405934a791SAdam Czachorowski         void foo(PARAM, TYPE Q, TYPE, TYPE W = BODY(P));
6415934a791SAdam Czachorowski         template <int x>
6425934a791SAdam Czachorowski         void ^foo(int Z, int b, int c, int d) {})cpp",
6435934a791SAdam Czachorowski        R"cpp(
6445934a791SAdam Czachorowski         #define TYPE int
6455934a791SAdam Czachorowski         #define PARAM TYPE Z
6465934a791SAdam Czachorowski         #define BODY(x) 5 * (x) + 2
6475934a791SAdam Czachorowski         template <int x>
6485934a791SAdam Czachorowski         void foo(PARAM, TYPE b, TYPE c, TYPE d = BODY(x)){}
6495934a791SAdam Czachorowski         )cpp"},
6505934a791SAdam Czachorowski   };
6515934a791SAdam Czachorowski   for (const auto &Case : Cases)
6525934a791SAdam Czachorowski     EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
6535934a791SAdam Czachorowski }
6545934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformTemplParamNames)6555934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformTemplParamNames) {
656c0e3c893SChristian Kühnel   auto *Test = R"cpp(
6575934a791SAdam Czachorowski     struct Foo {
6585934a791SAdam Czachorowski       struct Bar {
6595934a791SAdam Czachorowski         template <class, class X,
6605934a791SAdam Czachorowski                   template<typename> class, template<typename> class Y,
6615934a791SAdam Czachorowski                   int, int Z>
6625934a791SAdam Czachorowski         void foo(X, Y<X>, int W = 5 * Z + 2);
6635934a791SAdam Czachorowski       };
6645934a791SAdam Czachorowski     };
6655934a791SAdam Czachorowski 
6665934a791SAdam Czachorowski     template <class T, class U,
6675934a791SAdam Czachorowski               template<typename> class V, template<typename> class W,
6685934a791SAdam Czachorowski               int X, int Y>
6695934a791SAdam Czachorowski     void Foo::Bar::f^oo(U, W<U>, int Q) {})cpp";
670c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
6715934a791SAdam Czachorowski     struct Foo {
6725934a791SAdam Czachorowski       struct Bar {
6735934a791SAdam Czachorowski         template <class T, class U,
6745934a791SAdam Czachorowski                   template<typename> class V, template<typename> class W,
6755934a791SAdam Czachorowski                   int X, int Y>
6765934a791SAdam Czachorowski         void foo(U, W<U>, int Q = 5 * Y + 2){}
6775934a791SAdam Czachorowski       };
6785934a791SAdam Czachorowski     };
6795934a791SAdam Czachorowski 
6805934a791SAdam Czachorowski     )cpp";
6815934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
6825934a791SAdam Czachorowski }
6835934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TransformInlineNamespaces)6845934a791SAdam Czachorowski TEST_F(DefineInlineTest, TransformInlineNamespaces) {
685c0e3c893SChristian Kühnel   auto *Test = R"cpp(
6865934a791SAdam Czachorowski     namespace a { inline namespace b { namespace { struct Foo{}; } } }
6875934a791SAdam Czachorowski     void foo();
6885934a791SAdam Czachorowski 
6895934a791SAdam Czachorowski     using namespace a;
6905934a791SAdam Czachorowski     void ^foo() {Foo foo;})cpp";
691c0e3c893SChristian Kühnel   auto *Expected = R"cpp(
6925934a791SAdam Czachorowski     namespace a { inline namespace b { namespace { struct Foo{}; } } }
6935934a791SAdam Czachorowski     void foo(){a::Foo foo;}
6945934a791SAdam Czachorowski 
6955934a791SAdam Czachorowski     using namespace a;
6965934a791SAdam Czachorowski     )cpp";
6975934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected);
6985934a791SAdam Czachorowski }
6995934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,TokensBeforeSemicolon)7005934a791SAdam Czachorowski TEST_F(DefineInlineTest, TokensBeforeSemicolon) {
7015934a791SAdam Czachorowski   std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
7025934a791SAdam Czachorowski       {R"cpp(
7035934a791SAdam Czachorowski           void foo()    /*Comment -_-*/ /*Com 2*/ ;
7045934a791SAdam Czachorowski           void fo^o() { return ; })cpp",
7055934a791SAdam Czachorowski        R"cpp(
7065934a791SAdam Czachorowski           void foo()    /*Comment -_-*/ /*Com 2*/ { return ; }
7075934a791SAdam Czachorowski           )cpp"},
7085934a791SAdam Czachorowski 
7095934a791SAdam Czachorowski       {R"cpp(
7105934a791SAdam Czachorowski           void foo();
7115934a791SAdam Czachorowski           void fo^o() { return ; })cpp",
7125934a791SAdam Czachorowski        R"cpp(
7135934a791SAdam Czachorowski           void foo(){ return ; }
7145934a791SAdam Czachorowski           )cpp"},
7155934a791SAdam Czachorowski 
7165934a791SAdam Czachorowski       {R"cpp(
7175934a791SAdam Czachorowski           #define SEMI ;
7185934a791SAdam Czachorowski           void foo() SEMI
7195934a791SAdam Czachorowski           void fo^o() { return ; })cpp",
7205934a791SAdam Czachorowski        "fail: Couldn't find semicolon for target declaration."},
7215934a791SAdam Czachorowski   };
7225934a791SAdam Czachorowski   for (const auto &Case : Cases)
7235934a791SAdam Czachorowski     EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
7245934a791SAdam Czachorowski }
7255934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,HandleMacros)7265934a791SAdam Czachorowski TEST_F(DefineInlineTest, HandleMacros) {
7275934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
7285934a791SAdam Czachorowski     #define BODY { return; }
7295934a791SAdam Czachorowski     void foo();
7305934a791SAdam Czachorowski     void f^oo()BODY)cpp");
7315934a791SAdam Czachorowski 
7325934a791SAdam Czachorowski   EXPECT_UNAVAILABLE(R"cpp(
7335934a791SAdam Czachorowski     #define BODY void foo(){ return; }
7345934a791SAdam Czachorowski     void foo();
7355934a791SAdam Czachorowski     [[BODY]])cpp");
7365934a791SAdam Czachorowski 
7375934a791SAdam Czachorowski   std::pair<llvm::StringRef, llvm::StringRef> Cases[] = {
7385934a791SAdam Czachorowski       // We don't qualify declarations coming from macros.
7395934a791SAdam Czachorowski       {R"cpp(
7405934a791SAdam Czachorowski           #define BODY Foo
7415934a791SAdam Czachorowski           namespace a { class Foo{}; }
7425934a791SAdam Czachorowski           void foo();
7435934a791SAdam Czachorowski           using namespace a;
7445934a791SAdam Czachorowski           void f^oo(){BODY();})cpp",
7455934a791SAdam Czachorowski        R"cpp(
7465934a791SAdam Czachorowski           #define BODY Foo
7475934a791SAdam Czachorowski           namespace a { class Foo{}; }
7485934a791SAdam Czachorowski           void foo(){BODY();}
7495934a791SAdam Czachorowski           using namespace a;
7505934a791SAdam Czachorowski           )cpp"},
7515934a791SAdam Czachorowski 
7525934a791SAdam Czachorowski       // Macro is not visible at declaration location, but we proceed.
7535934a791SAdam Czachorowski       {R"cpp(
7545934a791SAdam Czachorowski           void foo();
7555934a791SAdam Czachorowski           #define BODY return;
7565934a791SAdam Czachorowski           void f^oo(){BODY})cpp",
7575934a791SAdam Czachorowski        R"cpp(
7585934a791SAdam Czachorowski           void foo(){BODY}
7595934a791SAdam Czachorowski           #define BODY return;
7605934a791SAdam Czachorowski           )cpp"},
7615934a791SAdam Czachorowski 
7625934a791SAdam Czachorowski       {R"cpp(
7635934a791SAdam Czachorowski           #define TARGET void foo()
7645934a791SAdam Czachorowski           TARGET;
7655934a791SAdam Czachorowski           void f^oo(){ return; })cpp",
7665934a791SAdam Czachorowski        R"cpp(
7675934a791SAdam Czachorowski           #define TARGET void foo()
7685934a791SAdam Czachorowski           TARGET{ return; }
7695934a791SAdam Czachorowski           )cpp"},
7705934a791SAdam Czachorowski 
7715934a791SAdam Czachorowski       {R"cpp(
7725934a791SAdam Czachorowski           #define TARGET foo
7735934a791SAdam Czachorowski           void TARGET();
7745934a791SAdam Czachorowski           void f^oo(){ return; })cpp",
7755934a791SAdam Czachorowski        R"cpp(
7765934a791SAdam Czachorowski           #define TARGET foo
7775934a791SAdam Czachorowski           void TARGET(){ return; }
7785934a791SAdam Czachorowski           )cpp"},
7795934a791SAdam Czachorowski   };
7805934a791SAdam Czachorowski   for (const auto &Case : Cases)
7815934a791SAdam Czachorowski     EXPECT_EQ(apply(Case.first), Case.second) << Case.first;
7825934a791SAdam Czachorowski }
7835934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,DropCommonNameSpecifiers)7845934a791SAdam Czachorowski TEST_F(DefineInlineTest, DropCommonNameSpecifiers) {
7855934a791SAdam Czachorowski   struct {
7865934a791SAdam Czachorowski     llvm::StringRef Test;
7875934a791SAdam Czachorowski     llvm::StringRef Expected;
7885934a791SAdam Czachorowski   } Cases[] = {
7895934a791SAdam Czachorowski       {R"cpp(
7905934a791SAdam Czachorowski         namespace a { namespace b { void aux(); } }
7915934a791SAdam Czachorowski         namespace ns1 {
7925934a791SAdam Czachorowski           void foo();
7935934a791SAdam Czachorowski           namespace qq { void test(); }
7945934a791SAdam Czachorowski           namespace ns2 {
7955934a791SAdam Czachorowski             void bar();
7965934a791SAdam Czachorowski             namespace ns3 { void baz(); }
7975934a791SAdam Czachorowski           }
7985934a791SAdam Czachorowski         }
7995934a791SAdam Czachorowski 
8005934a791SAdam Czachorowski         using namespace a;
8015934a791SAdam Czachorowski         using namespace a::b;
8025934a791SAdam Czachorowski         using namespace ns1::qq;
8035934a791SAdam Czachorowski         void ns1::ns2::ns3::b^az() {
8045934a791SAdam Czachorowski           foo();
8055934a791SAdam Czachorowski           bar();
8065934a791SAdam Czachorowski           baz();
8075934a791SAdam Czachorowski           ns1::ns2::ns3::baz();
8085934a791SAdam Czachorowski           aux();
8095934a791SAdam Czachorowski           test();
8105934a791SAdam Czachorowski         })cpp",
8115934a791SAdam Czachorowski        R"cpp(
8125934a791SAdam Czachorowski         namespace a { namespace b { void aux(); } }
8135934a791SAdam Czachorowski         namespace ns1 {
8145934a791SAdam Czachorowski           void foo();
8155934a791SAdam Czachorowski           namespace qq { void test(); }
8165934a791SAdam Czachorowski           namespace ns2 {
8175934a791SAdam Czachorowski             void bar();
8185934a791SAdam Czachorowski             namespace ns3 { void baz(){
8195934a791SAdam Czachorowski           foo();
8205934a791SAdam Czachorowski           bar();
8215934a791SAdam Czachorowski           baz();
8225934a791SAdam Czachorowski           ns1::ns2::ns3::baz();
8235934a791SAdam Czachorowski           a::b::aux();
8245934a791SAdam Czachorowski           qq::test();
8255934a791SAdam Czachorowski         } }
8265934a791SAdam Czachorowski           }
8275934a791SAdam Czachorowski         }
8285934a791SAdam Czachorowski 
8295934a791SAdam Czachorowski         using namespace a;
8305934a791SAdam Czachorowski         using namespace a::b;
8315934a791SAdam Czachorowski         using namespace ns1::qq;
8325934a791SAdam Czachorowski         )cpp"},
8335934a791SAdam Czachorowski       {R"cpp(
8345934a791SAdam Czachorowski         namespace ns1 {
8355934a791SAdam Czachorowski           namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; }
8365934a791SAdam Czachorowski           namespace ns2 { void baz(); }
8375934a791SAdam Czachorowski         }
8385934a791SAdam Czachorowski 
8395934a791SAdam Czachorowski         using namespace ns1::qq;
8405934a791SAdam Czachorowski         void ns1::ns2::b^az() { Foo f; B b; })cpp",
8415934a791SAdam Czachorowski        R"cpp(
8425934a791SAdam Czachorowski         namespace ns1 {
8435934a791SAdam Czachorowski           namespace qq { struct Foo { struct Bar {}; }; using B = Foo::Bar; }
8445934a791SAdam Czachorowski           namespace ns2 { void baz(){ qq::Foo f; qq::B b; } }
8455934a791SAdam Czachorowski         }
8465934a791SAdam Czachorowski 
8475934a791SAdam Czachorowski         using namespace ns1::qq;
8485934a791SAdam Czachorowski         )cpp"},
8495934a791SAdam Czachorowski       {R"cpp(
8505934a791SAdam Czachorowski         namespace ns1 {
8515934a791SAdam Czachorowski           namespace qq {
8525934a791SAdam Czachorowski             template<class T> struct Foo { template <class U> struct Bar {}; };
8535934a791SAdam Czachorowski             template<class T, class U>
8545934a791SAdam Czachorowski             using B = typename Foo<T>::template Bar<U>;
8555934a791SAdam Czachorowski           }
8565934a791SAdam Czachorowski           namespace ns2 { void baz(); }
8575934a791SAdam Czachorowski         }
8585934a791SAdam Czachorowski 
8595934a791SAdam Czachorowski         using namespace ns1::qq;
8605934a791SAdam Czachorowski         void ns1::ns2::b^az() { B<int, bool> b; })cpp",
8615934a791SAdam Czachorowski        R"cpp(
8625934a791SAdam Czachorowski         namespace ns1 {
8635934a791SAdam Czachorowski           namespace qq {
8645934a791SAdam Czachorowski             template<class T> struct Foo { template <class U> struct Bar {}; };
8655934a791SAdam Czachorowski             template<class T, class U>
8665934a791SAdam Czachorowski             using B = typename Foo<T>::template Bar<U>;
8675934a791SAdam Czachorowski           }
8685934a791SAdam Czachorowski           namespace ns2 { void baz(){ qq::B<int, bool> b; } }
8695934a791SAdam Czachorowski         }
8705934a791SAdam Czachorowski 
8715934a791SAdam Czachorowski         using namespace ns1::qq;
8725934a791SAdam Czachorowski         )cpp"},
8735934a791SAdam Czachorowski   };
8745934a791SAdam Czachorowski   for (const auto &Case : Cases)
8755934a791SAdam Czachorowski     EXPECT_EQ(apply(Case.Test), Case.Expected) << Case.Test;
8765934a791SAdam Czachorowski }
8775934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,QualifyWithUsingDirectives)8785934a791SAdam Czachorowski TEST_F(DefineInlineTest, QualifyWithUsingDirectives) {
8795934a791SAdam Czachorowski   llvm::StringRef Test = R"cpp(
8805934a791SAdam Czachorowski     namespace a {
8815934a791SAdam Czachorowski       void bar();
8825934a791SAdam Czachorowski       namespace b { struct Foo{}; void aux(); }
8835934a791SAdam Czachorowski       namespace c { void cux(); }
8845934a791SAdam Czachorowski     }
8855934a791SAdam Czachorowski     using namespace a;
8865934a791SAdam Czachorowski     using X = b::Foo;
8875934a791SAdam Czachorowski     void foo();
8885934a791SAdam Czachorowski 
8895934a791SAdam Czachorowski     using namespace b;
8905934a791SAdam Czachorowski     using namespace c;
8915934a791SAdam Czachorowski     void ^foo() {
8925934a791SAdam Czachorowski       cux();
8935934a791SAdam Czachorowski       bar();
8945934a791SAdam Czachorowski       X x;
8955934a791SAdam Czachorowski       aux();
8965934a791SAdam Czachorowski       using namespace c;
8975934a791SAdam Czachorowski       // FIXME: The last reference to cux() in body of foo should not be
8985934a791SAdam Czachorowski       // qualified, since there is a using directive inside the function body.
8995934a791SAdam Czachorowski       cux();
9005934a791SAdam Czachorowski     })cpp";
9015934a791SAdam Czachorowski   llvm::StringRef Expected = R"cpp(
9025934a791SAdam Czachorowski     namespace a {
9035934a791SAdam Czachorowski       void bar();
9045934a791SAdam Czachorowski       namespace b { struct Foo{}; void aux(); }
9055934a791SAdam Czachorowski       namespace c { void cux(); }
9065934a791SAdam Czachorowski     }
9075934a791SAdam Czachorowski     using namespace a;
9085934a791SAdam Czachorowski     using X = b::Foo;
9095934a791SAdam Czachorowski     void foo(){
9105934a791SAdam Czachorowski       c::cux();
9115934a791SAdam Czachorowski       bar();
9125934a791SAdam Czachorowski       X x;
9135934a791SAdam Czachorowski       b::aux();
9145934a791SAdam Czachorowski       using namespace c;
9155934a791SAdam Czachorowski       // FIXME: The last reference to cux() in body of foo should not be
9165934a791SAdam Czachorowski       // qualified, since there is a using directive inside the function body.
9175934a791SAdam Czachorowski       c::cux();
9185934a791SAdam Czachorowski     }
9195934a791SAdam Czachorowski 
9205934a791SAdam Czachorowski     using namespace b;
9215934a791SAdam Czachorowski     using namespace c;
9225934a791SAdam Czachorowski     )cpp";
9235934a791SAdam Czachorowski   EXPECT_EQ(apply(Test), Expected) << Test;
9245934a791SAdam Czachorowski }
9255934a791SAdam Czachorowski 
TEST_F(DefineInlineTest,AddInline)9265934a791SAdam Czachorowski TEST_F(DefineInlineTest, AddInline) {
9275934a791SAdam Czachorowski   llvm::StringMap<std::string> EditedFiles;
9285934a791SAdam Czachorowski   ExtraFiles["a.h"] = "void foo();";
9295934a791SAdam Czachorowski   apply(R"cpp(#include "a.h"
9305934a791SAdam Czachorowski               void fo^o() {})cpp",
9315934a791SAdam Czachorowski         &EditedFiles);
9325934a791SAdam Czachorowski   EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
9335934a791SAdam Czachorowski                                testPath("a.h"), "inline void foo(){}")));
9345934a791SAdam Czachorowski 
9355934a791SAdam Czachorowski   // Check we put inline before cv-qualifiers.
9365934a791SAdam Czachorowski   ExtraFiles["a.h"] = "const int foo();";
9375934a791SAdam Czachorowski   apply(R"cpp(#include "a.h"
9385934a791SAdam Czachorowski               const int fo^o() {})cpp",
9395934a791SAdam Czachorowski         &EditedFiles);
9405934a791SAdam Czachorowski   EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
9415934a791SAdam Czachorowski                                testPath("a.h"), "inline const int foo(){}")));
9425934a791SAdam Czachorowski 
9435934a791SAdam Czachorowski   // No double inline.
9445934a791SAdam Czachorowski   ExtraFiles["a.h"] = "inline void foo();";
9455934a791SAdam Czachorowski   apply(R"cpp(#include "a.h"
9465934a791SAdam Czachorowski               inline void fo^o() {})cpp",
9475934a791SAdam Czachorowski         &EditedFiles);
9485934a791SAdam Czachorowski   EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
9495934a791SAdam Czachorowski                                testPath("a.h"), "inline void foo(){}")));
9505934a791SAdam Czachorowski 
9515934a791SAdam Czachorowski   // Constexprs don't need "inline".
9525934a791SAdam Czachorowski   ExtraFiles["a.h"] = "constexpr void foo();";
9535934a791SAdam Czachorowski   apply(R"cpp(#include "a.h"
9545934a791SAdam Czachorowski               constexpr void fo^o() {})cpp",
9555934a791SAdam Czachorowski         &EditedFiles);
9565934a791SAdam Czachorowski   EXPECT_THAT(EditedFiles, testing::ElementsAre(FileWithContents(
9575934a791SAdam Czachorowski                                testPath("a.h"), "constexpr void foo(){}")));
9585934a791SAdam Czachorowski 
9595934a791SAdam Czachorowski   // Class members don't need "inline".
9605934a791SAdam Czachorowski   ExtraFiles["a.h"] = "struct Foo { void foo(); };";
9615934a791SAdam Czachorowski   apply(R"cpp(#include "a.h"
9625934a791SAdam Czachorowski               void Foo::fo^o() {})cpp",
9635934a791SAdam Czachorowski         &EditedFiles);
9645934a791SAdam Czachorowski   EXPECT_THAT(EditedFiles,
9655934a791SAdam Czachorowski               testing::ElementsAre(FileWithContents(
9665934a791SAdam Czachorowski                   testPath("a.h"), "struct Foo { void foo(){} };")));
9675934a791SAdam Czachorowski 
9685934a791SAdam Czachorowski   // Function template doesn't need to be "inline"d.
9695934a791SAdam Czachorowski   ExtraFiles["a.h"] = "template <typename T> void foo();";
9705934a791SAdam Czachorowski   apply(R"cpp(#include "a.h"
9715934a791SAdam Czachorowski               template <typename T>
9725934a791SAdam Czachorowski               void fo^o() {})cpp",
9735934a791SAdam Czachorowski         &EditedFiles);
9745934a791SAdam Czachorowski   EXPECT_THAT(EditedFiles,
9755934a791SAdam Czachorowski               testing::ElementsAre(FileWithContents(
9765934a791SAdam Czachorowski                   testPath("a.h"), "template <typename T> void foo(){}")));
9775934a791SAdam Czachorowski 
9785934a791SAdam Czachorowski   // Specializations needs to be marked "inline".
9795934a791SAdam Czachorowski   ExtraFiles["a.h"] = R"cpp(
9805934a791SAdam Czachorowski                             template <typename T> void foo();
9815934a791SAdam Czachorowski                             template <> void foo<int>();)cpp";
9825934a791SAdam Czachorowski   apply(R"cpp(#include "a.h"
9835934a791SAdam Czachorowski               template <>
9845934a791SAdam Czachorowski               void fo^o<int>() {})cpp",
9855934a791SAdam Czachorowski         &EditedFiles);
9865934a791SAdam Czachorowski   EXPECT_THAT(EditedFiles,
9875934a791SAdam Czachorowski               testing::ElementsAre(FileWithContents(testPath("a.h"),
9885934a791SAdam Czachorowski                                                     R"cpp(
9895934a791SAdam Czachorowski                             template <typename T> void foo();
9905934a791SAdam Czachorowski                             template <> inline void foo<int>(){})cpp")));
9915934a791SAdam Czachorowski }
9925934a791SAdam Czachorowski 
9935934a791SAdam Czachorowski } // namespace
9945934a791SAdam Czachorowski } // namespace clangd
9955934a791SAdam Czachorowski } // namespace clang
996