forked from OSchip/llvm-project
95 lines
3.2 KiB
C++
95 lines
3.2 KiB
C++
//===-- 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;
|
|
|
|
static TypeMatcher constRefType() {
|
|
return lValueReferenceType(pointee(isConstQualified()));
|
|
}
|
|
|
|
static TypeMatcher nonConstValueType() {
|
|
return qualType(unless(anyOf(referenceType(), isConstQualified())));
|
|
}
|
|
|
|
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(hasType(qualType(
|
|
// match only const-ref or a non-const value
|
|
// parameters, rvalues and const-values
|
|
// shouldn't be modified.
|
|
anyOf(constRefType(), nonConstValueType()))))
|
|
.bind(PassByValueParamId)))),
|
|
hasDeclaration(constructorDecl(
|
|
isNonDeletedCopyConstructor(),
|
|
hasDeclContext(recordDecl(isMoveConstructible())))))))
|
|
.bind(PassByValueInitializerId)))
|
|
.bind(PassByValueCtorId);
|
|
}
|