| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,255 @@ | ||
| // RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-crtp-constructor-accessibility %t -- -- -fno-delayed-template-parsing | ||
|
|
||
| namespace class_implicit_ctor { | ||
| template <typename T> | ||
| class CRTP {}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: CRTP() = default; | ||
| // CHECK-FIXES: friend T; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace class_implicit_ctor | ||
|
|
||
| namespace class_unconstructible { | ||
| template <typename T> | ||
| class CRTP { | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: friend T; | ||
| CRTP() = default; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace class_unconstructible | ||
|
|
||
| namespace class_public_default_ctor { | ||
| template <typename T> | ||
| class CRTP { | ||
| public: | ||
| CRTP() = default; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: | ||
| // CHECK-FIXES: friend T; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace class_public_default_ctor | ||
|
|
||
| namespace class_public_user_provided_ctor { | ||
| template <typename T> | ||
| class CRTP { | ||
| public: | ||
| CRTP(int) {} | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public: | ||
| // CHECK-FIXES: friend T; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace class_public_user_provided_ctor | ||
|
|
||
| namespace class_public_multiple_user_provided_ctors { | ||
| template <typename T> | ||
| class CRTP { | ||
| public: | ||
| CRTP(int) {} | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public: | ||
| CRTP(float) {} | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}public: | ||
|
|
||
| // CHECK-FIXES: friend T; | ||
| // CHECK-FIXES: friend T; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace class_public_multiple_user_provided_ctors | ||
|
|
||
| namespace class_protected_ctors { | ||
| template <typename T> | ||
| class CRTP { | ||
| protected: | ||
| CRTP(int) {} | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}protected: | ||
| CRTP() = default; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}protected: | ||
| CRTP(float) {} | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}protected: | ||
|
|
||
| // CHECK-FIXES: friend T; | ||
| // CHECK-FIXES: friend T; | ||
| // CHECK-FIXES: friend T; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace class_protected_ctors | ||
|
|
||
| namespace struct_implicit_ctor { | ||
| template <typename T> | ||
| struct CRTP {}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: | ||
| // CHECK-FIXES: friend T; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace struct_implicit_ctor | ||
|
|
||
| namespace struct_default_ctor { | ||
| template <typename T> | ||
| struct CRTP { | ||
| CRTP() = default; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: | ||
| // CHECK-FIXES: friend T; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace struct_default_ctor | ||
|
|
||
| namespace same_class_multiple_crtps { | ||
| template <typename T> | ||
| struct CRTP {}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: | ||
| // CHECK-FIXES: friend T; | ||
|
|
||
| template <typename T> | ||
| struct CRTP2 {}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: private:{{[[:space:]]*}}CRTP2() = default;{{[[:space:]]*}}public: | ||
| // CHECK-FIXES: friend T; | ||
|
|
||
| class A : CRTP<A>, CRTP2<A> {}; | ||
| } // namespace same_class_multiple_crtps | ||
|
|
||
| namespace same_crtp_multiple_classes { | ||
| template <typename T> | ||
| class CRTP { | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: friend T; | ||
| CRTP() = default; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| class B : CRTP<B> {}; | ||
| } // namespace same_crtp_multiple_classes | ||
|
|
||
| namespace crtp_template { | ||
| template <typename T, typename U> | ||
| class CRTP { | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: friend U; | ||
| CRTP() = default; | ||
| }; | ||
|
|
||
| class A : CRTP<int, A> {}; | ||
| } // namespace crtp_template | ||
|
|
||
| namespace crtp_template2 { | ||
| template <typename T, typename U> | ||
| class CRTP { | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: friend T; | ||
| CRTP() = default; | ||
| }; | ||
|
|
||
| class A : CRTP<A, A> {}; | ||
| } // namespace crtp_template2 | ||
|
|
||
| namespace template_derived { | ||
| template <typename T> | ||
| class CRTP {}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: CRTP() = default; | ||
| // CHECK-FIXES: friend T; | ||
|
|
||
| template<typename T> | ||
| class A : CRTP<A<T>> {}; | ||
|
|
||
| // FIXME: Ideally the warning should be triggered without instantiation. | ||
| void foo() { | ||
| A<int> A; | ||
| (void) A; | ||
| } | ||
| } // namespace template_derived | ||
|
|
||
| namespace template_derived_explicit_specialization { | ||
| template <typename T> | ||
| class CRTP {}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: CRTP() = default; | ||
| // CHECK-FIXES: friend T; | ||
|
|
||
| template<typename T> | ||
| class A : CRTP<A<T>> {}; | ||
|
|
||
| template<> | ||
| class A<int> : CRTP<A<int>> {}; | ||
| } // namespace template_derived_explicit_specialization | ||
|
|
||
| namespace explicit_derived_friend { | ||
| class A; | ||
|
|
||
| template <typename T> | ||
| class CRTP { | ||
| CRTP() = default; | ||
| friend A; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace explicit_derived_friend | ||
|
|
||
| namespace explicit_derived_friend_multiple { | ||
| class A; | ||
|
|
||
| template <typename T> | ||
| class CRTP { | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: friend T; | ||
| CRTP() = default; | ||
| friend A; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| class B : CRTP<B> {}; | ||
| } // namespace explicit_derived_friend_multiple | ||
|
|
||
| namespace no_need_for_friend { | ||
| class A; | ||
|
|
||
| template <typename T> | ||
| class CRTP { | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private [bugprone-crtp-constructor-accessibility] | ||
| // CHECK-FIXES: CRTP() = default; | ||
| friend A; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace no_need_for_friend | ||
|
|
||
| namespace no_warning { | ||
| template <typename T> | ||
| class CRTP | ||
| { | ||
| CRTP() = default; | ||
| friend T; | ||
| }; | ||
|
|
||
| class A : CRTP<A> {}; | ||
| } // namespace no_warning | ||
|
|
||
| namespace no_warning_unsupported { | ||
| template<typename... Types> | ||
| class CRTP | ||
| {}; | ||
|
|
||
| class A : CRTP<A> {}; | ||
|
|
||
| void foo() { | ||
| A A; | ||
| (void) A; | ||
| } | ||
| } // namespace no_warning_unsupported |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| // RUN: %check_clang_tidy %s google-explicit-constructor %t -std=c++20-or-later | ||
|
|
||
| namespace issue_81121 | ||
| { | ||
|
|
||
| static constexpr bool ConstFalse = false; | ||
| static constexpr bool ConstTrue = true; | ||
|
|
||
| struct A { | ||
| explicit(true) A(int); | ||
| }; | ||
|
|
||
| struct B { | ||
| explicit(false) B(int); | ||
| }; | ||
|
|
||
| struct C { | ||
| explicit(ConstTrue) C(int); | ||
| }; | ||
|
|
||
| struct D { | ||
| explicit(ConstFalse) D(int); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false' [google-explicit-constructor] | ||
| }; | ||
|
|
||
| template <typename> | ||
| struct E { | ||
| explicit(true) E(int); | ||
| }; | ||
|
|
||
| template <typename> | ||
| struct F { | ||
| explicit(false) F(int); | ||
| }; | ||
|
|
||
| template <typename> | ||
| struct G { | ||
| explicit(ConstTrue) G(int); | ||
| }; | ||
|
|
||
| template <typename> | ||
| struct H { | ||
| explicit(ConstFalse) H(int); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false' [google-explicit-constructor] | ||
| }; | ||
|
|
||
| template <int Val> | ||
| struct I { | ||
| explicit(Val > 0) I(int); | ||
| }; | ||
|
|
||
| template <int Val> | ||
| struct J { | ||
| explicit(Val > 0) J(int); | ||
| }; | ||
|
|
||
| void useJ(J<0>, J<100>); | ||
|
|
||
| } // namespace issue_81121 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,203 @@ | ||
| // RUN: %check_clang_tidy -std=c++17 %s modernize-use-designated-initializers %t \ | ||
| // RUN: -- \ | ||
| // RUN: -- -fno-delayed-template-parsing | ||
| // RUN: %check_clang_tidy -check-suffixes=,SINGLE-ELEMENT -std=c++17 %s modernize-use-designated-initializers %t \ | ||
| // RUN: -- -config="{CheckOptions: {modernize-use-designated-initializers.IgnoreSingleElementAggregates: false}}" \ | ||
| // RUN: -- -fno-delayed-template-parsing | ||
| // RUN: %check_clang_tidy -check-suffixes=POD -std=c++17 %s modernize-use-designated-initializers %t \ | ||
| // RUN: -- -config="{CheckOptions: {modernize-use-designated-initializers.RestrictToPODTypes: true}}" \ | ||
| // RUN: -- -fno-delayed-template-parsing | ||
| // RUN: %check_clang_tidy -check-suffixes=,MACROS -std=c++17 %s modernize-use-designated-initializers %t \ | ||
| // RUN: -- -config="{CheckOptions: {modernize-use-designated-initializers.IgnoreMacros: false}}" \ | ||
| // RUN: -- -fno-delayed-template-parsing | ||
|
|
||
| struct S1 {}; | ||
|
|
||
| S1 s11{}; | ||
| S1 s12 = {}; | ||
| S1 s13(); | ||
| S1 s14; | ||
|
|
||
| struct S2 { int i, j; }; | ||
|
|
||
| S2 s21{.i=1, .j =2}; | ||
|
|
||
| S2 s22 = {1, 2}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-6]]:1: note: aggregate type is defined here | ||
| // CHECK-MESSAGES-POD: :[[@LINE-3]]:10: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-8]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES: S2 s22 = {.i=1, .j=2}; | ||
|
|
||
| S2 s23{1}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-13]]:1: note: aggregate type is defined here | ||
| // CHECK-MESSAGES-POD: :[[@LINE-3]]:7: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-15]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES: S2 s23{.i=1}; | ||
|
|
||
| S2 s24{.i = 1}; | ||
|
|
||
| S2 s25 = {.i=1, 2}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use designated init expression to initialize field 'j' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-2]]:17: warning: use designated init expression to initialize field 'j' [modernize-use-designated-initializers] | ||
| // CHECK-FIXES: S2 s25 = {.i=1, .j=2}; | ||
|
|
||
| class S3 { | ||
| public: | ||
| S2 s2; | ||
| double d; | ||
| }; | ||
|
|
||
| S3 s31 = {.s2 = 1, 2, 3.1}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use designated init expression to initialize field 's2.j' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use designated init expression to initialize field 'd' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-3]]:20: warning: use designated init expression to initialize field 's2.j' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-4]]:23: warning: use designated init expression to initialize field 'd' [modernize-use-designated-initializers] | ||
| // CHECK-FIXES: S3 s31 = {.s2 = 1, .s2.j=2, .d=3.1}; | ||
|
|
||
| S3 s32 = {{.i = 1, 2}}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S3' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-15]]:1: note: aggregate type is defined here | ||
| // CHECK-MESSAGES: :[[@LINE-3]]:20: warning: use designated init expression to initialize field 'j' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-4]]:10: warning: use designated initializer list to initialize 'S3' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-18]]:1: note: aggregate type is defined here | ||
| // CHECK-MESSAGES-POD: :[[@LINE-6]]:20: warning: use designated init expression to initialize field 'j' [modernize-use-designated-initializers] | ||
| // CHECK-FIXES: S3 s32 = {.s2={.i = 1, .j=2}}; | ||
|
|
||
| S3 s33 = {{2}, .d=3.1}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use designated init expression to initialize field 's2' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-50]]:1: note: aggregate type is defined here | ||
| // CHECK-MESSAGES-POD: :[[@LINE-4]]:11: warning: use designated init expression to initialize field 's2' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-5]]:11: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-53]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES: S3 s33 = {.s2={.i=2}, .d=3.1}; | ||
|
|
||
| struct S4 { | ||
| double d; | ||
| private: static int i; | ||
| }; | ||
|
|
||
| S4 s41 {2.2}; | ||
| // CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-1]]:8: warning: use designated initializer list to initialize 'S4' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-7]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES-SINGLE-ELEMENT: S4 s41 {.d=2.2}; | ||
|
|
||
| S4 s42 = {{}}; | ||
| // CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S4' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-12]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES-SINGLE-ELEMENT: S4 s42 = {.d={}}; | ||
|
|
||
| template<typename S> S template1() { return {10, 11}; } | ||
|
|
||
| S2 s26 = template1<S2>(); | ||
|
|
||
| template<typename S> S template2() { return {}; } | ||
|
|
||
| S2 s27 = template2<S2>(); | ||
|
|
||
| struct S5: S2 { int x, y; }; | ||
|
|
||
| S5 s51 {1, 2, .x = 3, .y = 4}; | ||
|
|
||
| struct S6 { | ||
| int i; | ||
| struct { int j; } s; | ||
| }; | ||
|
|
||
| S6 s61 {1, 2}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use designated initializer list to initialize 'S6' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-7]]:1: note: aggregate type is defined here | ||
| // CHECK-MESSAGES-POD: :[[@LINE-3]]:8: warning: use designated initializer list to initialize 'S6' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-9]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES: S6 s61 {.i=1, .s.j=2}; | ||
|
|
||
| struct S7 { | ||
| union { | ||
| int k; | ||
| double d; | ||
| } u; | ||
| }; | ||
|
|
||
| S7 s71 {1}; | ||
| // CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-1]]:8: warning: use designated initializer list to initialize 'S7' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-9]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES-SINGLE-ELEMENT: S7 s71 {.u.k=1}; | ||
|
|
||
| struct S8: S7 { int i; }; | ||
|
|
||
| S8 s81{1, 2}; | ||
|
|
||
| struct S9 { | ||
| int i, j; | ||
| S9 &operator=(S9); | ||
| }; | ||
|
|
||
| S9 s91{1, 2}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use designated initializer list to initialize 'S9' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-7]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES: S9 s91{.i=1, .j=2}; | ||
|
|
||
| struct S10 { int i = 1, j = 2; }; | ||
|
|
||
| S10 s101 {1, .j=2}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use designated init expression to initialize field 'i' [modernize-use-designated-initializers] | ||
| // CHECK-FIXES: S10 s101 {.i=1, .j=2}; | ||
|
|
||
| struct S11 { int i; S10 s10; }; | ||
|
|
||
| S11 s111 { .i = 1 }; | ||
| S11 s112 { 1 }; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S11' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-5]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES: S11 s112 { .i=1 }; | ||
|
|
||
| S11 s113 { .i=1, {}}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use designated init expression to initialize field 's10' [modernize-use-designated-initializers] | ||
| // CHECK-FIXES: S11 s113 { .i=1, .s10={}}; | ||
|
|
||
| S11 s114 { .i=1, .s10={1, .j=2}}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use designated init expression to initialize field 'i' [modernize-use-designated-initializers] | ||
| // CHECK-FIXES: S11 s114 { .i=1, .s10={.i=1, .j=2}}; | ||
|
|
||
| struct S12 { | ||
| int i; | ||
| struct { int j; }; | ||
| }; | ||
|
|
||
| S12 s121 {1, 2}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S12' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-7]]:1: note: aggregate type is defined here | ||
| // CHECK-MESSAGES-POD: :[[@LINE-3]]:10: warning: use designated initializer list to initialize 'S12' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-9]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES: S12 s121 {.i=1, .j=2}; | ||
|
|
||
| struct S13 { | ||
| union { | ||
| int k; | ||
| double d; | ||
| }; | ||
| int i; | ||
| }; | ||
|
|
||
| S13 s131 {1, 2}; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S13' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES: :[[@LINE-10]]:1: note: aggregate type is defined here | ||
| // CHECK-MESSAGES-POD: :[[@LINE-3]]:10: warning: use designated initializer list to initialize 'S13' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-POD: :[[@LINE-12]]:1: note: aggregate type is defined here | ||
| // CHECK-FIXES: S13 s131 {.k=1, .i=2}; | ||
|
|
||
| #define A (3+2) | ||
| #define B .j=1 | ||
|
|
||
| S9 s92 {A, B}; | ||
| // CHECK-MESSAGES-MACROS: :[[@LINE-1]]:9: warning: use designated init expression to initialize field 'i' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-MACROS: :[[@LINE-5]]:11: note: expanded from macro 'A' | ||
|
|
||
| #define DECLARE_S93 S9 s93 {1, 2} | ||
|
|
||
| DECLARE_S93; | ||
| // CHECK-MESSAGES-MACROS: :[[@LINE-1]]:1: warning: use designated initializer list to initialize 'S9' [modernize-use-designated-initializers] | ||
| // CHECK-MESSAGES-MACROS: :[[@LINE-4]]:28: note: expanded from macro 'DECLARE_S93' | ||
| // CHECK-MESSAGES-MACROS: :[[@LINE-71]]:1: note: aggregate type is defined here |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| from sphinx.application import Sphinx | ||
| import re | ||
|
|
||
| __version__ = "1.0" | ||
|
|
||
|
|
||
| def subst_gh_links(app: Sphinx, docname, source): | ||
| regex = re.compile("#GH([0-9]+)") | ||
| out_pattern = r"`#\1 <https://github.com/llvm/llvm-project/issues/\1>`_" | ||
| result = source[0] | ||
| result = regex.sub(out_pattern, result) | ||
| source[0] = result | ||
|
|
||
|
|
||
| def setup(app: Sphinx): | ||
| app.connect("source-read", subst_gh_links) | ||
| return dict(version=__version__, parallel_read_safe=True, parallel_write_safe=True) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| //===- InstallAPI/Frontend.h -----------------------------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| /// | ||
| /// Top level wrappers for InstallAPI frontend operations. | ||
| /// | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_CLANG_INSTALLAPI_FRONTEND_H | ||
| #define LLVM_CLANG_INSTALLAPI_FRONTEND_H | ||
|
|
||
| #include "clang/AST/ASTConsumer.h" | ||
| #include "clang/AST/Availability.h" | ||
| #include "clang/Frontend/CompilerInstance.h" | ||
| #include "clang/Frontend/FrontendActions.h" | ||
| #include "clang/InstallAPI/Context.h" | ||
| #include "clang/InstallAPI/Visitor.h" | ||
| #include "llvm/ADT/Twine.h" | ||
| #include "llvm/Support/MemoryBuffer.h" | ||
|
|
||
| namespace clang { | ||
| namespace installapi { | ||
|
|
||
| using SymbolFlags = llvm::MachO::SymbolFlags; | ||
| using RecordLinkage = llvm::MachO::RecordLinkage; | ||
| using GlobalRecord = llvm::MachO::GlobalRecord; | ||
| using ObjCContainerRecord = llvm::MachO::ObjCContainerRecord; | ||
| using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord; | ||
| using ObjCCategoryRecord = llvm::MachO::ObjCCategoryRecord; | ||
| using ObjCIVarRecord = llvm::MachO::ObjCIVarRecord; | ||
|
|
||
| // Represents a collection of frontend records for a library that are tied to a | ||
| // darwin target triple. | ||
| class FrontendRecordsSlice : public llvm::MachO::RecordsSlice { | ||
| public: | ||
| FrontendRecordsSlice(const llvm::Triple &T) | ||
| : llvm::MachO::RecordsSlice({T}) {} | ||
|
|
||
| /// Add non-ObjC global record with attributes from AST. | ||
| /// | ||
| /// \param Name The name of symbol. | ||
| /// \param Linkage The linkage of symbol. | ||
| /// \param GV The kind of global. | ||
| /// \param Avail The availability information tied to the active target | ||
| /// triple. | ||
| /// \param D The pointer to the declaration from traversing AST. | ||
| /// \param Access The intended access level of symbol. | ||
| /// \param Flags The flags that describe attributes of the symbol. | ||
| /// \return The non-owning pointer to added record in slice. | ||
| GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage, | ||
| GlobalRecord::Kind GV, | ||
| const clang::AvailabilityInfo Avail, const Decl *D, | ||
| const HeaderType Access, | ||
| SymbolFlags Flags = SymbolFlags::None); | ||
|
|
||
| /// Add ObjC Class record with attributes from AST. | ||
| /// | ||
| /// \param Name The name of class, not symbol. | ||
| /// \param Linkage The linkage of symbol. | ||
| /// \param Avail The availability information tied to the active target | ||
| /// triple. | ||
| /// \param D The pointer to the declaration from traversing AST. | ||
| /// \param Access The intended access level of symbol. | ||
| /// \param IsEHType Whether declaration has an exception attribute. | ||
| /// \return The non-owning pointer to added record in slice. | ||
| ObjCInterfaceRecord *addObjCInterface(StringRef Name, RecordLinkage Linkage, | ||
| const clang::AvailabilityInfo Avail, | ||
| const Decl *D, HeaderType Access, | ||
| bool IsEHType); | ||
|
|
||
| /// Add ObjC Category record with attributes from AST. | ||
| /// | ||
| /// \param ClassToExtend The name of class that is extended by category, not | ||
| /// symbol. | ||
| /// \param CategoryName The name of category, not symbol. | ||
| /// \param Avail The availability information tied | ||
| /// to the active target triple. | ||
| /// \param D The pointer to the declaration from traversing AST. | ||
| /// \param Access The intended access level of symbol. | ||
| /// \return The non-owning pointer to added record in slice. | ||
| ObjCCategoryRecord *addObjCCategory(StringRef ClassToExtend, | ||
| StringRef CategoryName, | ||
| const clang::AvailabilityInfo Avail, | ||
| const Decl *D, HeaderType Access); | ||
|
|
||
| /// Add ObjC IVar record with attributes from AST. | ||
| /// | ||
| /// \param Container The owning pointer for instance variable. | ||
| /// \param Name The name of ivar, not symbol. | ||
| /// \param Linkage The linkage of symbol. | ||
| /// \param Avail The availability information tied to the active target | ||
| /// triple. | ||
| /// \param D The pointer to the declaration from traversing AST. | ||
| /// \param Access The intended access level of symbol. | ||
| /// \param AC The access control tied to the ivar declaration. | ||
| /// \return The non-owning pointer to added record in slice. | ||
| ObjCIVarRecord *addObjCIVar(ObjCContainerRecord *Container, | ||
| StringRef IvarName, RecordLinkage Linkage, | ||
| const clang::AvailabilityInfo Avail, | ||
| const Decl *D, HeaderType Access, | ||
| const clang::ObjCIvarDecl::AccessControl AC); | ||
|
|
||
| private: | ||
| /// Frontend information captured about records. | ||
| struct FrontendAttrs { | ||
| const AvailabilityInfo Avail; | ||
| const Decl *D; | ||
| const HeaderType Access; | ||
| }; | ||
|
|
||
| /// Mapping of records stored in slice to their frontend attributes. | ||
| llvm::DenseMap<llvm::MachO::Record *, FrontendAttrs> FrontendRecords; | ||
| }; | ||
|
|
||
| /// Create a buffer that contains all headers to scan | ||
| /// for global symbols with. | ||
| std::unique_ptr<llvm::MemoryBuffer> createInputBuffer(InstallAPIContext &Ctx); | ||
|
|
||
| class InstallAPIAction : public ASTFrontendAction { | ||
| public: | ||
| explicit InstallAPIAction(InstallAPIContext &Ctx) : Ctx(Ctx) {} | ||
|
|
||
| std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, | ||
| StringRef InFile) override { | ||
| return std::make_unique<InstallAPIVisitor>( | ||
| CI.getASTContext(), Ctx, CI.getSourceManager(), CI.getPreprocessor()); | ||
| } | ||
|
|
||
| private: | ||
| InstallAPIContext &Ctx; | ||
| }; | ||
| } // namespace installapi | ||
| } // namespace clang | ||
|
|
||
| #endif // LLVM_CLANG_INSTALLAPI_FRONTEND_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| //===- InstallAPI/Visitor.h -----------------------------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| /// | ||
| /// ASTVisitor Interface for InstallAPI frontend operations. | ||
| /// | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_CLANG_INSTALLAPI_VISITOR_H | ||
| #define LLVM_CLANG_INSTALLAPI_VISITOR_H | ||
|
|
||
| #include "clang/AST/Mangle.h" | ||
| #include "clang/AST/RecursiveASTVisitor.h" | ||
| #include "clang/Basic/TargetInfo.h" | ||
| #include "clang/Frontend/FrontendActions.h" | ||
| #include "clang/InstallAPI/Context.h" | ||
| #include "llvm/ADT/Twine.h" | ||
|
|
||
| namespace clang { | ||
| namespace installapi { | ||
|
|
||
| /// ASTVisitor for collecting declarations that represent global symbols. | ||
| class InstallAPIVisitor final : public ASTConsumer, | ||
| public RecursiveASTVisitor<InstallAPIVisitor> { | ||
| public: | ||
| InstallAPIVisitor(ASTContext &ASTCtx, InstallAPIContext &Ctx, | ||
| SourceManager &SrcMgr, Preprocessor &PP) | ||
| : Ctx(Ctx), SrcMgr(SrcMgr), PP(PP), | ||
| MC(ItaniumMangleContext::create(ASTCtx, ASTCtx.getDiagnostics())), | ||
| Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {} | ||
| void HandleTranslationUnit(ASTContext &ASTCtx) override; | ||
|
|
||
| /// Collect global variables. | ||
| bool VisitVarDecl(const VarDecl *D); | ||
|
|
||
| /// Collect Objective-C Interface declarations. | ||
| /// Every Objective-C class has an interface declaration that lists all the | ||
| /// ivars, properties, and methods of the class. | ||
| bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D); | ||
|
|
||
| /// Collect Objective-C Category/Extension declarations. | ||
| /// | ||
| /// The class that is being extended might come from a different library and | ||
| /// is therefore itself not collected. | ||
| bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D); | ||
|
|
||
| private: | ||
| std::string getMangledName(const NamedDecl *D) const; | ||
| std::string getBackendMangledName(llvm::Twine Name) const; | ||
| std::optional<HeaderType> getAccessForDecl(const NamedDecl *D) const; | ||
| void recordObjCInstanceVariables( | ||
| const ASTContext &ASTCtx, llvm::MachO::ObjCContainerRecord *Record, | ||
| StringRef SuperClass, | ||
| const llvm::iterator_range< | ||
| DeclContext::specific_decl_iterator<ObjCIvarDecl>> | ||
| Ivars); | ||
|
|
||
| InstallAPIContext &Ctx; | ||
| SourceManager &SrcMgr; | ||
| Preprocessor &PP; | ||
| std::unique_ptr<clang::ItaniumMangleContext> MC; | ||
| StringRef Layout; | ||
| }; | ||
|
|
||
| } // namespace installapi | ||
| } // namespace clang | ||
|
|
||
| #endif // LLVM_CLANG_INSTALLAPI_VISITOR_H |