23 const auto *TS = S->getAs<TypedefType>();
24 const auto *TD = D->getAs<TypedefType>();
28 QualType PtrS = S->getPointeeType();
29 QualType PtrD = D->getPointeeType();
31 if (!PtrS.isNull() && !PtrD.isNull())
34 const DeducedType *DT = S->getContainedDeducedType();
35 if (DT && DT->isDeduced())
36 return D == DT->getDeducedType();
53 const Expr *E,
bool IgnoreTypeAliases) {
56 const Expr *WithoutImplicitAndParen = E->IgnoreParenImpCasts();
57 if (!WithoutImplicitAndParen)
59 if (
const auto *B = dyn_cast<BinaryOperator>(WithoutImplicitAndParen)) {
60 const QualType Type = WithoutImplicitAndParen->getType();
64 const QualType NonReferenceType = Type.getNonReferenceType();
65 const QualType LHSType = B->getLHS()->IgnoreImplicit()->getType();
66 if (LHSType.isNull() || !
areTypesEqual(LHSType.getNonReferenceType(),
67 NonReferenceType, IgnoreTypeAliases))
69 const QualType RHSType = B->getRHS()->IgnoreImplicit()->getType();
70 if (RHSType.isNull() || !
areTypesEqual(RHSType.getNonReferenceType(),
71 NonReferenceType, IgnoreTypeAliases))
105 auto SimpleType = qualType(hasCanonicalType(
106 qualType(anyOf(builtinType(), references(builtinType()),
107 references(pointsTo(qualType())), pointsTo(qualType())))));
109 auto BitfieldMemberExpr = memberExpr(member(fieldDecl(isBitField())));
111 const ast_matchers::internal::VariadicDynCastAllOfMatcher<
112 Stmt, CXXParenListInitExpr>
113 cxxParenListInitExpr;
117 unless(hasCastKind(CK_ConstructorConversion)),
118 unless(hasCastKind(CK_UserDefinedConversion)),
119 unless(cxxFunctionalCastExpr(hasDestinationType(unless(SimpleType)))),
121 hasDestinationType(qualType().bind(
"dstType")),
122 hasSourceExpression(anyOf(
123 expr(unless(initListExpr()), unless(BitfieldMemberExpr),
124 unless(cxxParenListInitExpr()),
125 hasType(qualType().bind(
"srcType")))
127 initListExpr(unless(hasInit(1, expr())),
128 hasInit(0, expr(unless(BitfieldMemberExpr),
129 hasType(qualType().bind(
"srcType")))
136 const auto *SourceExpr = Result.Nodes.getNodeAs<Expr>(
"source");
137 auto TypeD = *Result.Nodes.getNodeAs<QualType>(
"dstType");
139 if (SourceExpr->getValueKind() == VK_LValue &&
140 TypeD.getCanonicalType()->isRValueReferenceType())
144 Result.Nodes.getNodeAs<QualType>(
"srcType")->getNonReferenceType();
145 TypeD = TypeD.getNonReferenceType();
151 SourceExpr, IgnoreTypeAliases))
154 const auto *CastExpr = Result.Nodes.getNodeAs<ExplicitCastExpr>(
"cast");
156 (CastExpr->getBeginLoc().isMacroID() ||
157 CastExpr->getEndLoc().isMacroID() || CastExpr->getExprLoc().isMacroID()))
161 auto Diag = diag(CastExpr->getExprLoc(),
162 "redundant explicit casting to the same type %0 as the "
163 "sub-expression, remove this casting");
166 const SourceManager &SM = *Result.SourceManager;
167 const SourceLocation SourceExprBegin =
168 SM.getExpansionLoc(SourceExpr->getBeginLoc());
169 const SourceLocation SourceExprEnd =
170 SM.getExpansionLoc(SourceExpr->getEndLoc());
172 if (SourceExprBegin != CastExpr->getBeginLoc())
173 Diag << FixItHint::CreateRemoval(SourceRange(
174 CastExpr->getBeginLoc(), SourceExprBegin.getLocWithOffset(-1)));
176 const SourceLocation NextToken = Lexer::getLocForEndOfToken(
177 SourceExprEnd, 0U, SM, Result.Context->getLangOpts());
179 if (SourceExprEnd != CastExpr->getEndLoc()) {
180 Diag << FixItHint::CreateRemoval(
181 SourceRange(NextToken, CastExpr->getEndLoc()));
185 Diag << FixItHint::CreateInsertion(SourceExprBegin,
"(")
186 << FixItHint::CreateInsertion(NextToken,
")");
194 if (
const auto *D = dyn_cast<CXXConstructorDecl>(SourceExprDecl)) {
195 diag(D->getLocation(),
196 "source type originates from the invocation of this constructor",
197 DiagnosticIDs::Note);
201 if (
const auto *D = dyn_cast<FunctionDecl>(SourceExprDecl)) {
202 diag(D->getLocation(),
203 "source type originates from the invocation of this "
204 "%select{function|method}0",
206 << isa<CXXMethodDecl>(D) << D->getReturnTypeSourceRange();
210 if (
const auto *D = dyn_cast<FieldDecl>(SourceExprDecl)) {
211 diag(D->getLocation(),
212 "source type originates from referencing this member",
214 << SourceRange(D->getTypeSpecStartLoc(), D->getTypeSpecEndLoc());
218 if (
const auto *D = dyn_cast<ParmVarDecl>(SourceExprDecl)) {
219 diag(D->getLocation(),
220 "source type originates from referencing this parameter",
222 << SourceRange(D->getTypeSpecStartLoc(), D->getTypeSpecEndLoc());
226 if (
const auto *D = dyn_cast<VarDecl>(SourceExprDecl)) {
227 diag(D->getLocation(),
228 "source type originates from referencing this variable",
230 << SourceRange(D->getTypeSpecStartLoc(), D->getTypeSpecEndLoc());
234 if (
const auto *D = dyn_cast<EnumConstantDecl>(SourceExprDecl)) {
235 diag(D->getLocation(),
236 "source type originates from referencing this enum constant",
237 DiagnosticIDs::Note);
241 if (
const auto *D = dyn_cast<BindingDecl>(SourceExprDecl)) {
242 diag(D->getLocation(),
243 "source type originates from referencing this bound variable",
244 DiagnosticIDs::Note);
248 if (
const auto *D = dyn_cast<NonTypeTemplateParmDecl>(SourceExprDecl)) {
249 diag(D->getLocation(),
250 "source type originates from referencing this non-type template "
252 DiagnosticIDs::Note);
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.