[PATCH] D131525: [analyzer] Fix false positive in use-after-move checker

2022-08-09 Thread Malavika Samak via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc74a204826da: [analyzer] Fix false positive in 
use-after-move checker (authored by malavikasamak).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131525/new/

https://reviews.llvm.org/D131525

Files:
  clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
  clang/test/Analysis/use-after-move.cpp


Index: clang/test/Analysis/use-after-move.cpp
===
--- clang/test/Analysis/use-after-move.cpp
+++ clang/test/Analysis/use-after-move.cpp
@@ -900,6 +900,28 @@
   }
 }
 
+void checkExplicitDestructorCalls() {
+  // The below code segments invoke the destructor twice (explicit and 
+  // implicit). While this is not a desired code behavior, it is 
+  // not the use-after-move checker's responsibility to issue such a warning.
+  {
+ B* b = new B;
+ B a = std::move(*b);
+ b->~B(); // no-warning 
+ delete b;
+  }
+  {
+B a, b;
+new (&a) B(reinterpret_cast(b));
+(&b)->~B(); // no-warning
+  }
+  {
+B b;
+B a  = std::move(b);
+b.~B(); // no-warning 
+  }
+}
+
 struct MoveOnlyWithDestructor {
   MoveOnlyWithDestructor();
   ~MoveOnlyWithDestructor();
Index: clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
@@ -618,10 +618,6 @@
   if (!IC)
 return;
 
-  // Calling a destructor on a moved object is fine.
-  if (isa(IC))
-return;
-
   const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
   if (!ThisRegion)
 return;
@@ -631,6 +627,10 @@
   if (!MethodDecl)
 return;
 
+  // Calling a destructor on a moved object is fine.
+  if (isa(MethodDecl))
+return;
+
   // We want to investigate the whole object, not only sub-object of a parent
   // class in which the encountered method defined.
   ThisRegion = ThisRegion->getMostDerivedObjectRegion();


Index: clang/test/Analysis/use-after-move.cpp
===
--- clang/test/Analysis/use-after-move.cpp
+++ clang/test/Analysis/use-after-move.cpp
@@ -900,6 +900,28 @@
   }
 }
 
