@@ -79,8 +79,10 @@ static bool isStdInitializerList(QualType Type) {
79
79
}
80
80
81
81
void ExplicitConstructorCheck::check (const MatchFinder::MatchResult &Result) {
82
- constexpr char WarningMessage [] =
82
+ constexpr char NoExpressionWarningMessage [] =
83
83
" %0 must be marked explicit to avoid unintentional implicit conversions" ;
84
+ constexpr char WithExpressionWarningMessage[] =
85
+ " %0 explicit expression evaluated to false" ;
84
86
85
87
if (const auto *Conversion =
86
88
Result.Nodes .getNodeAs <CXXConversionDecl>(" conversion" )) {
@@ -91,7 +93,7 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
91
93
// gmock to define matchers).
92
94
if (Loc.isMacroID ())
93
95
return ;
94
- diag (Loc, WarningMessage )
96
+ diag (Loc, NoExpressionWarningMessage )
95
97
<< Conversion << FixItHint::CreateInsertion (Loc, " explicit " );
96
98
return ;
97
99
}
@@ -101,9 +103,11 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
101
103
Ctor->getMinRequiredArguments () > 1 )
102
104
return ;
103
105
106
+ const ExplicitSpecifier ExplicitSpec = Ctor->getExplicitSpecifier ();
107
+
104
108
bool TakesInitializerList = isStdInitializerList (
105
109
Ctor->getParamDecl (0 )->getType ().getNonReferenceType ());
106
- if (Ctor-> isExplicit () &&
110
+ if (ExplicitSpec. isExplicit () &&
107
111
(Ctor->isCopyOrMoveConstructor () || TakesInitializerList)) {
108
112
auto IsKwExplicit = [](const Token &Tok) {
109
113
return Tok.is (tok::raw_identifier) &&
@@ -130,18 +134,30 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) {
130
134
return ;
131
135
}
132
136
133
- if (Ctor-> isExplicit () || Ctor->isCopyOrMoveConstructor () ||
137
+ if (ExplicitSpec. isExplicit () || Ctor->isCopyOrMoveConstructor () ||
134
138
TakesInitializerList)
135
139
return ;
136
140
141
+ // Don't complain about explicit(false)
142
+ const Expr *ExplicitExpr = ExplicitSpec.getExpr ();
143
+ if (ExplicitExpr) {
144
+ ExplicitExpr = ExplicitExpr->IgnoreImplicit ();
145
+ if (isa<CXXBoolLiteralExpr>(ExplicitExpr))
146
+ return ;
147
+ }
148
+
137
149
bool SingleArgument =
138
150
Ctor->getNumParams () == 1 && !Ctor->getParamDecl (0 )->isParameterPack ();
139
151
SourceLocation Loc = Ctor->getLocation ();
140
- diag (Loc, WarningMessage)
152
+ auto Diag =
153
+ diag (Loc, ExplicitExpr ? WithExpressionWarningMessage
154
+ : NoExpressionWarningMessage)
141
155
<< (SingleArgument
142
156
? " single-argument constructors"
143
- : " constructors that are callable with a single argument" )
144
- << FixItHint::CreateInsertion (Loc, " explicit " );
157
+ : " constructors that are callable with a single argument" );
158
+
159
+ if (!ExplicitExpr)
160
+ Diag << FixItHint::CreateInsertion (Loc, " explicit " );
145
161
}
146
162
147
163
} // namespace clang::tidy::google
0 commit comments