Szelethus created this revision.
Szelethus added reviewers: george.karpenkov, NoQ, xazax.hun, MTC.
Herald added subscribers: cfe-commits, dkrupp, donat.nagy, mikhail.ramalho, 
a.sidorin, rnkovacs, szepet, whisperity.

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.


Repository:
  rC Clang

https://reviews.llvm.org/D53856

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp
  test/Analysis/llvm-conventions.cpp

Index: test/Analysis/llvm-conventions.cpp
===================================================================
--- /dev/null
+++ test/Analysis/llvm-conventions.cpp
@@ -0,0 +1,271 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.llvm.Conventions \
+// RUN:   -std=c++14 -verify  %s
+
+//===----------------------------------------------------------------------===//
+// Forward declarations for StringRef tests.
+//===----------------------------------------------------------------------===//
+
+using size_t = unsigned long;
+using size_type = size_t;
+
+namespace std {
+
+using nullptr_t = decltype(nullptr);
+
+template <class T1, class T2>
+struct pair { T1 first; T2 second; };
+
+template<bool B, class T = void>
+struct enable_if {};
+
+template<class T>
+struct enable_if<true, T> { typedef T type; };
+
+template<class T, class U>
+struct is_same { const static bool value; };
+
+template <class T>
+struct numeric_limits { const static bool is_signed; };
+
+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;
+
+} // 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.
+    Ref = std::string("This is a fine string.");
+  }
+}
+
+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: 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