11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 24 auto CheckTemplate = [](
const TemplateSpecializationType *Spec) {
25 if (!Spec || !Spec->getTemplateName().getAsTemplateDecl()) {
28 const NamedDecl *TypeDecl =
29 Spec->getTemplateName().getAsTemplateDecl()->getTemplatedDecl();
30 return TypeDecl->isInStdNamespace() &&
31 (TypeDecl->getName().equals(
"enable_if") ||
32 TypeDecl->getName().equals(
"enable_if_t"));
34 const Type *BaseType = Node.getTypePtr();
36 while (BaseType->isPointerType() || BaseType->isReferenceType()) {
37 BaseType = BaseType->getPointeeType().getTypePtr();
40 if (
const auto *Dependent = BaseType->getAs<DependentNameType>()) {
41 BaseType = Dependent->getQualifier()->getAsType();
45 if (CheckTemplate(BaseType->getAs<TemplateSpecializationType>())) {
47 }
else if (
const auto *Elaborated = BaseType->getAs<ElaboratedType>()) {
48 if (
const auto *Qualifier = Elaborated->getQualifier()->getAsType()) {
49 if (CheckTemplate(Qualifier->getAs<TemplateSpecializationType>())) {
57 clang::ast_matchers::internal::Matcher<QualType>, TypeMatcher) {
58 return Node.hasDefaultArgument() &&
59 TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder);
63 void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) {
65 if (!getLangOpts().CPlusPlus11)
68 auto ForwardingRefParm =
70 hasType(qualType(rValueReferenceType(),
71 references(templateTypeParmType(hasDeclaration(
72 templateTypeParmDecl().bind(
"type-parm-decl")))),
73 unless(references(isConstQualified())))))
76 DeclarationMatcher findOverload =
78 hasParameter(0, ForwardingRefParm),
79 unless(hasAnyParameter(
81 parmVarDecl(hasType(isEnableIf())))),
82 unless(hasParent(functionTemplateDecl(has(templateTypeParmDecl(
84 hasDefaultArgument(isEnableIf())))))))
86 Finder->addMatcher(findOverload,
this);
89 void ForwardingReferenceOverloadCheck::check(
90 const MatchFinder::MatchResult &Result) {
91 const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>(
"parm-var");
92 const auto *TypeParmDecl =
93 Result.Nodes.getNodeAs<TemplateTypeParmDecl>(
"type-parm-decl");
97 const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());
100 const FunctionTemplateDecl *FuncTemplate =
101 FuncForParam->getDescribedFunctionTemplate();
108 const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();
109 if (std::find(Params->begin(), Params->end(), TypeParmDecl) == Params->end())
113 const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>(
"ctor");
114 for (
auto Iter = Ctor->param_begin() + 1; Iter != Ctor->param_end(); ++Iter) {
115 if (!(*Iter)->hasDefaultArg())
118 bool EnabledCopy =
false, DisabledCopy =
false, EnabledMove =
false,
119 DisabledMove =
false;
120 for (
const auto *OtherCtor : Ctor->getParent()->ctors()) {
121 if (OtherCtor->isCopyOrMoveConstructor()) {
122 if (OtherCtor->isDeleted() || OtherCtor->getAccess() == AS_private)
123 (OtherCtor->isCopyConstructor() ? DisabledCopy : DisabledMove) =
true;
125 (OtherCtor->isCopyConstructor() ? EnabledCopy : EnabledMove) =
true;
128 bool Copy = (!EnabledMove && !DisabledMove && !DisabledCopy) || EnabledCopy;
129 bool Move = !DisabledMove || EnabledMove;
132 diag(Ctor->getLocation(),
133 "constructor accepting a forwarding reference can " 134 "hide the %select{copy|move|copy and move}0 constructor%s1")
135 << (Copy && Move ? 2 : (Copy ? 0 : 1)) << Copy + Move;
136 for (
const auto *OtherCtor : Ctor->getParent()->ctors()) {
137 if (OtherCtor->isCopyOrMoveConstructor() && !OtherCtor->isDeleted() &&
138 OtherCtor->getAccess() != AS_private) {
139 diag(OtherCtor->getLocation(),
140 "%select{copy|move}0 constructor declared here", DiagnosticIDs::Note)
141 << OtherCtor->isMoveConstructor();
AST_MATCHER(BinaryOperator, isAssignmentOperator)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
AST_MATCHER_P(FunctionDecl, throws, internal::Matcher< Type >, InnerMatcher)