]> granicus.if.org Git - clang/commitdiff
Add notes for suppressing and (if it's a zero-arg function returning bool) fixing...
authorDavid Blaikie <dblaikie@gmail.com>
Fri, 9 Dec 2011 21:42:37 +0000 (21:42 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Fri, 9 Dec 2011 21:42:37 +0000 (21:42 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146280 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaChecking.cpp
test/CXX/over/over.over/p2-resolve-single-template-id.cpp
test/SemaCXX/condition.cpp
test/SemaCXX/warn-func-as-bool.cpp
test/SemaTemplate/resolve-single-template-id.cpp

index 5162941f9b54c9605960ceb9fd108d37f6387e95..670dec9781d4cc8734d0b4bee6e6e5a3a6993216 100644 (file)
@@ -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; }
 
index 9d3bccbb9e03f13eadabadda0d501636280c39c9..4f27d9f7acdfb9a9ee8d9c6d4af3e3de91af23ed 100644 (file)
@@ -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<BoolConversions>;
+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">,
index a0138d8723a0198ce1571341b8829c3fce831d12..db60f2388aaa27aac763436c86acf289eab175f2 100644 (file)
@@ -3771,6 +3771,16 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
         if (FunctionDecl* F = dyn_cast<FunctionDecl>(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;
         }
       }
index 470894990076a3895d8a20009ef2cf51e5801029..2a156f7b0dfa325704650a90bb618afd22c6f0ed 100644 (file)
@@ -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<int>(two); } //expected-error {{reinterpret_cast}}
   { (void) reinterpret_cast<int (*)(char, double)>(two); } //expected-error {{reinterpret_cast}}
 
-  { bool b = (twoT<int>); } // expected-warning {{address of function 'twoT<int>' will always evaluate to 'true'}}
-  { bool b = (twoT<int, int>); } // expected-warning {{address of function 'twoT<int, int>' will always evaluate to 'true'}}
+  { bool b = (twoT<int>); } 
+  { bool b = (twoT<int, int>); } 
 
   { bool b = &twoT<int>; //&foo<int>; }
     b = &(twoT<int>); }
@@ -142,20 +142,20 @@ namespace member_pointers {
     if (&s.f<char>) return; // expected-error {{cannot create a non-constant pointer to member function}}
     if (&s.f<int>) return; // expected-error {{cannot create a non-constant pointer to member function}}
 
-    if (S::g<char>) return; // expected-warning {{address of function 'member_pointers::S::g<char>' will always evaluate to 'true'}}
-    if (S::g<int>) return; // expected-warning {{address of function 'member_pointers::S::g<int>' will always evaluate to 'true'}}
+    if (S::g<char>) return;
+    if (S::g<int>) return;
     if (&S::g<char>) return;
     if (&S::g<int>) return;
-    if (s.g<char>) return; // expected-warning {{address of function 'member_pointers::S::g<char>' will always evaluate to 'true'}}
-    if (s.g<int>) return; // expected-warning {{address of function 'member_pointers::S::g<int>' will always evaluate to 'true'}}
+    if (s.g<char>) return;
+    if (s.g<int>) return;
     if (&s.g<char>) return;
     if (&s.g<int>) 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<int>) 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<int>) 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<int>) 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<int>) 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<char>; } // expected-error {{cannot create a non-constant pointer to member function}}
     { bool b = &s.f<int>; } // expected-error {{cannot create a non-constant pointer to member function}}
 
-    { bool b = S::g<char>; } // expected-warning {{address of function 'member_pointers::S::g<char>' will always evaluate to 'true'}}
-    { bool b = S::g<int>; } // expected-warning {{address of function 'member_pointers::S::g<int>' will always evaluate to 'true'}}
+    { bool b = S::g<char>; }
+    { bool b = S::g<int>; }
     { bool b = &S::g<char>; }
     { bool b = &S::g<int>; }
-    { bool b = s.g<char>; }  // expected-warning {{address of function 'member_pointers::S::g<char>' will always evaluate to 'true'}}
-    { bool b = s.g<int>; } // expected-warning {{address of function 'member_pointers::S::g<int>' will always evaluate to 'true'}}
+    { bool b = s.g<char>; }
+    { bool b = s.g<int>; }
     { bool b = &s.g<char>; }
     { bool b = &s.g<int>; }
 
-    { 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<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}}
     { bool b = &S::h<42>; }
     { bool b = &S::h<int>; }
-    { 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<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}}
     { bool b = &s.h<42>; }
     { bool b = &s.h<int>; } // expected-error {{can't form member pointer of type 'bool' without '&' and class name}}
index 7854d51bfd7649db5bb86b8565250ebf787b8c4a..099c11cb9eeeef9e8012ec9a89f1792960488f73 100644 (file)
@@ -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;
 }
 
index 2606b4da953deb71d7b1140df6ab3ed0d84e5055..b5df744f93067a77082d932c734fe63372a135a7 100644 (file)
@@ -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;
index 1beb65a0f510d71fd5e97a2b347383b7c6f10701..0c9bacca3eddb915fb4f0faa1cce515a67aa286c 100644 (file)
@@ -41,7 +41,7 @@ int main()
   *oneT<int>;   // 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<int>; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}}
-  !oneT<int>;  // expected-warning {{expression result unused}} expected-warning {{address of function 'oneT<int>' will always evaluate to 'true'}}
+  !oneT<int>;  // expected-warning {{expression result unused}} expected-warning {{address of function 'oneT<int>' will always evaluate to 'true'}} expected-note {{prefix with the address-of operator to silence this warning}}
   +oneT<int>;  // expected-warning {{expression result unused}}
   -oneT<int>;  //expected-error {{invalid argument type}}
   oneT<int> == 0;   // expected-warning {{equality comparison result unused}} \
@@ -53,7 +53,7 @@ int main()
   
   int i = (int) (false ? (void (*)(int))twoT<int> : oneT<int>); //expected-error {{incompatible operand}}
   (twoT<int>) == oneT<int>; //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<int>; // expected-warning {{address of function 'oneT<int>' will always evaluate to 'true'}}
+  bool b = oneT<int>; // expected-warning {{address of function 'oneT<int>' will always evaluate to 'true'}} expected-note {{prefix with the address-of operator to silence this warning}}
   void (*p)() = oneT<int>;
   test<oneT<int> > ti;
   void (*u)(int) = oneT<int>;