+void checkExplicitDestructorCalls() {
+  // The below code segments invoke the destructor twice (explicit and 
+  // implicit). While this is not a desired code behavior, it is 
+  // not the use-after-move checker's responsibility to issue such a warning.
+  {
+ B* b = new B;
+ B a = std::move(*b);
+ b->~B(); // no-warning 
+ delete b;
+  }
+  {
+B a, b;
+new (&a) B(reinterpret_cast(b));
+(&b)->~B(); // no-warning
+  }
+  {
+B b;
+B a  = std::move(b);
+b.~B(); // no-warning 
+  }
+}
+
 struct MoveOnlyWithDestructor {
   MoveOnlyWithDestructor();
   ~MoveOnlyWithDestructor();
Index: clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
@@ -618,10 +618,6 @@
   if (!IC)
 return;
 
-  // Calling a destructor on a moved object is fine.
-  if (isa(IC))
-return;
-
   const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
   if (!ThisRegion)
 return;
@@ -631,6 +627,10 @@
   if (!MethodDecl)
 return;
 
+  // Calling a destructor on a moved object is fine.
+  if (isa(MethodDecl))
+return;
+
   // We want to investigate the whole object, not only sub-object of a parent
   // class in which the encountered method defined.
   ThisRegion = ThisRegion->getMostDerivedObjectRegion();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D140062: [-Wunsafe-buffer-usage] Safe-buffers re-architecture to introduce Fixable gadgets

2023-01-06 Thread Malavika Samak via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG50d4a1f70e11: [-Wunsafe-buffer-usage] Safe-buffers 
re-architecture to introduce Fixable… (authored by malavikasamak).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Changed prior to commit:
  https://reviews.llvm.org/D140062?vs=486625&id=486952#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140062/new/

https://reviews.llvm.org/D140062

Files:
  clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
  clang/lib/Analysis/UnsafeBufferUsage.cpp

Index: clang/lib/Analysis/UnsafeBufferUsage.cpp
===
--- clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -137,9 +137,9 @@
 /// rigid AST structure that constitutes an operation on a pointer-type object.
 /// Discovery of a gadget in the code corresponds to claiming that we understand
 /// what this part of code is doing well enough to potentially improve it.
-/// Gadgets can be unsafe (immediately deserving a warning) or safe (not
-/// deserving a warning per se, but affecting our decision-making process
-/// nonetheless).
+/// Gadgets can be warning (immediately deserving a warning) or fixable (not
+/// always deserving a warning per se, but requires our attention to identify
+/// it warrants a fixit).
 class Gadget {
 public:
   enum class Kind {
@@ -156,7 +156,7 @@
 
   Kind getKind() const { return K; }
 
-  virtual bool isSafe() const = 0;
+  virtual bool isWarningGadget() const = 0;
   virtual const Stmt *getBaseStmt() const = 0;
 
   /// Returns the list of pointer-type variables on which this gadget performs
@@ -164,53 +164,55 @@
   /// of all DeclRefExprs in the gadget's AST!
   virtual DeclUseList getClaimedVarUseSites() const = 0;
 
-  /// Returns a fixit that would fix the current gadget according to
-  /// the current strategy. Returns None if the fix cannot be produced;
-  /// returns an empty list if no fixes are necessary.
-  virtual std::optional getFixits(const Strategy &) const {
-return std::nullopt;
-  }
-
   virtual ~Gadget() = default;
 
 private:
   Kind K;
 };
 
-using GadgetList = std::vector>;
 
-/// Unsafe gadgets correspond to unsafe code patterns that warrants
+/// Warning gadgets correspond to unsafe code patterns that warrants
 /// an immediate warning.
-class UnsafeGadget : public Gadget {
+class WarningGadget : public Gadget {
 public:
-  UnsafeGadget(Kind K) : Gadget(K) {}
+  WarningGadget(Kind K) : Gadget(K) {}
 
-  static bool classof(const Gadget *G) { return G->isSafe(); }
-  bool isSafe() const final { return false; }
+  static bool classof(const Gadget *G) { return G->isWarningGadget(); }
+  bool isWarningGadget() const final { return true; }
 };
 
-/// Safe gadgets correspond to code patterns that aren't unsafe but need to be
-/// properly recognized in order to emit correct warnings and fixes over unsafe
-/// gadgets. For example, if a raw pointer-type variable is replaced by
-/// a safe C++ container, every use of such variable may need to be
+/// Fixable gadgets correspond to code patterns that aren't always unsafe but need to be
+/// properly recognized in order to emit fixes. For example, if a raw pointer-type
+/// variable is replaced by a safe C++ container, every use of such variable must be
 /// carefully considered and possibly updated.
-class SafeGadget : public Gadget {
+class FixableGadget : public Gadget {
 public:
-  SafeGadget(Kind K) : Gadget(K) {}
+  FixableGadget(Kind K) : Gadget(K) {}
+
+  static bool classof(const Gadget *G) { return !G->isWarningGadget(); }
+  bool isWarningGadget() const final { return false; }
+
+  /// Returns a fixit that would fix the current gadget according to
+  /// the current strategy. Returns None if the fix cannot be produced;
+  /// returns an empty list if no fixes are necessary.
+  virtual Optional getFixits(const Strategy &) const {
+return None;
+  }
 
-  static bool classof(const Gadget *G) { return !G->isSafe(); }
-  bool isSafe() const final { return true; }
 };
 
+using FixableGadgetList = std::vector>;
+using WarningGadgetList = std::vector>;
+
 /// An increment of a pointer-type value is unsafe as it may run the pointer
 /// out of bounds.
-class IncrementGadget : public UnsafeGadget {
+class IncrementGadget : public WarningGadget {
   static constexpr const char *const OpTag = "op";
   const UnaryOperator *Op;
 
 public:
   IncrementGadget(const MatchFinder::MatchResult &Result)
-  : UnsafeGadget(Kind::Increment),
+  : WarningGadget(Kind::Increment),
 Op(Result.Nodes.getNodeAs(OpTag)) {}
 
   static bool classof(const Gadget *G) {
@@ -239,13 +241,13 @@
 
 /// A decrement of a pointer-type value is unsafe as it may run the pointer
 /// out of bounds.
-class DecrementGadget : public UnsafeGadget {
+class Decr

[PATCH] D143206: [-Wunsafe-buffer-usage] Add Fixable for simple pointer dereference

2023-03-22 Thread Malavika Samak via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGe7596a99fca6: [-Wunsafe-buffer-usage] Add Fixable for simple 
pointer dereference (authored by malavikasamak).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Changed prior to commit:
  https://reviews.llvm.org/D143206?vs=507463&id=507529#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143206/new/

https://reviews.llvm.org/D143206

Files:
  clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
  clang/lib/Analysis/UnsafeBufferUsage.cpp
  clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-deref.cpp

Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-deref.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-deref.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+void basic_dereference() {
+  int tmp;
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+  tmp = p[5];
+  int val = *p;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:14}:""
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:"[0]"
+}
+
+int return_method() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+  int tmp = p[5];
+  return *p;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:11}:""
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"[0]"
+}
+
+void foo(int v) {
+}
+
+void method_invocation() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+
+  int tmp = p[5];
+
+  foo(*p);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:8}:""
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:9-[[@LINE-2]]:9}:"[0]"
+}
+
+void binary_operation() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+
+  int tmp = p[5];
+
+  int k = *p + 20;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:12}:""
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"[0]"
+
+}
+
Index: clang/lib/Analysis/UnsafeBufferUsage.cpp
===
--- clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -463,6 +463,45 @@
 return {};
   }
 };
