]> granicus.if.org Git - clang/commitdiff
[analyzer] Put llvm.Conventions back in alpha
authorKristof Umann <dkszelethus@gmail.com>
Fri, 2 Nov 2018 16:02:10 +0000 (16:02 +0000)
committerKristof Umann <dkszelethus@gmail.com>
Fri, 2 Nov 2018 16:02:10 +0000 (16:02 +0000)
Interestingly, this many year old (when I last looked I remember 2010ish)
checker was committed without any tests, so I thought I'd implement them, but I
was shocked to see how I barely managed to get it working. The code is severely
outdated, I'm not even sure it has ever been used, so I'd propose to move it
back into alpha, and possibly even remove it.

Differential Revision: https://reviews.llvm.org/D53856

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@345990 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Checkers/Checkers.td
lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
test/Analysis/Inputs/system-header-simulator-cxx.h
test/Analysis/diagnostics/explicit-suppression.cpp
test/Analysis/inner-pointer.cpp
test/Analysis/llvm-conventions.cpp [new file with mode: 0644]
test/Analysis/temporaries.cpp
www/analyzer/alpha_checks.html

index 0b50aca495b4f6e7b00f9d2b93d8c77fe4f3277c..224dfc763d9a2ebaac9a93350a543c114cc13e47 100644 (file)
@@ -83,6 +83,7 @@ def LocalizabilityOptIn : Package<"localizability">, InPackage<CocoaOptIn>;
 def MPI : Package<"mpi">, InPackage<OptIn>;
 
 def LLVM : Package<"llvm">;
+def LLVMAlpha : Package<"llvm">, InPackage<Alpha>, Hidden;
 
 // The APIModeling package is for checkers that model APIs and don't perform
 // any diagnostics. These checkers are always turned on; this package is
