From: David Blaikie Date: Fri, 9 Dec 2011 21:42:37 +0000 (+0000) Subject: Add notes for suppressing and (if it's a zero-arg function returning bool) fixing... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2def77399ab3088106a2d61372344f5b7104e1a2;p=clang Add notes for suppressing and (if it's a zero-arg function returning bool) fixing the function-to-bool conversion warning. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146280 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 5162941f9b..670dec9781 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -2692,6 +2692,7 @@ public: explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { } + SourceLocation getExprLoc() const { return OpLoc; } SourceLocation getOperatorLoc() const { return OpLoc; } void setOperatorLoc(SourceLocation L) { OpLoc = L; } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9d3bccbb9e..4f27d9f7ac 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1657,6 +1657,10 @@ def warn_impcast_null_pointer_to_integer : Warning< def warn_impcast_function_to_bool : Warning< "address of function %q0 will always evaluate to 'true'">, InGroup; +def note_function_to_bool_silence : Note< + "prefix with the address-of operator to silence this warning">; +def note_function_to_bool_call : Note< + "suffix with parentheses to turn this into a function call">; def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index a0138d8723..db60f2388a 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -3771,6 +3771,16 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (FunctionDecl* F = dyn_cast(D)) { S.Diag(E->getExprLoc(), diag::warn_impcast_function_to_bool) << F << E->getSourceRange() << SourceRange(CC); + S.Diag(E->getExprLoc(), diag::note_function_to_bool_silence) + << FixItHint::CreateInsertion(E->getExprLoc(), "&"); + QualType ReturnType; + UnresolvedSet<4> NonTemplateOverloads; + S.isExprCallable(*E, ReturnType, NonTemplateOverloads); + if (!ReturnType.isNull() + && ReturnType->isSpecificBuiltinType(BuiltinType::Bool)) + S.Diag(E->getExprLoc(), diag::note_function_to_bool_call) + << FixItHint::CreateInsertion( + S.getPreprocessor().getLocForEndOfToken(E->getLocEnd()), "()"); return; } } diff --git a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp index 4708949900..2a156f7b0d 100644 --- a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp +++ b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-bool-conversions %s typedef __typeof__(((int*)0)-((int*)0)) ptrdiff_t; @@ -100,8 +100,8 @@ int main() { (void) reinterpret_cast(two); } //expected-error {{reinterpret_cast}} { (void) reinterpret_cast(two); } //expected-error {{reinterpret_cast}} - { bool b = (twoT); } // expected-warning {{address of function 'twoT' will always evaluate to 'true'}} - { bool b = (twoT); } // expected-warning {{address of function 'twoT' will always evaluate to 'true'}} + { bool b = (twoT); } + { bool b = (twoT); } { bool b = &twoT; //&foo; } b = &(twoT); } @@ -142,20 +142,20 @@ namespace member_pointers { if (&s.f) return; // expected-error {{cannot create a non-constant pointer to member function}} if (&s.f) return; // expected-error {{cannot create a non-constant pointer to member function}} - if (S::g) return; // expected-warning {{address of function 'member_pointers::S::g' will always evaluate to 'true'}} - if (S::g) return; // expected-warning {{address of function 'member_pointers::S::g' will always evaluate to 'true'}} + if (S::g) return; + if (S::g) return; if (&S::g) return; if (&S::g) return; - if (s.g) return; // expected-warning {{address of function 'member_pointers::S::g' will always evaluate to 'true'}} - if (s.g) return; // expected-warning {{address of function 'member_pointers::S::g' will always evaluate to 'true'}} + if (s.g) return; + if (s.g) return; if (&s.g) return; if (&s.g) return; - if (S::h<42>) return; // expected-warning {{address of function 'member_pointers::S::h<42>' will always evaluate to 'true'}} + if (S::h<42>) return; if (S::h) return; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} if (&S::h<42>) return; if (&S::h) return; - if (s.h<42>) return; // expected-warning {{address of function 'member_pointers::S::h<42>' will always evaluate to 'true'}} + if (s.h<42>) return; if (s.h) return; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} if (&s.h<42>) return; if (&s.h) return; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} @@ -170,20 +170,20 @@ namespace member_pointers { { bool b = &s.f; } // expected-error {{cannot create a non-constant pointer to member function}} { bool b = &s.f; } // expected-error {{cannot create a non-constant pointer to member function}} - { bool b = S::g; } // expected-warning {{address of function 'member_pointers::S::g' will always evaluate to 'true'}} - { bool b = S::g; } // expected-warning {{address of function 'member_pointers::S::g' will always evaluate to 'true'}} + { bool b = S::g; } + { bool b = S::g; } { bool b = &S::g; } { bool b = &S::g; } - { bool b = s.g; } // expected-warning {{address of function 'member_pointers::S::g' will always evaluate to 'true'}} - { bool b = s.g; } // expected-warning {{address of function 'member_pointers::S::g' will always evaluate to 'true'}} + { bool b = s.g; } + { bool b = s.g; } { bool b = &s.g; } { bool b = &s.g; } - { bool b = S::h<42>; } // expected-warning {{address of function 'member_pointers::S::h<42>' will always evaluate to 'true'}} + { bool b = S::h<42>; } { bool b = S::h; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} { bool b = &S::h<42>; } { bool b = &S::h; } - { bool b = s.h<42>; } // expected-warning {{address of function 'member_pointers::S::h<42>' will always evaluate to 'true'}} + { bool b = s.h<42>; } { bool b = s.h; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} { bool b = &s.h<42>; } { bool b = &s.h; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}} diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp index 7854d51bfd..099c11cb9e 100644 --- a/test/SemaCXX/condition.cpp +++ b/test/SemaCXX/condition.cpp @@ -49,7 +49,8 @@ void test3() { if ("help") (void) 0; - if (test3) // expected-warning {{address of function 'test3' will always evaluate to 'true'}} + if (test3) // expected-warning {{address of function 'test3' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} (void) 0; } diff --git a/test/SemaCXX/warn-func-as-bool.cpp b/test/SemaCXX/warn-func-as-bool.cpp index 2606b4da95..b5df744f93 100644 --- a/test/SemaCXX/warn-func-as-bool.cpp +++ b/test/SemaCXX/warn-func-as-bool.cpp @@ -12,13 +12,25 @@ struct S2 { static void f4() __attribute__((weak_import)); }; +bool f5(); +bool f6(int); + void bar() { bool b; - b = f1; // expected-warning {{address of function 'f1' will always evaluate to 'true'}} - if (f1) {} // expected-warning {{address of function 'f1' will always evaluate to 'true'}} - b = S::f2; // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} - if (S::f2) {} // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} + b = f1; // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + if (f1) {} // expected-warning {{address of function 'f1' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + b = S::f2; // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + if (S::f2) {} // expected-warning {{address of function 'S::f2' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} + b = f5; // expected-warning {{address of function 'f5' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} \ + expected-note {{suffix with parentheses to turn this into a function call}} + b = f6; // expected-warning {{address of function 'f6' will always evaluate to 'true'}} \ + expected-note {{prefix with the address-of operator to silence this warning}} // implicit casts of weakly imported symbols are ok: b = f3; diff --git a/test/SemaTemplate/resolve-single-template-id.cpp b/test/SemaTemplate/resolve-single-template-id.cpp index 1beb65a0f5..0c9bacca3e 100644 --- a/test/SemaTemplate/resolve-single-template-id.cpp +++ b/test/SemaTemplate/resolve-single-template-id.cpp @@ -41,7 +41,7 @@ int main() *oneT; // expected-warning {{expression result unused}} *two; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{indirection requires pointer operand}} *twoT; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} - !oneT; // expected-warning {{expression result unused}} expected-warning {{address of function 'oneT' will always evaluate to 'true'}} + !oneT; // expected-warning {{expression result unused}} expected-warning {{address of function 'oneT' will always evaluate to 'true'}} expected-note {{prefix with the address-of operator to silence this warning}} +oneT; // expected-warning {{expression result unused}} -oneT; //expected-error {{invalid argument type}} oneT == 0; // expected-warning {{equality comparison result unused}} \ @@ -53,7 +53,7 @@ int main() int i = (int) (false ? (void (*)(int))twoT : oneT); //expected-error {{incompatible operand}} (twoT) == oneT; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} {{cannot resolve overloaded function 'twoT' from context}} - bool b = oneT; // expected-warning {{address of function 'oneT' will always evaluate to 'true'}} + bool b = oneT; // expected-warning {{address of function 'oneT' will always evaluate to 'true'}} expected-note {{prefix with the address-of operator to silence this warning}} void (*p)() = oneT; test > ti; void (*u)(int) = oneT;