Fix UseAuto not transforming iterator when non-fully qualifiers are used and

using inline namespaces is specified.

UseAuto used to fail to transform iterators when using inline namespaces and
non-fully qualified types, relying on a using directive previously declared.
- This fix uses the already define isFromStdNamespace matcher.
- Fixed tests and added a new test using inline namespaces.
- Added CustomMatchers to reuse common matchers among transforms.

llvm-svn: 186327
This commit is contained in:
Ariel J. Bernal 2013-07-15 15:37:05 +00:00
parent eaa534450c
commit 601858aed7
6 changed files with 79 additions and 54 deletions

View File

@ -0,0 +1,59 @@
//===-- Core/CustomMatchers.h - Perf measurement helpers -----------*- C++ -*-===//
//
// 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 provides custom matchers to be used by different
/// transforms that requier the same matchers.
///
//===----------------------------------------------------------------------===//
#ifndef CPP11_MIGRATE_CUSTOMMATCHERS_H
#define CPP11_MIGRATE_CUSTOMMATCHERS_H
#include "clang/ASTMatchers/ASTMatchers.h"
namespace clang {
namespace ast_matchers {
/// \brief Matches declarations whose declaration context is the C++ standard
/// library namespace \c std.
///
/// Note that inline namespaces are silently ignored during the lookup since
/// both libstdc++ and libc++ are known to use them for versioning purposes.
///
/// Given
/// \code
/// namespace ns {
/// struct my_type {};
/// using namespace std;
/// }
///
/// using std::vector;
/// using ns::my_type;
/// using ns::list;
/// \endcode
/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(isFromStdNamespace())))
/// matches "using std::vector" and "using ns::list".
AST_MATCHER(Decl, isFromStdNamespace) {
const DeclContext *D = Node.getDeclContext();
while (D->isInlineNamespace())
D = D->getParent();
if (!D->isNamespace() || !D->getParent()->isTranslationUnit())
return false;
const IdentifierInfo *Info = cast<NamespaceDecl>(D)->getIdentifier();
return Info && Info->isStr("std");
}
} // namespace ast_matchers
} // namespace clang
#endif // CPP11_MIGRATE_CUSTOMMATCHERS_H

View File

@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "ReplaceAutoPtrMatchers.h"
#include "Core/CustomMatchers.h"
const char *AutoPtrTokenId = "AutoPtrTokenId";
const char *AutoPtrOwnershipTransferId = "AutoPtrOwnershipTransferId";
@ -34,39 +35,6 @@ AST_MATCHER(Expr, isLValue) {
return Node.getValueKind() == VK_LValue;
}
/// \brief Matches declarations whose declaration context is the C++ standard
/// library namespace \c std.
///
/// Note that inline namespaces are silently ignored during the lookup since
/// both libstdc++ and libc++ are known to use them for versioning purposes.
///
/// Given
/// \code
/// namespace ns {
/// struct my_type {};
/// using namespace std;
/// }
///
/// using std::vector;
/// using ns::my_type;
/// using ns::list;
/// \endcode
/// usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(isFromStdNamespace())))
/// matches "using std::vector" and "using ns::list".
AST_MATCHER(Decl, isFromStdNamespace) {
const DeclContext *D = Node.getDeclContext();
while (D->isInlineNamespace())
D = D->getParent();
if (!D->isNamespace() || !D->getParent()->isTranslationUnit())
return false;
const IdentifierInfo *Info = cast<NamespaceDecl>(D)->getIdentifier();
return Info && Info->isStr("std");
}
} // end namespace ast_matchers
} // end namespace clang

View File