+
+class PointerDereferenceGadget : public FixableGadget {
+  static constexpr const char *const BaseDeclRefExprTag = "BaseDRE";
+  static constexpr const char *const OperatorTag = "op";
+
+  const DeclRefExpr *BaseDeclRefExpr = nullptr;
+  const UnaryOperator *Op = nullptr;
+
+public:
+  PointerDereferenceGadget(const MatchFinder::MatchResult &Result)
+  : FixableGadget(Kind::PointerDereference),
+BaseDeclRefExpr(
+Result.Nodes.getNodeAs(BaseDeclRefExprTag)),
+Op(Result.Nodes.getNodeAs(OperatorTag)) {}
+
+  static bool classof(const Gadget *G) {
+return G->getKind() == Kind::PointerDereference;
+  }
+
+  static Matcher matcher() {
+auto Target =
+unaryOperator(
+hasOperatorName("*"),
+has(expr(ignoringParenImpCasts(
+declRefExpr(to(varDecl())).bind(BaseDeclRefExprTag)
+.bind(OperatorTag);
+
+return expr(isInUnspecifiedLvalueContext(Target));
+  }
+
+  DeclUseList getClaimedVarUseSites() const override {
+return {BaseDeclRefExpr};
+  }
+
+  virtual const Stmt *getBaseStmt() const final { return Op; }
+
+  virtual std::optional getFixits(const Strategy &S) const override;
+};
+
 } // namespace
 
 namespace {
@@ -914,6 +953,37 @@
   return std::nullopt; // something wrong or unsupported, give up
 }
 
+std::optional
+PointerDereferenceGadget::getFixits(const Strategy &S) const {
+  const VarDecl *VD = cast(BaseDeclRefExpr->getDecl());
+  switch (S.lookup(VD)) {
+  case Strategy::Kind::Span: {
+ASTContext &Ctx = VD->getASTContext();
+SourceManager &SM = Ctx.getSourceManager();
+// Required changes: *(ptr); => (ptr[0]); and *ptr; => ptr[0]
+// Deletes the *operand
+CharSourceRange derefRange = clang::CharSourceRange::getCharRange(
+Op->getB

[PATCH] D143128: [-Wunsafe-buffer-usage] Fix-Its transforming `&DRE[any]` to `(DRE.data() + any)`

2023-03-24 Thread Malavika Samak via Phabricator via cfe-commits
malavikasamak added inline comments.



Comment at: clang/lib/Analysis/UnsafeBufferUsage.cpp:1096
+  } else {
+SS << "&" << getExprText(DRE, SM, LangOpts).str() << ".data()"
+   << "[" << getExprText(Idx, SM, LangOpts).str() << "]";

The title and summary of this patch indicates this gadget emits fixit of the 
form  &DRE.data() + any when it encounters &DRE[any], but the code seems to 
emits &DRE.data()[any] instead? If yes, can you please update the summary?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143128/new/

https://reviews.llvm.org/D143128

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144064: [-Wunsafe-buffer-usage] Match unsafe pointers being casted to bool or participating in pointer subtractions

2023-03-08 Thread Malavika Samak via Phabricator via cfe-commits
malavikasamak added inline comments.



Comment at: clang/lib/Analysis/UnsafeBufferUsage.cpp:156
+  // 2. the operand of a cast-to-(Integer or Boolean) operation; or
+  // 3. the operand of a pointer subtraction operation; or
+  // 4. the operand of a pointer comparison operation; or

I don't understand why we are special handling only pointer subtraction here. 
Won't pointer addition be also considered UPC? If so, can we just add it to 
this patch.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144064/new/

https://reviews.llvm.org/D144064

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144064: [-Wunsafe-buffer-usage] Match unsafe pointers being casted to bool or participating in pointer subtractions

2023-03-08 Thread Malavika Samak via Phabricator via cfe-commits
malavikasamak added inline comments.



Comment at: clang/lib/Analysis/UnsafeBufferUsage.cpp:156
+  // 2. the operand of a cast-to-(Integer or Boolean) operation; or
+  // 3. the operand of a pointer subtraction operation; or
+  // 4. the operand of a pointer comparison operation; or

malavikasamak wrote:
> I don't understand why we are special handling only pointer subtraction here. 
> Won't pointer addition be also considered UPC? If so, can we just add it to 
> this patch.
Never mind. It looks like pointer addition is not even legal and subtraction is 
a special case. 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144064/new/

https://reviews.llvm.org/D144064

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143676: [-Wunsafe-buffer-usage] FixableGadget for handling stand alone pointers under UPC.

2023-04-07 Thread Malavika Samak via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa046d1877201: [-Wunsafe-buffer-usage] FixableGadget for 
handling stand alone pointers under… (authored by malavikasamak).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Changed prior to commit:
  https://reviews.llvm.org/D143676?vs=507918&id=511810#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143676/new/

https://reviews.llvm.org/D143676

Files:
  clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
  clang/lib/Analysis/UnsafeBufferUsage.cpp
  clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp

Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
@@ -0,0 +1,110 @@
+// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+void foo(int* v) {
+}
+
+void m1(int* v1, int* v2, int) {
+
+}
+
+void condition_check_nullptr() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+
+  int tmp = p[5];
+  if(p != nullptr) {}
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
+}
+
+void condition_check() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+
+  auto q = new int[10];
+
+  int tmp = p[5];
+  if(p == q) {}
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
+
+  if(q != p){}
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:12-[[@LINE-1]]:12}:".data()"
+
+  if(p < q) {}
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
+
+  if(p <= q) {}
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
+
+  if(p > q) {}
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
+
+  if(p >= q) {}
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
+
+  if( p == q && p != nullptr) {}
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:8-[[@LINE-1]]:8}:".data()"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:18-[[@LINE-2]]:18}:".data()"
+}
+
+void condition_check_two_usafe_buffers() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+
+  auto q = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span q"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+
+  int tmp = p[5];
+  tmp = q[5];
+
+  if(p == q) {}
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:".data()"
+}
+
+void unsafe_method_invocation_single_param() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+
+  int tmp = p[5];
+  foo(p);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:8-[[@LINE-1]]:8}:".data()"
+
+}
+
+void safe_method_invocation_single_param() {
+  auto p = new int[10];
+  foo(p);
+}
+
+void unsafe_method_invocation_double_param() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+
+  int tmp = p[5];
+  m1(p, p, 10);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:10-[[@LINE-2]]:10}:".data()"
+
+  auto q = new int[10];
+
+  m1(p, q, 4);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:".data()"
+
+  m1(q, p, 9);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:10}:".data()"
+
+  m1(q, q, 8);
+}
+
Index: clang/lib/Analysis/UnsafeBufferUsage.cpp
===
--- clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -165,17 +165,22 @@
   // 1. an argument of a function call (except the callee has [[unsafe_...]]
   // attribute), or
   // 2. the operand of a cast operation; or
