Szelethus updated this revision to Diff 172253.
Szelethus added a comment.

- Moved `std::string` implementation from `InnerPointerChecker`'s testfile to 
the system header simulator header file.


https://reviews.llvm.org/D53856

Files:
  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
  test/Analysis/temporaries.cpp
  www/analyzer/alpha_checks.html

Index: www/analyzer/alpha_checks.html
===================================================================
--- www/analyzer/alpha_checks.html
+++ www/analyzer/alpha_checks.html
@@ -27,6 +27,7 @@
 <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>
@@ -554,6 +555,31 @@
 </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">
Index: test/Analysis/temporaries.cpp
===================================================================
--- test/Analysis/temporaries.cpp
+++ test/Analysis/temporaries.cpp
@@ -9,7 +9,7 @@
 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: test/Analysis/llvm-conventions.cpp
===================================================================
--- /dev/null
+++ test/Analysis/llvm-conventions.cpp
@@ -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: test/Analysis/inner-pointer.cpp
===================================================================
--- test/Analysis/inner-pointer.cpp
+++ test/Analysis/inner-pointer.cpp
@@ -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);
 
Index: test/Analysis/diagnostics/explicit-suppression.cpp
===================================================================
--- test/Analysis/diagnostics/explicit-suppression.cpp
+++ test/Analysis/diagnostics/explicit-suppression.cpp
@@ -19,6 +19,6 @@
 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: test/Analysis/Inputs/system-header-simulator-cxx.h
===================================================================
--- test/Analysis/Inputs/system-header-simulator-cxx.h
+++ test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -11,6 +11,13 @@
 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 @@
     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: lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
+++ lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
@@ -32,8 +32,7 @@
   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: include/clang/StaticAnalyzer/Checkers/Checkers.td
===================================================================
--- include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -83,6 +83,7 @@
 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 @@
 //===----------------------------------------------------------------------===//
 
 def LLVMConventionsChecker : Checker<"Conventions">,
-  InPackage<LLVM>,
+  InPackage<LLVMAlpha>,
   HelpText<"Check code for LLVM codebase conventions">,
   DescFile<"LLVMConventionsChecker.cpp">;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to