@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "UseAutoMatchers.h"
#include "Core/CustomMatchers.h"
#include "clang/AST/ASTContext.h"
using namespace clang::ast_matchers;
@ -123,7 +124,7 @@ AST_MATCHER(NamedDecl, hasStdIteratorName) {
///
/// \c recordDecl(hasStdContainerName()) matches \c vector and \c forward_list
/// but not \c my_vec.
AST_MATCHER_P(NamedDecl, hasStdContainerName, bool, WithStd) {
AST_MATCHER(NamedDecl, hasStdContainerName) {
static const char *ContainerNames[] = {
"array",
"deque",
@ -146,13 +147,8 @@ AST_MATCHER_P(NamedDecl, hasStdContainerName, bool, WithStd) {
"stack"
};
for (unsigned int i = 0;
i < llvm::array_lengthof(ContainerNames);
++i) {
std::string Name(ContainerNames[i]);
if (WithStd)
Name = "std::" + Name;
if (hasName(Name).matches(Node, Finder, Builder))
for (unsigned int i = 0; i < llvm::array_lengthof(ContainerNames); ++i) {
if (hasName(ContainerNames[i]).matches(Node, Finder, Builder))
return true;
}
return false;
@ -170,7 +166,7 @@ TypeMatcher typedefIterator() {
allOf(
namedDecl(hasStdIteratorName()),
hasDeclContext(
recordDecl(hasStdContainerName(true))
recordDecl(hasStdContainerName(), isFromStdNamespace())
)
)
)
@ -185,7 +181,7 @@ TypeMatcher nestedIterator() {
allOf(
namedDecl(hasStdIteratorName()),
hasDeclContext(
recordDecl(hasStdContainerName(true))
recordDecl(hasStdContainerName(), isFromStdNamespace())
)
)
)
@ -201,18 +197,15 @@ TypeMatcher iteratorFromUsingDeclaration() {
allOf(
// Unwrap the nested name specifier to test for
// one of the standard containers.
hasQualifier(allOf(
hasQualifier(
specifiesType(
templateSpecializationType(
hasDeclaration(
namedDecl(hasStdContainerName(false))
namedDecl(hasStdContainerName(), isFromStdNamespace())
)
)
),
hasPrefix(
specifiesNamespace(hasName("std"))
)
)),
),
// The named type is what comes after the final
// '::' in the type. It should name one of the
// standard iterator names.

View File

@ -64,7 +64,7 @@ public:
namespace std {
#if USE_INLINE_NAMESPACE
namespace _1 {
inline namespace _1 {
#endif
template <typename T>
@ -114,7 +114,6 @@ public:
#if USE_INLINE_NAMESPACE
} // namespace _1
using _1::CONTAINER;
#endif
} // namespace std

View File

@ -15,17 +15,17 @@
//
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
// RUN: cpp11-migrate -use-auto %t.cpp -- -DCONTAINER=array \
// RUN: -DUSE_INLINE_NAMESPACE -I %S/Inputs
// RUN: -DUSE_INLINE_NAMESPACE=1 -I %S/Inputs
// RUN: FileCheck -input-file=%t.cpp %s
//
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
// RUN: cpp11-migrate -use-auto %t.cpp -- -DCONTAINER=array \
// RUN: -DUSE_BASE_CLASS_ITERATORS -I %S/Inputs
// RUN: -DUSE_BASE_CLASS_ITERATORS=1 -I %S/Inputs
// RUN: FileCheck -input-file=%t.cpp %s
//
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
// RUN: cpp11-migrate -use-auto %t.cpp -- -DCONTAINER=array \
// RUN: -DUSE_INNER_CLASS_ITERATORS -I %S/Inputs
// RUN: -DUSE_INNER_CLASS_ITERATORS=1 -I %S/Inputs
// RUN: FileCheck -input-file=%t.cpp %s
//
//

View File

@ -1,6 +1,12 @@
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
// RUN: cpp11-migrate -use-auto %t.cpp -- --std=c++11 -I %S/Inputs
// RUN: FileCheck -input-file=%t.cpp %s
//
// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
// RUN: cpp11-migrate -use-auto %t.cpp -- --std=c++11 -I %S/Inputs \
// RUN: -DUSE_INLINE_NAMESPACE=1
// RUN: FileCheck -input-file=%t.cpp %s
#define CONTAINER array
#include "test_std_container.h"