[PATCH] Clang-Modernize.Pass-By-Value: Fix removing of namespace in parameter type
Guillaume Papin
guillaume.papin at epitech.eu
Thu Sep 5 14:46:42 PDT 2013
I changed the way I handled things since my first submission. Now the
pass-by-value transform will try to transform only const-ref parameters and
non-const value parameters.
The test have been updated to reflect the changes.
Hi revane, arielbernal, tareqsiraj,
http://llvm-reviews.chandlerc.com/D1600
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D1600?vs=4040&id=4074#toc
Files:
clang-modernize/PassByValue/PassByValueActions.cpp
clang-modernize/PassByValue/PassByValueMatchers.cpp
test/clang-modernize/PassByValue/basic.cpp
Index: clang-modernize/PassByValue/PassByValueActions.cpp
===================================================================
--- clang-modernize/PassByValue/PassByValueActions.cpp
+++ clang-modernize/PassByValue/PassByValueActions.cpp
@@ -113,16 +113,20 @@
collectParamDecls(Ctor, ParamDecl, AllParamDecls);
// Generate all replacements for the params.
- llvm::SmallVector<Replacement, 2> ParamReplaces(AllParamDecls.size());
+ llvm::SmallVector<Replacement, 2> ParamReplaces;
for (unsigned I = 0, E = AllParamDecls.size(); I != E; ++I) {
TypeLoc ParamTL = AllParamDecls[I]->getTypeSourceInfo()->getTypeLoc();
+ ReferenceTypeLoc RefTL = ParamTL.getAs<ReferenceTypeLoc>();
SourceRange Range(AllParamDecls[I]->getLocStart(), ParamTL.getLocEnd());
CharSourceRange CharRange = Lexer::makeFileCharRange(
CharSourceRange::getTokenRange(Range), SM, LangOptions());
- TypeLoc ValueTypeLoc = ParamTL;
+
+ // do not generate a replacement when the parameter is already a value
+ if (RefTL.isNull())
+ continue;
+
// transform non-value parameters (e.g: const-ref) to values
- if (!ParamTL.getNextTypeLoc().isNull())
- ValueTypeLoc = ParamTL.getNextTypeLoc();
+ TypeLoc ValueTypeLoc = RefTL.getPointeeLoc();
llvm::SmallString<32> ValueStr = Lexer::getSourceText(
CharSourceRange::getTokenRange(ValueTypeLoc.getSourceRange()), SM,
LangOptions());
@@ -136,7 +140,7 @@
// 'const Foo ¶m' -> 'Foo param'
// ~~~~~~~~~~~ ~~~^
ValueStr += ' ';
- ParamReplaces[I] = Replacement(SM, CharRange, ValueStr);
+ ParamReplaces.push_back(Replacement(SM, CharRange, ValueStr));
}
// Reject the changes if the the risk level is not acceptable.
Index: clang-modernize/PassByValue/PassByValueMatchers.cpp
===================================================================
--- clang-modernize/PassByValue/PassByValueMatchers.cpp
+++ clang-modernize/PassByValue/PassByValueMatchers.cpp
@@ -63,15 +63,29 @@
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().bind(PassByValueParamId)))),
+ 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())))))))
Index: test/clang-modernize/PassByValue/basic.cpp
===================================================================
--- test/clang-modernize/PassByValue/basic.cpp
+++ test/clang-modernize/PassByValue/basic.cpp
@@ -72,11 +72,17 @@
// Test unnamed parameter in declaration
struct G {
G(const Movable &);
- // CHECK: G(Movable );
+ // CHECK: G(Movable);
+
+ // Test that a space is not added unnecessarily before a comma
+ G(const Movable &, int);
+ // CHECK: G(Movable, int);
Movable M;
};
G::G(const Movable &M) : M(M) {}
// CHECK: G::G(Movable M) : M(std::move(M)) {}
+G::G(const Movable &M, int) : M(M) {}
+// CHECK: G::G(Movable M, int) : M(std::move(M)) {}
// Test parameter with and without qualifier
namespace ns_H {
@@ -150,7 +156,7 @@
// Test with a const-value parameter
struct P {
P(const Movable M) : M(M) {}
- // CHECK: P(Movable M) : M(std::move(M)) {}
+ // CHECK: P(const Movable M) : M(M) {}
Movable M;
};
@@ -166,3 +172,20 @@
Movable C;
double D;
};
+
+// Test that value-parameters with a nested name specifier are left as-is
+namespace ns_R {
+typedef ::Movable RMovable;
+}
+struct R {
+ R(ns_R::RMovable M) : M(M) {}
+ // CHECK: R(ns_R::RMovable M) : M(std::move(M)) {}
+ ns_R::RMovable M;
+};
+
+// Test with rvalue parameter
+struct S {
+ S(Movable &&M) : M(M) {}
+ // CHECK: S(Movable &&M) : M(M) {}
+ Movable M;
+};
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1600.2.patch
Type: text/x-patch
Size: 4814 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130905/6923618c/attachment.bin>
More information about the cfe-commits
mailing list