courbet created this revision.
Herald added subscribers: cfe-commits, xazax.hun.

Context: https://twitter.com/willkirkby/status/1084219580799741953


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D56657

Files:
  clang-tidy/bugprone/StringConstructorCheck.cpp
  test/clang-tidy/bugprone-string-constructor.cpp


Index: test/clang-tidy/bugprone-string-constructor.cpp
===================================================================
--- test/clang-tidy/bugprone-string-constructor.cpp
+++ test/clang-tidy/bugprone-string-constructor.cpp
@@ -9,6 +9,7 @@
 struct basic_string {
   basic_string();
   basic_string(const C*, unsigned int size);
+  basic_string(const C*, const A& allocator = A());
   basic_string(unsigned int size, C c);
 };
 typedef basic_string<char> string;
@@ -45,6 +46,13 @@
   // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger then string 
literal size
   std::string q5(kText3,  0x1000000);
   // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+  std::string q6(nullptr);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructing string from nullptr 
is undefined behaviour
+}
+
+std::string StringFromZero() {
+  return 0;
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: constructing string from nullptr 
is undefined behaviour
 }
 
 void Valid() {
@@ -53,4 +61,5 @@
   std::wstring wstr(4, L'x');
   std::string s1("test", 4);
   std::string s2("test", 3);
+  std::string s3("test");
 }
Index: clang-tidy/bugprone/StringConstructorCheck.cpp
===================================================================
--- clang-tidy/bugprone/StringConstructorCheck.cpp
+++ clang-tidy/bugprone/StringConstructorCheck.cpp
@@ -100,6 +100,17 @@
                                        integerLiteral().bind("int"))))))
           .bind("constructor"),
       this);
+
+  // Check the literal string constructor with char pointer.
+  // [i.e. string (const char* s);]
+  Finder->addMatcher(
+      cxxConstructExpr(
+          hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
+          //hasArgument(0, hasType(CharPtrType)),
+          hasArgument(0, expr().bind("from-ptr")),
+          hasArgument(1, unless(hasType(isInteger()))))
+          .bind("constructor"),
+      this);
 }
 
 void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
@@ -128,6 +139,14 @@
     if (Lit->getValue().ugt(Str->getLength())) {
       diag(Loc, "length is bigger then string literal size");
     }
+  } else if (const Expr* Ptr = Result.Nodes.getNodeAs<Expr>("from-ptr")) {
+    Expr::EvalResult ConstPtr;
+    if (Ptr->EvaluateAsRValue(ConstPtr, Ctx) && (
+        (ConstPtr.Val.isInt() && ConstPtr.Val.getInt().isNullValue()) ||
+            (ConstPtr.Val.isLValue() && ConstPtr.Val.isNullPointer())
+      )) {
+      diag(Loc, "constructing string from nullptr is undefined behaviour");
+    }
   }
 }
 


Index: test/clang-tidy/bugprone-string-constructor.cpp
===================================================================
--- test/clang-tidy/bugprone-string-constructor.cpp
+++ test/clang-tidy/bugprone-string-constructor.cpp
@@ -9,6 +9,7 @@
 struct basic_string {
   basic_string();
   basic_string(const C*, unsigned int size);
+  basic_string(const C*, const A& allocator = A());
   basic_string(unsigned int size, C c);
 };
 typedef basic_string<char> string;
@@ -45,6 +46,13 @@
   // CHECK-MESSAGES: [[@LINE-1]]:15: warning: length is bigger then string literal size
   std::string q5(kText3,  0x1000000);
   // CHECK-MESSAGES: [[@LINE-1]]:15: warning: suspicious large length parameter
+  std::string q6(nullptr);
+  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: constructing string from nullptr is undefined behaviour
+}
+
+std::string StringFromZero() {
+  return 0;
+  // CHECK-MESSAGES: [[@LINE-1]]:10: warning: constructing string from nullptr is undefined behaviour
 }
 
 void Valid() {
@@ -53,4 +61,5 @@
   std::wstring wstr(4, L'x');
   std::string s1("test", 4);
   std::string s2("test", 3);
+  std::string s3("test");
 }
Index: clang-tidy/bugprone/StringConstructorCheck.cpp
===================================================================
--- clang-tidy/bugprone/StringConstructorCheck.cpp
+++ clang-tidy/bugprone/StringConstructorCheck.cpp
@@ -100,6 +100,17 @@
                                        integerLiteral().bind("int"))))))
           .bind("constructor"),
       this);
+
+  // Check the literal string constructor with char pointer.
+  // [i.e. string (const char* s);]
+  Finder->addMatcher(
+      cxxConstructExpr(
+          hasDeclaration(cxxMethodDecl(hasName("basic_string"))),
+          //hasArgument(0, hasType(CharPtrType)),
+          hasArgument(0, expr().bind("from-ptr")),
+          hasArgument(1, unless(hasType(isInteger()))))
+          .bind("constructor"),
+      this);
 }
 
 void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) {
@@ -128,6 +139,14 @@
     if (Lit->getValue().ugt(Str->getLength())) {
       diag(Loc, "length is bigger then string literal size");
     }
+  } else if (const Expr* Ptr = Result.Nodes.getNodeAs<Expr>("from-ptr")) {
+    Expr::EvalResult ConstPtr;
+    if (Ptr->EvaluateAsRValue(ConstPtr, Ctx) && (
+        (ConstPtr.Val.isInt() && ConstPtr.Val.getInt().isNullValue()) ||
+            (ConstPtr.Val.isLValue() && ConstPtr.Val.isNullPointer())
+      )) {
+      diag(Loc, "constructing string from nullptr is undefined behaviour");
+    }
   }
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to