11#include "clang/AST/DeclCXX.h"
12#include "clang/Sema/Sema.h"
13#include "clang/Tooling/Core/Replacement.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/Casting.h"
16#include "llvm/Support/Error.h"
24std::string buildSpecialMemberDeclarations(
const CXXRecordDecl &
Class) {
26 const CXXMethodDecl *Copy =
nullptr;
27 const CXXMethodDecl *
Move =
nullptr;
30 for (
const auto &
M :
Class.methods()) {
31 if (
M->isCopyAssignmentOperator())
33 else if (
M->isMoveAssignmentOperator())
35 if (
const auto *
C = llvm::dyn_cast<CXXConstructorDecl>(
M)) {
36 if (
C->isCopyConstructor())
38 else if (
C->isMoveConstructor())
44 llvm::raw_string_ostream
OS(S);
46 auto PrintMember = [&](
const CXXMethodDecl *D,
const char *MemberPattern,
47 const char *ParmPattern) {
48 if (D && !D->isImplicit())
50 bool Delete = !D || D->isDeleted();
53 llvm::formatv(MemberPattern,
Class.getName(),
54 llvm::formatv(ParmPattern,
Class.getName())),
55 Delete ?
"delete" :
"default");
57 auto PrintMembers = [&](
const Members &
M,
const char *MemberPattern) {
58 PrintMember(
M.Copy, MemberPattern,
"const {0}&");
59 PrintMember(
M.Move, MemberPattern,
"{0}&&");
61 PrintMembers(Ctor,
"{0}({1})");
62 PrintMembers(Assign,
"{0} &operator=({1})");
84class SpecialMembers :
public Tweak {
86 const char *id() const final;
87 llvm::StringLiteral kind()
const override {
90 std::string title()
const override {
91 return llvm::formatv(
"Declare implicit {0} members",
92 NeedCopy ? NeedMove ?
"copy/move" :
"copy" :
"move");
95 bool prepare(
const Selection &Inputs)
override {
97 if (!Inputs.AST->getLangOpts().CPlusPlus11)
101 if (
auto *N = Inputs.ASTSelection.commonAncestor())
102 Class =
const_cast<CXXRecordDecl *
>(N->ASTNode.get<CXXRecordDecl>());
103 if (!Class || !Class->isThisDeclarationADefinition() || Class->isUnion())
107 NeedCopy = !Class->hasUserDeclaredCopyConstructor() ||
108 !Class->hasUserDeclaredCopyAssignment();
109 NeedMove = !Class->hasUserDeclaredMoveAssignment() ||
110 !Class->hasUserDeclaredMoveConstructor();
111 return NeedCopy || NeedMove;
114 Expected<Effect> apply(
const Selection &Inputs)
override {
117 Inputs.AST->getSema().ForceDeclarationOfImplicitMembers(Class);
118 std::string Code = buildSpecialMemberDeclarations(*Class);
121 std::vector<Anchor> Anchors = {
124 if (
const auto *CCD = llvm::dyn_cast<CXXConstructorDecl>(D))
125 return CCD->isDefaultConstructor();
130 {[](
const Decl *D) {
return llvm::isa<CXXConstructorDecl>(D); },
135 auto Edit =
insertDecl(Code, *Class, std::move(Anchors), AS_public);
137 return Edit.takeError();
138 return Effect::mainFileEdit(Inputs.AST->getSourceManager(),
139 tooling::Replacements{std::move(*Edit)});
143 bool NeedCopy =
false, NeedMove =
false;
144 CXXRecordDecl *Class =
nullptr;
const FunctionDecl * Decl
const google::protobuf::Message & M
#define REGISTER_TWEAK(Subclass)
llvm::Expected< tooling::Replacement > insertDecl(llvm::StringRef Code, const DeclContext &DC, llvm::ArrayRef< Anchor > Anchors)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Some operations such as code completion produce a set of candidates.
static const llvm::StringLiteral REFACTOR_KIND