@@ -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 evaluates 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,31 @@ 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
137
- bool SingleArgument =
141
+ // Don't complain about explicit(false) or dependent expressions
142
+ const Expr *ExplicitExpr = ExplicitSpec.getExpr ();
143
+ if (ExplicitExpr) {
144
+ ExplicitExpr = ExplicitExpr->IgnoreImplicit ();
145
+ if (isa<CXXBoolLiteralExpr>(ExplicitExpr) ||
146
+ ExplicitExpr->isInstantiationDependent ())
147
+ return ;
148
+ }
149
+
150
+ const bool SingleArgument =
138
151
Ctor->getNumParams () == 1 && !Ctor->getParamDecl (0 )->isParameterPack ();
139
152
SourceLocation Loc = Ctor->getLocation ();
140
- diag (Loc, WarningMessage)
153
+ auto Diag =
154
+ diag (Loc, ExplicitExpr ? WithExpressionWarningMessage
155
+ : NoExpressionWarningMessage)
141
156
<< (SingleArgument
142
157
? " single-argument constructors"
143
- : " constructors that are callable with a single argument" )
144
- << FixItHint::CreateInsertion (Loc, " explicit " );
158
+ : " constructors that are callable with a single argument" );
159
+
160
+ if (!ExplicitExpr)
161
+ Diag << FixItHint::CreateInsertion (Loc, " explicit " );
145
162
}
146
163
147
164
} // namespace clang::tidy::google
0 commit comments