Skip to content

Commit b53538c

Browse files
committed
concatenate friend fix with others
1 parent 24338d5 commit b53538c

File tree

2 files changed

+86
-44
lines changed

2 files changed

+86
-44
lines changed

clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static const NamedDecl *
4242
getDerivedParameter(const ClassTemplateSpecializationDecl *CRTP,
4343
const CXXRecordDecl *Derived) {
4444
size_t Idx = 0;
45-
bool AnyOf = llvm::any_of(
45+
const bool AnyOf = llvm::any_of(
4646
CRTP->getTemplateArgs().asArray(), [&](const TemplateArgument &Arg) {
4747
++Idx;
4848
return Arg.getKind() == TemplateArgument::Type &&
@@ -95,38 +95,52 @@ void CrtpConstructorAccessibilityCheck::check(
9595
const CXXRecordDecl *CRTPDeclaration =
9696
CRTPInstantiation->getSpecializedTemplate()->getTemplatedDecl();
9797

98-
if (!CRTPDeclaration->hasUserDeclaredConstructor()) {
99-
const bool IsStruct = CRTPDeclaration->isStruct();
100-
101-
diag(CRTPDeclaration->getLocation(),
102-
"the implicit default constructor of the CRTP is publicly accessible")
103-
<< CRTPDeclaration
104-
<< FixItHint::CreateInsertion(
105-
CRTPDeclaration->getBraceRange().getBegin().getLocWithOffset(1),
106-
(IsStruct ? "\nprivate:\n" : "\n") +
107-
CRTPDeclaration->getNameAsString() + "() = default;\n" +
108-
(IsStruct ? "public:\n" : ""));
109-
diag(CRTPDeclaration->getLocation(), "consider making it private",
110-
DiagnosticIDs::Note);
111-
}
112-
11398
const auto *DerivedTemplateParameter =
11499
getDerivedParameter(CRTPInstantiation, DerivedRecord);
115100

116101
assert(DerivedTemplateParameter &&
117102
"No template parameter corresponds to the derived class of the CRTP.");
118103

119-
if (hasPrivateConstructor(CRTPDeclaration) &&
120-
!isDerivedParameterBefriended(CRTPDeclaration,
121-
DerivedTemplateParameter) &&
122-
!isDerivedClassBefriended(CRTPDeclaration, DerivedRecord)) {
104+
bool NeedsFriend = !isDerivedParameterBefriended(CRTPDeclaration,
105+
DerivedTemplateParameter) &&
106+
!isDerivedClassBefriended(CRTPDeclaration, DerivedRecord);
107+
108+
const FixItHint HintFriend = FixItHint::CreateInsertion(
109+
CRTPDeclaration->getBraceRange().getEnd(),
110+
"friend " + DerivedTemplateParameter->getNameAsString() + ';' + '\n');
111+
112+
if (!CRTPDeclaration->hasUserDeclaredConstructor()) {
113+
const bool IsStruct = CRTPDeclaration->isStruct();
114+
115+
// FIXME: Clean this up!
116+
{
117+
DiagnosticBuilder Diag =
118+
diag(CRTPDeclaration->getLocation(),
119+
"the implicit default constructor of the CRTP is publicly "
120+
"accessible")
121+
<< CRTPDeclaration
122+
<< FixItHint::CreateInsertion(
123+
CRTPDeclaration->getBraceRange().getBegin().getLocWithOffset(
124+
1),
125+
(IsStruct ? "\nprivate:\n" : "\n") +
126+
CRTPDeclaration->getNameAsString() + "() = default;\n" +
127+
(IsStruct ? "public:\n" : ""));
128+
129+
if (NeedsFriend)
130+
Diag << HintFriend;
131+
}
132+
133+
diag(CRTPDeclaration->getLocation(),
134+
"consider making it private%select{| and declaring the derived class "
135+
"as friend}0",
136+
DiagnosticIDs::Note)
137+
<< NeedsFriend;
138+
}
139+
140+
if (hasPrivateConstructor(CRTPDeclaration) && NeedsFriend) {
123141
diag(CRTPDeclaration->getLocation(),
124142
"the CRTP cannot be constructed from the derived class")
125-
<< CRTPDeclaration
126-
<< FixItHint::CreateInsertion(
127-
CRTPDeclaration->getBraceRange().getEnd(),
128-
"friend " + DerivedTemplateParameter->getNameAsString() + ';' +
129-
'\n');
143+
<< CRTPDeclaration << HintFriend;
130144
diag(CRTPDeclaration->getLocation(),
131145
"consider declaring the derived class as friend", DiagnosticIDs::Note);
132146
}
@@ -138,12 +152,24 @@ void CrtpConstructorAccessibilityCheck::check(
138152
const bool IsPublic = Ctor->getAccess() == AS_public;
139153
const std::string Access = IsPublic ? "public" : "protected";
140154

155+
// FIXME: Clean this up!
156+
{
157+
DiagnosticBuilder Diag =
158+
diag(Ctor->getLocation(),
159+
"%0 contructor allows the CRTP to be %select{inherited "
160+
"from|constructed}1 as a regular template class")
161+
<< Access << IsPublic << Ctor << hintMakeCtorPrivate(Ctor, Access);
162+
163+
if (NeedsFriend)
164+
Diag << HintFriend;
165+
}
166+
167+
// FIXME: Test the NeedsFriend false case!
141168
diag(Ctor->getLocation(),
142-
"%0 contructor allows the CRTP to be %select{inherited "
143-
"from|constructed}1 as a regular template class")
144-
<< Access << IsPublic << Ctor << hintMakeCtorPrivate(Ctor, Access);
145-
diag(Ctor->getLocation(), "consider making it private",
146-
DiagnosticIDs::Note);
169+
"consider making it private%select{| and declaring the derived class "
170+
"as friend}0",
171+
DiagnosticIDs::Note)
172+
<< NeedsFriend;
147173
}
148174
}
149175

clang-tools-extra/test/clang-tidy/checkers/bugprone/crtp-constructor-accessibility.cpp

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ namespace class_implicit_ctor {
44
template <typename T>
55
class CRTP {};
66
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible [bugprone-crtp-constructor-accessibility]
7-
// CHECK-MESSAGES: :[[@LINE-2]]:7: note: consider making it private
7+
// CHECK-MESSAGES: :[[@LINE-2]]:7: note: consider making it private and declaring the derived class as friend
88
// CHECK-FIXES: CRTP() = default;
9+
// CHECK-FIXES: friend T;
910

1011
class A : CRTP<A> {};
1112
} // namespace class_implicit_ctor
@@ -28,8 +29,9 @@ class CRTP {
2829
public:
2930
CRTP() = default;
3031
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class [bugprone-crtp-constructor-accessibility]
31-
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private
32+
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private and declaring the derived class as friend
3233
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:
34+
// CHECK-FIXES: friend T;
3335
};
3436

3537
class A : CRTP<A> {};
@@ -41,8 +43,9 @@ class CRTP {
4143
public:
4244
CRTP(int) {}
4345
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class [bugprone-crtp-constructor-accessibility]
44-
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private
46+
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private and declaring the derived class as friend
4547
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public:
48+
// CHECK-FIXES: friend T;
4649
};
4750

4851
class A : CRTP<A> {};
@@ -54,12 +57,15 @@ class CRTP {
5457
public:
5558
CRTP(int) {}
5659
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class [bugprone-crtp-constructor-accessibility]
57-
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private
60+
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private and declaring the derived class as friend
5861
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public:
5962
CRTP(float) {}
6063
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class [bugprone-crtp-constructor-accessibility]
61-
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private
64+
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private and declaring the derived class as friend
6265
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}public:
66+
67+
// CHECK-FIXES: friend T;
68+
// CHECK-FIXES: friend T;
6369
};
6470

6571
class A : CRTP<A> {};
@@ -71,16 +77,20 @@ class CRTP {
7177
protected:
7278
CRTP(int) {}
7379
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class [bugprone-crtp-constructor-accessibility]
74-
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private
80+
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private and declaring the derived class as friend
7581
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}protected:
7682
CRTP() = default;
7783
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class [bugprone-crtp-constructor-accessibility]
78-
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private
84+
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private and declaring the derived class as friend
7985
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}protected:
8086
CRTP(float) {}
8187
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class [bugprone-crtp-constructor-accessibility]
82-
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private
88+
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private and declaring the derived class as friend
8389
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}protected:
90+
91+
// CHECK-FIXES: friend T;
92+
// CHECK-FIXES: friend T;
93+
// CHECK-FIXES: friend T;
8494
};
8595

