Skip to content

Commit 41fcd17

Browse files
committed
[Sema] Avoid Wrange-loop-analysis false positives
When Wrange-loop-analysis issues a diagnostic on a dependent type in a template the diagnostic may not be valid for all instantiations. Therefore the diagnostic is suppressed during the instantiation. Non dependent types still issue a diagnostic. The same can happen when using macros. Therefore the diagnostic is disabled for macros. Fixes https://bugs.llvm.org/show_bug.cgi?id=44556 Differential Revision: https://reviews.llvm.org/D73007
1 parent 6b9a5e6 commit 41fcd17

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

clang/lib/Sema/SemaStmt.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2838,6 +2838,9 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
28382838
/// Suggest "const foo &x" to prevent the copy.
28392839
static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
28402840
const CXXForRangeStmt *ForStmt) {
2841+
if (SemaRef.inTemplateInstantiation())
2842+
return;
2843+
28412844
if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy,
28422845
ForStmt->getBeginLoc()) &&
28432846
SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy,
@@ -2860,6 +2863,9 @@ static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
28602863
if (!InitExpr)
28612864
return;
28622865

2866+
if (InitExpr->getExprLoc().isMacroID())
2867+
return;
2868+
28632869
if (VariableType->isReferenceType()) {
28642870
DiagnoseForRangeReferenceVariableCopies(SemaRef, VD,
28652871
ForStmt->getRangeInit()->getType());

clang/test/SemaCXX/warn-range-loop-analysis.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,75 @@ void test10() {
454454
// expected-note@-2 {{'Bar'}}
455455
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:18}:" "
456456
}
457+
458+
template <class T>
459+
void test_template_function() {
460+
// In a template instantiation the diagnostics should not be emitted for
461+
// loops with dependent types.
462+
Container<Bar> C;
463+
for (const Bar &x : C) {}
464+
// expected-warning@-1 {{always a copy}}
465+
// expected-note@-2 {{'Bar'}}
466+
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
467+
468+
Container<T> Dependent;
469+
for (const T &x : Dependent) {}
470+
}
471+
template void test_template_function<Bar>();
472+
473+
template <class T>
474+
struct test_template_struct {
475+
static void static_member() {
476+
Container<Bar> C;
477+
for (const Bar &x : C) {}
478+
// expected-warning@-1 {{always a copy}}
479+
// expected-note@-2 {{'Bar'}}
480+
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""
481+
482+
Container<T> Dependent;
483+
for (const T &x : Dependent) {}
484+
}
485+
486+
void member() {
487+
Container<Bar> C;
488+
for (const Bar &x : C) {}
489+
// expected-warning@-1 {{always a copy}}
490+
// expected-note@-2 {{'Bar'}}
491+
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""
492+
493+
Container<T> Dependent;
494+
for (const T &x : Dependent) {}
495+
}
496+
};
497+
template struct test_template_struct<Bar>;
498+
499+
struct test_struct_with_templated_member {
500+
void member() {
501+
Container<Bar> C;
502+
for (const Bar &x : C) {}
503+
// expected-warning@-1 {{always a copy}}
504+
// expected-note@-2 {{'Bar'}}
505+
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""
506+
}
507+
508+
template <class T>
509+
void template_member() {
510+
Container<Bar> C;
511+
for (const Bar &x : C) {}
512+
// expected-warning@-1 {{always a copy}}
513+
// expected-note@-2 {{'Bar'}}
514+
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""
515+
516+
Container<T> Dependent;
517+
for (const T &x : Dependent) {}
518+
}
519+
};
520+
template void test_struct_with_templated_member::template_member<Bar>();
521+
522+
#define TEST_MACRO \
523+
void test_macro() { \
524+
Container<Bar> C; \
525+
for (const Bar &x : C) {} \
526+
}
527+
528+
TEST_MACRO

0 commit comments

Comments
 (0)