@@ -31,6 +31,11 @@ void AvoidCStyleCastsCheck::registerMatchers(
31
31
unless (isInTemplateInstantiation ()))
32
32
.bind (" cast" ),
33
33
this );
34
+ Finder->addMatcher (
35
+ cxxFunctionalCastExpr (unless (hasDescendant (cxxConstructExpr ())),
36
+ unless (hasDescendant (initListExpr ())))
37
+ .bind (" cast" ),
38
+ this );
34
39
}
35
40
36
41
static bool needsConstCast (QualType SourceType, QualType DestType) {
@@ -55,8 +60,39 @@ static bool pointedUnqualifiedTypesAreEqual(QualType T1, QualType T2) {
55
60
return T1.getUnqualifiedType () == T2.getUnqualifiedType ();
56
61
}
57
62
63
+ static clang::CharSourceRange getReplaceRange (const ExplicitCastExpr *Expr) {
64
+ if (const auto *CastExpr = dyn_cast<CStyleCastExpr>(Expr)) {
65
+ return CharSourceRange::getCharRange (
66
+ CastExpr->getLParenLoc (),
67
+ CastExpr->getSubExprAsWritten ()->getBeginLoc ());
68
+ } else if (const auto *CastExpr = dyn_cast<CXXFunctionalCastExpr>(Expr)) {
69
+ return CharSourceRange::getCharRange (CastExpr->getBeginLoc (),
70
+ CastExpr->getLParenLoc ());
71
+ } else
72
+ llvm_unreachable (" Unsupported CastExpr" );
73
+ }
74
+
75
+ static StringRef getDestTypeString (const SourceManager &SM,
76
+ const LangOptions &LangOpts,
77
+ const ExplicitCastExpr *Expr) {
78
+ SourceLocation BeginLoc;
79
+ SourceLocation EndLoc;
80
+
81
+ if (const auto *CastExpr = dyn_cast<CStyleCastExpr>(Expr)) {
82
+ BeginLoc = CastExpr->getLParenLoc ().getLocWithOffset (1 );
83
+ EndLoc = CastExpr->getRParenLoc ().getLocWithOffset (-1 );
84
+ } else if (const auto *CastExpr = dyn_cast<CXXFunctionalCastExpr>(Expr)) {
85
+ BeginLoc = CastExpr->getBeginLoc ();
86
+ EndLoc = CastExpr->getLParenLoc ().getLocWithOffset (-1 );
87
+ } else
88
+ llvm_unreachable (" Unsupported CastExpr" );
89
+
90
+ return Lexer::getSourceText (CharSourceRange::getTokenRange (BeginLoc, EndLoc),
91
+ SM, LangOpts);
92
+ }
93
+
58
94
void AvoidCStyleCastsCheck::check (const MatchFinder::MatchResult &Result) {
59
- const auto *CastExpr = Result.Nodes .getNodeAs <CStyleCastExpr >(" cast" );
95
+ const auto *CastExpr = Result.Nodes .getNodeAs <ExplicitCastExpr >(" cast" );
60
96
61
97
// Ignore casts in macros.
62
98
if (CastExpr->getExprLoc ().isMacroID ())
@@ -80,8 +116,7 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
80
116
const QualType SourceType = SourceTypeAsWritten.getCanonicalType ();
81
117
const QualType DestType = DestTypeAsWritten.getCanonicalType ();
82
118
83
- auto ReplaceRange = CharSourceRange::getCharRange (
84
- CastExpr->getLParenLoc (), CastExpr->getSubExprAsWritten ()->getBeginLoc ());
119
+ CharSourceRange ReplaceRange = getReplaceRange (CastExpr);
85
120
86
121
bool FnToFnCast =
87
122
IsFunction (SourceTypeAsWritten) && IsFunction (DestTypeAsWritten);
@@ -124,18 +159,14 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) {
124
159
125
160
// Leave type spelling exactly as it was (unlike
126
161
// getTypeAsWritten().getAsString() which would spell enum types 'enum X').
127
- StringRef DestTypeString =
128
- Lexer::getSourceText (CharSourceRange::getTokenRange (
129
- CastExpr->getLParenLoc ().getLocWithOffset (1 ),
130
- CastExpr->getRParenLoc ().getLocWithOffset (-1 )),
131
- SM, getLangOpts ());
162
+ StringRef DestTypeString = getDestTypeString (SM, getLangOpts (), CastExpr);
132
163
133
164
auto Diag =
134
165
diag (CastExpr->getBeginLoc (), " C-style casts are discouraged; use %0" );
135
166
136
167
auto ReplaceWithCast = [&](std::string CastText) {
137
168
const Expr *SubExpr = CastExpr->getSubExprAsWritten ()->IgnoreImpCasts ();
138
- if (!isa<ParenExpr>(SubExpr)) {
169
+ if (!isa<ParenExpr>(SubExpr) && !isa<CXXFunctionalCastExpr>(CastExpr) ) {
139
170
CastText.push_back (' (' );
140
171
Diag << FixItHint::CreateInsertion (
141
172
Lexer::getLocForEndOfToken (SubExpr->getEndLoc (), 0 , SM,
0 commit comments