[clang-tools-extra] r182114 - Fix UseAuto replacing variable declaration lists containing non-initialized
Ariel J. Bernal
ariel.j.bernal at intel.com
Fri May 17 08:30:17 PDT 2013
Author: ajbernal
Date: Fri May 17 10:30:17 2013
New Revision: 182114
URL: http://llvm.org/viewvc/llvm-project?rev=182114&view=rev
Log:
Fix UseAuto replacing variable declaration lists containing non-initialized
variables.
UseAuto used to match initialized variable declarations independently of
whether they were defined in a declaration list or as a single declaration.
Now it matches declaration statements where every variable declaration is
initialized.
Modified:
clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.cpp
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
Modified: 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=182114&r1=182113&r2=182114&view=diff
==============================================================================
--- clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.cpp (original)
+++ clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoActions.cpp Fri May 17 10:30:17 2013
@@ -20,54 +20,60 @@ using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace clang;
-void IteratorReplacer::run(const MatchFinder::MatchResult &Result) {
- const VarDecl *D = Result.Nodes.getNodeAs<VarDecl>(IteratorDeclId);
+void IteratorReplacer::run(const MatchFinder::MatchResult &Result) {
+ const DeclStmt *D = Result.Nodes.getNodeAs<DeclStmt>(IteratorDeclStmtId);
assert(D && "Bad Callback. No node provided");
SourceManager &SM = *Result.SourceManager;
if (!SM.isFromMainFile(D->getLocStart()))
return;
- const Expr *ExprInit = D->getInit();
-
- // Skip expressions with cleanups from the initializer expression.
- if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(ExprInit))
- ExprInit = E->getSubExpr();
-
- const CXXConstructExpr *Construct = cast<CXXConstructExpr>(ExprInit);
-
- 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))
+ for (clang::DeclStmt::const_decl_iterator I = D->decl_begin(),
+ E = D->decl_end(); I != E; ++I) {
+ const VarDecl *V = cast<VarDecl>(*I);
+
+ const Expr *ExprInit = V->getInit();
+
+ // Skip expressions with cleanups from the initializer expression.
+ if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(ExprInit))
+ ExprInit = E->getSubExpr();
+
+ const CXXConstructExpr *Construct = cast<CXXConstructExpr>(ExprInit);
+
+ 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 (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;
+ 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(V->getType(), E->getType()))
+ return;
}
+ // Get the type location using the first declartion.
+ const VarDecl *V = cast<VarDecl>(*D->decl_begin());
+ TypeLoc TL = V->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;
}
void NewReplacer::run(const MatchFinder::MatchResult &Result) {
@@ -77,7 +83,7 @@ void NewReplacer::run(const MatchFinder:
SourceManager &SM = *Result.SourceManager;
if (!SM.isFromMainFile(D->getLocStart()))
return;
-
+
const CXXNewExpr *NewExpr = Result.Nodes.getNodeAs<CXXNewExpr>(NewExprId);
assert(NewExpr && "Bad Callback. No CXXNewExpr bound");
Modified: 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=182114&r1=182113&r2=182114&view=diff
==============================================================================
--- clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.cpp (original)
+++ clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.cpp Fri May 17 10:30:17 2013
@@ -18,7 +18,7 @@
using namespace clang::ast_matchers;
using namespace clang;
-const char *IteratorDeclId = "iterator_decl";
+const char *IteratorDeclStmtId = "iterator_decl";
const char *DeclWithNewId = "decl_new";
const char *NewExprId = "new_expr";
@@ -232,20 +232,30 @@ TypeMatcher iteratorFromUsingDeclaration
}
} // namespace
-DeclarationMatcher makeIteratorDeclMatcher() {
- return varDecl(allOf(
- hasWrittenNonListInitializer(),
- unless(hasType(autoType())),
- hasType(
- isSugarFor(
- anyOf(
- typedefIterator(),
- nestedIterator(),
- iteratorFromUsingDeclaration()
- )
- )
- )
- )).bind(IteratorDeclId);
+// \brief This matcher returns delaration statements that contain variable
+// declarations with written non-list initializer for standard iterators.
+StatementMatcher makeIteratorDeclMatcher() {
+ return declStmt(
+ // At least one varDecl should be a child of the declStmt to ensure it's a
+ // declaration list and avoid matching other declarations
+ // e.g. using directives.
+ has(varDecl()),
+ unless(has(varDecl(
+ anyOf(
+ unless(hasWrittenNonListInitializer()),
+ hasType(autoType()),
+ unless(hasType(
+ isSugarFor(
+ anyOf(
+ typedefIterator(),
+ nestedIterator(),
+ iteratorFromUsingDeclaration()
+ )
+ )
+ ))
+ )
+ )))
+ ).bind(IteratorDeclStmtId);
}
DeclarationMatcher makeDeclWithNewMatcher() {
Modified: 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=182114&r1=182113&r2=182114&view=diff
==============================================================================
--- clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.h (original)
+++ clang-tools-extra/trunk/cpp11-migrate/UseAuto/UseAutoMatchers.h Fri May 17 10:30:17 2013
@@ -17,14 +17,14 @@
#include "clang/ASTMatchers/ASTMatchers.h"
-extern const char *IteratorDeclId;
+extern const char *IteratorDeclStmtId;
extern const char *DeclWithNewId;
extern const char *NewExprId;
-/// \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 makeIteratorDeclMatcher();
+/// \brief Create a matcher that matches declaration staments that have
+/// variable declarations where the type is an iterator for an std container
+/// and has an explicit initializer of the same type.
+clang::ast_matchers::StatementMatcher makeIteratorDeclMatcher();
/// \brief Create a matcher that matches variable declarations that are
/// initialized by a C++ new expression.
Modified: 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=182114&r1=182113&r2=182114&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/iterator.cpp (original)
+++ clang-tools-extra/trunk/test/cpp11-migrate/UseAuto/iterator.cpp Fri May 17 10:30:17 2013
@@ -156,5 +156,17 @@ int main(int argc, char **argv) {
// CHECK: auto I = MapFind.find("foo");
}
+ // Test for declaration lists
+ {
+ // Ensusre declaration lists that matches the declaration type with written
+ // no-list initializer are transformed.
+ std::vector<int>::iterator I = Vec.begin(), E = Vec.end();
+ // CHECK: auto I = Vec.begin(), E = Vec.end();
+
+ // Declaration lists with non-initialized variables should not be
+ // transformed.
+ std::vector<int>::iterator J = Vec.begin(), K;
+ // CHECK: std::vector<int>::iterator J = Vec.begin(), K;
+ }
return 0;
}
More information about the cfe-commits
mailing list