[clang-tools-extra] r176266 - Introducing Use-Auto transform for cpp11-migrate
David Blaikie
dblaikie at gmail.com
Thu Feb 28 11:36:24 PST 2013
On Thu, Feb 28, 2013 at 8:29 AM, Edwin Vane <edwin.vane at intel.com> wrote:
> Author: revane
> Date: Thu Feb 28 10:29:24 2013
> New Revision: 176266
>
> URL: http://llvm.org/viewvc/llvm-project?rev=176266&view=rev
> Log:
> Introducing Use-Auto transform for cpp11-migrate
>
> The new Use-Auto transform replaces the type specifier for variable
> declarations with the special C++11 'auto' type specifier. For now, the
> replacement is done only for variables that are iterators of any of the
> std containers and only if the type used is one of those explicitly
> allowed by the standard (i.e. not an implementation-specific type).
>
> Reviewers: gribozavr, silvas, klimek
>
> Added:
> clang-tools-extra/trunk/cpp11-migrate/UseAuto/
> clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.cpp
> clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.h
> clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.cpp
> clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.h
> clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.cpp
> clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.h
> clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/iterator.cpp
Failing here: http://lab.llvm.org:8011/builders/clang-x86_64-ubuntu-gdb-75/builds/2711
http://lab.llvm.org:8011/builders/clang-x86_64-ubuntu-gdb-75/builds/2711/steps/check-all/logs/Clang%20Tools%20%3A%3A%20cpp11-migrate__UseAuto__iterator.cpp
Please fix or revert.
> Modified:
> clang-tools-extra/trunk/cpp11-migrate/CMakeLists.txt
> clang-tools-extra/trunk/cpp11-migrate/Makefile
> clang-tools-extra/trunk/cpp11-migrate/Transforms.cpp
> clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py
> clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py
>
> Modified: clang-tools-extra/trunk/cpp11-migrate/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/CMakeLists.txt?rev=176266&r1=176265&r2=176266&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/cpp11-migrate/CMakeLists.txt (original)
> +++ clang-tools-extra/trunk/cpp11-migrate/CMakeLists.txt Thu Feb 28 10:29:24 2013
> @@ -15,6 +15,9 @@ list(APPEND Cpp11MigrateSources ${LoopCo
> file(GLOB_RECURSE UseNullptrSources "UseNullptr/*.cpp")
> list(APPEND Cpp11MigrateSources ${UseNullptrSources})
>
> +file(GLOB_RECURSE UseAutoSources "UseAuto/*.cpp")
> +list(APPEND Cpp11MigrateSources ${UseAutoSources})
> +
> add_clang_executable(cpp11-migrate
> ${Cpp11MigrateSources}
> )
>
> Modified: clang-tools-extra/trunk/cpp11-migrate/Makefile
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/Makefile?rev=176266&r1=176265&r2=176266&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/cpp11-migrate/Makefile (original)
> +++ clang-tools-extra/trunk/cpp11-migrate/Makefile Thu Feb 28 10:29:24 2013
> @@ -26,6 +26,8 @@ SOURCES += $(addprefix LoopConvert/,$(no
> BUILT_SOURCES = $(ObjDir)/LoopConvert/.objdir
> SOURCES += $(addprefix UseNullptr/,$(notdir $(wildcard $(PROJ_SRC_DIR)/UseNullptr/*.cpp)))
> BUILT_SOURCES += $(ObjDir)/UseNullptr/.objdir
> +SOURCES += $(addprefix UseAuto/,$(notdir $(wildcard $(PROJ_SRC_DIR)/UseAuto/*.cpp)))
> +BUILT_SOURCES += $(ObjDir)/UseAuto/.objdir
>
> LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc
> USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
>
> Modified: clang-tools-extra/trunk/cpp11-migrate/Transforms.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/Transforms.cpp?rev=176266&r1=176265&r2=176266&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/cpp11-migrate/Transforms.cpp (original)
> +++ clang-tools-extra/trunk/cpp11-migrate/Transforms.cpp Thu Feb 28 10:29:24 2013
> @@ -15,6 +15,7 @@
> #include "Transforms.h"
> #include "LoopConvert/LoopConvert.h"
> #include "UseNullptr/UseNullptr.h"
> +#include "UseAuto/UseAuto.h"
>
> namespace cl = llvm::cl;
>
> @@ -47,6 +48,12 @@ void Transforms::createTransformOpts() {
> cl::desc("Make use of nullptr keyword where possible")),
> &ConstructTransform<UseNullptrTransform>));
>
> + Options.push_back(
> + OptionVec::value_type(
> + new cl::opt<bool>("use-auto",
> + cl::desc("Use of 'auto' type specifier")),
> + &ConstructTransform<UseAutoTransform>));
> +
> // Add more transform options here.
> }
>
>
> Added: clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.cpp?rev=176266&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.cpp (added)
> +++ clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.cpp Thu Feb 28 10:29:24 2013
> @@ -0,0 +1,58 @@
> +//===-- UseAuto/UseAuto.cpp - Use auto type specifier ---------------------===//
> +//
> +// 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 the implementation of the UseAutoTransform class.
> +///
> +//===----------------------------------------------------------------------===//
> +
> +#include "UseAuto.h"
> +#include "UseAutoActions.h"
> +#include "UseAutoMatchers.h"
> +
> +using clang::ast_matchers::MatchFinder;
> +using namespace clang;
> +using namespace clang::tooling;
> +
> +int UseAutoTransform::apply(const FileContentsByPath &InputStates,
> + RiskLevel MaxRisk,
> + const clang::tooling::CompilationDatabase &Database,
> + const std::vector<std::string> &SourcePaths,
> + FileContentsByPath &ResultStates) {
> + RefactoringTool UseAutoTool(Database, SourcePaths);
> +
> + for (FileContentsByPath::const_iterator I = InputStates.begin(),
> + E = InputStates.end();
> + I != E; ++I)
> + UseAutoTool.mapVirtualFile(I->first, I->second);
> +
> + unsigned AcceptedChanges = 0;
> +
> + MatchFinder Finder;
> + UseAutoFixer Fixer(UseAutoTool.getReplacements(), AcceptedChanges, MaxRisk);
> +
> + Finder.addMatcher(makeIteratorMatcher(), &Fixer);
> +
> + if (int Result = UseAutoTool.run(newFrontendActionFactory(&Finder))) {
> + llvm::errs() << "Error encountered during translation.\n";
> + return Result;
> + }
> +
> + RewriterContainer Rewrite(UseAutoTool.getFiles(), InputStates);
> +
> + // FIXME: Do something if some replacements didn't get applied?
> + UseAutoTool.applyAllReplacements(Rewrite.getRewriter());
> +
> + collectResults(Rewrite.getRewriter(), InputStates, ResultStates);
> +
> + if (AcceptedChanges > 0)
> + setChangesMade();
> +
> + return 0;
> +}
>
> Added: clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.h?rev=176266&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.h (added)
> +++ clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAuto.h Thu Feb 28 10:29:24 2013
> @@ -0,0 +1,40 @@
> +//===-- UseAuto/UseAuto.h - Use auto type specifier -------------*- 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 the definition of the UseAutoTransform class
> +/// which is the main interface to the use-auto transform that replaces
> +/// type specifiers with the special C++11 'auto' type specifier in certain
> +/// situations.
> +///
> +//===----------------------------------------------------------------------===//
> +#ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_H
> +#define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_H
> +
> +#include "Transform.h"
> +#include "llvm/Support/Compiler.h"
> +
> +/// \brief Subclass of Transform that transforms type specifiers for variable
> +/// declarations into the special C++11 'auto' type specifier for certain cases:
> +/// * Iterators of std containers.
> +/// * More to come...
> +///
> +/// Other uses of the auto type specifier as outlined in C++11 [dcl.spec.auto]
> +/// p2 are not handled by this transform.
> +class UseAutoTransform : public Transform {
> +public:
> + /// \see Transform::run().
> + virtual int apply(const FileContentsByPath &InputStates,
> + RiskLevel MaxRiskLEvel,
> + const clang::tooling::CompilationDatabase &Database,
> + const std::vector<std::string> &SourcePaths,
> + FileContentsByPath &ResultStates) LLVM_OVERRIDE;
> +};
> +
> +#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_H
>
> Added: clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.cpp?rev=176266&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.cpp (added)
> +++ clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.cpp Thu Feb 28 10:29:24 2013
> @@ -0,0 +1,63 @@
> +//===-- UseAuto/UseAutoActions.cpp - Matcher callback impl ----------------===//
> +//
> +// 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 implementation of the UseAutoFixer class.
> +///
> +//===----------------------------------------------------------------------===//
> +#include "UseAutoActions.h"
> +#include "UseAutoMatchers.h"
> +#include "clang/AST/ASTContext.h"
> +
> +using namespace clang::ast_matchers;
> +using namespace clang::tooling;
> +using namespace clang;
> +
> +void UseAutoFixer::run(const MatchFinder::MatchResult &Result) {
> + const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>(DeclNodeId);
> +
> + assert(D && "Bad Callback. No node provided");
> +
> + SourceManager &SM = *Result.SourceManager;
> + if (!SM.isFromMainFile(D->getLocStart()))
> + return;
> +
> + const CXXConstructExpr *Construct = cast<CXXConstructExpr>(D->getInit());
> + assert(Construct->getNumArgs() == 1u &&
> + "Expected constructor with single argument");
> +
> + // Drill down to the as-written initializer.
> + const Expr *E = Construct->arg_begin()->IgnoreParenImpCasts();
> + if (E != E->IgnoreConversionOperator())
> + // We hit a conversion operator. Early-out now as they imply an implicit
> + // conversion from a different type. Could also mean an explicit conversion
> + // from the same type but that's pretty rare.
> + return;
> +
> + if (const CXXConstructExpr *NestedConstruct = dyn_cast<CXXConstructExpr>(E))
> + // If we ran into an implicit conversion constructor, can't convert.
> + //
> + // FIXME: The following only checks if the constructor can be used
> + // implicitly, not if it actually was. Cases where the converting constructor
> + // was used explicitly won't get converted.
> + if (NestedConstruct->getConstructor()->isConvertingConstructor(false))
> + return;
> +
> + if (Result.Context->hasSameType(D->getType(), E->getType())) {
> + TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc();
> +
> + // WARNING: TypeLoc::getSourceRange() will include the identifier for things
> + // like function pointers. Not a concern since this action only works with
> + // iterators but something to keep in mind in the future.
> +
> + CharSourceRange Range(TL.getSourceRange(), true);
> + Replace.insert(tooling::Replacement(SM, Range, "auto"));
> + ++AcceptedChanges;
> + }
> +}
>
> Added: clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.h?rev=176266&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.h (added)
> +++ clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.h Thu Feb 28 10:29:24 2013
> @@ -0,0 +1,38 @@
> +//===-- UseAuto/Actions.h - Matcher callback ---------------------*- 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 contains the declaration of the UseAutoFixer class which
> +/// is used as an ASTMatcher callback.
> +///
> +//===----------------------------------------------------------------------===//
> +#ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_ACTIONS_H
> +#define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_ACTIONS_H
> +
> +#include "Transform.h"
> +#include "clang/ASTMatchers/ASTMatchFinder.h"
> +#include "clang/Tooling/Refactoring.h"
> +
> +/// \brief The callback to be used for use-auto AST matchers.
> +class UseAutoFixer : public clang::ast_matchers::MatchFinder::MatchCallback {
> +public:
> + UseAutoFixer(clang::tooling::Replacements &Replace, unsigned &AcceptedChanges,
> + RiskLevel)
> + : Replace(Replace), AcceptedChanges(AcceptedChanges) {
> + }
> +
> + /// \brief Entry point to the callback called when matches are made.
> + virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result);
> +
> +private:
> + clang::tooling::Replacements &Replace;
> + unsigned &AcceptedChanges;
> +};
> +
> +#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_ACTIONS_H
>
> Added: clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.cpp?rev=176266&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.cpp (added)
> +++ clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.cpp Thu Feb 28 10:29:24 2013
> @@ -0,0 +1,247 @@
> +//===-- UseAutoMatchers.cpp - Matchers for use-auto transform -------------===//
> +//
> +// 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 implementation for matcher-generating
> +/// functions and custom AST_MATCHERs.
> +///
> +//===----------------------------------------------------------------------===//
> +#include "UseAutoMatchers.h"
> +#include "clang/AST/ASTContext.h"
> +
> +using namespace clang::ast_matchers;
> +using namespace clang;
> +
> +const char *DeclNodeId = "decl";
> +
> +namespace clang {
> +namespace ast_matchers {
> +
> +/// \brief Matches variable declarations that have explicit initializers that
> +/// are not initializer lists.
> +///
> +/// Given
> +/// \code
> +/// iterator I = Container.begin();
> +/// MyType A(42);
> +/// MyType B{2};
> +/// MyType C;
> +/// \endcode
> +/// varDecl(hasWrittenNonListInitializer()) matches \c I and \c A but not \c B
> +/// or \c C.
> +AST_MATCHER(VarDecl, hasWrittenNonListInitializer) {
> + const Expr *Init = Node.getAnyInitializer();
> + if (!Init)
> + return false;
> +
> + // The following test is based on DeclPrinter::VisitVarDecl() to find if an
> + // initializer is implicit or not.
> + bool ImplicitInit = false;
> + if (const CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) {
> + if (Construct->isListInitialization())
> + return false;
> + ImplicitInit = Construct->getNumArgs() == 0 ||
> + Construct->getArg(0)->isDefaultArgument();
> + } else
> + if (Node.getInitStyle() == VarDecl::ListInit)
> + return false;
> +
> + return !ImplicitInit;
> +}
> +
> +/// \brief Matches QualTypes that are type sugar for QualTypes that match \c
> +/// SugarMatcher.
> +///
> +/// Given
> +/// \code
> +/// class C {};
> +/// typedef C my_type
> +/// typedef my_type my_other_type;
> +/// \code
> +///
> +/// \c qualType(isSugarFor(recordType(hasDeclaration(namedDecl(hasName("C"))))))
> +/// matches \c my_type and \c my_other_type.
> +AST_MATCHER_P(QualType, isSugarFor, internal::Matcher<QualType>, SugarMatcher) {
> + QualType QT = Node;
> + for (;;) {
> + if (SugarMatcher.matches(QT, Finder, Builder))
> + return true;
> +
> + QualType NewQT = QT.getSingleStepDesugaredType(Finder->getASTContext());
> + if (NewQT == QT)
> + break;
> + QT = NewQT;
> + }
> + return false;
> +}
> +
> +/// \brief Matches named declarations that have one of the standard iterator
> +/// names: iterator, reverse_iterator, const_iterator, const_reverse_iterator.
> +///
> +/// Given
> +/// \code
> +/// iterator I;
> +/// const_iterator CI;
> +/// \code
> +///
> +/// \c namedDecl(hasStdIteratorName()) matches \c I and \c CI.
> +AST_MATCHER(NamedDecl, hasStdIteratorName) {
> + static const char *IteratorNames[] = {
> + "iterator",
> + "reverse_iterator",
> + "const_iterator",
> + "const_reverse_iterator"
> + };
> +
> + for (unsigned int i = 0;
> + i < llvm::array_lengthof(IteratorNames);
> + ++i) {
> + if (hasName(IteratorNames[i]).matches(Node, Finder, Builder))
> + return true;
> + }
> + return false;
> +}
> +
> +/// \brief Matches named declarations that have one of the standard container
> +/// names.
> +///
> +/// Given
> +/// \code
> +/// class vector {};
> +/// class forward_list {};
> +/// class my_vec {};
> +/// \code
> +///
> +/// \c recordDecl(hasStdContainerName()) matches \c vector and \c forward_list
> +/// but not \c my_vec.
> +AST_MATCHER_P(NamedDecl, hasStdContainerName, bool, WithStd) {
> + static const char *ContainerNames[] = {
> + "array",
> + "deque",
> + "forward_list",
> + "list",
> + "vector",
> +
> + "map",
> + "multimap",
> + "set",
> + "multiset",
> +
> + "unordered_map",
> + "unordered_multimap",
> + "unordered_set",
> + "unordered_multiset",
> +
> + "queue",
> + "priority_queue",
> + "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))
> + return true;
> + }
> + return false;
> +}
> +
> +} // namespace ast_matchers
> +} // namespace clang
> +
> +namespace {
> +// \brief Returns a TypeMatcher that matches typedefs for standard iterators
> +// inside records with a standard container name.
> +TypeMatcher typedefIterator() {
> + return typedefType(
> + hasDeclaration(
> + allOf(
> + namedDecl(hasStdIteratorName()),
> + hasDeclContext(
> + recordDecl(hasStdContainerName(true))
> + )
> + )
> + )
> + );
> +}
> +
> +// \brief Returns a TypeMatcher that matches records named for standard
> +// iterators nested inside records named for standard containers.
> +TypeMatcher nestedIterator() {
> + return recordType(
> + hasDeclaration(
> + allOf(
> + namedDecl(hasStdIteratorName()),
> + hasDeclContext(
> + recordDecl(hasStdContainerName(true))
> + )
> + )
> + )
> + );
> +}
> +
> +// \brief Returns a TypeMatcher that matches types declared with using
> +// declarations and which name standard iterators for standard containers.
> +TypeMatcher iteratorFromUsingDeclaration() {
> + // Types resulting from using declarations are
> + // represented by ElaboratedType.
> + return elaboratedType(
> + allOf(
> + // Unwrap the nested name specifier to test for
> + // one of the standard containers.
> + hasQualifier(allOf(
> + specifiesType(
> + templateSpecializationType(
> + hasDeclaration(
> + namedDecl(hasStdContainerName(false))
> + )
> + )
> + ),
> + 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.
> + namesType(anyOf(
> + typedefType(
> + hasDeclaration(
> + namedDecl(hasStdIteratorName())
> + )
> + ),
> + recordType(
> + hasDeclaration(
> + namedDecl(hasStdIteratorName())
> + )
> + )
> + ))
> + )
> + );
> +}
> +} // namespace
> +
> +DeclarationMatcher makeIteratorMatcher() {
> + return varDecl(allOf(
> + hasWrittenNonListInitializer(),
> + unless(hasType(autoType())),
> + hasType(
> + isSugarFor(
> + anyOf(
> + typedefIterator(),
> + nestedIterator(),
> + iteratorFromUsingDeclaration()
> + )
> + )
> + )
> + )).bind(DeclNodeId);
> +}
>
> Added: clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.h?rev=176266&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.h (added)
> +++ clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.h Thu Feb 28 10:29:24 2013
> @@ -0,0 +1,27 @@
> +//===-- UseAutoMatchers.h - Matchers for use-auto transform ----*- 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 contains the declarations for matcher-generating functions
> +/// and names for bound nodes found by AST matchers.
> +///
> +//===----------------------------------------------------------------------===//
> +#ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_MATCHERS_H
> +#define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_MATCHERS_H
> +
> +#include "clang/ASTMatchers/ASTMatchers.h"
> +
> +extern const char *DeclNodeId;
> +
> +/// \brief Create a matcher that matches variable declarations where the type
> +/// is an iterator for an std container and has an explicit initializer of the
> +/// same type.
> +clang::ast_matchers::DeclarationMatcher makeIteratorMatcher();
> +
> +#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_USE_AUTO_MATCHERS_H
>
> Modified: clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py?rev=176266&r1=176265&r2=176266&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py (original)
> +++ clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/Inputs/gen_my_std.h.py Thu Feb 28 10:29:24 2013
> @@ -1,47 +1,57 @@
> #!/usr/bin/python
>
> +# Each std container is represented below. To test the various ways in which
> +# a type may be defined, the containers are split into categories:
> +# * Define iterator types with typedefs
> +# * Define iterator types as nested classes
> +# * Define iterator types with using declarations
> +#
> +# Further, one class in each category is chosen to be defined in a way mimicing
> +# libc++: The container is actually defined in a different namespace (std::_1
> +# is used here) and then imported into the std namespace with a using
> +# declaration. This is controlled with the 'using' key in the dictionary
> +# describing each container.
> typedef_containers = [
> - "array",
> - "deque",
> - "forward_list",
> - "list",
> - "vector"
> + {"name" : "array",
> + "using" : True},
> + {"name" : "deque",
> + "using" : False},
> + {"name" : "forward_list",
> + "using" : False},
> + {"name" : "list",
> + "using" : False},
> + {"name" : "vector",
> + "using" : False}
> ]
> subclass_containers = [
> - "map",
> - "multimap",
> - "set",
> - "multiset",
> + {"name" : "map",
> + "using" : True},
> + {"name" : "multimap",
> + "using" : False},
> + {"name" : "set",
> + "using" : False},
> + {"name" : "multiset",
> + "using" : False},
> ]
> using_containers = [
> - "unordered_map",
> - "unordered_multimap",
> - "unordered_set",
> - "unordered_multiset",
> - "queue",
> - "priority_queue",
> - "stack"
> + {"name" : "unordered_map",
> + "using" : True},
> + {"name" : "unordered_multimap",
> + "using" : False},
> + {"name" : "unordered_set",
> + "using" : False},
> + {"name" : "unordered_multiset",
> + "using" : False},
> + {"name" : "queue",
> + "using" : False},
> + {"name" : "priority_queue",
> + "using" : False},
> + {"name" : "stack",
> + "using" : False}
> ]
>
> -print """namespace internal {
> -
> -template <typename T, int i>
> -struct iterator_wrapper {
> -};
> -
> -template <typename T>
> -class iterator_provider {
> -public:
> - class iterator {};
> - class const_iterator {};
> - class reverse_iterator {};
> - class const_reverse_iterator {};
> -};
> -
> -} // namespace internal
> -
> -namespace std {"""
>
> +# Every class requires these functions.
> iterator_generators = """
> iterator begin() { return iterator(); }
> iterator end() { return iterator(); }
> @@ -56,21 +66,97 @@ iterator_generators = """
> const_reverse_iterator rend() const { return const_reverse_iterator(); }
> """
>
> +
> +# Convenience function for nested class definition within a special namespace
> +# to mimic libc++ style std container definitions.
> +def outputClassDef(Definition, ClassName, Import):
> + if Import:
> + print "namespace _1 {"
> +
> + print Definition
> +
> + if Import:
> + print """
> +}} // namespace _1
> +using _1::{0};""".format(ClassName)
> +
> +
> +# Output preamble and common functionality
> +print """
> +//===-----------------------------------------------------------*- C++ -*--===//
> +//
> +// This file was automatically generated from gen_my_std.h.py by the build
> +// system as a dependency for cpp11-migrate's test suite.
> +//
> +// This file contains a shell implementation of std containers and iterators for
> +// testing the use-auto transform of cpp11-migrate. All std containers and
> +// iterators are present. Container and iterator implementations vary to cover
> +// various ways the std container and iterator types are made available:
> +//
> +// Variations for how iterator types are presented:
> +// * Typedef (array, deque, forward_list, list, vector)
> +// * Nested class (map, multimap, set, multiset)
> +// * Using declaration {unordered_} X {map, multimap, set, multiset}
> +//
> +// Variations for how container types are presented:
> +// * Defined directly in namespace std
> +// * Imported into namespace std with using declarations (a la libc++).
> +//
> +//===----------------------------------------------------------------------===//
> +
> +namespace internal {
> +
> +template <typename T, int i>
> +struct iterator_wrapper {
> + iterator_wrapper() {}
> +
> + // These are required for tests using iteration statements.
> + bool operator!=(const iterator_wrapper<T, i>&) { return false; }
> + iterator_wrapper& operator++() { return *this; }
> + typename T::value_type operator*() { return typename T::value_type(); }
> +};
> +
> +template <typename T>
> +class iterator_provider {
> +public:
> + class iterator {
> + public:
> + iterator() {}
> + iterator(const iterator&) {}
> + };
> + class const_iterator {
> + public:
> + const_iterator(int i=0) {}
> + const_iterator(const iterator &) {}
> + const_iterator(const const_iterator &) {}
> + operator iterator() { return iterator(); }
> + };
> + class reverse_iterator {};
> + class const_reverse_iterator {};
> +};
> +
> +} // namespace internal
> +
> +namespace std {""".lstrip() # Take off leading newline
> +
> for c in typedef_containers:
> - print """
> + Definition = """
> template <typename T>
> class {0} {{
> public:
> + typedef T value_type;
> typedef typename internal::iterator_wrapper<{0}<T>, 0> iterator;
> typedef typename internal::iterator_wrapper<{0}<T>, 1> const_iterator;
> typedef typename internal::iterator_wrapper<{0}<T>, 3> reverse_iterator;
> typedef typename internal::iterator_wrapper<{0}<T>, 2> const_reverse_iterator;
>
> {0}() {{}}
> - {1}}};""".format(c, iterator_generators)
> + {1}}};""".format(c['name'], iterator_generators)
> +
> + outputClassDef(Definition, c['name'], c['using'])
>
> for c in subclass_containers:
> - print """
> + Definition = """
> template <typename T>
> class {0} {{
> public:
> @@ -80,10 +166,12 @@ public:
> class const_reverse_iterator {{}};
>
> {0}() {{}}
> - {1}}};""".format(c, iterator_generators)
> + {1}}};""".format(c['name'], iterator_generators)
> +
> + outputClassDef(Definition, c['name'], c['using'])
>
> for c in using_containers:
> - print """
> + Definition = """
> template <typename T>
> class {0} : internal::iterator_provider<{0}<T> > {{
> public:
> @@ -93,6 +181,8 @@ public:
> using typename internal::iterator_provider<{0}<T> >::const_reverse_iterator;
>
> {0}() {{}}
> - {1}}};""".format(c, iterator_generators)
> + {1}}};""".format(c['name'], iterator_generators)
> +
> + outputClassDef(Definition, c['name'], c['using'])
>
> print "} // namespace std"
>
> Modified: clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py?rev=176266&r1=176265&r2=176266&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py (original)
> +++ clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/gen_basic_std_iterator_tests.cpp.py Thu Feb 28 10:29:24 2013
> @@ -19,13 +19,26 @@ containers = [
> "stack"
> ]
>
> -print """// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> -// RUN: cpp11-migrate -use-auto %t.cpp -- --std=c++11 -I %S/Inputs
> +print """
> +//===----------------------------------------------------------------------===//
> +//
> +// This file was automatically generated from
> +// gen_basic_std_iterator_tests.cpp.py by the build system as a dependency for
> +// cpp11-migrate's test suite.
> +//
> +// This file contains basic positive tests for the use-auto transform's ability
> +// to replace standard iterators. Variables considered:
> +// * All std container names
> +// * All std iterator names
> +//
> +//===----------------------------------------------------------------------===//
> +
> +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> +// RUN: cpp11-migrate -use-auto %t.cpp -- -I %S/Inputs
> // RUN: FileCheck -input-file=%t.cpp %s
> -// XFAIL: *
> #include "my_std.h"
>
> -int main(int argc, char **argv) {"""
> +int main(int argc, char **argv) {""".lstrip() # Strip leading newline
>
> for c in containers:
> print """
>
> Added: clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/iterator.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/iterator.cpp?rev=176266&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/iterator.cpp (added)
> +++ clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/iterator.cpp Thu Feb 28 10:29:24 2013
> @@ -0,0 +1,139 @@
> +// RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
> +// RUN: cpp11-migrate -use-auto %t.cpp -- --std=c++11 -I %gen_root/UseAuto/Inputs
> +// RUN: FileCheck -input-file=%t.cpp %s
> +#include "my_std.h"
> +
> +typedef std::vector<int>::iterator int_iterator;
> +
> +namespace foo {
> + template <typename T>
> + class vector {
> + public:
> + class iterator {};
> +
> + iterator begin() { return iterator(); }
> + };
> +} // namespace foo
> +
> +int main(int argc, char **argv) {
> + std::vector<int> Vec;
> + // CHECK: std::vector<int> Vec;
> +
> + std::unordered_map<int> Map;
> + // CHECK: std::unordered_map<int> Map;
> +
> + // Types with more sugar should work. Types with less should not.
> + {
> + int_iterator more_sugar = Vec.begin();
> + // CHECK: auto more_sugar = Vec.begin();
> +
> + internal::iterator_wrapper<std::vector<int>, 0> less_sugar = Vec.begin();
> + // CHECK: internal::iterator_wrapper<std::vector<int>, 0> less_sugar = Vec.begin();
> + }
> +
> + // Initialization from initializer lists isn't allowed. Using 'auto'
> + // would result in std::initializer_list being deduced for the type.
> + {
> + std::unordered_map<int>::iterator I{Map.begin()};
> + // CHECK: std::unordered_map<int>::iterator I{Map.begin()};
> +
> + std::unordered_map<int>::iterator I2 = {Map.begin()};
> + // CHECK: std::unordered_map<int>::iterator I2 = {Map.begin()};
> + }
> +
> + // Various forms of construction. Default constructors and constructors with
> + // all-default parameters shouldn't get transformed. Construction from other
> + // types is also not allowed.
> + {
> + std::unordered_map<int>::iterator copy(Map.begin());
> + // CHECK: auto copy(Map.begin());
> +
> + std::unordered_map<int>::iterator def;
> + // CHECK: std::unordered_map<int>::iterator def;
> +
> + // const_iterator has no default constructor, just one that has >0 params
> + // with defaults.
> + std::unordered_map<int>::const_iterator constI;
> + // CHECK: std::unordered_map<int>::const_iterator constI;
> +
> + // Uses iterator_provider::const_iterator's conversion constructor.
> +
> + std::unordered_map<int>::const_iterator constI2 = def;
> + // CHECK: std::unordered_map<int>::const_iterator constI2 = def;
> +
> + std::unordered_map<int>::const_iterator constI3(def);
> + // CHECK: std::unordered_map<int>::const_iterator constI3(def);
> +
> + // Explicit use of conversion constructor
> +
> + std::unordered_map<int>::const_iterator constI4 = std::unordered_map<int>::const_iterator(def);
> + // CHECK: auto constI4 = std::unordered_map<int>::const_iterator(def);
> +
> + // Uses iterator_provider::iterator's const_iterator conversion operator.
> +
> + std::unordered_map<int>::iterator I = constI;
> + // CHECK: std::unordered_map<int>::iterator I = constI;
> +
> + std::unordered_map<int>::iterator I2(constI);
> + // CHECK: std::unordered_map<int>::iterator I2(constI);
> + }
> +
> + // Weird cases of pointers and references to iterators are not transformed.
> + {
> + int_iterator I = Vec.begin();
> +
> + int_iterator *IPtr = &I;
> + // CHECK: int_iterator *IPtr = &I;
> +
> + int_iterator &IRef = I;
> + // CHECK: int_iterator &IRef = I;
> + }
> +
> + {
> + // Variable declarations in iteration statements.
> + for (std::vector<int>::iterator I = Vec.begin(); I != Vec.end(); ++I) {
> + // CHECK: for (auto I = Vec.begin(); I != Vec.end(); ++I) {
> + }
> +
> + // Range-based for loops.
> + std::array<std::vector<int>::iterator> iter_arr;
> + for (std::vector<int>::iterator I: iter_arr) {
> + // CHECK: for (auto I: iter_arr) {
> + }
> +
> + // Test with init-declarator-list.
> + for (int_iterator I = Vec.begin(),
> + E = Vec.end(); I != E; ++I) {
> + // CHECK: for (auto I = Vec.begin(),
> + // CHECK-NEXT: E = Vec.end(); I != E; ++I) {
> + }
> + }
> +
> + // Only std containers should be changed.
> + {
> + using namespace foo;
> + vector<int> foo_vec;
> + vector<int>::iterator I = foo_vec.begin();
> + // CHECK: vector<int>::iterator I = foo_vec.begin();
> + }
> +
> + // Ensure using directives don't interfere with replacement.
> + {
> + using namespace std;
> + vector<int> std_vec;
> + vector<int>::iterator I = std_vec.begin();
> + // CHECK: auto I = std_vec.begin();
> + }
> +
> + // Make sure references and cv qualifiers don't get removed (i.e. replaced
> + // with just 'auto').
> + {
> + const auto & I = Vec.begin();
> + // CHECK: const auto & I = Vec.begin();
> +
> + auto && I2 = Vec.begin();
> + // CHECK: auto && I2 = Vec.begin();
> + }
> +
> + return 0;
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list