24 const auto *TS = S->getAs<TypedefType>();
25 const auto *TD = D->getAs<TypedefType>();
29 const QualType PtrS = S->getPointeeType();
30 const QualType PtrD = D->getPointeeType();
32 if (!PtrS.isNull() && !PtrD.isNull())
33 return areTypesEqual(PtrS.IgnoreParens(), PtrD.IgnoreParens());
35 const DeducedType *DT = S->getContainedDeducedType();
36 if (DT && DT->isDeduced())
37 return D == DT->getDeducedType();
54 const Expr *E,
bool IgnoreTypeAliases) {
57 const Expr *WithoutImplicitAndParen = E->IgnoreParenImpCasts();
58 if (!WithoutImplicitAndParen)
60 if (
const auto *B = dyn_cast<BinaryOperator>(WithoutImplicitAndParen)) {
61 const QualType Type = WithoutImplicitAndParen->getType();
65 const QualType NonReferenceType = Type.getNonReferenceType();
66 const QualType LHSType = B->getLHS()->IgnoreImplicit()->getType();
67 if (LHSType.isNull() || !
areTypesEqual(LHSType.getNonReferenceType(),
68 NonReferenceType, IgnoreTypeAliases))
70 const QualType RHSType = B->getRHS()->IgnoreImplicit()->getType();
71 if (RHSType.isNull() || !
areTypesEqual(RHSType.getNonReferenceType(),
72 NonReferenceType, IgnoreTypeAliases))
106 auto SimpleType = qualType(hasCanonicalType(
107 qualType(anyOf(builtinType(), references(builtinType()),
108 references(pointsTo(qualType())), pointsTo(qualType())))));
110 auto BitfieldMemberExpr = memberExpr(member(fieldDecl(isBitField())));
112 const ast_matchers::internal::VariadicDynCastAllOfMatcher<
113 Stmt, CXXParenListInitExpr>
114 cxxParenListInitExpr;
118 unless(hasCastKind(CK_ConstructorConversion)),
119 unless(hasCastKind(CK_UserDefinedConversion)),
120 unless(cxxFunctionalCastExpr(hasDestinationType(unless(SimpleType)))),
122 hasDestinationType(qualType().bind(
"dstType")),
123 hasSourceExpression(anyOf(
124 expr(unless(initListExpr()), unless(BitfieldMemberExpr),
125 unless(cxxParenListInitExpr()),
126 hasType(qualType().bind(
"srcType")))
128 initListExpr(unless(hasInit(1, expr())),
129 hasInit(0, expr(unless(BitfieldMemberExpr),
130 hasType(qualType().bind(
"srcType")))
137 const auto *SourceExpr = Result.Nodes.getNodeAs<Expr>(
"source");
138 auto TypeD = *Result.Nodes.getNodeAs<QualType>(
"dstType");
140 if (SourceExpr->getValueKind() == VK_LValue &&
141 TypeD.getCanonicalType()->isRValueReferenceType())
145 Result.Nodes.getNodeAs<QualType>(
"srcType")->getNonReferenceType();
146 TypeD = TypeD.getNonReferenceType();
152 SourceExpr, IgnoreTypeAliases))
155 const auto *CastExpr = Result.Nodes.getNodeAs<ExplicitCastExpr>(
"cast");
157 (CastExpr->getBeginLoc().isMacroID() ||
158 CastExpr->getEndLoc().isMacroID() || CastExpr->getExprLoc().isMacroID()))
162 auto Diag = diag(CastExpr->getExprLoc(),
163 "redundant explicit casting to the same type %0 as the "
164 "sub-expression, remove this casting");
167 const SourceManager &SM = *Result.SourceManager;
168 const SourceLocation SourceExprBegin =
169 SM.getExpansionLoc(SourceExpr->getBeginLoc());
170 const SourceLocation SourceExprEnd =
171 SM.getExpansionLoc(SourceExpr->getEndLoc());
173 if (SourceExprBegin != CastExpr->getBeginLoc())
174 Diag << FixItHint::CreateRemoval(SourceRange(
175 CastExpr->getBeginLoc(), SourceExprBegin.getLocWithOffset(-1)));
177 const SourceLocation NextToken = Lexer::getLocForEndOfToken(
178 SourceExprEnd, 0U, SM, Result.Context->getLangOpts());
180 if (SourceExprEnd != CastExpr->getEndLoc()) {
181 Diag << FixItHint::CreateRemoval(
182 SourceRange(NextToken, CastExpr->getEndLoc()));
186 Diag << FixItHint::CreateInsertion(SourceExprBegin,
"(")
187 << FixItHint::CreateInsertion(NextToken,
")");
195 if (
const auto *D = dyn_cast<CXXConstructorDecl>(SourceExprDecl)) {
196 diag(D->getLocation(),
197 "source type originates from the invocation of this constructor",
198 DiagnosticIDs::Note);
202 if (
const auto *D = dyn_cast<FunctionDecl>(SourceExprDecl)) {
203 diag(D->getLocation(),
204 "source type originates from the invocation of this "
205 "%select{function|method}0",
207 << isa<CXXMethodDecl>(D) << D->getReturnTypeSourceRange();
211 if (
const auto *D = dyn_cast<FieldDecl>(SourceExprDecl)) {
212 diag(D->getLocation(),
213 "source type originates from referencing this member",
215 << SourceRange(D->getTypeSpecStartLoc(), D->getTypeSpecEndLoc());
219 if (
const auto *D = dyn_cast<ParmVarDecl>(SourceExprDecl)) {
220 diag(D->getLocation(),
221 "source type originates from referencing this parameter",
223 << SourceRange(D->getTypeSpecStartLoc(), D->getTypeSpecEndLoc());
227 if (
const auto *D = dyn_cast<VarDecl>(SourceExprDecl)) {
228 diag(D->getLocation(),
229 "source type originates from referencing this variable",
231 << SourceRange(D->getTypeSpecStartLoc(), D->getTypeSpecEndLoc());
235 if (
const auto *D = dyn_cast<EnumConstantDecl>(SourceExprDecl)) {
236 diag(D->getLocation(),
237 "source type originates from referencing this enum constant",
238 DiagnosticIDs::Note);
242 if (
const auto *D = dyn_cast<BindingDecl>(SourceExprDecl)) {
243 diag(D->getLocation(),
244 "source type originates from referencing this bound variable",
245 DiagnosticIDs::Note);
249 if (
const auto *D = dyn_cast<NonTypeTemplateParmDecl>(SourceExprDecl)) {
250 diag(D->getLocation(),
251 "source type originates from referencing this non-type template "
253 DiagnosticIDs::Note);
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.