On Thu, Feb 28, 2013 at 8:29 AM, Edwin Vane <[email protected]> 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 > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
