diff options
Diffstat (limited to 'clang-tools-extra/cpp11-migrate/PassByValue/PassByValueMatchers.cpp')
-rw-r--r-- | clang-tools-extra/cpp11-migrate/PassByValue/PassByValueMatchers.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueMatchers.cpp b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueMatchers.cpp new file mode 100644 index 00000000000..32095e167b7 --- /dev/null +++ b/clang-tools-extra/cpp11-migrate/PassByValue/PassByValueMatchers.cpp @@ -0,0 +1,80 @@ +//===-- PassByValueMatchers.cpp -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file contains the definitions for matcher-generating functions +/// and names for bound nodes found by AST matchers. +/// +//===----------------------------------------------------------------------===// + +#include "PassByValueMatchers.h" + +const char *PassByValueCtorId = "Ctor"; +const char *PassByValueParamId = "Param"; +const char *PassByValueInitializerId = "Initializer"; + +namespace clang { +namespace ast_matchers { + +/// \brief Matches move constructible classes. +/// +/// Given +/// \code +/// // POD types are trivially move constructible +/// struct Foo { int a; }; +/// +/// struct Bar { +/// Bar(Bar &&) = deleted; +/// int a; +/// }; +/// \endcode +/// recordDecl(isMoveConstructible()) +/// matches "Foo". +AST_MATCHER(CXXRecordDecl, isMoveConstructible) { + for (CXXRecordDecl::ctor_iterator I = Node.ctor_begin(), E = Node.ctor_end(); I != E; ++I) { + const CXXConstructorDecl *Ctor = *I; + if (Ctor->isMoveConstructor() && !Ctor->isDeleted()) + return true; + } + return false; +} + +/// \brief Matches non-deleted copy constructors. +/// +/// Given +/// \code +/// struct Foo { Foo(const Foo &) = default; }; +/// struct Bar { Bar(const Bar &) = deleted; }; +/// \endcode +/// constructorDecl(isNonDeletedCopyConstructor()) +/// matches "Foo(const Foo &)". +AST_MATCHER(CXXConstructorDecl, isNonDeletedCopyConstructor) { + return Node.isCopyConstructor() && !Node.isDeleted(); +} +} // namespace ast_matchers +} // namespace clang + +using namespace clang; +using namespace clang::ast_matchers; + +DeclarationMatcher makePassByValueCtorParamMatcher() { + return constructorDecl( + forEachConstructorInitializer(ctorInitializer( + // Clang builds a CXXConstructExpr only when it knowns which + // constructor will be called. In dependent contexts a ParenListExpr + // is generated instead of a CXXConstructExpr, filtering out templates + // automatically for us. + withInitializer(constructExpr( + has(declRefExpr(to(parmVarDecl().bind(PassByValueParamId)))), + hasDeclaration(constructorDecl( + isNonDeletedCopyConstructor(), + hasDeclContext(recordDecl(isMoveConstructible()))))))) + .bind(PassByValueInitializerId))) + .bind(PassByValueCtorId); +} |