r211989 - Extend -Wtautological-undefined-compare and -Wundefined-bool-conversion to

Richard Trieu rtrieu at google.com
Sat Jun 28 16:25:38 PDT 2014


Author: rtrieu
Date: Sat Jun 28 18:25:37 2014
New Revision: 211989

URL: http://llvm.org/viewvc/llvm-project?rev=211989&view=rev
Log:
Extend -Wtautological-undefined-compare and -Wundefined-bool-conversion to
trigger on taking the address of a reference that is returned from a function
call.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/test/SemaCXX/warn-tautological-undefined-compare.cpp
    cfe/trunk/test/SemaCXX/warn-undefined-bool-conversion.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=211989&r1=211988&r2=211989&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Jun 28 18:25:37 2014
@@ -2433,6 +2433,7 @@ def warn_address_of_reference_null_compa
   "code; comparison may be assumed to always evaluate to "
   "%select{true|false}0">,
   InGroup<TautologicalUndefinedCompare>;
+def note_reference_is_return_value : Note<"%0 returns a reference">;
 
 def note_function_warning_silence : Note<
     "prefix with the address-of operator to silence this warning">;

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=211989&r1=211988&r2=211989&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Sat Jun 28 18:25:37 2014
@@ -6192,6 +6192,38 @@ enum {
   ArrayPointer
 };
 
+// Helper function for Sema::DiagnoseAlwaysNonNullPointer.
+// Returns true when emitting a warning about taking the address of a reference.
+static bool CheckForReference(Sema &SemaRef, const Expr *E,
+                              PartialDiagnostic PD) {
+  E = E->IgnoreParenImpCasts();
+
+  const FunctionDecl *FD = nullptr;
+
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    if (!DRE->getDecl()->getType()->isReferenceType())
+      return false;
+  } else if (const MemberExpr *M = dyn_cast<MemberExpr>(E)) {
+    if (!M->getMemberDecl()->getType()->isReferenceType())
+      return false;
+  } else if (const CallExpr *Call = dyn_cast<CallExpr>(E)) {
+    if (!Call->getCallReturnType()->isReferenceType())
+      return false;
+    FD = Call->getDirectCallee();
+  } else {
+    return false;
+  }
+
+  SemaRef.Diag(E->getExprLoc(), PD);
+
+  // If possible, point to location of function.
+  if (FD) {
+    SemaRef.Diag(FD->getLocation(), diag::note_reference_is_return_value) << FD;
+  }
+
+  return true;
+}
+
 /// \brief Diagnose pointers that are always non-null.
 /// \param E the expression containing the pointer
 /// \param NullKind NPCK_NotNull if E is a cast to bool, otherwise, E is
@@ -6227,6 +6259,17 @@ void Sema::DiagnoseAlwaysNonNullPointer(
     E = UO->getSubExpr();
   }
 
+  if (IsAddressOf) {
+    unsigned DiagID = IsCompare
+                          ? diag::warn_address_of_reference_null_compare
+                          : diag::warn_address_of_reference_bool_conversion;
+    PartialDiagnostic PD = PDiag(DiagID) << E->getSourceRange() << Range
+                                         << IsEqual;
+    if (CheckForReference(*this, E, PD)) {
+      return;
+    }
+  }
+
   // Expect to find a single Decl.  Skip anything more complicated.
   ValueDecl *D = nullptr;
   if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {
@@ -6243,18 +6286,9 @@ void Sema::DiagnoseAlwaysNonNullPointer(
   const bool IsArray = T->isArrayType();
   const bool IsFunction = T->isFunctionType();
 
-  if (IsAddressOf) {
-    // Address of function is used to silence the function warning.
-    if (IsFunction)
-      return;
-
-    if (T->isReferenceType()) {
-      unsigned DiagID = IsCompare
-                            ? diag::warn_address_of_reference_null_compare
-                            : diag::warn_address_of_reference_bool_conversion;
-      Diag(E->getExprLoc(), DiagID) << E->getSourceRange() << Range << IsEqual;
-      return;
-    }
+  // Address of function is used to silence the function warning.
+  if (IsAddressOf && IsFunction) {
+    return;
   }
 
   // Found nothing.

Modified: cfe/trunk/test/SemaCXX/warn-tautological-undefined-compare.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-tautological-undefined-compare.cpp?rev=211989&r1=211988&r2=211989&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-tautological-undefined-compare.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-tautological-undefined-compare.cpp Sat Jun 28 18:25:37 2014
@@ -32,3 +32,81 @@ class test2 {
   int &x;
   int y;
 };
+
+namespace function_return_reference {
+  int& get_int();
+  // expected-note at -1 4{{'get_int' returns a reference}}
+  class B {
+  public:
+    static int &stat();
+    // expected-note at -1 4{{'stat' returns a reference}}
+    int &get();
+    // expected-note at -1 8{{'get' returns a reference}}
+  };
+
+  void test() {
+    if (&get_int() == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+    if (&(get_int()) == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+
+    if (&get_int() != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+    if (&(get_int()) != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+
+    if (&B::stat() == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+    if (&(B::stat()) == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+
+    if (&B::stat() != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+    if (&(B::stat()) != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+
+    B b;
+    if (&b.get() == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+    if (&(b.get()) == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+
+    if (&b.get() != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+    if (&(b.get()) != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+
+    B* b_ptr = &b;
+    if (&b_ptr->get() == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+    if (&(b_ptr->get()) == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+
+    if (&b_ptr->get() != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+    if (&(b_ptr->get()) != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+
+    int& (B::*m_ptr)() = &B::get;
+    if (&(b.*m_ptr)() == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+    if (&((b.*m_ptr)()) == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+
+    if (&(b.*m_ptr)() != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+    if (&((b.*m_ptr)()) != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+
+    int& (*f_ptr)() = &get_int;
+    if (&(*f_ptr)() == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+    if (&((*f_ptr)()) == 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false}}
+
+    if (&(*f_ptr)() != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+    if (&((*f_ptr)()) != 0) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to true}}
+  }
+}

Modified: cfe/trunk/test/SemaCXX/warn-undefined-bool-conversion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-undefined-bool-conversion.cpp?rev=211989&r1=211988&r2=211989&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-undefined-bool-conversion.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-undefined-bool-conversion.cpp Sat Jun 28 18:25:37 2014
@@ -35,3 +35,63 @@ class test2 {
   int &x;
   int y;
 };
+
+namespace function_return_reference {
+  int& get_int();
+  // expected-note at -1 3{{'get_int' returns a reference}}
+  class B {
+  public:
+    static int &stat();
+    // expected-note at -1 3{{'stat' returns a reference}}
+    int &get();
+    // expected-note at -1 6{{'get' returns a reference}}
+  };
+
+  void test() {
+    if (&get_int()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (&(get_int())) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (!&get_int()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+
+    if (&B::stat()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (&(B::stat())) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (!&B::stat()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+
+    B b;
+    if (&b.get()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (&(b.get())) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (!&b.get()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+
+    B* b_ptr = &b;
+    if (&b_ptr->get()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (&(b_ptr->get())) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (!&b_ptr->get()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+
+    int& (B::*m_ptr)() = &B::get;
+    if (&(b.*m_ptr)()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (&((b.*m_ptr)())) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (!&(b.*m_ptr)()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+
+    int& (*f_ptr)() = &get_int;
+    if (&(*f_ptr)()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (&((*f_ptr)())) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+    if (!&(*f_ptr)()) {}
+    // expected-warning at -1{{reference cannot be bound to dereferenced null pointer in well-defined C++ code; pointer may be assumed to always convert to true}}
+  }
+}





More information about the cfe-commits mailing list