-  // ...
+  // 3. the operand of

[PATCH] D144905: [-Wunsafe-buffer-usage] Handle unevaluated contexts that contain unsafe buffer usages

2023-04-19 Thread Malavika Samak via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG777eb4bcfc32: [-Wunsafe-buffer-usage] Handle unevaluated 
contexts that contain unsafe buffer… (authored by malavikasamak).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Changed prior to commit:
  https://reviews.llvm.org/D144905?vs=515094&id=515114#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144905/new/

https://reviews.llvm.org/D144905

Files:
  clang/lib/Analysis/UnsafeBufferUsage.cpp
  clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-unevaluated-context.cpp
  clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-unevaluated-context.cpp
  clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp

Index: clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
===
--- clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp
@@ -102,12 +102,6 @@
   foo(ap4[1]);// expected-note{{used in buffer access here}}
 }
 
-//TODO: do not warn for unevaluated context
-void testUnevaluatedContext(int * p) {// expected-warning{{'p' is an unsafe pointer used for buffer access}}
-  foo(sizeof(p[1]), // expected-note{{used in buffer access here}}
-  sizeof(decltype(p[1])));  // expected-note{{used in buffer access here}}
-}
-
 void testQualifiedParameters(const int * p, const int * const q, const int a[10], const int b[10][10]) {
   // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
   // expected-warning@-2{{'q' is an unsafe pointer used for buffer access}}
Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-unevaluated-context.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-warning-unevaluated-context.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage -fblocks -include %s -verify %s
+
+// RUN: %clang -x c++ -fsyntax-only -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s
+// RUN: %clang_cc1 -std=c++11 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s
+// RUN: %clang_cc1 -std=c++20 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s
+// CHECK-NOT: [-Wunsafe-buffer-usage]
+
+#ifndef INCLUDED
+#define INCLUDED
+#pragma clang system_header
+
+// no spanification warnings for system headers
+void foo(...);  // let arguments of `foo` to hold testing expressions
+#else
+
+namespace std {
+  class type_info;
+  class bad_cast;
+  class bad_typeid;
+}
+using size_t = __typeof(sizeof(int));
+void *malloc(size_t);
+
+void foo(int v) {
+}
+
+void foo(int *p){}
+
+void uneval_context_fix() {
+  auto p = new int[10]; // expected-warning{{'p' is an unsafe pointer used for buffer access}}
+
+  // Warn on the following DREs
+  _Generic(1, int: p[2], float: 3); // expected-note{{used in buffer access here}}
+
+  // Do not warn for following DREs
+  auto q = new int[10];
+  foo(sizeof(q[1]), // no-note
+  sizeof(decltype(q[1]))); // no-note
+  __typeof(q[5]) x; // no-note
+  int *r = (int *)malloc(sizeof(q[5])); // no-note
+  int y = sizeof(q[5]); // no-note
+  __is_pod(__typeof(q[5])); // no-note
+  __is_trivially_constructible(__typeof(q[5]), decltype(q[5])); // no-note
+  _Generic(q[1], int: 2, float: 3); // no-note
+  _Generic(1, int: 2, float: q[3]); // no-note
+  decltype(q[2]) var = y; // no-note
+  noexcept(q[2]); // no-note
+  typeid(q[3]); // no-note
+}
+#endif
Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-unevaluated-context.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-unevaluated-context.cpp
@@ -0,0 +1,79 @@
+// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits -fsyntax-only %s 2>&1 | FileCheck %s
+
+namespace std {
+  class type_info;
+  class bad_cast;
+  class bad_typeid;
+}
+using size_t = __typeof(sizeof(int));
+void *malloc(size_t);
+
+void foo(...);
+int bar(int *ptr);
+
+void uneval_context_fix_pointer_dereference() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+
+  int tmp = p[5];
+  typeid(foo(*p));
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:14-[[@LINE-1]]:15}:""
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"[0]"
+  _Generic(*p, int: 2, float: 3);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:12-[[@LINE-1]]:13}:""
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:14-[[@LINE-2]]:14}:"[0]" 
+}
+
+void uneval_context_fix_pointer_array_access() {
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-i

[PATCH] D146450: [-Wunsafe-buffer-usage] Bug fix: Handles the assertion violations for code within macros.

2023-04-24 Thread Malavika Samak via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9bd0db80784e: [-Wunsafe-buffer-usage] Bug fix: Handles the 
assertion violations for code… (authored by malavikasamak).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D146450/new/

https://reviews.llvm.org/D146450

Files:
  clang/lib/Analysis/UnsafeBufferUsage.cpp
  clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp

Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp
===
--- clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp
+++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-local-var-span.cpp
@@ -2,6 +2,8 @@
 typedef int * Int_ptr_t;
 typedef int Int_t;
 
+#define DEFINE_PTR(X) int* ptr = (X);
+
 void local_array_subscript_simple() {
   int tmp;
   int *p = new int[10];
@@ -222,3 +224,28 @@
   tmp = r[j] + r[k]; // both `j` and `k` are unsigned so they must be non-negative
   tmp = r[(unsigned int)-1]; // a cast-to-unsigned-expression is also non-negative
 }
+
+void all_vars_in_macro() {
+  int* local;
+  DEFINE_PTR(local)
+  ptr[1] = 0;
+}
+
+void few_vars_in_macro() {
+  int* local;
+  DEFINE_PTR(local)
+  ptr[1] = 0;
+  int tmp;
+  ptr[2] = 30;
+  auto p = new int[10];
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span p"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:12-[[@LINE-2]]:12}:"{"
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:23-[[@LINE-3]]:23}:", 10}"
+  tmp = p[5];
+  int val = *p;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:14}:""
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:"[0]"
+  val = *p + 30;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:10}:""
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:11}:"[0]"
+}
Index: clang/lib/Analysis/UnsafeBufferUsage.cpp
===
--- clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -1117,42 +1117,44 @@
 
 // Return the source location of the last character of the AST `Node`.
 template 
