42 Type = Type.getCanonicalType();
43 if (
const auto *TS = Type->getAs<TemplateSpecializationType>()) {
44 if (
const TemplateDecl *TD = TS->getTemplateName().getAsTemplateDecl())
47 if (
const auto *RT = Type->getAs<RecordType>()) {
48 if (
const auto *Specialization =
49 dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()))
56 constexpr char NoExpressionWarningMessage[] =
57 "%0 must be marked explicit to avoid unintentional implicit conversions";
58 constexpr char WithExpressionWarningMessage[] =
59 "%0 explicit expression evaluates to 'false'";
61 if (
const auto *Conversion =
62 Result.Nodes.getNodeAs<CXXConversionDecl>(
"conversion")) {
63 if (Conversion->isOutOfLine())
65 const SourceLocation Loc = Conversion->getLocation();
70 diag(Loc, NoExpressionWarningMessage)
71 << Conversion << FixItHint::CreateInsertion(Loc,
"explicit ");
75 const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>(
"ctor");
76 if (Ctor->isOutOfLine() || Ctor->getNumParams() == 0 ||
77 Ctor->getMinRequiredArguments() > 1)
80 const ExplicitSpecifier ExplicitSpec = Ctor->getExplicitSpecifier();
83 Ctor->getParamDecl(0)->getType().getNonReferenceType());
84 if (ExplicitSpec.isExplicit() &&
85 (Ctor->isCopyOrMoveConstructor() || TakesInitializerList)) {
86 auto IsKwExplicit = [](
const Token &Tok) {
87 return Tok.is(tok::raw_identifier) &&
88 Tok.getRawIdentifier() ==
"explicit";
90 const CharSourceRange ConstructorRange = CharSourceRange::getTokenRange(
91 Ctor->getOuterLocStart(), Ctor->getEndLoc());
92 const CharSourceRange ExplicitTokenRange =
94 *Result.SourceManager, getLangOpts(),
96 StringRef ConstructorDescription;
97 if (Ctor->isMoveConstructor())
98 ConstructorDescription =
"move";
99 else if (Ctor->isCopyConstructor())
100 ConstructorDescription =
"copy";
102 ConstructorDescription =
"initializer-list";
104 auto Diag = diag(Ctor->getLocation(),
105 "%0 constructor should not be declared explicit")
106 << ConstructorDescription;
107 if (ExplicitTokenRange.isValid())
108 Diag << FixItHint::CreateRemoval(ExplicitTokenRange);
112 if (ExplicitSpec.isExplicit() || Ctor->isCopyOrMoveConstructor() ||
113 TakesInitializerList)
117 const Expr *ExplicitExpr = ExplicitSpec.getExpr();
119 ExplicitExpr = ExplicitExpr->IgnoreImplicit();
120 if (isa<CXXBoolLiteralExpr>(ExplicitExpr) ||
121 ExplicitExpr->isInstantiationDependent())
125 const bool SingleArgument =
126 Ctor->getNumParams() == 1 && !Ctor->getParamDecl(0)->isParameterPack();
127 const SourceLocation Loc = Ctor->getLocation();
129 diag(Loc, ExplicitExpr ? WithExpressionWarningMessage
130 : NoExpressionWarningMessage)
132 ?
"single-argument constructors"
133 :
"constructors that are callable with a single argument");
136 Diag << FixItHint::CreateInsertion(Loc,
"explicit ");
CharSourceRange findTokenTextInRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, llvm::function_ref< bool(const Token &)> Pred)
Returns source range of the first token in Range matching Pred. The returned char range starts at the...