@@ -730,7 +731,7 @@ let ParentPackage = MPI in {
 //===----------------------------------------------------------------------===//
 
 def LLVMConventionsChecker : Checker<"Conventions">,
-  InPackage<LLVM>,
+  InPackage<LLVMAlpha>,
   HelpText<"Check code for LLVM codebase conventions">,
   DescFile<"LLVMConventionsChecker.cpp">;
 
index db4fbca36deb8505d54be6a8c82f692e6b65ce7d..18618d04598912785d300c273bc7f146626c5878 100644 (file)
@@ -32,8 +32,7 @@ static bool IsLLVMStringRef(QualType T) {
   if (!RT)
     return false;
 
-  return StringRef(QualType(RT, 0).getAsString()) ==
-          "class StringRef";
+  return StringRef(QualType(RT, 0).getAsString()) == "class StringRef";
 }
 
 /// Check whether the declaration is semantically inside the top-level
index ccd54cf3b28970a0afe8a962a2152d4a13cd8b0c..66ead1c05ce05a23ea02bd9a0149dbf1a478a5d4 100644 (file)
@@ -11,6 +11,13 @@ typedef __typeof__(sizeof(int)) size_t;
 typedef __typeof__((char*)0-(char*)0) ptrdiff_t;
 void *memmove(void *s1, const void *s2, size_t n);
 
+namespace std {
+  typedef size_t size_type;
+#if __cplusplus >= 201103L
+  using nullptr_t = decltype(nullptr);
+#endif
+}
+
 namespace std {
   struct input_iterator_tag { };
   struct output_iterator_tag { };
@@ -517,6 +524,42 @@ namespace std {
     const T& front() const { return *begin(); }
   };
 
+  template <typename CharT>
+  class basic_string {
+  public:
+    basic_string();
+    basic_string(const CharT *s);
+
+    ~basic_string();
+    void clear();
+
+    basic_string &operator=(const basic_string &str);
+    basic_string &operator+=(const basic_string &str);
+
+    const CharT *c_str() const;
+    const CharT *data() const;
+    CharT *data();
+
+    basic_string &append(size_type count, CharT ch);
+    basic_string &assign(size_type count, CharT ch);
+    basic_string &erase(size_type index, size_type count);
+    basic_string &insert(size_type index, size_type count, CharT ch);
+    basic_string &replace(size_type pos, size_type count, const basic_string &str);
+    void pop_back();
+    void push_back(CharT ch);
+    void reserve(size_type new_cap);
+    void resize(size_type count);
+    void shrink_to_fit();
+    void swap(basic_string &other);
+  };
+
+  typedef basic_string<char> string;
+  typedef basic_string<wchar_t> wstring;
+#if __cplusplus >= 201103L
+  typedef basic_string<char16_t> u16string;
+  typedef basic_string<char32_t> u32string;
+#endif
+
   class exception {
   public:
     exception() throw();
index 50d24fd53f899b2828dadfc9491ccd42306798af..a80d680140a02a472b6a0efd1a77ce7a1581a4c5 100644 (file)
@@ -19,6 +19,6 @@ class C {
 void testCopyNull(C *I, C *E) {
   std::copy(I, E, (C *)0);
 #ifndef SUPPRESSED
-  // expected-warning@../Inputs/system-header-simulator-cxx.h:627 {{Called C++ object pointer is null}}
+  // expected-warning@../Inputs/system-header-simulator-cxx.h:668 {{Called C++ object pointer is null}}
 #endif
 }
index 25d7069ed346cca22428a8658deb905f6437632a..81b750d7e5dd3ac6d069a43e9ca44128fe6ba104 100644 (file)
@@ -1,43 +1,9 @@
-//RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer %s -analyzer-output=text -verify
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer \
+// RUN:   %s -analyzer-output=text -verify
 
+#include "Inputs/system-header-simulator-cxx.h"
 namespace std {
 
-typedef int size_type;
-
-template <typename CharT>
-class basic_string {
-public:
-  basic_string();
-  basic_string(const CharT *s);
-
-  ~basic_string();
-  void clear();
-
-  basic_string &operator=(const basic_string &str);
-  basic_string &operator+=(const basic_string &str);
-
-  const CharT *c_str() const;
-  const CharT *data() const;
-  CharT *data();
-
-  basic_string &append(size_type count, CharT ch);
-  basic_string &assign(size_type count, CharT ch);
-  basic_string &erase(size_type index, size_type count);
-  basic_string &insert(size_type index, size_type count, CharT ch);
-  basic_string &replace(size_type pos, size_type count, const basic_string &str);
-  void pop_back();
-  void push_back(CharT ch);
-  void reserve(size_type new_cap);
-  void resize(size_type count);
-  void shrink_to_fit();
-  void swap(basic_string &other);
-};
-
-typedef basic_string<char> string;
-typedef basic_string<wchar_t> wstring;
-typedef basic_string<char16_t> u16string;
-typedef basic_string<char32_t> u32string;
-
 template <typename T>
 void func_ref(T &a);
 
diff --git a/test/Analysis/llvm-conventions.cpp b/test/Analysis/llvm-conventions.cpp
new file mode 100644 (file)
index 0000000..a0431fb
--- /dev/null
@@ -0,0 +1,226 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.llvm.Conventions \
+// RUN:   -std=c++14 -verify  %s
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+//===----------------------------------------------------------------------===//
+// Forward declarations for StringRef tests.
+//===----------------------------------------------------------------------===//
+
+using size_t = unsigned long;
+using size_type = size_t;
+
+namespace std {
+
+template <class T>
+struct numeric_limits { const static bool is_signed; };
+
+} // end of namespace std
+
+namespace llvm {
+
+template <class T>
+struct iterator_range;
+
+template <class Func>
+struct function_ref;
+
+struct hash_code;
+
+template <class T>
+struct SmallVectorImpl;
+
+struct APInt;
+
+class StringRef {
+public:
+  static const size_t npos = ~size_t(0);
+  using iterator = const char *;
+  using const_iterator = const char *;
+  using size_type = size_t;
+
+  /*implicit*/ StringRef() = default;
+  StringRef(std::nullptr_t) = delete;
+  /*implicit*/ StringRef(const char *Str);
+  /*implicit*/ constexpr StringRef(const char *data, size_t length);
+  /*implicit*/ StringRef(const std::string &Str);
+
+  static StringRef withNullAsEmpty(const char *data);
+  iterator begin() const;
+  iterator end() const;
+  const unsigned char *bytes_begin() const;
+  const unsigned char *bytes_end() const;
+  iterator_range<const unsigned char *> bytes() const;
+  const char *data() const;
+  bool empty() const;
+  size_t size() const;
+  char front() const;
+  char back() const;
+  template <typename Allocator>
+  StringRef copy(Allocator &A) const;
+  bool equals(StringRef RHS) const;
+  bool equals_lower(StringRef RHS) const;
+  int compare(StringRef RHS) const;
+  int compare_lower(StringRef RHS) const;
+  int compare_numeric(StringRef RHS) const;
+  unsigned edit_distance(StringRef Other, bool AllowReplacements = true,
+                         unsigned MaxEditDistance = 0) const;
+  std::string str() const;
+  char operator[](size_t Index) const;
+  template <typename T>
+  typename std::enable_if<std::is_same<T, std::string>::value,
+                          StringRef>::type &
+  operator=(T &&Str) = delete;
+  operator std::string() const;
+  bool startswith(StringRef Prefix) const;
+  bool startswith_lower(StringRef Prefix) const;
+  bool endswith(StringRef Suffix) const;
+  bool endswith_lower(StringRef Suffix) const;
+  size_t find(char C, size_t From = 0) const;
+  size_t find_lower(char C, size_t From = 0) const;
+  size_t find_if(function_ref<bool(char)> F, size_t From = 0) const;
+  size_t find_if_not(function_ref<bool(char)> F, size_t From = 0) const;
+  size_t find(StringRef Str, size_t From = 0) const;
+  size_t find_lower(StringRef Str, size_t From = 0) const;
+  size_t rfind(char C, size_t From = npos) const;
+  size_t rfind_lower(char C, size_t From = npos) const;
+  size_t rfind(StringRef Str) const;
+  size_t rfind_lower(StringRef Str) const;
+  size_t find_first_of(char C, size_t From = 0) const;
+  size_t find_first_of(StringRef Chars, size_t From = 0) const;
+  size_t find_first_not_of(char C, size_t From = 0) const;
+  size_t find_first_not_of(StringRef Chars, size_t From = 0) const;
+  size_t find_last_of(char C, size_t From = npos) const;
+  size_t find_last_of(StringRef Chars, size_t From = npos) const;
+  size_t find_last_not_of(char C, size_t From = npos) const;
+  size_t find_last_not_of(StringRef Chars, size_t From = npos) const;
+  bool contains(StringRef Other) const;
+  bool contains(char C) const;
+  bool contains_lower(StringRef Other) const;
+  bool contains_lower(char C) const;
+  size_t count(char C) const;
+  size_t count(StringRef Str) const;
+  template <typename T>
+  typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
+  getAsInteger(unsigned Radix, T &Result) const;
+  template <typename T>
+  typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
+  getAsInteger(unsigned Radix, T &Result) const;
+  template <typename T>
+  typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type
+  consumeInteger(unsigned Radix, T &Result);
+  template <typename T>
+  typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type
+  consumeInteger(unsigned Radix, T &Result);
+  bool getAsInteger(unsigned Radix, APInt &Result) const;
+  bool getAsDouble(double &Result, bool AllowInexact = true) const;
+  std::string lower() const;
+  std::string upper() const;
+  StringRef substr(size_t Start, size_t N = npos) const;
+  StringRef take_front(size_t N = 1) const;
+  StringRef take_back(size_t N = 1) const;
+  StringRef take_while(function_ref<bool(char)> F) const;
+  StringRef take_until(function_ref<bool(char)> F) const;
+  StringRef drop_front(size_t N = 1) const;
+  StringRef drop_back(size_t N = 1) const;
+  StringRef drop_while(function_ref<bool(char)> F) const;
+  StringRef drop_until(function_ref<bool(char)> F) const;
+  bool consume_front(StringRef Prefix);
+  bool consume_back(StringRef Suffix);
+  StringRef slice(size_t Start, size_t End) const;
+  std::pair<StringRef, StringRef> split(char Separator) const;
+  std::pair<StringRef, StringRef> split(StringRef Separator) const;
+  std::pair<StringRef, StringRef> rsplit(StringRef Separator) const;
+  void split(SmallVectorImpl<StringRef> &A,
+             StringRef Separator, int MaxSplit = -1,
+             bool KeepEmpty = true) const;
+  void split(SmallVectorImpl<StringRef> &A, char Separator, int MaxSplit = -1,
+             bool KeepEmpty = true) const;
+  std::pair<StringRef, StringRef> rsplit(char Separator) const;
+  StringRef ltrim(char Char) const;
+  StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const;
+  StringRef rtrim(char Char) const;
+  StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const;
+  StringRef trim(char Char) const;
+  StringRef trim(StringRef Chars = " \t\n\v\f\r") const;
+};
+
+inline bool operator==(StringRef LHS, StringRef RHS);
+inline bool operator!=(StringRef LHS, StringRef RHS);
+inline bool operator<(StringRef LHS, StringRef RHS);
+inline bool operator<=(StringRef LHS, StringRef RHS);
+inline bool operator>(StringRef LHS, StringRef RHS);
+inline bool operator>=(StringRef LHS, StringRef RHS);
+inline std::string &operator+=(std::string &buffer, StringRef string);
+hash_code hash_value(StringRef S);
+template <typename T> struct isPodLike;
+template <> struct isPodLike<StringRef> { static const bool value = true; };
+
+} // end of namespace llvm
+
+//===----------------------------------------------------------------------===//
+// Tests for StringRef.
+//===----------------------------------------------------------------------===//
+
+void temporarayStringToStringRefAssignmentTest() {
+  // TODO: Emit a warning.
+  llvm::StringRef Ref = std::string("Yimmy yummy test.");
+}
+
+void assigningStringToStringRefWithLongerLifetimeTest() {
+  llvm::StringRef Ref;
+  {
+    // TODO: Emit a warning.
+    std::string TmpStr("This is a fine string.");
+    Ref = TmpStr;
+  }
+}
+
+std::string getTemporaryString() {
+  return "One two three.";
+}
+
+void assigningTempStringFromFunctionToStringRefTest() {
+  // TODO: Emit a warning.
+  llvm::StringRef Ref = getTemporaryString();
+}
+
+//===----------------------------------------------------------------------===//
+// Forward declaration for Clang AST nodes.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+
+template <class T, int Size>
+struct SmallVector {};
+
+} // end of namespace llvm
+
+namespace clang {
+
+struct Type;
+struct Decl;
+struct Stmt;
+struct Attr;
+
+} // end of namespace clang
+
+//===----------------------------------------------------------------------===//
+// Tests for Clang AST nodes.
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+
+struct Type {
+  std::string str; // expected-warning{{AST class 'Type' has a field 'str' that allocates heap memory (type std::string)}}
+};
+
+} // end of namespace clang
+
+namespace clang {
+
+struct Decl {
+  llvm::SmallVector<int, 5> Vec; // expected-warning{{AST class 'Decl' has a field 'Vec' that allocates heap memory (type llvm::SmallVector<int, 5>)}}
+};
+
+} // end of namespace clang
index 4a0a9f194cc097cd763357c0022b53e57356edb3..7a6b8b040919a9155d8600ba954024a8b9608205 100644 (file)
@@ -9,7 +9,7 @@ extern bool clang_analyzer_eval(bool);
 extern bool clang_analyzer_warnIfReached();
 void clang_analyzer_checkInlined(bool);
 
-#include "Inputs/system-header-simulator-cxx.h";
+#include "Inputs/system-header-simulator-cxx.h"
 
 struct Trivial {
   Trivial(int x) : value(x) {}
index d6aaa02a8e117d81691c1dd51d8a21feb6affe18..3f429b50680b6b0be5647fdce76a1d408128a408 100644 (file)
@@ -27,6 +27,7 @@ Patches welcome!
 <li><a href="#clone_alpha_checkers">Clone Alpha Checkers</a></li>
 <li><a href="#core_alpha_checkers">Core Alpha Checkers</a></li>
 <li><a href="#cplusplus_alpha_checkers">C++ Alpha Checkers</a></li>
+<li><a href="#llvm_alpha_checkers">LLVM Checkers</a></li>
 <li><a href="#valist_alpha_checkers">Variable Argument Alpha Checkers</a></li>
 <li><a href="#deadcode_alpha_checkers">Dead Code Alpha Checkers</a></li>
 <li><a href="#osx_alpha_checkers">OS X Alpha Checkers</a></li>
@@ -583,6 +584,31 @@ void test(id x) {
 </pre></div></div></td></tr>
 </tbody></table>
 
+<!-- =========================== llvm alpha =========================== -->
+<h3 id="llvm_alpha_checkers">LLVM Checkers</h3>
+<table class="checkers">
+<colgroup><col class="namedescr"><col class="example"></colgroup>
+<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
+
+<tbody>
+<tr><td><div class="namedescr expandable"><span class="name">
+alpha.llvm.Conventions</span><span class="lang">
+(C)</span><div class="descr">
+Check code for LLVM codebase conventions:
+<ul>
+  <li>A <code>StringRef</code> should not be bound to a temporary std::string
+  whose lifetime is shorter than the <code>StringRef</code>'s.</li>
+  <li>Clang AST nodes should not have fields that can allocate memory.</li>
+</ul>
+</div></div></td>
+<td><div class="exampleContainer expandable">
+<div class="example"><pre>
+<!-- TODO: Add examples, as currently it's hard to get this checker working. -->
+</pre></div></div></td></tr>
+
+</tbody></table>
+
+
 <!-- ============================== OS X alpha ============================== -->
 <h3 id="osx_alpha_checkers">OS X Alpha Checkers</h3>
 <table class="checkers">