[PATCH] Add -Wrange-loop-analysis to warn when a range-based for-loop is creating a copy.
David Blaikie
dblaikie at gmail.com
Sun Jun 22 08:37:14 PDT 2014
================
Comment at: lib/Sema/SemaStmt.cpp:2361
@@ +2360,3 @@
+ const CXXForRangeStmt *ForStmt) {
+ if (SemaRef.Diags.getDiagnosticLevel(
+ diag::warn_for_range_const_reference_copy, ForStmt->getLocStart()) ==
----------------
I think Alp's been trying to move to using an "isIgnored" function to do this test for some reason - I haven't looked into the motivation, but it might be something to check if you should be consistent with.
================
Comment at: lib/Sema/SemaStmt.cpp:2373
@@ +2372,3 @@
+
+ const VarDecl *VD = ForStmt->getLoopVariable();
+ if (!VD)
----------------
What are the cases where a for loop has no loop variable? (or the loop variable has no init, down on line 2382)
================
Comment at: lib/Sema/SemaStmt.cpp:2386
@@ +2385,3 @@
+
+ if (VariableType->isReferenceType()) {
+ // Foo foos[5];
----------------
Might be worth splitting out these cases as separate functions, maybe?
================
Comment at: lib/Sema/SemaStmt.cpp:2449
@@ +2448,3 @@
+ // Foo foos[5];
+ // for (const Bar bar : foos);
+ bool MakeCopy = false;
----------------
The header comment for this function doesn't mention this case of Foo v Bar, it just mentions:
Foo foos[5];
for (const Foo f : foos);
->
for (const Foo &f : foos);
And the implementation looks like that's the intent of the code. Is the comment out of date/wrong?
================
Comment at: lib/Sema/SemaStmt.cpp:2452
@@ +2451,3 @@
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitExpr)) {
+ if (CE->getConstructor()->isCopyConstructor())
+ MakeCopy = true;
----------------
Not sure if it'd be more readable, but you could just assign:
MakeCopy = CE->getConstructor()->isCopyConstructor();
================
Comment at: lib/Sema/SemaStmt.cpp:2455
@@ +2454,3 @@
+ } else if (const CastExpr *CE = dyn_cast<CastExpr>(InitExpr)) {
+ if (CE->getCastKind() == CK_LValueToRValue)
+ MakeCopy = true;
----------------
Same assignment possible here
================
Comment at: lib/Sema/SemaStmt.cpp:2467
@@ +2466,3 @@
+ }
+ return;
+ }
----------------
return here seems a bit unnecessary (and/or as above, this whole case might be nice as a separate function for readability)
================
Comment at: test/SemaCXX/warn-range-loop-analysis.cpp:14
@@ +13,3 @@
+class Container {
+ typedef Iterator<return_type> I;
+
----------------
I'm not sure if this merits a change to the test code, but this is a bit surprising/out-of-character to have a container of T return T by value from its iterator's op*. (usually it would return a reference to T)
================
Comment at: test/SemaCXX/warn-range-loop-analysis.cpp:41
@@ +40,3 @@
+
+ for (const int x : int_ref_container) {}
+ // expected-warning at -1 {{loop variable 'x' of type 'const int' creates a copy from type 'int'}}
----------------
I think this is going to have a pretty high false positive rate... do you have some numbers?
================
Comment at: test/SemaCXX/warn-range-loop-analysis.cpp:46
@@ +45,3 @@
+
+void test1() {
+ typedef Container<int> non_reference_iterator_container;
----------------
If these test functions provide logical grouping, perhaps they could be named based on that grouping, or have a comment describing it?
================
Comment at: test/SemaCXX/warn-range-loop-analysis.cpp:47
@@ +46,3 @@
+void test1() {
+ typedef Container<int> non_reference_iterator_container;
+ non_reference_iterator_container A;
----------------
any reason for the typedef here, but not in test0 above?
================
Comment at: test/SemaCXX/warn-range-loop-analysis.cpp:50
@@ +49,3 @@
+
+ for (const int &x : A) {}
+ // expected-warning at -1 {{always a copy}}
----------------
Looks the same as the previous tests? (line 33, specifically)
If this test is to ensure that a container wrapped in a typedef is handled correctly - what kind of problems did you have with this situation that you had to handle/correct for?
================
Comment at: test/SemaCXX/warn-range-loop-analysis.cpp:73
@@ +72,3 @@
+ // expected-note at -2 {{'const Bar'}}
+ for (const Bar x : A) {}
+ // No warning, non-reference type indicates copy is made
----------------
I worry about people creating expensive copies this way, but maybe that'll need to be a clang-tidy check rather than a warning.
================
Comment at: test/SemaCXX/warn-range-loop-analysis.cpp:83
@@ +82,3 @@
+ typedef Container<int&> reference_iterator_container;
+ reference_iterator_container B;
+
----------------
Same questions as above
http://reviews.llvm.org/D4169
More information about the cfe-commits
mailing list