-static SourceLocation getEndCharLoc(const NodeTy *Node, const SourceManager &SM,
-const LangOptions &LangOpts) {
+static std::optional
+getEndCharLoc(const NodeTy *Node, const SourceManager &SM,
+  const LangOptions &LangOpts) {
   unsigned TkLen = Lexer::MeasureTokenLength(Node->getEndLoc(), SM, LangOpts);
   SourceLocation Loc = Node->getEndLoc().getLocWithOffset(TkLen - 1);
 
-  // We expect `Loc` to be valid. The location is obtained by moving forward
-  // from the beginning of the token 'len(token)-1' characters. The file ID of
-  // the locations within a token must be consistent.
-  assert(Loc.isValid() && "Expected the source location of the last"
-  "character of an AST Node to be always valid");
-  return Loc;
+  if (Loc.isValid())
+return Loc;
+
+  return std::nullopt;
 }
 
 // Return the source location just past the last character of the AST `Node`.
 template 
-static SourceLocation getPastLoc(const NodeTy *Node, const SourceManager &SM,
- const LangOptions &LangOpts) {
+static std::optional getPastLoc(const NodeTy *Node,
+const SourceManager &SM,
+const LangOptions &LangOpts) {
   SourceLocation Loc =
   Lexer::getLocForEndOfToken(Node->getEndLoc(), 0, SM, LangOpts);
 
-  // We expect `Loc` to be valid as it is either associated to a file ID or
-  //   it must be the end of a macro expansion. (see
-  //   `Lexer::getLocForEndOfToken`)
-  assert(Loc.isValid() && "Expected the source location just past the last "
-  "character of an AST Node to be always valid");
-  return Loc;
+  if (Loc.isValid())
+return Loc;
+
+  return std::nullopt;
 }
 
 // Return text representation of an `Expr`.
-static StringRef getExprText(const Expr *E, const SourceManager &SM,
- const LangOptions &LangOpts) {
-  SourceLocation LastCharLoc = getPastLoc(E, SM, LangOpts);
+static std::optional getExprText(const Expr *E,
+const SourceManager &SM,
+const LangOptions &LangOpts) {
+  std::optional LastCharLoc = getPastLoc(E, SM, LangOpts);
+
+  if (LastCharLoc)
+return Lexer::getSourceText(
+CharSourceRange::getCharRange(E->getBeginLoc(), *LastCharLoc), SM,
+LangOpts);
 
-  return Lexer::getSourceText(
-  CharSourceRange::getCharRange(E->getBeginLoc(), LastCharLoc), SM,
-  LangOpts);
+  return std::nullopt;
 }
 
 std::optional
@@ -1191,12 +1

[PATCH] D146773: [-Wunsafe-buffer-usage] Make raw (ungrouped) warnings a bit more verbose.

2023-04-26 Thread Malavika Samak via Phabricator via cfe-commits
malavikasamak added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:11786
+  "%select{"
+"unsafe operation on raw pointer in expression|"
+"unsafe arithmetic on raw pointer|"

NoQ wrote:
> The first mode doesn't show up in any tests and it's probably dead code at 
> this point.
What do you think of specifying the variable name in these warnings? It could 
be helpful when there are more than one DREs in a statement.  


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D146773/new/

https://reviews.llvm.org/D146773

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135851: [clang] Support for read-only types

2022-12-15 Thread Malavika Samak via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG678ded017f21: [clang] Support for read-only types (authored 
by malavikasamak).
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Changed prior to commit:
  https://reviews.llvm.org/D135851?vs=481148&id=483289#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135851/new/

https://reviews.llvm.org/D135851

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  clang/test/Sema/attr-read-only-placement.cpp

Index: clang/test/Sema/attr-read-only-placement.cpp
===
--- /dev/null
+++ clang/test/Sema/attr-read-only-placement.cpp
@@ -0,0 +1,170 @@
+// RUN: %clang_cc1 -Wread-only-types %s -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++2a -Wread-only-types %s -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++17 -Wread-only-types %s -verify -fsyntax-only
+
+struct __attribute__((enforce_read_only_placement)) A { // #A_DECL
+};
+
+A a1; // expected-warning {{object of type 'A' cannot be placed in read-only memory}}
+  // expected-note@#A_DECL {{type was declared read-only here}}
+const A a2[10]; // no-warning
+A a3[20]; // expected-warning {{object of type 'A' cannot be placed in read-only memory}}
+  // expected-note@#A_DECL {{type was declared read-only here}}
+
+
+
+struct B;
+struct __attribute__((enforce_read_only_placement)) B { //#B_DECL
+};
+
+B b1; // expected-warning {{object of type 'B' cannot be placed in read-only memory}}
+  // expected-note@#B_DECL {{type was declared read-only here}}
+const B b2; // no-warning
+const B b3[4]; // no-warning
+B b4[5]; // expected-warning {{object of type 'B' cannot be placed in read-only memory}}
+ // expected-note@#B_DECL {{type was declared read-only here}}
+B b5[5][5]; // expected-warning {{object of type 'B' cannot be placed in read-only memory}}
+// expected-note@#B_DECL {{type was declared read-only here}}
+B b10[5][5][5]; // expected-warning {{object of type 'B' cannot be placed in read-only memory}}
+// expected-note@#B_DECL {{type was declared read-only here}}
+
+void method1() {
+static const B b6;
+static B b7;// expected-warning {{object of type 'B' cannot be placed in read-only memory}}
+// expected-note@#B_DECL {{type was declared read-only here}}
+B b8; // no-warning
+const B b9; // no-warning
+}
+
+struct C;
+struct __attribute__((enforce_read_only_placement)) C; // expected-note {{type was declared read-only here}}
+struct C { // no-note. The note should be attached to the definition/declaration bearing the attribute
+};
+
+C c1; // expected-warning {{object of type 'C' cannot be placed in read-only memory}}
+
+// Cases to be handled by the follow-up patches.
+
+// Attaching and checking the attribute in reverse, where the attribute is attached after the
+// type definition
+struct D;
+struct D { //expected-note{{previous definition is here}}
+};
+struct __attribute__((enforce_read_only_placement)) D; // #3
+// expected-warning@#3{{attribute declaration must precede definition}}
+
+D d1; // We do not  emit a warning here, as there is another warning for declaring
+  // a type after the definition
+
+
+// Cases where the attribute must be explicitly attached to another type
+// Case 1: Inheriting from a type that has the attribute
+struct E : C { // FIXME: warn the user declarations of type `E`, that extends `C`, won't be
+   // checked for read only placement because `E` is not marked as `C` is.
+};
+
+// Case 2: Declaring a field of the type that has the attribute
+struct F {
+C c1; // FIXME: warn the user type `F` that wraps type `C` won't be checked for
+  // read only placement
+};
+
+struct BaseWithoutAttribute {
+int a;
+};
+
+struct  __attribute__((enforce_read_only_placement)) J : BaseWithoutAttribute { // no-warning
+};
+
+struct __attribute__((enforce_read_only_placement)) BaseWithAttribute {
+int i;
+};
+
+struct __attribute__((enforce_read_only_placement)) Derived : BaseWithAttribute { // no-warning
+int j;
+};
+
+struct __attribute__((enforce_read_only_placement)) WrapperToAttributeInstance { // no-warning
+BaseWithAttribute b;
+};
+
+struct __attribute__((enforce_read_only_placement)) WrapperToNoAttributeInstance { // no-warning
+BaseWithoutAttribute b;
+};
+
+// Cases where the const qualification doesn't ensure read-only memory placement
+// of an instance.
+
+// Case 1: The type defines/inherits mutable data members
+struct __att