Skip to content

Commit

Permalink
[Sema] Avoid Wrange-loop-analysis false positives
Browse files Browse the repository at this point in the history
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

(cherry picked from commit 41fcd17)
  • Loading branch information
mordante authored and zmodem committed Jan 23, 2020
1 parent a3982a5 commit 318677e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
6 changes: 6 additions & 0 deletions clang/lib/Sema/SemaStmt.cpp
Expand Up @@ -2838,6 +2838,9 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
/// Suggest "const foo &x" to prevent the copy.
static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
const CXXForRangeStmt *ForStmt) {
if (SemaRef.inTemplateInstantiation())
return;

if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy,
ForStmt->getBeginLoc()) &&
SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy,
Expand All @@ -2860,6 +2863,9 @@ static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
if (!InitExpr)
return;

if (InitExpr->getExprLoc().isMacroID())
return;

if (VariableType->isReferenceType()) {
DiagnoseForRangeReferenceVariableCopies(SemaRef, VD,
ForStmt->getRangeInit()->getType());
Expand Down
72 changes: 72 additions & 0 deletions clang/test/SemaCXX/warn-range-loop-analysis.cpp
Expand Up @@ -454,3 +454,75 @@ void test10() {
// expected-note@-2 {{'Bar'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:18}:" "
}

template <class T>
void test_template_function() {
// In a template instantiation the diagnostics should not be emitted for
// loops with dependent types.
Container<Bar> C;
for (const Bar &x : C) {}
// expected-warning@-1 {{always a copy}}
// expected-note@-2 {{'Bar'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""

Container<T> Dependent;
for (const T &x : Dependent) {}
}
template void test_template_function<Bar>();

template <class T>
struct test_template_struct {
static void static_member() {
Container<Bar> C;
for (const Bar &x : C) {}
// expected-warning@-1 {{always a copy}}
// expected-note@-2 {{'Bar'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""

Container<T> Dependent;
for (const T &x : Dependent) {}
}

void member() {
Container<Bar> C;
for (const Bar &x : C) {}
// expected-warning@-1 {{always a copy}}
// expected-note@-2 {{'Bar'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""

Container<T> Dependent;
for (const T &x : Dependent) {}
}
};
template struct test_template_struct<Bar>;

struct test_struct_with_templated_member {
void member() {
Container<Bar> C;
for (const Bar &x : C) {}
// expected-warning@-1 {{always a copy}}
// expected-note@-2 {{'Bar'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""
}

template <class T>
void template_member() {
Container<Bar> C;
for (const Bar &x : C) {}
// expected-warning@-1 {{always a copy}}
// expected-note@-2 {{'Bar'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""

Container<T> Dependent;
for (const T &x : Dependent) {}
}
};
template void test_struct_with_templated_member::template_member<Bar>();

#define TEST_MACRO \
void test_macro() { \
Container<Bar> C; \
for (const Bar &x : C) {} \
}

TEST_MACRO

0 comments on commit 318677e

Please sign in to comment.