10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 12 #include "clang/Lex/Lexer.h" 20 void CopyConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
21 if (!getLangOpts().CPlusPlus)
28 hasAnyConstructorInitializer(cxxCtorInitializer(
30 withInitializer(cxxConstructExpr(hasDeclaration(
31 cxxConstructorDecl(isDefaultConstructor())))))),
32 unless(isInstantiated()))
37 void CopyConstructorInitCheck::check(
const MatchFinder::MatchResult &
Result) {
38 const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>(
"ctor");
39 std::string ParamName = Ctor->getParamDecl(0)->getNameAsString();
42 std::string FixItInitList;
43 bool HasRelevantBaseInit =
false;
44 bool ShouldNotDoFixit =
false;
45 bool HasWrittenInitializer =
false;
46 SmallVector<FixItHint, 2> SafeFixIts;
47 for (
const auto *Init : Ctor->inits()) {
48 bool CtorInitIsWritten = Init->isWritten();
49 HasWrittenInitializer = HasWrittenInitializer || CtorInitIsWritten;
50 if (!Init->isBaseInitializer())
52 const Type *BaseType = Init->getBaseClass();
56 if (
const auto *TempSpecTy = dyn_cast<TemplateSpecializationType>(BaseType))
57 ShouldNotDoFixit = ShouldNotDoFixit || TempSpecTy->isTypeAlias();
58 ShouldNotDoFixit = ShouldNotDoFixit || isa<TypedefType>(BaseType);
59 ShouldNotDoFixit = ShouldNotDoFixit || CtorInitIsWritten;
60 const CXXRecordDecl *BaseClass =
61 BaseType->getAsCXXRecordDecl()->getDefinition();
62 if (BaseClass->field_empty() &&
63 BaseClass->forallBases(
64 [](
const CXXRecordDecl *Class) {
return Class->field_empty(); }))
66 bool NonCopyableBase =
false;
67 for (
const auto *Ctor : BaseClass->ctors()) {
68 if (Ctor->isCopyConstructor() &&
69 (Ctor->getAccess() == AS_private || Ctor->isDeleted())) {
70 NonCopyableBase =
true;
76 const auto *CExpr = dyn_cast<CXXConstructExpr>(Init->getInit());
77 if (!CExpr || !CExpr->getConstructor()->isDefaultConstructor())
79 HasRelevantBaseInit =
true;
80 if (CtorInitIsWritten) {
81 if (!ParamName.empty())
83 FixItHint::CreateInsertion(CExpr->getEndLoc(), ParamName));
85 if (Init->getSourceLocation().isMacroID() ||
86 Ctor->getLocation().isMacroID() || ShouldNotDoFixit)
88 FixItInitList += BaseClass->getNameAsString();
89 FixItInitList +=
"(" + ParamName +
"), ";
92 if (!HasRelevantBaseInit)
95 auto Diag = diag(Ctor->getLocation(),
96 "calling a base constructor other than the copy constructor")
99 if (FixItInitList.empty() || ParamName.empty() || ShouldNotDoFixit)
102 std::string FixItMsg{FixItInitList.substr(0, FixItInitList.size() - 2)};
103 SourceLocation FixItLoc;
105 if (!HasWrittenInitializer) {
106 FixItLoc = Ctor->getBody()->getBeginLoc();
107 FixItMsg =
" : " + FixItMsg;
110 FixItLoc = (*Ctor->init_begin())->getSourceLocation();
115 Diag << FixItHint::CreateInsertion(FixItLoc, FixItMsg);
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result