8696
class A : CRTP<A> {};
@@ -90,8 +100,9 @@ namespace struct_implicit_ctor {
90100
template <typename T>
91101
struct CRTP {};
92102
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible [bugprone-crtp-constructor-accessibility]
93-
// CHECK-MESSAGES: :[[@LINE-2]]:8: note: consider making it private
103+
// CHECK-MESSAGES: :[[@LINE-2]]:8: note: consider making it private and declaring the derived class as friend
94104
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:
105+
// CHECK-FIXES: friend T;
95106

96107
class A : CRTP<A> {};
97108
} // namespace struct_implicit_ctor
@@ -101,8 +112,9 @@ template <typename T>
101112
struct CRTP {
102113
CRTP() = default;
103114
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class [bugprone-crtp-constructor-accessibility]
104-
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private
115+
// CHECK-MESSAGES: :[[@LINE-2]]:5: note: consider making it private and declaring the derived class as friend
105116
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:
117+
// CHECK-FIXES: friend T;
106118
};
107119

108120
class A : CRTP<A> {};
@@ -112,14 +124,16 @@ namespace same_class_multiple_crtps {
112124
template <typename T>
113125
struct CRTP {};
114126
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible [bugprone-crtp-constructor-accessibility]
115-
// CHECK-MESSAGES: :[[@LINE-2]]:8: note: consider making it private
127+
// CHECK-MESSAGES: :[[@LINE-2]]:8: note: consider making it private and declaring the derived class as friend
116128
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:
129+
// CHECK-FIXES: friend T;
117130

118131
template <typename T>
119132
struct CRTP2 {};
120133
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible [bugprone-crtp-constructor-accessibility]
121-
// CHECK-MESSAGES: :[[@LINE-2]]:8: note: consider making it private
134+
// CHECK-MESSAGES: :[[@LINE-2]]:8: note: consider making it private and declaring the derived class as friend
122135
// CHECK-FIXES: private:{{[[:space:]]*}}CRTP2() = default;{{[[:space:]]*}}public:
136+
// CHECK-FIXES: friend T;
123137

124138
class A : CRTP<A>, CRTP2<A> {};
125139
} // namespace same_class_multiple_crtps
@@ -165,8 +179,9 @@ namespace template_derived {
165179
template <typename T>
166180
class CRTP {};
167181
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible [bugprone-crtp-constructor-accessibility]
168-
// CHECK-MESSAGES: :[[@LINE-2]]:7: note: consider making it private
182+
// CHECK-MESSAGES: :[[@LINE-2]]:7: note: consider making it private and declaring the derived class as friend
169183
// CHECK-FIXES: CRTP() = default;
184+
// CHECK-FIXES: friend T;
170185

171186
template<typename T>
172187
class A : CRTP<A<T>> {};
@@ -182,8 +197,9 @@ namespace template_derived_explicit_specialization {
182197
template <typename T>
183198
class CRTP {};
184199
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible [bugprone-crtp-constructor-accessibility]
185-
// CHECK-MESSAGES: :[[@LINE-2]]:7: note: consider making it private
200+
// CHECK-MESSAGES: :[[@LINE-2]]:7: note: consider making it private and declaring the derived class as friend
186201
// CHECK-FIXES: CRTP() = default;
202+
// CHECK-FIXES: friend T;
187203

188204
template<typename T>
189205
class A : CRTP<A<T>> {};

0 commit comments

Comments
 (0)