diff options
| author | Alexander Kornienko <alexfh@google.com> | 2017-05-09 14:56:28 +0000 |
|---|---|---|
| committer | Alexander Kornienko <alexfh@google.com> | 2017-05-09 14:56:28 +0000 |
| commit | d0488d427c74564a1f95849c5faa9b1f3b9ee45b (patch) | |
| tree | 51097882a9c431d1f0a88d9d969a53b1f93b6823 /clang-tools-extra/clang-tidy/misc/ForwardingReferenceOverloadCheck.cpp | |
| parent | 66fb0d9768edf37c65c20e9d4dafc5d7f96669de (diff) | |
| download | bcm5719-llvm-d0488d427c74564a1f95849c5faa9b1f3b9ee45b.tar.gz bcm5719-llvm-d0488d427c74564a1f95849c5faa9b1f3b9ee45b.zip | |
Change EOL style to LF. NFC
llvm-svn: 302534
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc/ForwardingReferenceOverloadCheck.cpp')
| -rw-r--r-- | clang-tools-extra/clang-tidy/misc/ForwardingReferenceOverloadCheck.cpp | 292 |
1 files changed, 146 insertions, 146 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/misc/ForwardingReferenceOverloadCheck.cpp index 9b9a21b9ef3..2efa53597b5 100644 --- a/clang-tools-extra/clang-tidy/misc/ForwardingReferenceOverloadCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/ForwardingReferenceOverloadCheck.cpp @@ -1,146 +1,146 @@ -//===--- ForwardingReferenceOverloadCheck.cpp - clang-tidy-----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ForwardingReferenceOverloadCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include <algorithm>
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-namespace {
-// Check if the given type is related to std::enable_if.
-AST_MATCHER(QualType, isEnableIf) {
- auto CheckTemplate = [](const TemplateSpecializationType *Spec) {
- if (!Spec || !Spec->getTemplateName().getAsTemplateDecl()) {
- return false;
- }
- const NamedDecl *TypeDecl =
- Spec->getTemplateName().getAsTemplateDecl()->getTemplatedDecl();
- return TypeDecl->isInStdNamespace() &&
- (TypeDecl->getName().equals("enable_if") ||
- TypeDecl->getName().equals("enable_if_t"));
- };
- const Type *BaseType = Node.getTypePtr();
- // Case: pointer or reference to enable_if.
- while (BaseType->isPointerType() || BaseType->isReferenceType()) {
- BaseType = BaseType->getPointeeType().getTypePtr();
- }
- // Case: type parameter dependent (enable_if<is_integral<T>>).
- if (const auto *Dependent = BaseType->getAs<DependentNameType>()) {
- BaseType = Dependent->getQualifier()->getAsType();
- }
- if (CheckTemplate(BaseType->getAs<TemplateSpecializationType>())) {
- return true; // Case: enable_if_t< >.
- } else if (const auto *Elaborated = BaseType->getAs<ElaboratedType>()) {
- if (const auto *Qualifier = Elaborated->getQualifier()->getAsType()) {
- if (CheckTemplate(Qualifier->getAs<TemplateSpecializationType>())) {
- return true; // Case: enable_if< >::type.
- }
- }
- }
- return false;
-}
-AST_MATCHER_P(TemplateTypeParmDecl, hasDefaultArgument,
- clang::ast_matchers::internal::Matcher<QualType>, TypeMatcher) {
- return Node.hasDefaultArgument() &&
- TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder);
-}
-} // namespace
-
-void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) {
- // Forwarding references require C++11 or later.
- if (!getLangOpts().CPlusPlus11)
- return;
-
- auto ForwardingRefParm =
- parmVarDecl(
- hasType(qualType(rValueReferenceType(),
- references(templateTypeParmType(hasDeclaration(
- templateTypeParmDecl().bind("type-parm-decl")))),
- unless(references(isConstQualified())))))
- .bind("parm-var");
-
- DeclarationMatcher findOverload =
- cxxConstructorDecl(
- hasParameter(0, ForwardingRefParm),
- unless(hasAnyParameter(
- // No warning: enable_if as constructor parameter.
- parmVarDecl(hasType(isEnableIf())))),
- unless(hasParent(functionTemplateDecl(has(templateTypeParmDecl(
- // No warning: enable_if as type parameter.
- hasDefaultArgument(isEnableIf())))))))
- .bind("ctor");
- Finder->addMatcher(findOverload, this);
-}
-
-void ForwardingReferenceOverloadCheck::check(
- const MatchFinder::MatchResult &Result) {
- const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>("parm-var");
- const auto *TypeParmDecl =
- Result.Nodes.getNodeAs<TemplateTypeParmDecl>("type-parm-decl");
-
- // Get the FunctionDecl and FunctionTemplateDecl containing the function
- // parameter.
- const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());
- if (!FuncForParam)
- return;
- const FunctionTemplateDecl *FuncTemplate =
- FuncForParam->getDescribedFunctionTemplate();
- if (!FuncTemplate)
- return;
-
- // Check that the template type parameter belongs to the same function
- // template as the function parameter of that type. (This implies that type
- // deduction will happen on the type.)
- const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();
- if (std::find(Params->begin(), Params->end(), TypeParmDecl) == Params->end())
- return;
-
- // Every parameter after the first must have a default value.
- const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
- for (auto Iter = Ctor->param_begin() + 1; Iter != Ctor->param_end(); ++Iter) {
- if (!(*Iter)->hasDefaultArg())
- return;
- }
- bool EnabledCopy = false, DisabledCopy = false, EnabledMove = false,
- DisabledMove = false;
- for (const auto *OtherCtor : Ctor->getParent()->ctors()) {
- if (OtherCtor->isCopyOrMoveConstructor()) {
- if (OtherCtor->isDeleted() || OtherCtor->getAccess() == AS_private)
- (OtherCtor->isCopyConstructor() ? DisabledCopy : DisabledMove) = true;
- else
- (OtherCtor->isCopyConstructor() ? EnabledCopy : EnabledMove) = true;
- }
- }
- bool Copy = (!EnabledMove && !DisabledMove && !DisabledCopy) || EnabledCopy;
- bool Move = !DisabledMove || EnabledMove;
- if (!Copy && !Move)
- return;
- diag(Ctor->getLocation(),
- "constructor accepting a forwarding reference can "
- "hide the %select{copy|move|copy and move}0 constructor%s1")
- << (Copy && Move ? 2 : (Copy ? 0 : 1)) << Copy + Move;
- for (const auto *OtherCtor : Ctor->getParent()->ctors()) {
- if (OtherCtor->isCopyOrMoveConstructor() && !OtherCtor->isDeleted() &&
- OtherCtor->getAccess() != AS_private) {
- diag(OtherCtor->getLocation(),
- "%select{copy|move}0 constructor declared here", DiagnosticIDs::Note)
- << OtherCtor->isMoveConstructor();
- }
- }
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
+//===--- ForwardingReferenceOverloadCheck.cpp - clang-tidy-----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ForwardingReferenceOverloadCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include <algorithm> + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace misc { + +namespace { +// Check if the given type is related to std::enable_if. +AST_MATCHER(QualType, isEnableIf) { + auto CheckTemplate = [](const TemplateSpecializationType *Spec) { + if (!Spec || !Spec->getTemplateName().getAsTemplateDecl()) { + return false; + } + const NamedDecl *TypeDecl = + Spec->getTemplateName().getAsTemplateDecl()->getTemplatedDecl(); + return TypeDecl->isInStdNamespace() && + (TypeDecl->getName().equals("enable_if") || + TypeDecl->getName().equals("enable_if_t")); + }; + const Type *BaseType = Node.getTypePtr(); + // Case: pointer or reference to enable_if. + while (BaseType->isPointerType() || BaseType->isReferenceType()) { + BaseType = BaseType->getPointeeType().getTypePtr(); + } + // Case: type parameter dependent (enable_if<is_integral<T>>). + if (const auto *Dependent = BaseType->getAs<DependentNameType>()) { + BaseType = Dependent->getQualifier()->getAsType(); + } + if (CheckTemplate(BaseType->getAs<TemplateSpecializationType>())) { + return true; // Case: enable_if_t< >. + } else if (const auto *Elaborated = BaseType->getAs<ElaboratedType>()) { + if (const auto *Qualifier = Elaborated->getQualifier()->getAsType()) { + if (CheckTemplate(Qualifier->getAs<TemplateSpecializationType>())) { + return true; // Case: enable_if< >::type. + } + } + } + return false; +} +AST_MATCHER_P(TemplateTypeParmDecl, hasDefaultArgument, + clang::ast_matchers::internal::Matcher<QualType>, TypeMatcher) { + return Node.hasDefaultArgument() && + TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder); +} +} // namespace + +void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) { + // Forwarding references require C++11 or later. + if (!getLangOpts().CPlusPlus11) + return; + + auto ForwardingRefParm = + parmVarDecl( + hasType(qualType(rValueReferenceType(), + references(templateTypeParmType(hasDeclaration( + templateTypeParmDecl().bind("type-parm-decl")))), + unless(references(isConstQualified()))))) + .bind("parm-var"); + + DeclarationMatcher findOverload = + cxxConstructorDecl( + hasParameter(0, ForwardingRefParm), + unless(hasAnyParameter( + // No warning: enable_if as constructor parameter. + parmVarDecl(hasType(isEnableIf())))), + unless(hasParent(functionTemplateDecl(has(templateTypeParmDecl( + // No warning: enable_if as type parameter. + hasDefaultArgument(isEnableIf()))))))) + .bind("ctor"); + Finder->addMatcher(findOverload, this); +} + +void ForwardingReferenceOverloadCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>("parm-var"); + const auto *TypeParmDecl = + Result.Nodes.getNodeAs<TemplateTypeParmDecl>("type-parm-decl"); + + // Get the FunctionDecl and FunctionTemplateDecl containing the function + // parameter. + const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext()); + if (!FuncForParam) + return; + const FunctionTemplateDecl *FuncTemplate = + FuncForParam->getDescribedFunctionTemplate(); + if (!FuncTemplate) + return; + + // Check that the template type parameter belongs to the same function + // template as the function parameter of that type. (This implies that type + // deduction will happen on the type.) + const TemplateParameterList *Params = FuncTemplate->getTemplateParameters(); + if (std::find(Params->begin(), Params->end(), TypeParmDecl) == Params->end()) + return; + + // Every parameter after the first must have a default value. + const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor"); + for (auto Iter = Ctor->param_begin() + 1; Iter != Ctor->param_end(); ++Iter) { + if (!(*Iter)->hasDefaultArg()) + return; + } + bool EnabledCopy = false, DisabledCopy = false, EnabledMove = false, + DisabledMove = false; + for (const auto *OtherCtor : Ctor->getParent()->ctors()) { + if (OtherCtor->isCopyOrMoveConstructor()) { + if (OtherCtor->isDeleted() || OtherCtor->getAccess() == AS_private) + (OtherCtor->isCopyConstructor() ? DisabledCopy : DisabledMove) = true; + else + (OtherCtor->isCopyConstructor() ? EnabledCopy : EnabledMove) = true; + } + } + bool Copy = (!EnabledMove && !DisabledMove && !DisabledCopy) || EnabledCopy; + bool Move = !DisabledMove || EnabledMove; + if (!Copy && !Move) + return; + diag(Ctor->getLocation(), + "constructor accepting a forwarding reference can " + "hide the %select{copy|move|copy and move}0 constructor%s1") + << (Copy && Move ? 2 : (Copy ? 0 : 1)) << Copy + Move; + for (const auto *OtherCtor : Ctor->getParent()->ctors()) { + if (OtherCtor->isCopyOrMoveConstructor() && !OtherCtor->isDeleted() && + OtherCtor->getAccess() != AS_private) { + diag(OtherCtor->getLocation(), + "%select{copy|move}0 constructor declared here", DiagnosticIDs::Note) + << OtherCtor->isMoveConstructor(); + } + } +} + +} // namespace misc +} // namespace tidy +} // namespace clang |

