36 constexpr char NoExpressionWarningMessage[] =
37 "%0 must be marked explicit to avoid unintentional implicit conversions";
38 constexpr char WithExpressionWarningMessage[] =
39 "%0 explicit expression evaluates to 'false'";
41 if (
const auto *Conversion =
42 Result.Nodes.getNodeAs<CXXConversionDecl>(
"conversion")) {
43 if (Conversion->isOutOfLine())
45 const SourceLocation Loc = Conversion->getLocation();
50 diag(Loc, NoExpressionWarningMessage)
51 << Conversion << FixItHint::CreateInsertion(Loc,
"explicit ");
55 const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>(
"ctor");
56 if (Ctor->isOutOfLine() || Ctor->getNumParams() == 0 ||
57 Ctor->getMinRequiredArguments() > 1)
60 const ExplicitSpecifier ExplicitSpec = Ctor->getExplicitSpecifier();
63 Ctor->getParamDecl(0)->getType().getNonReferenceType());
64 if (ExplicitSpec.isExplicit() &&
65 (Ctor->isCopyOrMoveConstructor() || TakesInitializerList)) {
66 auto IsKwExplicit = [](
const Token &Tok) {
67 return Tok.is(tok::raw_identifier) &&
68 Tok.getRawIdentifier() ==
"explicit";
70 const CharSourceRange ConstructorRange = CharSourceRange::getTokenRange(
71 Ctor->getOuterLocStart(), Ctor->getEndLoc());
72 const CharSourceRange ExplicitTokenRange =
74 *Result.SourceManager, getLangOpts(),
76 StringRef ConstructorDescription;
77 if (Ctor->isMoveConstructor())
78 ConstructorDescription =
"move";
79 else if (Ctor->isCopyConstructor())
80 ConstructorDescription =
"copy";
82 ConstructorDescription =
"initializer-list";
84 auto Diag = diag(Ctor->getLocation(),
85 "%0 constructor should not be declared explicit")
86 << ConstructorDescription;
87 if (ExplicitTokenRange.isValid())
88 Diag << FixItHint::CreateRemoval(ExplicitTokenRange);
92 if (ExplicitSpec.isExplicit() || Ctor->isCopyOrMoveConstructor() ||
97 const Expr *ExplicitExpr = ExplicitSpec.getExpr();
99 ExplicitExpr = ExplicitExpr->IgnoreImplicit();
100 if (isa<CXXBoolLiteralExpr>(ExplicitExpr) ||
101 ExplicitExpr->isInstantiationDependent())
105 const bool SingleArgument =
106 Ctor->getNumParams() == 1 && !Ctor->getParamDecl(0)->isParameterPack();
107 const SourceLocation Loc = Ctor->getLocation();
109 diag(Loc, ExplicitExpr ? WithExpressionWarningMessage
110 : NoExpressionWarningMessage)
112 ?
"single-argument constructors"
113 :
"constructors that are callable with a single argument");
116 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...