[clang] [clang][AArch64] multilib: fix deduction of "-march=" option (PR #81474)

2024-02-14 Thread Dominik Wójt via cfe-commits

domin144 wrote:

@MaskRay @petrhosek @smithp35 @mplatings 
Looking at previous reviews for multilib related changes you might be 
interested.
(ingore the buildkite failure for now. It seems unrelated.)

https://github.com/llvm/llvm-project/pull/81474
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect more trivial functions (PR #81829)

2024-02-14 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81829

>From 382ce72e206ca80e3414d5a141afa0f4f8b8 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Wed, 14 Feb 2024 23:30:27 -0800
Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Detect more trivial
 functions

Allow address-of operator (&), enum constant, and a reference to constant
as well as materializing temporqary expression and an expression with cleanups
to appear within a trivial function.
---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 20 +++-
 .../Analysis/Checkers/WebKit/mock-types.h |  1 +
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 95 ++-
 3 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index bf6f9a64877c64..6f236db0474079 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -285,7 +285,8 @@ class TrivialFunctionAnalysisVisitor
 
   bool VisitUnaryOperator(const UnaryOperator *UO) {
 // Operator '*' and '!' are allowed as long as the operand is trivial.
-if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf ||
+UO->getOpcode() == UO_LNot)
   return Visit(UO->getSubExpr());
 
 // Other operators are non-trivial.
@@ -306,6 +307,10 @@ class TrivialFunctionAnalysisVisitor
 if (auto *decl = DRE->getDecl()) {
   if (isa(decl))
 return true;
+  if (isa(decl))
+return true;
+  if (auto *VD = dyn_cast(decl))
+return VD->hasConstantInitialization() && VD->getEvaluatedValue();
 }
 return false;
   }
@@ -377,6 +382,14 @@ class TrivialFunctionAnalysisVisitor
 return Visit(ECE->getSubExpr());
   }
 
+  bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT) {
+return Visit(VMT->getSubExpr());
+  }
+
+  bool VisitExprWithCleanups(const ExprWithCleanups *EWC) {
+return Visit(EWC->getSubExpr());
+  }
+
   bool VisitParenExpr(const ParenExpr *PE) { return Visit(PE->getSubExpr()); }
 
   bool VisitInitListExpr(const InitListExpr *ILE) {
@@ -397,6 +410,11 @@ class TrivialFunctionAnalysisVisitor
 return true;
   }
 
+  bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
+// nullptr is trivial.
+return true;
+  }
+
   // Constant literal expressions are always trivial
   bool VisitIntegerLiteral(const IntegerLiteral *E) { return true; }
   bool VisitFloatingLiteral(const FloatingLiteral *E) { return true; }
diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h 
b/clang/test/Analysis/Checkers/WebKit/mock-types.h
index cc40487614a83d..d08a997aa8c043 100644
--- a/clang/test/Analysis/Checkers/WebKit/mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h
@@ -19,6 +19,7 @@ template  struct RefPtr {
   RefPtr(T *t) : t(t) {}
   T *get() { return t; }
   T *operator->() { return t; }
+  const T *operator->() const { return t; }
   T *() { return *t; }
   RefPtr =(T *) { return *this; }
   operator bool() { return t; }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 156a2480901bf0..83c4414d1d01aa 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -1,7 +1,6 @@
 // RUN: %clang_analyze_cc1 
-analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
 
 #include "mock-types.h"
-//#include 
 
 void WTFBreakpointTrap();
 void WTFCrashWithInfo(int, const char*, const char*, int);
@@ -60,11 +59,86 @@ NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void 
WTFCrashWithInfo(int line, const char*
 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason));
 }
 
+enum class Flags : unsigned short {
+  Flag1 = 1 << 0,
+  Flag2 = 1 << 1,
+  Flag3 = 1 << 2,
+};
+
+template class OptionSet {
+public:
+  using StorageType = unsigned short;
+
+  static constexpr OptionSet fromRaw(StorageType rawValue) {
+return OptionSet(static_cast(rawValue), FromRawValue);
+  }
+
+  constexpr OptionSet() = default;
+
+  constexpr OptionSet(E e)
+: m_storage(static_cast(e)) {
+  }
+
+  constexpr StorageType toRaw() const { return m_storage; }
+
+  constexpr bool isEmpty() const { return !m_storage; }
+
+  constexpr explicit operator bool() const { return !isEmpty(); }
+
+  constexpr bool contains(E option) const { return containsAny(option); }
+  constexpr bool containsAny(OptionSet optionSet) const {
+return !!(*this & optionSet);
+  }
+
+  constexpr bool containsAll(OptionSet optionSet) const {
+return (*this & optionSet) == optionSet;
+  }
+
+  constexpr void add(OptionSet optionSet) { m_storage |= optionSet.m_storage; }
+
+  constexpr void remove(OptionSet optionSet)
+  {
+   

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect more trivial functions (PR #81829)

2024-02-14 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff dcbb574cfc3445251ff1c751f27b52ed6503bead 
793c72168db3a27ad189e9c95d7701d19cefec1e -- 
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
clang/test/Analysis/Checkers/WebKit/mock-types.h 
clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index e8295938a8..6f236db047 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -285,7 +285,8 @@ public:
 
   bool VisitUnaryOperator(const UnaryOperator *UO) {
 // Operator '*' and '!' are allowed as long as the operand is trivial.
-if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf || 
UO->getOpcode() == UO_LNot)
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf ||
+UO->getOpcode() == UO_LNot)
   return Visit(UO->getSubExpr());
 
 // Other operators are non-trivial.
@@ -381,8 +382,7 @@ public:
 return Visit(ECE->getSubExpr());
   }
 
-  bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT)
-  {
+  bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT) {
 return Visit(VMT->getSubExpr());
   }
 
@@ -410,8 +410,7 @@ public:
 return true;
   }
 
-  bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
-  {
+  bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
 // nullptr is trivial.
 return true;
   }

``




https://github.com/llvm/llvm-project/pull/81829
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect more trivial functions (PR #81829)

2024-02-14 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-static-analyzer-1

Author: Ryosuke Niwa (rniwa)


Changes

Allow address-of operator (), enum constant, and a reference to constant 
as well as materializing temporqary expression and an expression with cleanups 
to appear within a trivial function.

---
Full diff: https://github.com/llvm/llvm-project/pull/81829.diff


3 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
(+20-1) 
- (modified) clang/test/Analysis/Checkers/WebKit/mock-types.h (+1) 
- (modified) clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp (+94-1) 


``diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index bf6f9a64877c64..e8295938a855d7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -285,7 +285,7 @@ class TrivialFunctionAnalysisVisitor
 
   bool VisitUnaryOperator(const UnaryOperator *UO) {
 // Operator '*' and '!' are allowed as long as the operand is trivial.
-if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf || 
UO->getOpcode() == UO_LNot)
   return Visit(UO->getSubExpr());
 
 // Other operators are non-trivial.
@@ -306,6 +306,10 @@ class TrivialFunctionAnalysisVisitor
 if (auto *decl = DRE->getDecl()) {
   if (isa(decl))
 return true;
+  if (isa(decl))
+return true;
+  if (auto *VD = dyn_cast(decl))
+return VD->hasConstantInitialization() && VD->getEvaluatedValue();
 }
 return false;
   }
@@ -377,6 +381,15 @@ class TrivialFunctionAnalysisVisitor
 return Visit(ECE->getSubExpr());
   }
 
+  bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT)
+  {
+return Visit(VMT->getSubExpr());
+  }
+
+  bool VisitExprWithCleanups(const ExprWithCleanups *EWC) {
+return Visit(EWC->getSubExpr());
+  }
+
   bool VisitParenExpr(const ParenExpr *PE) { return Visit(PE->getSubExpr()); }
 
   bool VisitInitListExpr(const InitListExpr *ILE) {
@@ -397,6 +410,12 @@ class TrivialFunctionAnalysisVisitor
 return true;
   }
 
+  bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
+  {
+// nullptr is trivial.
+return true;
+  }
+
   // Constant literal expressions are always trivial
   bool VisitIntegerLiteral(const IntegerLiteral *E) { return true; }
   bool VisitFloatingLiteral(const FloatingLiteral *E) { return true; }
diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h 
b/clang/test/Analysis/Checkers/WebKit/mock-types.h
index cc40487614a83d..d08a997aa8c043 100644
--- a/clang/test/Analysis/Checkers/WebKit/mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h
@@ -19,6 +19,7 @@ template  struct RefPtr {
   RefPtr(T *t) : t(t) {}
   T *get() { return t; }
   T *operator->() { return t; }
+  const T *operator->() const { return t; }
   T *() { return *t; }
   RefPtr =(T *) { return *this; }
   operator bool() { return t; }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 156a2480901bf0..83c4414d1d01aa 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -1,7 +1,6 @@
 // RUN: %clang_analyze_cc1 
-analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
 
 #include "mock-types.h"
-//#include 
 
 void WTFBreakpointTrap();
 void WTFCrashWithInfo(int, const char*, const char*, int);
@@ -60,11 +59,86 @@ NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void 
WTFCrashWithInfo(int line, const char*
 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason));
 }
 
+enum class Flags : unsigned short {
+  Flag1 = 1 << 0,
+  Flag2 = 1 << 1,
+  Flag3 = 1 << 2,
+};
+
+template class OptionSet {
+public:
+  using StorageType = unsigned short;
+
+  static constexpr OptionSet fromRaw(StorageType rawValue) {
+return OptionSet(static_cast(rawValue), FromRawValue);
+  }
+
+  constexpr OptionSet() = default;
+
+  constexpr OptionSet(E e)
+: m_storage(static_cast(e)) {
+  }
+
+  constexpr StorageType toRaw() const { return m_storage; }
+
+  constexpr bool isEmpty() const { return !m_storage; }
+
+  constexpr explicit operator bool() const { return !isEmpty(); }
+
+  constexpr bool contains(E option) const { return containsAny(option); }
+  constexpr bool containsAny(OptionSet optionSet) const {
+return !!(*this & optionSet);
+  }
+
+  constexpr bool containsAll(OptionSet optionSet) const {
+return (*this & optionSet) == optionSet;
+  }
+
+  constexpr void add(OptionSet optionSet) { m_storage |= optionSet.m_storage; }
+
+  constexpr void remove(OptionSet optionSet)
+  {
+  m_storage &= ~optionSet.m_storage;
+  }
+
+  constexpr void set(OptionSet optionSet, bool 

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect more trivial functions (PR #81829)

2024-02-14 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Ryosuke Niwa (rniwa)


Changes

Allow address-of operator (), enum constant, and a reference to constant 
as well as materializing temporqary expression and an expression with cleanups 
to appear within a trivial function.

---
Full diff: https://github.com/llvm/llvm-project/pull/81829.diff


3 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
(+20-1) 
- (modified) clang/test/Analysis/Checkers/WebKit/mock-types.h (+1) 
- (modified) clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp (+94-1) 


``diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index bf6f9a64877c64..e8295938a855d7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -285,7 +285,7 @@ class TrivialFunctionAnalysisVisitor
 
   bool VisitUnaryOperator(const UnaryOperator *UO) {
 // Operator '*' and '!' are allowed as long as the operand is trivial.
-if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf || 
UO->getOpcode() == UO_LNot)
   return Visit(UO->getSubExpr());
 
 // Other operators are non-trivial.
@@ -306,6 +306,10 @@ class TrivialFunctionAnalysisVisitor
 if (auto *decl = DRE->getDecl()) {
   if (isa(decl))
 return true;
+  if (isa(decl))
+return true;
+  if (auto *VD = dyn_cast(decl))
+return VD->hasConstantInitialization() && VD->getEvaluatedValue();
 }
 return false;
   }
@@ -377,6 +381,15 @@ class TrivialFunctionAnalysisVisitor
 return Visit(ECE->getSubExpr());
   }
 
+  bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT)
+  {
+return Visit(VMT->getSubExpr());
+  }
+
+  bool VisitExprWithCleanups(const ExprWithCleanups *EWC) {
+return Visit(EWC->getSubExpr());
+  }
+
   bool VisitParenExpr(const ParenExpr *PE) { return Visit(PE->getSubExpr()); }
 
   bool VisitInitListExpr(const InitListExpr *ILE) {
@@ -397,6 +410,12 @@ class TrivialFunctionAnalysisVisitor
 return true;
   }
 
+  bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
+  {
+// nullptr is trivial.
+return true;
+  }
+
   // Constant literal expressions are always trivial
   bool VisitIntegerLiteral(const IntegerLiteral *E) { return true; }
   bool VisitFloatingLiteral(const FloatingLiteral *E) { return true; }
diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h 
b/clang/test/Analysis/Checkers/WebKit/mock-types.h
index cc40487614a83d..d08a997aa8c043 100644
--- a/clang/test/Analysis/Checkers/WebKit/mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h
@@ -19,6 +19,7 @@ template  struct RefPtr {
   RefPtr(T *t) : t(t) {}
   T *get() { return t; }
   T *operator->() { return t; }
+  const T *operator->() const { return t; }
   T *() { return *t; }
   RefPtr =(T *) { return *this; }
   operator bool() { return t; }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 156a2480901bf0..83c4414d1d01aa 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -1,7 +1,6 @@
 // RUN: %clang_analyze_cc1 
-analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
 
 #include "mock-types.h"
-//#include 
 
 void WTFBreakpointTrap();
 void WTFCrashWithInfo(int, const char*, const char*, int);
@@ -60,11 +59,86 @@ NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void 
WTFCrashWithInfo(int line, const char*
 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason));
 }
 
+enum class Flags : unsigned short {
+  Flag1 = 1 << 0,
+  Flag2 = 1 << 1,
+  Flag3 = 1 << 2,
+};
+
+template class OptionSet {
+public:
+  using StorageType = unsigned short;
+
+  static constexpr OptionSet fromRaw(StorageType rawValue) {
+return OptionSet(static_cast(rawValue), FromRawValue);
+  }
+
+  constexpr OptionSet() = default;
+
+  constexpr OptionSet(E e)
+: m_storage(static_cast(e)) {
+  }
+
+  constexpr StorageType toRaw() const { return m_storage; }
+
+  constexpr bool isEmpty() const { return !m_storage; }
+
+  constexpr explicit operator bool() const { return !isEmpty(); }
+
+  constexpr bool contains(E option) const { return containsAny(option); }
+  constexpr bool containsAny(OptionSet optionSet) const {
+return !!(*this & optionSet);
+  }
+
+  constexpr bool containsAll(OptionSet optionSet) const {
+return (*this & optionSet) == optionSet;
+  }
+
+  constexpr void add(OptionSet optionSet) { m_storage |= optionSet.m_storage; }
+
+  constexpr void remove(OptionSet optionSet)
+  {
+  m_storage &= ~optionSet.m_storage;
+  }
+
+  constexpr void set(OptionSet optionSet, bool value)
+  {
+if 

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect more trivial functions (PR #81829)

2024-02-14 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa created https://github.com/llvm/llvm-project/pull/81829

Allow address-of operator (&), enum constant, and a reference to constant as 
well as materializing temporqary expression and an expression with cleanups to 
appear within a trivial function.

>From 793c72168db3a27ad189e9c95d7701d19cefec1e Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Wed, 14 Feb 2024 23:30:27 -0800
Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Detect more trivial
 functions

Allow address-of operator (&), enum constant, and a reference to constant
as well as materializing temporqary expression and an expression with cleanups
to appear within a trivial function.
---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 21 +++-
 .../Analysis/Checkers/WebKit/mock-types.h |  1 +
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 95 ++-
 3 files changed, 115 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index bf6f9a64877c64..e8295938a855d7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -285,7 +285,7 @@ class TrivialFunctionAnalysisVisitor
 
   bool VisitUnaryOperator(const UnaryOperator *UO) {
 // Operator '*' and '!' are allowed as long as the operand is trivial.
-if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf || 
UO->getOpcode() == UO_LNot)
   return Visit(UO->getSubExpr());
 
 // Other operators are non-trivial.
@@ -306,6 +306,10 @@ class TrivialFunctionAnalysisVisitor
 if (auto *decl = DRE->getDecl()) {
   if (isa(decl))
 return true;
+  if (isa(decl))
+return true;
+  if (auto *VD = dyn_cast(decl))
+return VD->hasConstantInitialization() && VD->getEvaluatedValue();
 }
 return false;
   }
@@ -377,6 +381,15 @@ class TrivialFunctionAnalysisVisitor
 return Visit(ECE->getSubExpr());
   }
 
+  bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *VMT)
+  {
+return Visit(VMT->getSubExpr());
+  }
+
+  bool VisitExprWithCleanups(const ExprWithCleanups *EWC) {
+return Visit(EWC->getSubExpr());
+  }
+
   bool VisitParenExpr(const ParenExpr *PE) { return Visit(PE->getSubExpr()); }
 
   bool VisitInitListExpr(const InitListExpr *ILE) {
@@ -397,6 +410,12 @@ class TrivialFunctionAnalysisVisitor
 return true;
   }
 
+  bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
+  {
+// nullptr is trivial.
+return true;
+  }
+
   // Constant literal expressions are always trivial
   bool VisitIntegerLiteral(const IntegerLiteral *E) { return true; }
   bool VisitFloatingLiteral(const FloatingLiteral *E) { return true; }
diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h 
b/clang/test/Analysis/Checkers/WebKit/mock-types.h
index cc40487614a83d..d08a997aa8c043 100644
--- a/clang/test/Analysis/Checkers/WebKit/mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h
@@ -19,6 +19,7 @@ template  struct RefPtr {
   RefPtr(T *t) : t(t) {}
   T *get() { return t; }
   T *operator->() { return t; }
+  const T *operator->() const { return t; }
   T *() { return *t; }
   RefPtr =(T *) { return *this; }
   operator bool() { return t; }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp 
b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 156a2480901bf0..83c4414d1d01aa 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -1,7 +1,6 @@
 // RUN: %clang_analyze_cc1 
-analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
 
 #include "mock-types.h"
-//#include 
 
 void WTFBreakpointTrap();
 void WTFCrashWithInfo(int, const char*, const char*, int);
@@ -60,11 +59,86 @@ NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void 
WTFCrashWithInfo(int line, const char*
 WTFCrashWithInfoImpl(line, file, function, counter, wtfCrashArg(reason));
 }
 
+enum class Flags : unsigned short {
+  Flag1 = 1 << 0,
+  Flag2 = 1 << 1,
+  Flag3 = 1 << 2,
+};
+
+template class OptionSet {
+public:
+  using StorageType = unsigned short;
+
+  static constexpr OptionSet fromRaw(StorageType rawValue) {
+return OptionSet(static_cast(rawValue), FromRawValue);
+  }
+
+  constexpr OptionSet() = default;
+
+  constexpr OptionSet(E e)
+: m_storage(static_cast(e)) {
+  }
+
+  constexpr StorageType toRaw() const { return m_storage; }
+
+  constexpr bool isEmpty() const { return !m_storage; }
+
+  constexpr explicit operator bool() const { return !isEmpty(); }
+
+  constexpr bool contains(E option) const { return containsAny(option); }
+  constexpr bool containsAny(OptionSet optionSet) const {
+return !!(*this & optionSet);
+  }
+
+  constexpr bool containsAll(OptionSet optionSet) const {

[clang] [RISCV] Disable generation of asynchronous unwind tables for RISCV baremetal (PR #81727)

2024-02-14 Thread Kito Cheng via cfe-commits

kito-cheng wrote:

RISC-V GCC has enabled `-fasynchronous-unwind-tables` and `-funwind-tables` by 
default for Linux target, and disabled by default for baremetal, so generally 
LGTM since it align the behavior with GCC, but I would like to wait @asb's 
response. 

NOTE: The patch[1] is come from SUSE folks, so I assume it's necessary from the 
distro's point of view.

Ref:
[1] 
https://github.com/gcc-mirror/gcc/commit/3cd08f7168c196d7a481b9ed9f4289fd1f14eea8

https://github.com/llvm/llvm-project/pull/81727
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [MC/DC] Refactor: Let MCDCConditionID int16_t with zero-origin (PR #81257)

2024-02-14 Thread NAKAMURA Takumi via cfe-commits

https://github.com/chapuni closed 
https://github.com/llvm/llvm-project/pull/81257
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] ab76e48 - [MC/DC] Refactor: Let MCDCConditionID int16_t with zero-origin (#81257)

2024-02-14 Thread via cfe-commits

Author: NAKAMURA Takumi
Date: 2024-02-15T16:24:37+09:00
New Revision: ab76e48ac2c2dbfc7d6a600b9b0dd0672e6d9439

URL: 
https://github.com/llvm/llvm-project/commit/ab76e48ac2c2dbfc7d6a600b9b0dd0672e6d9439
DIFF: 
https://github.com/llvm/llvm-project/commit/ab76e48ac2c2dbfc7d6a600b9b0dd0672e6d9439.diff

LOG: [MC/DC] Refactor: Let MCDCConditionID int16_t with zero-origin (#81257)

Also, Let `NumConditions` `uint16_t`.

It is smarter to handle the ID as signed.
Narrowing to `int16_t` will reduce costs of handling byvalue. (See also
#81221 and #81227)

External behavior doesn't change. They below handle values as internal
values plus 1.
* `-dump-coverage-mapping`
* `CoverageMappingReader.cpp`
* `CoverageMappingWriter.cpp`

Added: 


Modified: 
clang/lib/CodeGen/CodeGenPGO.cpp
clang/lib/CodeGen/CodeGenPGO.h
clang/lib/CodeGen/CoverageMappingGen.cpp
llvm/include/llvm/ProfileData/Coverage/MCDCTypes.h
llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
llvm/unittests/ProfileData/CoverageMappingTest.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CodeGenPGO.cpp 
b/clang/lib/CodeGen/CodeGenPGO.cpp
index b5ce1aad7ea1e5..48c5e68a3b7ba4 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -1031,7 +1031,7 @@ void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
 
   std::string CoverageMapping;
   llvm::raw_string_ostream OS(CoverageMapping);
-  RegionMCDCState->CondIDMap.clear();
+  RegionCondIDMap.reset(new llvm::DenseMap);
   CoverageMappingGen MappingGen(
   *CGM.getCoverageMapping(), CGM.getContext().getSourceManager(),
   CGM.getLangOpts(), RegionCounterMap.get(), RegionMCDCState.get());
@@ -1195,8 +1195,8 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy 
, const Expr *S,
 return;
 
   // Extract the ID of the condition we are setting in the bitmap.
-  unsigned CondID = ExprMCDCConditionIDMapIterator->second;
-  assert(CondID > 0 && "Condition has no ID!");
+  auto CondID = ExprMCDCConditionIDMapIterator->second;
+  assert(CondID >= 0 && "Condition has no ID!");
 
   auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext());
 
@@ -1205,7 +1205,7 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy 
, const Expr *S,
   // the resulting value is used to update the boolean expression's bitmap.
   llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
   Builder.getInt64(FunctionHash),
-  Builder.getInt32(CondID - 1),
+  Builder.getInt32(CondID),
   MCDCCondBitmapAddr.getPointer(), Val};
   Builder.CreateCall(
   CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update),

diff  --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h
index d3c2b277238fc7..369bf05b59a0d2 100644
--- a/clang/lib/CodeGen/CodeGenPGO.h
+++ b/clang/lib/CodeGen/CodeGenPGO.h
@@ -36,6 +36,8 @@ class CodeGenPGO {
   unsigned NumRegionCounters;
   uint64_t FunctionHash;
   std::unique_ptr> RegionCounterMap;
+  std::unique_ptr> RegionMCDCBitmapMap;
+  std::unique_ptr> RegionCondIDMap;
   std::unique_ptr> StmtCountMap;
   std::unique_ptr ProfRecord;
   std::unique_ptr RegionMCDCState;

diff  --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 93c3c31e71fa83..fdf821a0eb6928 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -686,11 +686,12 @@ struct MCDCCoverageBuilder {
   llvm::SmallVector DecisionStack;
   MCDC::State 
   llvm::DenseMap 
-  mcdc::ConditionID NextID = 1;
+  mcdc::ConditionID NextID = 0;
   bool NotMapped = false;
 
-  /// Represent a sentinel value of [0,0] for the bottom of DecisionStack.
-  static constexpr mcdc::ConditionIDs DecisionStackSentinel{0, 0};
+  /// Represent a sentinel value as a pair of final decisions for the bottom
+  // of DecisionStack.
+  static constexpr mcdc::ConditionIDs DecisionStackSentinel{-1, -1};
 
   /// Is this a logical-AND operation?
   bool isLAnd(const BinaryOperator *E) const {
@@ -705,12 +706,12 @@ struct MCDCCoverageBuilder {
   /// Return whether the build of the control flow map is at the top-level
   /// (root) of a logical operator nest in a boolean expression prior to the
   /// assignment of condition IDs.
-  bool isIdle() const { return (NextID == 1 && !NotMapped); }
+  bool isIdle() const { return (NextID == 0 && !NotMapped); }
 
   /// Return whether any IDs have been assigned in the build of the control
   /// flow map, indicating that the map is being generated for this boolean
   /// expression.
-  bool isBuilding() const { return (NextID > 1); }
+  bool isBuilding() const { return (NextID > 0); }
 
   /// Set the given condition's ID.
   

[clang-tools-extra] Add support for renaming objc methods, even those with multiple selector pieces (PR #76466)

2024-02-14 Thread kadir çetinkaya via cfe-commits


@@ -538,11 +564,222 @@ std::optional checkName(const NamedDecl 
,
 Conflict->getLocation().printToString(ASTCtx.getSourceManager())};
 }
   }
-  if (Result)
+  if (Result) {
 InvalidNameMetric.record(1, toString(Result->K));
+return makeError(*Result);
+  }
+  return llvm::Error::success();
+}
+
+bool isSelectorLike(const syntax::Token , const syntax::Token ) {
+  return Cur.kind() == tok::identifier && Next.kind() == tok::colon &&
+ // We require the selector name and : to be contiguous.
+ // e.g. support `foo:` but not `foo :`.
+ Cur.endLocation() == Next.location();
+}
+
+bool isMatchingSelectorName(const syntax::Token , const syntax::Token 
,
+const SourceManager ,
+llvm::StringRef SelectorName) {
+  if (SelectorName.empty())
+return Cur.kind() == tok::colon;
+  return isSelectorLike(Cur, Next) && Cur.text(SM) == SelectorName;
+}
+
+// Scan through Tokens to find ranges for each selector fragment in Sel at the
+// top level (not nested in any () or {} or []). The search will terminate upon
+// seeing Terminator or a ; at the top level.
+std::optional
+findAllSelectorPieces(llvm::ArrayRef Tokens,
+  const SourceManager , Selector Sel,
+  tok::TokenKind Terminator) {
+
+  unsigned NumArgs = Sel.getNumArgs();
+  llvm::SmallVector Closes;
+  std::vector SelectorPieces;
+  unsigned Last = Tokens.size() - 1;

kadircet wrote:

nit: `Last` is not used outside the loop, and it's still confusing me to see 
loop condition below as `Index < Last`. what about

`for (unsigned Index = 0, Last = Tokens.size(); Index < Last - 1; ++Index)`

https://github.com/llvm/llvm-project/pull/76466
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add support for renaming objc methods, even those with multiple selector pieces (PR #76466)

2024-02-14 Thread kadir çetinkaya via cfe-commits


@@ -538,11 +564,222 @@ std::optional checkName(const NamedDecl 
,
 Conflict->getLocation().printToString(ASTCtx.getSourceManager())};
 }
   }
-  if (Result)
+  if (Result) {
 InvalidNameMetric.record(1, toString(Result->K));
+return makeError(*Result);
+  }
+  return llvm::Error::success();
+}
+
+bool isSelectorLike(const syntax::Token , const syntax::Token ) {
+  return Cur.kind() == tok::identifier && Next.kind() == tok::colon &&
+ // We require the selector name and : to be contiguous.
+ // e.g. support `foo:` but not `foo :`.
+ Cur.endLocation() == Next.location();
+}
+
+bool isMatchingSelectorName(const syntax::Token , const syntax::Token 
,
+const SourceManager ,
+llvm::StringRef SelectorName) {
+  if (SelectorName.empty())
+return Cur.kind() == tok::colon;
+  return isSelectorLike(Cur, Next) && Cur.text(SM) == SelectorName;
+}
+
+// Scan through Tokens to find ranges for each selector fragment in Sel at the
+// top level (not nested in any () or {} or []). The search will terminate upon
+// seeing Terminator or a ; at the top level.
+std::optional
+findAllSelectorPieces(llvm::ArrayRef Tokens,
+  const SourceManager , Selector Sel,
+  tok::TokenKind Terminator) {
+
+  unsigned NumArgs = Sel.getNumArgs();
+  llvm::SmallVector Closes;
+  std::vector SelectorPieces;
+  unsigned Last = Tokens.size() - 1;
+  for (unsigned Index = 0; Index < Last; ++Index) {
+const auto  = Tokens[Index];
+
+if (Closes.empty()) {
+  auto PieceCount = SelectorPieces.size();
+  if (PieceCount < NumArgs &&
+  isMatchingSelectorName(Tok, Tokens[Index + 1], SM,
+ Sel.getNameForSlot(PieceCount))) {
+// If 'foo:' instead of ':' (empty selector), we need to skip the ':'

kadircet wrote:

as discussed we aren't actually handling this case probably (we won't have a 
token for an empty selector name).

can you just leave a comment explaining what & why it doesn't work (i don't 
necessarily see it as a TODO, as utility/complexity ratio is pretty low)?

https://github.com/llvm/llvm-project/pull/76466
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add support for renaming objc methods, even those with multiple selector pieces (PR #76466)

2024-02-14 Thread kadir çetinkaya via cfe-commits


@@ -696,7 +982,7 @@ renameOutsideFile(const NamedDecl , 
llvm::StringRef MainFilePath,
FilePath);
 }
 auto RenameEdit =
-buildRenameEdit(FilePath, AffectedFileCode, *RenameRanges, NewName);
+buildRenameEdit(FilePath, AffectedFileCode, *RenameRanges, NewNames);

kadircet wrote:

as discussed yesterday, i was suggesting to move:
```
llvm::SmallVector NewNames;
NewName.split(NewNames, ":");
```

from lines 928/936 to right before this call to `buildRenameEdit`

https://github.com/llvm/llvm-project/pull/76466
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add support for renaming objc methods, even those with multiple selector pieces (PR #76466)

2024-02-14 Thread kadir çetinkaya via cfe-commits


@@ -538,11 +564,222 @@ std::optional checkName(const NamedDecl 
,
 Conflict->getLocation().printToString(ASTCtx.getSourceManager())};
 }
   }
-  if (Result)
+  if (Result) {
 InvalidNameMetric.record(1, toString(Result->K));
+return makeError(*Result);
+  }
+  return llvm::Error::success();
+}
+
+bool isSelectorLike(const syntax::Token , const syntax::Token ) {
+  return Cur.kind() == tok::identifier && Next.kind() == tok::colon &&
+ // We require the selector name and : to be contiguous.
+ // e.g. support `foo:` but not `foo :`.
+ Cur.endLocation() == Next.location();
+}
+
+bool isMatchingSelectorName(const syntax::Token , const syntax::Token 
,
+const SourceManager ,
+llvm::StringRef SelectorName) {
+  if (SelectorName.empty())
+return Cur.kind() == tok::colon;
+  return isSelectorLike(Cur, Next) && Cur.text(SM) == SelectorName;
+}
+
+// Scan through Tokens to find ranges for each selector fragment in Sel at the
+// top level (not nested in any () or {} or []). The search will terminate upon
+// seeing Terminator or a ; at the top level.
+std::optional
+findAllSelectorPieces(llvm::ArrayRef Tokens,
+  const SourceManager , Selector Sel,
+  tok::TokenKind Terminator) {
+

kadircet wrote:

`assert(!Tokens.empty())`

https://github.com/llvm/llvm-project/pull/76466
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add support for renaming objc methods, even those with multiple selector pieces (PR #76466)

2024-02-14 Thread kadir çetinkaya via cfe-commits

https://github.com/kadircet approved this pull request.

thanks, lgtm!

https://github.com/llvm/llvm-project/pull/76466
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add support for renaming objc methods, even those with multiple selector pieces (PR #76466)

2024-02-14 Thread kadir çetinkaya via cfe-commits


@@ -538,11 +564,222 @@ std::optional checkName(const NamedDecl 
,
 Conflict->getLocation().printToString(ASTCtx.getSourceManager())};
 }
   }
-  if (Result)
+  if (Result) {
 InvalidNameMetric.record(1, toString(Result->K));
+return makeError(*Result);
+  }
+  return llvm::Error::success();
+}
+
+bool isSelectorLike(const syntax::Token , const syntax::Token ) {
+  return Cur.kind() == tok::identifier && Next.kind() == tok::colon &&
+ // We require the selector name and : to be contiguous.
+ // e.g. support `foo:` but not `foo :`.
+ Cur.endLocation() == Next.location();
+}
+
+bool isMatchingSelectorName(const syntax::Token , const syntax::Token 
,
+const SourceManager ,
+llvm::StringRef SelectorName) {
+  if (SelectorName.empty())
+return Cur.kind() == tok::colon;
+  return isSelectorLike(Cur, Next) && Cur.text(SM) == SelectorName;
+}
+
+// Scan through Tokens to find ranges for each selector fragment in Sel at the
+// top level (not nested in any () or {} or []). The search will terminate upon

kadircet wrote:

but that's true for this function, as it's achieved by the outer loop that 
calls this function in `collectRenameIdentifierRanges`.

in here we're only trying to match `Sel` assuming its first segment is located 
at `Tokens.front()`.

https://github.com/llvm/llvm-project/pull/76466
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add support for renaming objc methods, even those with multiple selector pieces (PR #76466)

2024-02-14 Thread kadir çetinkaya via cfe-commits

https://github.com/kadircet edited 
https://github.com/llvm/llvm-project/pull/76466
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][AArch64] multilib: fix deduction of "-march=" option (PR #81474)

2024-02-14 Thread Dominik Wójt via cfe-commits

https://github.com/domin144 updated 
https://github.com/llvm/llvm-project/pull/81474

From e25d580c7297071f067200639d8b8fe3be74eec6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20W=C3=B3jt?= 
Date: Mon, 12 Feb 2024 13:38:14 +0100
Subject: [PATCH 1/2] [clang][AArch64] multilib: fix deduction of "-march="
 option

The deduced "-march=" option always started with aarch64, which is not a
valid value. There was also no way to distinguish between armv8-r and
armv8-a. After this commit, the deduced "-march=" option will start with
greatest available "armv*-a" value or "armv8-r".
---
 clang/lib/Driver/ToolChain.cpp | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 657577cea6c7d8..623d52e9471f23 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -191,7 +191,11 @@ static void getAArch64MultilibFlags(const Driver ,
   for (const auto  : AArch64::Extensions)
 if (FeatureSet.contains(Ext.NegFeature))
   MArch.push_back(("no" + Ext.Name).str());
-  MArch.insert(MArch.begin(), ("-march=" + Triple.getArchName()).str());
+  StringRef ArchName;
+  for (const auto  : AArch64::ArchInfos)
+if (FeatureSet.contains(ArchInfo->ArchFeature))
+  ArchName = ArchInfo->Name;
+  MArch.insert(MArch.begin(), ("-march=" + ArchName).str());
   Result.push_back(llvm::join(MArch, "+"));
 }
 

From e3c59b8e5915881ce34f7b064c31268f8b1a843a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20W=C3=B3jt?= 
Date: Mon, 12 Feb 2024 14:46:26 +0100
Subject: [PATCH 2/2] fix tests

---
 clang/test/Driver/print-multi-selection-flags.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/test/Driver/print-multi-selection-flags.c 
b/clang/test/Driver/print-multi-selection-flags.c
index 248d9a3cdf49b2..06a12db9d97792 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -51,9 +51,10 @@
 // CHECK-M85_NO_FP_DP: -mfpu=fp-armv8-fullfp16-sp-d16
 
 // RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf 
-march=armv8-a+lse | FileCheck --check-prefix=CHECK-LSE %s
-// CHECK-LSE: -march=aarch64{{.*}}+lse{{.*}}
+// CHECK-LSE: --target=aarch64-none-unknown-elf
+// CHECK-LSE: -march=armv8-a{{.*}}+lse{{.*}}
 
 // RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf 
-march=armv8.5-a+sve+sve2 | FileCheck --check-prefix=CHECK-SVE2 %s
 // RUN: %clang -print-multi-flags-experimental --target=aarch64-none-elf 
-march=armv9-a| FileCheck --check-prefix=CHECK-SVE2 %s
 // CHECK-SVE2: --target=aarch64-none-unknown-elf
-// CHECK-SVE2: -march=aarch64{{.*}}+simd{{.*}}+sve{{.*}}+sve2{{.*}}
+// CHECK-SVE2: -march=armv{{.*}}-a{{.*}}+simd{{.*}}+sve{{.*}}+sve2{{.*}}

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


[clang] [llvm] [ASAN] For Asan instrumented global, emit two symbols, one with actual size and other with instrumented size. (PR #70166)

2024-02-14 Thread via cfe-commits

skc7 wrote:

Hi @hctim,
In this patch, we are identifying globals that are instrumented using an new IR 
attribute and for them extra symbol with padded size is emitted. This is done 
only in ASAN pass. Not sure how would that affect HWAsan and MTE-globals. Could 
you please give an example for this ?
At AMD, we have complex HPC/AI applications and libraries and this patch seems 
to not create any issue as such. Could you please give a concrete example test 
case where this patch would create an issue?

https://github.com/llvm/llvm-project/pull/70166
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 36adfec - Adding support of AMDLIBM vector library (#78560)

2024-02-14 Thread via cfe-commits

Author: Rohit Aggarwal
Date: 2024-02-15T12:13:07+05:30
New Revision: 36adfec155de366d722f2bac8ff9162289dcf06c

URL: 
https://github.com/llvm/llvm-project/commit/36adfec155de366d722f2bac8ff9162289dcf06c
DIFF: 
https://github.com/llvm/llvm-project/commit/36adfec155de366d722f2bac8ff9162289dcf06c.diff

LOG: Adding support of AMDLIBM vector library (#78560)

Hi,

AMD has it's own implementation of vector calls. This patch include the
changes to enable the use of AMD's math library using -fveclib=AMDLIBM.
Please refer https://github.com/amd/aocl-libm-ose 

-

Co-authored-by: Rohit Aggarwal 

Added: 
llvm/test/Transforms/LoopVectorize/X86/amdlibm-calls-finite.ll
llvm/test/Transforms/LoopVectorize/X86/amdlibm-calls.ll

Modified: 
clang/include/clang/Driver/Options.td
clang/test/Driver/autocomplete.c
llvm/include/llvm/Analysis/TargetLibraryInfo.h
llvm/include/llvm/Analysis/VecFuncs.def
llvm/include/llvm/Frontend/Driver/CodeGenOptions.h
llvm/lib/Analysis/TargetLibraryInfo.cpp
llvm/lib/Frontend/Driver/CodeGenOptions.cpp
llvm/test/CodeGen/Generic/replace-intrinsics-with-veclib.ll
llvm/test/Transforms/SLPVectorizer/X86/sin-sqrt.ll
llvm/test/Transforms/Util/add-TLI-mappings.ll

Removed: 




diff  --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 95b464e7d61834..b302afd65e2811 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3204,10 +3204,10 @@ def fno_experimental_isel : Flag<["-"], 
"fno-experimental-isel">, Group,
-
Values<"Accelerate,libmvec,MASSV,SVML,SLEEF,Darwin_libsystem_m,ArmPL,none">,
+
Values<"Accelerate,libmvec,MASSV,SVML,SLEEF,Darwin_libsystem_m,ArmPL,AMDLIBM,none">,
 NormalizedValuesScope<"llvm::driver::VectorLibrary">,
 NormalizedValues<["Accelerate", "LIBMVEC", "MASSV", "SVML", "SLEEF",
-  "Darwin_libsystem_m", "ArmPL", "NoLibrary"]>,
+  "Darwin_libsystem_m", "ArmPL", "AMDLIBM", "NoLibrary"]>,
 MarshallingInfoEnum, "NoLibrary">;
 def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, 
Group,
   Alias, AliasArgs<["none"]>;

diff  --git a/clang/test/Driver/autocomplete.c 
b/clang/test/Driver/autocomplete.c
index d6f57708b67eb6..c8ceaaf404672f 100644
--- a/clang/test/Driver/autocomplete.c
+++ b/clang/test/Driver/autocomplete.c
@@ -80,6 +80,7 @@
 // FLTOALL-NEXT: thin
 // RUN: %clang --autocomplete=-fveclib= | FileCheck %s -check-prefix=FVECLIBALL
 // FVECLIBALL: Accelerate
+// FVECLIBALL-NEXT: AMDLIBM
 // FVECLIBALL-NEXT: ArmPL
 // FVECLIBALL-NEXT: Darwin_libsystem_m
 // FVECLIBALL-NEXT: libmvec

diff  --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h 
b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
index daf1d8e2079f85..46f31f918e7b61 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
@@ -129,7 +129,8 @@ class TargetLibraryInfoImpl {
 MASSV,// IBM MASS vector library.
 SVML, // Intel short vector math library.
 SLEEFGNUABI, // SLEEF - SIMD Library for Evaluating Elementary Functions.
-ArmPL// Arm Performance Libraries.
+ArmPL,   // Arm Performance Libraries.
+AMDLIBM  // AMD Math Vector library.
   };
 
   TargetLibraryInfoImpl();

diff  --git a/llvm/include/llvm/Analysis/VecFuncs.def 
b/llvm/include/llvm/Analysis/VecFuncs.def
index 07edf68c667a27..394e4a05fbc0cf 100644
--- a/llvm/include/llvm/Analysis/VecFuncs.def
+++ b/llvm/include/llvm/Analysis/VecFuncs.def
@@ -1067,6 +1067,199 @@ TLI_DEFINE_VECFUNC("tgammaf", "armpl_vtgammaq_f32", 
FIXED(4), NOMASK, "_ZGV_LLVM
 TLI_DEFINE_VECFUNC("tgamma", "armpl_svtgamma_f64_x",  SCALABLE(2), MASKED, 
"_ZGVsMxv")
 TLI_DEFINE_VECFUNC("tgammaf", "armpl_svtgamma_f32_x", SCALABLE(4), MASKED, 
"_ZGVsMxv")
 
+#elif defined(TLI_DEFINE_AMDLIBM_VECFUNCS)
+TLI_DEFINE_VECFUNC("sinf", "amd_vrs16_sinf", FIXED(16), NOMASK, 
"_ZGV_LLVM_N16v")
+TLI_DEFINE_VECFUNC("sinf", "amd_vrs8_sinf", FIXED(8), NOMASK, "_ZGV_LLVM_N8v")
+TLI_DEFINE_VECFUNC("sinf", "amd_vrs4_sinf", FIXED(4), NOMASK, "_ZGV_LLVM_N4v")
+TLI_DEFINE_VECFUNC("sin", "amd_vrd8_sin", FIXED(8), NOMASK, "_ZGV_LLVM_N8v")
+TLI_DEFINE_VECFUNC("sin", "amd_vrd4_sin", FIXED(4), NOMASK, "_ZGV_LLVM_N4v")
+TLI_DEFINE_VECFUNC("sin", "amd_vrd2_sin", FIXED(2), NOMASK, "_ZGV_LLVM_N2v")
+
+TLI_DEFINE_VECFUNC("llvm.sin.f32", "amd_vrs16_sinf", FIXED(16), NOMASK, 
"_ZGV_LLVM_N16v")
+TLI_DEFINE_VECFUNC("llvm.sin.f32", "amd_vrs8_sinf", FIXED(8), NOMASK, 
"_ZGV_LLVM_N8v")
+TLI_DEFINE_VECFUNC("llvm.sin.f32", "amd_vrs4_sinf", FIXED(4), NOMASK, 
"_ZGV_LLVM_N4v")
+TLI_DEFINE_VECFUNC("llvm.sin.f64", "amd_vrd8_sin", FIXED(8), NOMASK, 
"_ZGV_LLVM_N8v")
+TLI_DEFINE_VECFUNC("llvm.sin.f64", "amd_vrd4_sin", FIXED(4), NOMASK, 
"_ZGV_LLVM_N4v")
+TLI_DEFINE_VECFUNC("llvm.sin.f64", "amd_vrd2_sin", FIXED(2), NOMASK, 

[clang] [llvm] Adding support of AMDLIBM vector library (PR #78560)

2024-02-14 Thread via cfe-commits

https://github.com/ganeshgit closed 
https://github.com/llvm/llvm-project/pull/78560
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] b93916c - [clang][Interp][NFC] Convert test to verify=expected,both style

2024-02-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-02-15T07:23:35+01:00
New Revision: b93916c9798ea09488e30b9b0aae9e54ef0b1956

URL: 
https://github.com/llvm/llvm-project/commit/b93916c9798ea09488e30b9b0aae9e54ef0b1956
DIFF: 
https://github.com/llvm/llvm-project/commit/b93916c9798ea09488e30b9b0aae9e54ef0b1956.diff

LOG: [clang][Interp][NFC] Convert test to verify=expected,both style

Added: 


Modified: 
clang/test/AST/Interp/functions.cpp

Removed: 




diff  --git a/clang/test/AST/Interp/functions.cpp 
b/clang/test/AST/Interp/functions.cpp
index 34a832c794c75d..320691336bdd99 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
-// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -verify 
%s
-// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify 
%s
-// RUN: %clang_cc1 -verify=ref %s
-// RUN: %clang_cc1 -std=c++14 -verify=ref %s
-// RUN: %clang_cc1 -std=c++20 -verify=ref %s
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
+// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
+// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
+// RUN: %clang_cc1 -verify=ref,both %s
+// RUN: %clang_cc1 -std=c++14 -verify=ref,both %s
+// RUN: %clang_cc1 -std=c++20 -verify=ref,both %s
 
 constexpr void doNothing() {}
 constexpr int gimme5() {
@@ -23,16 +23,13 @@ static_assert(!identity(false), "");
 
 template
 constexpr bool sameSize() {
-  static_assert(sizeof(A) == sizeof(B), ""); // expected-error {{static 
assertion failed}} \
- // ref-error {{static assertion 
failed}} \
- // expected-note {{evaluates to}} 
\
- // ref-note {{evaluates to}}
+  static_assert(sizeof(A) == sizeof(B), ""); // both-error {{static assertion 
failed}} \
+ // both-note {{evaluates to}}
   return true;
 }
 static_assert(sameSize(), "");
 static_assert(sameSize(), "");
-static_assert(sameSize(), ""); // expected-note {{in instantiation 
of function template specialization}} \
-   // ref-note {{in instantiation of 
function template specialization}}
+static_assert(sameSize(), ""); // both-note {{in instantiation of 
function template specialization}}
 
 
 constexpr auto add(int a, int b) -> int {
@@ -92,12 +89,9 @@ static_assert(getNum<-2>() == -2, "");
 static_assert(getNum<10>() == 10, "");
 static_assert(getNum() == 5, "");
 
-constexpr int f(); // expected-note {{declared here}} \
-   // ref-note {{declared here}}
-static_assert(f() == 5, ""); // expected-error {{not an integral constant 
expression}} \
- // expected-note {{undefined function 'f'}} \
- // ref-error {{not an integral constant 
expression}} \
- // ref-note {{undefined function 'f'}}
+constexpr int f(); // both-note {{declared here}}
+static_assert(f() == 5, ""); // both-error {{not an integral constant 
expression}} \
+ // both-note {{undefined function 'f'}}
 constexpr int a() {
   return f();
 }
@@ -108,17 +102,14 @@ static_assert(a() == 5, "");
 
 constexpr int invalid() {
   // Invalid expression in visit().
-  while(huh) {} // expected-error {{use of undeclared identifier}} \
-// ref-error {{use of undeclared identifier}}
-
+  while(huh) {} // both-error {{use of undeclared identifier}}
   return 0;
 }
 
 constexpr void invalid2() {
   int i = 0;
   // Invalid expression in discard().
-  huh(); // expected-error {{use of undeclared identifier}} \
- // ref-error {{use of undeclared identifier}}
+  huh(); // both-error {{use of undeclared identifier}}
 }
 
 namespace FunctionPointers {
@@ -160,8 +151,7 @@ namespace FunctionReturnType {
   constexpr ptr fun() {
   return 
   }
-  static_assert(fun() == nullptr, ""); // expected-error {{static assertion 
failed}} \
-   // ref-error {{static assertion failed}}
+  static_assert(fun() == nullptr, ""); // both-error {{static assertion 
failed}}
 
   constexpr int foo() {
 int (*f)(int *) = fun();
@@ -188,32 +178,23 @@ namespace FunctionReturnType {
   constexpr int (*op2)(int, int) = nullptr;
   static_assert(!op2, "");
 
-  int m() { return 5;} // ref-note {{declared here}} \
-   // expected-note {{declared here}}
+  int m() { return 5;} // both-note {{declared here}}
   constexpr int (*invalidFnPtr)() = m;
-  static_assert(invalidFnPtr() == 5, ""); // ref-error {{not an integral 
constant expression}} \
- // 

[clang] [clang][Interp] Do r-to-l conversion immediately when returning (PR #80662)

2024-02-14 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/80662

>From b93916c9798ea09488e30b9b0aae9e54ef0b1956 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Thu, 15 Feb 2024 07:03:58 +0100
Subject: [PATCH 1/2] [clang][Interp][NFC] Convert test to verify=expected,both
 style

---
 clang/test/AST/Interp/functions.cpp | 198 ++--
 1 file changed, 68 insertions(+), 130 deletions(-)

diff --git a/clang/test/AST/Interp/functions.cpp 
b/clang/test/AST/Interp/functions.cpp
index 34a832c794c75d..320691336bdd99 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
-// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -verify 
%s
-// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify 
%s
-// RUN: %clang_cc1 -verify=ref %s
-// RUN: %clang_cc1 -std=c++14 -verify=ref %s
-// RUN: %clang_cc1 -std=c++20 -verify=ref %s
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
+// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
+// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
+// RUN: %clang_cc1 -verify=ref,both %s
+// RUN: %clang_cc1 -std=c++14 -verify=ref,both %s
+// RUN: %clang_cc1 -std=c++20 -verify=ref,both %s
 
 constexpr void doNothing() {}
 constexpr int gimme5() {
@@ -23,16 +23,13 @@ static_assert(!identity(false), "");
 
 template
 constexpr bool sameSize() {
-  static_assert(sizeof(A) == sizeof(B), ""); // expected-error {{static 
assertion failed}} \
- // ref-error {{static assertion 
failed}} \
- // expected-note {{evaluates to}} 
\
- // ref-note {{evaluates to}}
+  static_assert(sizeof(A) == sizeof(B), ""); // both-error {{static assertion 
failed}} \
+ // both-note {{evaluates to}}
   return true;
 }
 static_assert(sameSize(), "");
 static_assert(sameSize(), "");
-static_assert(sameSize(), ""); // expected-note {{in instantiation 
of function template specialization}} \
-   // ref-note {{in instantiation of 
function template specialization}}
+static_assert(sameSize(), ""); // both-note {{in instantiation of 
function template specialization}}
 
 
 constexpr auto add(int a, int b) -> int {
@@ -92,12 +89,9 @@ static_assert(getNum<-2>() == -2, "");
 static_assert(getNum<10>() == 10, "");
 static_assert(getNum() == 5, "");
 
-constexpr int f(); // expected-note {{declared here}} \
-   // ref-note {{declared here}}
-static_assert(f() == 5, ""); // expected-error {{not an integral constant 
expression}} \
- // expected-note {{undefined function 'f'}} \
- // ref-error {{not an integral constant 
expression}} \
- // ref-note {{undefined function 'f'}}
+constexpr int f(); // both-note {{declared here}}
+static_assert(f() == 5, ""); // both-error {{not an integral constant 
expression}} \
+ // both-note {{undefined function 'f'}}
 constexpr int a() {
   return f();
 }
@@ -108,17 +102,14 @@ static_assert(a() == 5, "");
 
 constexpr int invalid() {
   // Invalid expression in visit().
-  while(huh) {} // expected-error {{use of undeclared identifier}} \
-// ref-error {{use of undeclared identifier}}
-
+  while(huh) {} // both-error {{use of undeclared identifier}}
   return 0;
 }
 
 constexpr void invalid2() {
   int i = 0;
   // Invalid expression in discard().
-  huh(); // expected-error {{use of undeclared identifier}} \
- // ref-error {{use of undeclared identifier}}
+  huh(); // both-error {{use of undeclared identifier}}
 }
 
 namespace FunctionPointers {
@@ -160,8 +151,7 @@ namespace FunctionReturnType {
   constexpr ptr fun() {
   return 
   }
-  static_assert(fun() == nullptr, ""); // expected-error {{static assertion 
failed}} \
-   // ref-error {{static assertion failed}}
+  static_assert(fun() == nullptr, ""); // both-error {{static assertion 
failed}}
 
   constexpr int foo() {
 int (*f)(int *) = fun();
@@ -188,32 +178,23 @@ namespace FunctionReturnType {
   constexpr int (*op2)(int, int) = nullptr;
   static_assert(!op2, "");
 
-  int m() { return 5;} // ref-note {{declared here}} \
-   // expected-note {{declared here}}
+  int m() { return 5;} // both-note {{declared here}}
   constexpr int (*invalidFnPtr)() = m;
-  static_assert(invalidFnPtr() == 5, ""); // ref-error {{not an integral 
constant expression}} \
- // ref-note {{non-constexpr function 

[clang] b200dfc - [clang][Interp] Fix calling invalid function pointers

2024-02-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-02-15T07:23:35+01:00
New Revision: b200dfc15904f0f7f19443fd5a399242c80213dc

URL: 
https://github.com/llvm/llvm-project/commit/b200dfc15904f0f7f19443fd5a399242c80213dc
DIFF: 
https://github.com/llvm/llvm-project/commit/b200dfc15904f0f7f19443fd5a399242c80213dc.diff

LOG: [clang][Interp] Fix calling invalid function pointers

Checking for isConstexpr() is wrong; we need to (try to) call
the function and let later code diagnose the failure accordingly.

Added: 


Modified: 
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/functions.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 77c724f08e8eef..5bbb9f169a800e 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2071,8 +2071,7 @@ inline bool CallPtr(InterpState , CodePtr OpPC, 
uint32_t ArgSize) {
   const FunctionPointer  = S.Stk.pop();
 
   const Function *F = FuncPtr.getFunction();
-  if (!F || !F->isConstexpr())
-return false;
+  assert(F);
 
   assert(ArgSize >= F->getWrittenArgSize());
   uint32_t VarArgSize = ArgSize - F->getWrittenArgSize();

diff  --git a/clang/test/AST/Interp/functions.cpp 
b/clang/test/AST/Interp/functions.cpp
index 7b8278cf13aa88..34a832c794c75d 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -187,6 +187,14 @@ namespace FunctionReturnType {
   static_assert(!!op, "");
   constexpr int (*op2)(int, int) = nullptr;
   static_assert(!op2, "");
+
+  int m() { return 5;} // ref-note {{declared here}} \
+   // expected-note {{declared here}}
+  constexpr int (*invalidFnPtr)() = m;
+  static_assert(invalidFnPtr() == 5, ""); // ref-error {{not an integral 
constant expression}} \
+ // ref-note {{non-constexpr function 'm'}} \
+ // expected-error {{not an integral constant 
expression}} \
+ // expected-note {{non-constexpr function 
'm'}}
 }
 
 namespace Comparison {



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


[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

2024-02-14 Thread Atousa Duprat via cfe-commits

https://github.com/Atousa updated 
https://github.com/llvm/llvm-project/pull/80939

>From ac75fc2873fc7b8eec6c24ba97f4673e94457c8e Mon Sep 17 00:00:00 2001
From: Atousa Duprat 
Date: Tue, 6 Feb 2024 21:02:05 -0800
Subject: [PATCH 1/5] [clang] Use separator for large numeric values in
 overflow diagnostic

Add functionality to APInt::toString() that allows it to insert
separators between groups of digits, using the C++ litteral
separator ' between groups.

Fixes issue #58228
---
 clang/lib/AST/ExprConstant.cpp  |   6 +-
 clang/test/AST/Interp/c.c   |   4 +-
 clang/test/C/drs/dr0xx.c|   2 +-
 clang/test/C/drs/dr2xx.c|   2 +-
 clang/test/Sema/integer-overflow.c  | 100 -
 clang/test/Sema/switch-1.c  |   6 +-
 clang/test/SemaCXX/enum.cpp |   4 +-
 clang/test/SemaCXX/integer-overflow.cpp | 112 ++--
 clang/test/SemaObjC/integer-overflow.m  |   4 +-
 clang/test/SemaObjC/objc-literal-nsnumber.m |   2 +-
 llvm/include/llvm/ADT/APInt.h   |   3 +-
 llvm/include/llvm/ADT/StringExtras.h|   5 +-
 llvm/lib/Support/APInt.cpp  |  24 -
 llvm/unittests/ADT/APIntTest.cpp|  35 ++
 14 files changed, 185 insertions(+), 124 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 089bc2094567f7..d9037072c6767f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2774,7 +2774,8 @@ static bool CheckedIntArithmetic(EvalInfo , const 
Expr *E,
 if (Info.checkingForUndefinedBehavior())
   Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_integer_constant_overflow)
-  << toString(Result, 10) << E->getType() << E->getSourceRange();
+  << toString(Result, 10, Result.isSigned(), false, true, true)
+  << E->getType() << E->getSourceRange();
 return HandleOverflow(Info, E, Value, E->getType());
   }
   return true;
@@ -13852,7 +13853,8 @@ bool IntExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   if (Info.checkingForUndefinedBehavior())
 Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
  diag::warn_integer_constant_overflow)
-<< toString(Value, 10) << E->getType() << E->getSourceRange();
+<< toString(Value, 10, Value.isSigned(), false, true, true)
+<< E->getType() << E->getSourceRange();
 
   if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
   E->getType()))
diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 9ab271a82aeef9..aa067b0bc74831 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -109,9 +109,9 @@ int somefunc(int i) {
  // pedantic-expected-warning {{left operand of 
comma operator has no effect}} \
  // pedantic-expected-warning {{overflow in 
expression; result is 131073}} \
  // ref-warning {{left operand of comma operator 
has no effect}} \
- // ref-warning {{overflow in expression; result 
is 131073}} \
+ // ref-warning {{overflow in expression; result 
is 131'073}} \
  // pedantic-ref-warning {{left operand of comma 
operator has no effect}} \
- // pedantic-ref-warning {{overflow in expression; 
result is 131073}}
+ // pedantic-ref-warning {{overflow in expression; 
result is 131'073}}
 
 }
 
diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c
index d9c1fbe4ee40ab..c93cfb63d604cf 100644
--- a/clang/test/C/drs/dr0xx.c
+++ b/clang/test/C/drs/dr0xx.c
@@ -214,7 +214,7 @@ _Static_assert(__builtin_types_compatible_p(struct S { int 
a; }, union U { int a
  */
 void dr031(int i) {
   switch (i) {
-  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; 
result is -2147483648 with type 'int'}} */
+  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; 
result is -2'147'483'648 with type 'int'}} */
   #pragma clang diagnostic push
   #pragma clang diagnostic ignored "-Wswitch"
   /* Silence the targets which issue:
diff --git a/clang/test/C/drs/dr2xx.c b/clang/test/C/drs/dr2xx.c
index 9c8d77518ab55e..1b68b65acca6af 100644
--- a/clang/test/C/drs/dr2xx.c
+++ b/clang/test/C/drs/dr2xx.c
@@ -277,7 +277,7 @@ void dr258(void) {
 void dr261(void) {
   /* This is still an integer constant expression despite the overflow. */
   enum e1 {
-ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; 
result is -2147483648 with type 'int'}} */
+ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; 
result is -2'147'483'648 with type 'int'}} */
   };
 
   /* This is not an integer constant 

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-14 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

My original idea was to get the SIO sanitizer working with `-fwrapv`, the issue 
[here](https://github.com/KSPP/linux/issues/26) even suggests it as a viable 
option. However, after seeing literal checks like:

```cpp
case LangOptions::SOB_Undefined:
if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
```

... I think the best option is to instrument a wrap sanitizer (which this PR 
does). A wrap sanitizer best captures the language semantics at hand while 
maintaining existing functionality of the SIO sanitizer. I think Kees can speak 
first hand about how picky some folks are about the language being used for 
this arithmetic overflow/wraparound stuff (he linked some gcc threads above my 
comment but I've also seen some spicy LKML discussions about how OVERFLOW 
doesn't exist in the Linux Kernel and as such WRAPAROUND instrumentation is 
needed).

I think this PR bridges the gap between folks like Kees (who just want all this 
suspicious kernel arithmetic to go away) and folks like Linus (who is really 
particular about language).

https://github.com/llvm/llvm-project/pull/80089
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 6087d7b - [clang-format][NFC] Sort options in Format.cpp

2024-02-14 Thread Owen Pan via cfe-commits

Author: Owen Pan
Date: 2024-02-14T21:40:07-08:00
New Revision: 6087d7bc0a9d7d4ad2c94a131c2bc427b767c9d7

URL: 
https://github.com/llvm/llvm-project/commit/6087d7bc0a9d7d4ad2c94a131c2bc427b767c9d7
DIFF: 
https://github.com/llvm/llvm-project/commit/6087d7bc0a9d7d4ad2c94a131c2bc427b767c9d7.diff

LOG: [clang-format][NFC] Sort options in Format.cpp

Added: 


Modified: 
clang/lib/Format/Format.cpp

Removed: 




diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 56cd9495920c7b..e67b2101f5821b 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1406,29 +1406,28 @@ static void expandPresetsSpacesInParens(FormatStyle 
) {
 
 FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
   FormatStyle LLVMStyle;
-  LLVMStyle.InheritsParentConfig = false;
-  LLVMStyle.Language = Language;
   LLVMStyle.AccessModifierOffset = -2;
-  LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
   LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
   LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
-  LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
   LLVMStyle.AlignConsecutiveAssignments = {};
-  LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
-  LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
   LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;
+  LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
   LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;
   LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false;
+  LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
   LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
   LLVMStyle.AlignConsecutiveBitFields = {};
   LLVMStyle.AlignConsecutiveDeclarations = {};
   LLVMStyle.AlignConsecutiveMacros = {};
   LLVMStyle.AlignConsecutiveShortCaseStatements = {};
+  LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
+  LLVMStyle.AlignOperands = FormatStyle::OAS_Align;
   LLVMStyle.AlignTrailingComments = {};
   LLVMStyle.AlignTrailingComments.Kind = FormatStyle::TCAS_Always;
   LLVMStyle.AlignTrailingComments.OverEmptyLines = 0;
   LLVMStyle.AllowAllArgumentsOnNextLine = true;
   LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
+  LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
   LLVMStyle.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never;
   LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
   LLVMStyle.AllowShortCompoundRequirementOnASingleLine = true;
@@ -1439,11 +1438,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.AllowShortLoopsOnASingleLine = false;
   LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
   LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
-  LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
   LLVMStyle.AttributeMacros.push_back("__capability");
-  LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
   LLVMStyle.BinPackArguments = true;
   LLVMStyle.BinPackParameters = true;
+  LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both;
   LLVMStyle.BracedInitializerIndentWidth = std::nullopt;
   LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false,
  /*AfterClass=*/false,
@@ -1472,11 +1470,11 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
   LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
   LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
-  LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
   LLVMStyle.BreakBeforeTernaryOperators = true;
   LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
   LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
   LLVMStyle.BreakStringLiterals = true;
+  LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
   LLVMStyle.ColumnLimit = 80;
   LLVMStyle.CommentPragmas = "^ IWYU pragma:";
   LLVMStyle.CompactNamespaces = false;
@@ -1493,22 +1491,23 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
   LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
   LLVMStyle.IfMacros.push_back("KJ_IF_MAYBE");
+  LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
   LLVMStyle.IncludeStyle.IncludeCategories = {
   {"^\"(llvm|llvm-c|clang|clang-c)/", 2, 0, false},
   {"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
   {".*", 1, 0, false}};
   LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
-  LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
   LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
   LLVMStyle.IndentAccessModifiers = false;
-  LLVMStyle.IndentCaseLabels = false;
   

[clang] d53515a - [clang][Interp] Fix variadic member functions

2024-02-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-02-15T05:59:53+01:00
New Revision: d53515afef57a3abf84daff169fbc7626a306817

URL: 
https://github.com/llvm/llvm-project/commit/d53515afef57a3abf84daff169fbc7626a306817
DIFF: 
https://github.com/llvm/llvm-project/commit/d53515afef57a3abf84daff169fbc7626a306817.diff

LOG: [clang][Interp] Fix variadic member functions

For variadic member functions, the way we calculated the instance
pointer and RVO pointer offsts on the stack was incorrect, due
to Func->getArgSize() not returning the full size of all the
passed arguments. When calling variadic functions, we need
to pass the size of the passed (variadic) arguments to the Call*
ops, so they can use that information to properly check the
instance pointer, etc.

This patch adds a bit of code duplication in Interp.h, which I
will get rid of in later cleanup NFC patches.

Added: 


Modified: 
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeStmtGen.cpp
clang/lib/AST/Interp/Context.cpp
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/Function.h
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/InterpFrame.cpp
clang/lib/AST/Interp/InterpFrame.h
clang/lib/AST/Interp/Opcodes.td
clang/test/AST/Interp/functions.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 91b9985eefbd30..988765972a36e6 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1829,8 +1829,19 @@ bool ByteCodeExprGen::VisitCXXConstructExpr(
 return false;
 }
 
-if (!this->emitCall(Func, E))
-  return false;
+if (Func->isVariadic()) {
+  uint32_t VarArgSize = 0;
+  unsigned NumParams = Func->getNumWrittenParams();
+  for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I) {
+VarArgSize +=
+
align(primSize(classify(E->getArg(I)->getType()).value_or(PT_Ptr)));
+  }
+  if (!this->emitCallVar(Func, VarArgSize, E))
+return false;
+} else {
+  if (!this->emitCall(Func, 0, E))
+return false;
+}
 
 // Immediately call the destructor if we have to.
 if (DiscardResult) {
@@ -1863,7 +1874,7 @@ bool ByteCodeExprGen::VisitCXXConstructExpr(
   return false;
   }
 
-  if (!this->emitCall(Func, E))
+  if (!this->emitCall(Func, 0, E))
 return false;
 }
 return true;
@@ -2049,7 +2060,7 @@ bool 
ByteCodeExprGen::VisitCXXInheritedCtorInitExpr(
 Offset += align(primSize(PT));
   }
 
-  return this->emitCall(F, E);
+  return this->emitCall(F, 0, E);
 }
 
 template 
@@ -2846,20 +2857,38 @@ bool ByteCodeExprGen::VisitCallExpr(const 
CallExpr *E) {
 // and if the function has RVO, we already have the pointer on the stack to
 // write the result into.
 if (IsVirtual && !HasQualifier) {
-  if (!this->emitCallVirt(Func, E))
+  uint32_t VarArgSize = 0;
+  unsigned NumParams = Func->getNumWrittenParams();
+  for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
+VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
+
+  if (!this->emitCallVirt(Func, VarArgSize, E))
+return false;
+} else if (Func->isVariadic()) {
+  uint32_t VarArgSize = 0;
+  unsigned NumParams = Func->getNumWrittenParams();
+  for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
+VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
+  if (!this->emitCallVar(Func, VarArgSize, E))
 return false;
 } else {
-  if (!this->emitCall(Func, E))
+  if (!this->emitCall(Func, 0, E))
 return false;
 }
   } else {
 // Indirect call. Visit the callee, which will leave a FunctionPointer on
 // the stack. Cleanup of the returned value if necessary will be done after
 // the function call completed.
+
+// Sum the size of all args from the call expr.
+uint32_t ArgSize = 0;
+for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+  ArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
+
 if (!this->visit(E->getCallee()))
   return false;
 
-if (!this->emitCallPtr(E))
+if (!this->emitCallPtr(ArgSize, E))
   return false;
   }
 
@@ -3386,7 +3415,7 @@ bool 
ByteCodeExprGen::emitRecordDestruction(const Descriptor *Desc) {
   assert(DtorFunc->getNumParams() == 1);
   if (!this->emitDupPtr(SourceInfo{}))
 return false;
-  if (!this->emitCall(DtorFunc, SourceInfo{}))
+  if (!this->emitCall(DtorFunc, 0, SourceInfo{}))
 return false;
 }
   }

diff  --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp 
b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
index bedcc78dc23555..7e2043f8de90b0 100644
--- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
+++ 

[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

2024-02-14 Thread Timm Baeder via cfe-commits


@@ -2187,6 +2188,12 @@ void APInt::toString(SmallVectorImpl , 
unsigned Radix, bool Signed,
 }
   }
 
+  // Number of digits in a group between separators.
+  unsigned Grouping = (Radix == 8 || Radix == 10) ? 3 : 4;
+  if (Radix == 8 || Radix == 10) {
+Grouping = 3;
+  }
+

tbaederr wrote:

This code block is now unnecessary.

https://github.com/llvm/llvm-project/pull/80939
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Fix behavior of `__is_trivially_relocatable(volatile int)` (PR #77092)

2024-02-14 Thread Amirreza Ashouri via cfe-commits

AMP999 wrote:

Thanks all for the review! @AaronBallman, Could you please land this patch for 
me?

https://github.com/llvm/llvm-project/pull/77092
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [MC/DC] Refactor: Let MCDCConditionID int16_t with zero-origin (PR #81257)

2024-02-14 Thread Jessica Paquette via cfe-commits

https://github.com/ornata approved this pull request.


https://github.com/llvm/llvm-project/pull/81257
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [clang] Use separator for large numeric values in overflow diagnostic (PR #80939)

2024-02-14 Thread Atousa Duprat via cfe-commits

https://github.com/Atousa updated 
https://github.com/llvm/llvm-project/pull/80939

>From ac75fc2873fc7b8eec6c24ba97f4673e94457c8e Mon Sep 17 00:00:00 2001
From: Atousa Duprat 
Date: Tue, 6 Feb 2024 21:02:05 -0800
Subject: [PATCH 1/5] [clang] Use separator for large numeric values in
 overflow diagnostic

Add functionality to APInt::toString() that allows it to insert
separators between groups of digits, using the C++ litteral
separator ' between groups.

Fixes issue #58228
---
 clang/lib/AST/ExprConstant.cpp  |   6 +-
 clang/test/AST/Interp/c.c   |   4 +-
 clang/test/C/drs/dr0xx.c|   2 +-
 clang/test/C/drs/dr2xx.c|   2 +-
 clang/test/Sema/integer-overflow.c  | 100 -
 clang/test/Sema/switch-1.c  |   6 +-
 clang/test/SemaCXX/enum.cpp |   4 +-
 clang/test/SemaCXX/integer-overflow.cpp | 112 ++--
 clang/test/SemaObjC/integer-overflow.m  |   4 +-
 clang/test/SemaObjC/objc-literal-nsnumber.m |   2 +-
 llvm/include/llvm/ADT/APInt.h   |   3 +-
 llvm/include/llvm/ADT/StringExtras.h|   5 +-
 llvm/lib/Support/APInt.cpp  |  24 -
 llvm/unittests/ADT/APIntTest.cpp|  35 ++
 14 files changed, 185 insertions(+), 124 deletions(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 089bc2094567f7..d9037072c6767f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2774,7 +2774,8 @@ static bool CheckedIntArithmetic(EvalInfo , const 
Expr *E,
 if (Info.checkingForUndefinedBehavior())
   Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
diag::warn_integer_constant_overflow)
-  << toString(Result, 10) << E->getType() << E->getSourceRange();
+  << toString(Result, 10, Result.isSigned(), false, true, true)
+  << E->getType() << E->getSourceRange();
 return HandleOverflow(Info, E, Value, E->getType());
   }
   return true;
@@ -13852,7 +13853,8 @@ bool IntExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   if (Info.checkingForUndefinedBehavior())
 Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
  diag::warn_integer_constant_overflow)
-<< toString(Value, 10) << E->getType() << E->getSourceRange();
+<< toString(Value, 10, Value.isSigned(), false, true, true)
+<< E->getType() << E->getSourceRange();
 
   if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
   E->getType()))
diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 9ab271a82aeef9..aa067b0bc74831 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -109,9 +109,9 @@ int somefunc(int i) {
  // pedantic-expected-warning {{left operand of 
comma operator has no effect}} \
  // pedantic-expected-warning {{overflow in 
expression; result is 131073}} \
  // ref-warning {{left operand of comma operator 
has no effect}} \
- // ref-warning {{overflow in expression; result 
is 131073}} \
+ // ref-warning {{overflow in expression; result 
is 131'073}} \
  // pedantic-ref-warning {{left operand of comma 
operator has no effect}} \
- // pedantic-ref-warning {{overflow in expression; 
result is 131073}}
+ // pedantic-ref-warning {{overflow in expression; 
result is 131'073}}
 
 }
 
diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c
index d9c1fbe4ee40ab..c93cfb63d604cf 100644
--- a/clang/test/C/drs/dr0xx.c
+++ b/clang/test/C/drs/dr0xx.c
@@ -214,7 +214,7 @@ _Static_assert(__builtin_types_compatible_p(struct S { int 
a; }, union U { int a
  */
 void dr031(int i) {
   switch (i) {
-  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; 
result is -2147483648 with type 'int'}} */
+  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; 
result is -2'147'483'648 with type 'int'}} */
   #pragma clang diagnostic push
   #pragma clang diagnostic ignored "-Wswitch"
   /* Silence the targets which issue:
diff --git a/clang/test/C/drs/dr2xx.c b/clang/test/C/drs/dr2xx.c
index 9c8d77518ab55e..1b68b65acca6af 100644
--- a/clang/test/C/drs/dr2xx.c
+++ b/clang/test/C/drs/dr2xx.c
@@ -277,7 +277,7 @@ void dr258(void) {
 void dr261(void) {
   /* This is still an integer constant expression despite the overflow. */
   enum e1 {
-ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; 
result is -2147483648 with type 'int'}} */
+ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; 
result is -2'147'483'648 with type 'int'}} */
   };
 
   /* This is not an integer constant 

[clang] fa9e297 - [ClangPackager] Fix passing in multiple instances of `file`

2024-02-14 Thread Joseph Huber via cfe-commits

Author: Joseph Huber
Date: 2024-02-14T22:11:21-06:00
New Revision: fa9e297b8b63dacb962d99814e698658ad71f946

URL: 
https://github.com/llvm/llvm-project/commit/fa9e297b8b63dacb962d99814e698658ad71f946
DIFF: 
https://github.com/llvm/llvm-project/commit/fa9e297b8b63dacb962d99814e698658ad71f946.diff

LOG: [ClangPackager] Fix passing in multiple instances of `file`

Summary:
This is necessary because CMake build tools might need to generate
several files but are unable to put them in separate images. This patch
sipmly moves the file handling out into a separate split iterator.

Added: 


Modified: 
clang/tools/clang-offload-packager/ClangOffloadPackager.cpp

Removed: 




diff  --git a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp 
b/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp
index 08de3f3a3771c1..c36a5aa58cee50 100644
--- a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp
+++ b/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp
@@ -104,33 +104,36 @@ static Error bundleImages() {
   inconvertibleErrorCode(),
   "'file' and 'triple' are required image arguments");
 
-OffloadBinary::OffloadingImage ImageBinary{};
-std::unique_ptr DeviceImage;
-for (const auto &[Key, Value] : Args) {
-  if (Key == "file") {
-llvm::ErrorOr> ObjectOrErr =
-llvm::MemoryBuffer::getFileOrSTDIN(Value);
-if (std::error_code EC = ObjectOrErr.getError())
-  return errorCodeToError(EC);
-
-// Clang uses the '.o' suffix for LTO bitcode.
-if (identify_magic((*ObjectOrErr)->getBuffer()) == file_magic::bitcode)
-  ImageBinary.TheImageKind = object::IMG_Bitcode;
-else
-  ImageBinary.TheImageKind =
-  getImageKind(sys::path::extension(Value).drop_front());
-ImageBinary.Image = std::move(*ObjectOrErr);
-  } else if (Key == "kind") {
-ImageBinary.TheOffloadKind = getOffloadKind(Value);
-  } else {
-ImageBinary.StringData[Key] = Value;
+// Permit using multiple instances of `file` in a single string.
+for (auto  : llvm::split(Args["file"], ",")) {
+  OffloadBinary::OffloadingImage ImageBinary{};
+  std::unique_ptr DeviceImage;
+
+  llvm::ErrorOr> ObjectOrErr =
+  llvm::MemoryBuffer::getFileOrSTDIN(File);
+  if (std::error_code EC = ObjectOrErr.getError())
+return errorCodeToError(EC);
+
+  // Clang uses the '.o' suffix for LTO bitcode.
+  if (identify_magic((*ObjectOrErr)->getBuffer()) == file_magic::bitcode)
+ImageBinary.TheImageKind = object::IMG_Bitcode;
+  else
+ImageBinary.TheImageKind =
+getImageKind(sys::path::extension(File).drop_front());
+  ImageBinary.Image = std::move(*ObjectOrErr);
+  for (const auto &[Key, Value] : Args) {
+if (Key == "kind") {
+  ImageBinary.TheOffloadKind = getOffloadKind(Value);
+} else if (Key != "file") {
+  ImageBinary.StringData[Key] = Value;
+}
   }
+  llvm::SmallString<0> Buffer = OffloadBinary::write(ImageBinary);
+  if (Buffer.size() % OffloadBinary::getAlignment() != 0)
+return createStringError(inconvertibleErrorCode(),
+ "Offload binary has invalid size alignment");
+  OS << Buffer;
 }
-llvm::SmallString<0> Buffer = OffloadBinary::write(ImageBinary);
-if (Buffer.size() % OffloadBinary::getAlignment() != 0)
-  return createStringError(inconvertibleErrorCode(),
-   "Offload binary has invalid size alignment");
-OS << Buffer;
   }
 
   if (Error E = writeFile(OutputFile,



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


[clang] [clang-format][NFC] Drop "Always" in "AlwaysBreakAfterReturnType". (PR #81591)

2024-02-14 Thread Owen Pan via cfe-commits

https://github.com/owenca closed https://github.com/llvm/llvm-project/pull/81591
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] d821650 - [clang-format][NFC] Drop "Always" in "AlwaysBreakAfterReturnType". (#81591)

2024-02-14 Thread via cfe-commits

Author: rmarker
Date: 2024-02-14T20:10:56-08:00
New Revision: d821650e13145a1acccd337c9853354ad6531507

URL: 
https://github.com/llvm/llvm-project/commit/d821650e13145a1acccd337c9853354ad6531507
DIFF: 
https://github.com/llvm/llvm-project/commit/d821650e13145a1acccd337c9853354ad6531507.diff

LOG: [clang-format][NFC] Drop "Always" in "AlwaysBreakAfterReturnType". (#81591)

Complete the switch from "AlwaysBreakAfterReturnType" to
"BreakAfterReturnType".

Added: 


Modified: 
clang/include/clang/Format/Format.h
clang/lib/Format/ContinuationIndenter.cpp
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/ConfigParseTest.cpp
clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/FormatTestCSharp.cpp

Removed: 




diff  --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 737cbfced9e9ce..e9b2160a7b9243 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -1013,7 +1013,7 @@ struct FormatStyle {
   /// This option is renamed to ``BreakAfterReturnType``.
   /// \version 3.8
   /// @deprecated
-  ReturnTypeBreakingStyle AlwaysBreakAfterReturnType;
+  // ReturnTypeBreakingStyle AlwaysBreakAfterReturnType;
 
   /// If ``true``, always break before multiline string literals.
   ///
@@ -1579,7 +1579,7 @@ struct FormatStyle {
 
   /// The function declaration return type breaking style to use.
   /// \version 19
-  // ReturnTypeBreakingStyle BreakAfterReturnType;
+  ReturnTypeBreakingStyle BreakAfterReturnType;
 
   /// If ``true``, clang-format will always break after a Json array ``[``
   /// otherwise it will scan until the closing ``]`` to determine if it should
@@ -4824,7 +4824,6 @@ struct FormatStyle {
R.AllowShortIfStatementsOnASingleLine &&
AllowShortLambdasOnASingleLine == R.AllowShortLambdasOnASingleLine 
&&
AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine &&
-   AlwaysBreakAfterReturnType == R.AlwaysBreakAfterReturnType &&
AlwaysBreakBeforeMultilineStrings ==
R.AlwaysBreakBeforeMultilineStrings &&
AttributeMacros == R.AttributeMacros &&
@@ -4835,6 +4834,7 @@ struct FormatStyle {
BreakAdjacentStringLiterals == R.BreakAdjacentStringLiterals &&
BreakAfterAttributes == R.BreakAfterAttributes &&
BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations 
&&
+   BreakAfterReturnType == R.BreakAfterReturnType &&
BreakArrays == R.BreakArrays &&
BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators &&
BreakBeforeBraces == R.BreakBeforeBraces &&

diff  --git a/clang/lib/Format/ContinuationIndenter.cpp 
b/clang/lib/Format/ContinuationIndenter.cpp
index 0b2ef97af44d83..159d130cb67332 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -329,12 +329,12 @@ bool ContinuationIndenter::canBreak(const LineState 
) {
   // Don't break after very short return types (e.g. "void") as that is often
   // unexpected.
   if (Current.is(TT_FunctionDeclarationName)) {
-if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None &&
+if (Style.BreakAfterReturnType == FormatStyle::RTBS_None &&
 State.Column < 6) {
   return false;
 }
 
-if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_ExceptShortType) 
{
+if (Style.BreakAfterReturnType == FormatStyle::RTBS_ExceptShortType) {
   assert(State.Column >= State.FirstIndent);
   if (State.Column - State.FirstIndent < 6)
 return false;
@@ -597,7 +597,7 @@ bool ContinuationIndenter::mustBreak(const LineState 
) {
   !State.Line->ReturnTypeWrapped &&
   // Don't break before a C# function when no break after return type.
   (!Style.isCSharp() ||
-   Style.AlwaysBreakAfterReturnType > FormatStyle::RTBS_ExceptShortType) &&
+   Style.BreakAfterReturnType > FormatStyle::RTBS_ExceptShortType) &&
   // Don't always break between a JavaScript `function` and the function
   // name.
   !Style.isJavaScript() && Previous.isNot(tok::kw_template) &&

diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 8efc42e0576cf9..56cd9495920c7b 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -877,8 +877,7 @@ template <> struct MappingTraits {
 if (!IO.outputting()) {
   IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
   IO.mapOptional("AllowAllConstructorInitializersOnNextLine", OnNextLine);
-  IO.mapOptional("AlwaysBreakAfterReturnType",
- Style.AlwaysBreakAfterReturnType);
+  IO.mapOptional("AlwaysBreakAfterReturnType", Style.BreakAfterReturnType);
   

[clang] dcbb574 - [analyzer] Teach scan-build to filter reports by file.

2024-02-14 Thread Artem Dergachev via cfe-commits

Author: Brianna Fan
Date: 2024-02-14T19:08:07-08:00
New Revision: dcbb574cfc3445251ff1c751f27b52ed6503bead

URL: 
https://github.com/llvm/llvm-project/commit/dcbb574cfc3445251ff1c751f27b52ed6503bead
DIFF: 
https://github.com/llvm/llvm-project/commit/dcbb574cfc3445251ff1c751f27b52ed6503bead.diff

LOG: [analyzer] Teach scan-build to filter reports by file.

That's a new GUI bell-and-whistle in the index.html page.

Added: 


Modified: 
clang/test/Analysis/scan-build/html_output.test
clang/tools/scan-build/bin/scan-build
clang/tools/scan-build/share/scan-build/sorttable.js

Removed: 




diff  --git a/clang/test/Analysis/scan-build/html_output.test 
b/clang/test/Analysis/scan-build/html_output.test
index eed2051d4df627..add35d83b95887 100644
--- a/clang/test/Analysis/scan-build/html_output.test
+++ b/clang/test/Analysis/scan-build/html_output.test
@@ -19,13 +19,17 @@ CHECK-FILENAMES: report-{{.*}}.html
 CHECK-FILENAMES: scanview.css
 CHECK-FILENAMES: sorttable.js
 
-
-// The index should have a link to the report for the single issue.
+// Tests for the front page.
 RUN: cat %t.output_dir/*/index.html \
 RUN: | FileCheck %s -check-prefix CHECK-INDEX-HTML
 
+// Let's confirm that the new filtering facility is present.
+CHECK-INDEX-HTML: Filter Results by File
+
+// The index should have a link to the report for the single issue.
 CHECK-INDEX-HTML: 
 
+
 // The report should describe the issue.
 RUN: cat %t.output_dir/*/report-*.html \
 RUN: | FileCheck %s -check-prefix CHECK-REPORT-HTML

diff  --git a/clang/tools/scan-build/bin/scan-build 
b/clang/tools/scan-build/bin/scan-build
index 04734d9cfa9af6..37241c6d85c5b2 100755
--- a/clang/tools/scan-build/bin/scan-build
+++ b/clang/tools/scan-build/bin/scan-build
@@ -722,9 +722,18 @@ ENDTEXT
 
 print OUT <
+
+Filter Results by File
+
+
 Reports
 
-
+
 
   Bug Group
   Bug Type

diff  --git a/clang/tools/scan-build/share/scan-build/sorttable.js 
b/clang/tools/scan-build/share/scan-build/sorttable.js
index 32faa078d89934..e608daa9e39bc5 100644
--- a/clang/tools/scan-build/share/scan-build/sorttable.js
+++ b/clang/tools/scan-build/share/scan-build/sorttable.js
@@ -490,3 +490,23 @@ var forEach = function(object, block, context) {
resolve.forEach(object, block, context);
}
 };
+
+// filter results by filename
+const searchFiles = () => {
+  const columns = [
+{ name: 'Filename', index: 2, isFilter: true },
+  ]
+  const filterColumns = columns.filter(c => c.isFilter).map(c => c.index)
+  const trs = document.querySelectorAll(`#reports_table tr:not(.header)`)
+  const filter = document.querySelector('#file_input').value
+  const regex = new RegExp(escape(filter), 'i')
+  const isFoundInTds = td => regex.test(td.innerHTML)
+  const isFound = childrenArr => childrenArr.some(isFoundInTds)
+  const setTrStyleDisplay = ({ style, children }) => {
+style.display = isFound([
+  ...filterColumns.map(c => children[c])
+]) ? '' : 'none'
+  }
+
+  trs.forEach(setTrStyleDisplay)
+}



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


[clang] [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (PR #81343)

2024-02-14 Thread via cfe-commits

https://github.com/jkorous-apple closed 
https://github.com/llvm/llvm-project/pull/81343
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 6fce42f - [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (#81343)

2024-02-14 Thread via cfe-commits

Author: jkorous-apple
Date: 2024-02-14T19:03:37-08:00
New Revision: 6fce42f89a2c3f12b019bd3d7fef3e8db2d4671f

URL: 
https://github.com/llvm/llvm-project/commit/6fce42f89a2c3f12b019bd3d7fef3e8db2d4671f
DIFF: 
https://github.com/llvm/llvm-project/commit/6fce42f89a2c3f12b019bd3d7fef3e8db2d4671f.diff

LOG: [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (#81343)

Introducing CArrayToPtrAssignment gadget and implementing fixits for some cases
of array being assigned to pointer.

Key observations:
- const size array can be assigned to std::span and bounds are propagated
- const size array can't be on LHS of assignment
This means array to pointer assignment has no strategy implications.

Fixits are implemented for cases where one of the variables in the assignment is
safe. For assignment of a safe array to unsafe pointer we know that the RHS will
never be transformed since it's safe and can immediately emit the optimal fixit.
Similarly for assignment of unsafe array to safe pointer.
(Obviously this is not and can't be future-proof in regards to what
variables we consider unsafe and that is fine.)

Fixits for assignment from unsafe array to unsafe pointer (from Array to Span
strategy) are not implemented in this patch as that needs to be properly 
designed
first - we might possibly implement optimal fixits for partially transformed
cases, put both variables in a single fixit group or do something else.

Added: 
clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-array-assign-to-ptr.cpp

Modified: 
clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
clang/lib/Analysis/UnsafeBufferUsage.cpp
clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp

Removed: 




diff  --git 
a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def 
b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
index 07f805ebb11013..3273c642eed517 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
@@ -45,7 +45,8 @@ FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in 
an Unspecified Poin
 FIXABLE_GADGET(UPCStandalonePointer)
 FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified 
Pointer Context
 FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified 
Untyped Context
-FIXABLE_GADGET(PointerAssignment)
+FIXABLE_GADGET(PtrToPtrAssignment)
+FIXABLE_GADGET(CArrayToPtrAssignment)
 FIXABLE_GADGET(PointerInit)
 
 #undef FIXABLE_GADGET

diff  --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index a74c113e29f1cf..769c6d9ebefaa5 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -7,11 +7,14 @@
 
//===--===//
 
 #include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Lex/Lexer.h"
@@ -799,7 +802,8 @@ class PointerInitGadget : public FixableGadget {
 ///  \code
 ///  p = q;
 ///  \endcode
-class PointerAssignmentGadget : public FixableGadget {
+/// where both `p` and `q` are pointers.
+class PtrToPtrAssignmentGadget : public FixableGadget {
 private:
   static constexpr const char *const PointerAssignLHSTag = "ptrLHS";
   static constexpr const char *const PointerAssignRHSTag = "ptrRHS";
@@ -807,13 +811,13 @@ class PointerAssignmentGadget : public FixableGadget {
   const DeclRefExpr * PtrRHS; // the RHS pointer expression in `PA`
 
 public:
-  PointerAssignmentGadget(const MatchFinder::MatchResult )
-  : FixableGadget(Kind::PointerAssignment),
-PtrLHS(Result.Nodes.getNodeAs(PointerAssignLHSTag)),
-PtrRHS(Result.Nodes.getNodeAs(PointerAssignRHSTag)) {}
+  PtrToPtrAssignmentGadget(const MatchFinder::MatchResult )
+  : FixableGadget(Kind::PtrToPtrAssignment),
+PtrLHS(Result.Nodes.getNodeAs(PointerAssignLHSTag)),
+PtrRHS(Result.Nodes.getNodeAs(PointerAssignRHSTag)) {}
 
   static bool classof(const Gadget *G) {
-return G->getKind() == Kind::PointerAssignment;
+return G->getKind() == Kind::PtrToPtrAssignment;
   }
 
   static Matcher matcher() {
@@ -848,6 +852,60 @@ class PointerAssignmentGadget : public FixableGadget {
   }
 };
 
+/// An assignment expression of the form:
+///  \code
+///  ptr = array;
+///  \endcode
+/// where `p` is a pointer and `array` is a constant size array.
+class CArrayToPtrAssignmentGadget : public FixableGadget {
+private:
+  static constexpr const 

[clang] [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (PR #81343)

2024-02-14 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ approved this pull request.

LGTM let's land!

https://github.com/llvm/llvm-project/pull/81343
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (PR #81343)

2024-02-14 Thread via cfe-commits

https://github.com/jkorous-apple updated 
https://github.com/llvm/llvm-project/pull/81343

>From 791130c5c5de31084c168db33531a5d856104506 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Thu, 8 Feb 2024 14:30:20 -0800
Subject: [PATCH 1/5] [-Wunsafe-buffer-usage][NFC] Factor out .data() fixit to
 a function

---
 clang/lib/Analysis/UnsafeBufferUsage.cpp | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index a74c113e29f1cf..cc49876779ece2 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -1490,6 +1490,9 @@ PointerAssignmentGadget::getFixits(const FixitStrategy 
) const {
   return std::nullopt;
 }
 
+/// \returns fixit that adds .data() call after \DRE.
+static inline std::optional createDataFixit(const ASTContext& Ctx, 
const DeclRefExpr * DRE);
+
 std::optional
 PointerInitGadget::getFixits(const FixitStrategy ) const {
   const auto *LeftVD = PtrInitLHS;
@@ -1907,6 +1910,18 @@ PointerDereferenceGadget::getFixits(const FixitStrategy 
) const {
   return std::nullopt;
 }
 
+static inline std::optional createDataFixit(const ASTContext& Ctx, 
const DeclRefExpr * DRE) {
+  const SourceManager  = Ctx.getSourceManager();
+  // Inserts the .data() after the DRE
+  std::optional EndOfOperand =
+  getPastLoc(DRE, SM, Ctx.getLangOpts());
+
+  if (EndOfOperand)
+return FixItList{{FixItHint::CreateInsertion(*EndOfOperand, ".data()")}};
+
+  return std::nullopt;
+}
+
 // Generates fix-its replacing an expression of the form UPC(DRE) with
 // `DRE.data()`
 std::optional
@@ -1915,14 +1930,7 @@ UPCStandalonePointerGadget::getFixits(const 
FixitStrategy ) const {
   switch (S.lookup(VD)) {
   case FixitStrategy::Kind::Array:
   case FixitStrategy::Kind::Span: {
-ASTContext  = VD->getASTContext();
-SourceManager  = Ctx.getSourceManager();
-// Inserts the .data() after the DRE
-std::optional EndOfOperand =
-getPastLoc(Node, SM, Ctx.getLangOpts());
-
-if (EndOfOperand)
-  return FixItList{{FixItHint::CreateInsertion(*EndOfOperand, ".data()")}};
+return createDataFixit(VD->getASTContext(), Node);
 // FIXME: Points inside a macro expansion.
 break;
   }

>From 1b12f7413288b01d1806b98fb90c2d44e53b7437 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Thu, 8 Feb 2024 14:33:03 -0800
Subject: [PATCH 2/5] [-Wunsafe-buffer-usage][NFC] Rename PointerAssignment
 gadget to PtrToPtrAssignment

---
 .../Analysis/Analyses/UnsafeBufferUsageGadgets.def|  2 +-
 clang/lib/Analysis/UnsafeBufferUsage.cpp  | 11 ++-
 clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp |  2 +-
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def 
b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
index 07f805ebb11013..2babc1df93d515 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
@@ -45,7 +45,7 @@ FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in 
an Unspecified Poin
 FIXABLE_GADGET(UPCStandalonePointer)
 FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified 
Pointer Context
 FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified 
Untyped Context
-FIXABLE_GADGET(PointerAssignment)
+FIXABLE_GADGET(PtrToPtrAssignment)
 FIXABLE_GADGET(PointerInit)
 
 #undef FIXABLE_GADGET
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index cc49876779ece2..927baef2fffa39 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -799,7 +799,8 @@ class PointerInitGadget : public FixableGadget {
 ///  \code
 ///  p = q;
 ///  \endcode
-class PointerAssignmentGadget : public FixableGadget {
+/// where both `p` and `q` are pointers.
+class PtrToPtrAssignmentGadget : public FixableGadget {
 private:
   static constexpr const char *const PointerAssignLHSTag = "ptrLHS";
   static constexpr const char *const PointerAssignRHSTag = "ptrRHS";
@@ -807,13 +808,13 @@ class PointerAssignmentGadget : public FixableGadget {
   const DeclRefExpr * PtrRHS; // the RHS pointer expression in `PA`
 
 public:
-  PointerAssignmentGadget(const MatchFinder::MatchResult )
-  : FixableGadget(Kind::PointerAssignment),
+  PtrToPtrAssignmentGadget(const MatchFinder::MatchResult )
+  : FixableGadget(Kind::PtrToPtrAssignment),
 PtrLHS(Result.Nodes.getNodeAs(PointerAssignLHSTag)),
 PtrRHS(Result.Nodes.getNodeAs(PointerAssignRHSTag)) {}
 
   static bool classof(const Gadget *G) {
-return G->getKind() == Kind::PointerAssignment;
+return G->getKind() == Kind::PtrToPtrAssignment;
   }
 
   static Matcher matcher() {
@@ -1471,7 +1472,7 @@ bool clang::internal::anyConflict(const 
SmallVectorImpl ,
 }
 
 

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ closed https://github.com/llvm/llvm-project/pull/81808
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] a7982d5 - [analyzer] UncountedCallArgsChecker: Detect & ignore trivial function calls. (#81808)

2024-02-14 Thread via cfe-commits

Author: Ryosuke Niwa
Date: 2024-02-14T18:46:30-08:00
New Revision: a7982d5e7a16f681e80891a819bdf14dde928755

URL: 
https://github.com/llvm/llvm-project/commit/a7982d5e7a16f681e80891a819bdf14dde928755
DIFF: 
https://github.com/llvm/llvm-project/commit/a7982d5e7a16f681e80891a819bdf14dde928755.diff

LOG: [analyzer] UncountedCallArgsChecker: Detect & ignore trivial function 
calls. (#81808)

This PR introduces the concept of a "trivial function" which applies to
a function that only calls other trivial functions and contain literals
and expressions that don't result in heap mutations (specifically it
does not call deref). This is implemented using ConstStmtVisitor and
checking each statement and expression's trivialness.

This PR also introduces the concept of a "ingleton function", which is a
static member function or a free standing function which ends with the
suffix "singleton". Such a function's return value is understood to be
safe to call any function with.

Added: 


Modified: 
clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
clang/test/Analysis/Checkers/WebKit/call-args.cpp
clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index b76c0551c77bb0..94eaa81af51772 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -66,9 +66,13 @@ tryToFindPtrOrigin(const Expr *E, bool 
StopAtFirstRefCountedObj) {
   E = call->getArg(0);
   continue;
 }
+
 if (isReturnValueRefCounted(callee))
   return {E, true};
 
+if (isSingleton(callee))
+  return {E, true};
+
 if (isPtrConversion(callee)) {
   E = call->getArg(0);
   continue;

diff  --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 907244013d0871..bf6f9a64877c64 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include 
 
 using namespace clang;
@@ -222,4 +223,216 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+if (auto *RV = RS->getRetValue())
+  return Visit(RV);
+return true;
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ approved this pull request.

Looks great now!

https://github.com/llvm/llvm-project/pull/81808
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (PR #81343)

2024-02-14 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ commented:

LGTM! I have a couple minor nitpicks.

https://github.com/llvm/llvm-project/pull/81343
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (PR #81343)

2024-02-14 Thread Artem Dergachev via cfe-commits


@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \
+// RUN:-fsafe-buffer-usage-suggestions \
+// RUN:-fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+void safe_array_assigned_to_safe_ptr(unsigned idx) {
+  int buffer[10];
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+  int* ptr;
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+  ptr = buffer;
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+}
+
+void safe_array_assigned_to_unsafe_ptr(unsigned idx) {
+  int buffer[10];
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+  int* ptr;
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:11}:"std::span ptr"
+  ptr = buffer;
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+  ptr[idx] = 0;
+}
+
+void unsafe_array_assigned_to_safe_ptr(unsigned idx) {
+  int buffer[10];
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:17}:"std::array buffer"
+  int* ptr;
+  // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
+  ptr = buffer;
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:15-[[@LINE-1]]:15}:".data()"
+  buffer[idx] = 0;
+}
+
+void unsafe_array_assigned_to_unsafe_ptr(unsigned idx) {

haoNoQ wrote:

Similarly, let's mark this test as a FIXME test, and add a comment explaining 
why this is hard and the naive fix would be incorrect.

https://github.com/llvm/llvm-project/pull/81343
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (PR #81343)

2024-02-14 Thread Artem Dergachev via cfe-commits


@@ -1490,6 +1548,26 @@ PointerAssignmentGadget::getFixits(const FixitStrategy 
) const {
   return std::nullopt;
 }
 
+/// \returns fixit that adds .data() call after \DRE.
+static inline std::optional createDataFixit(const ASTContext ,
+   const DeclRefExpr *DRE);
+
+std::optional
+CArrayToPtrAssignmentGadget::getFixits(const FixitStrategy ) const {

haoNoQ wrote:

I think there should be a comment explaining why the "both sides are fixed" 
case is tricky. Otherwise somebody may accidentally implement it 

https://github.com/llvm/llvm-project/pull/81343
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][InstallAPI] Add input file support to library (PR #81701)

2024-02-14 Thread Cyndy Ishida via cfe-commits

https://github.com/cyndyishida updated 
https://github.com/llvm/llvm-project/pull/81701

>From 9d0da0010f145b23ce2b7e5b6183558609600789 Mon Sep 17 00:00:00 2001
From: Cyndy Ishida 
Date: Tue, 13 Feb 2024 18:22:23 -0800
Subject: [PATCH 1/4] [clang][InstallAPI] Add input file support to library

This patch adds support for expected InstallAPI inputs.
InstallAPI  accepts a well defined filelist of headers and how those headers
represent a single library.

InstallAPI captures header files to determine linkable symbols
to then compare against what was compiled in a binary dylib and
generate TBD files.
---
 clang/include/clang/InstallAPI/FileList.h |  53 +
 clang/include/clang/InstallAPI/HeaderFile.h   |  72 +++
 clang/lib/ExtractAPI/CMakeLists.txt   |   1 +
 clang/lib/ExtractAPI/ExtractAPIConsumer.cpp   |   7 +-
 clang/lib/InstallAPI/CMakeLists.txt   |   2 +
 clang/lib/InstallAPI/FileList.cpp | 196 ++
 clang/lib/InstallAPI/HeaderFile.cpp   |  37 
 clang/unittests/CMakeLists.txt|   1 +
 clang/unittests/InstallAPI/CMakeLists.txt |   9 +
 clang/unittests/InstallAPI/FileListTest.cpp   | 140 +
 clang/unittests/InstallAPI/HeaderFileTest.cpp |  89 
 11 files changed, 603 insertions(+), 4 deletions(-)
 create mode 100644 clang/include/clang/InstallAPI/FileList.h
 create mode 100644 clang/include/clang/InstallAPI/HeaderFile.h
 create mode 100644 clang/lib/InstallAPI/FileList.cpp
 create mode 100644 clang/lib/InstallAPI/HeaderFile.cpp
 create mode 100644 clang/unittests/InstallAPI/CMakeLists.txt
 create mode 100644 clang/unittests/InstallAPI/FileListTest.cpp
 create mode 100644 clang/unittests/InstallAPI/HeaderFileTest.cpp

diff --git a/clang/include/clang/InstallAPI/FileList.h 
b/clang/include/clang/InstallAPI/FileList.h
new file mode 100644
index 00..01ec9b35e31490
--- /dev/null
+++ b/clang/include/clang/InstallAPI/FileList.h
@@ -0,0 +1,53 @@
+//===- InstallAPI/FileList.h *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// The JSON file list parser is used to communicate input to InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_FILELIST_H
+#define LLVM_CLANG_INSTALLAPI_FILELIST_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/InstallAPI/HeaderFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace clang {
+namespace installapi {
+
+/// JSON decoder for InstallAPI Inputs.
+class FileListReader {
+
+  class Implementation;
+  Implementation 
+
+  FileListReader(std::unique_ptr InputBuffer,
+ llvm::Error );
+
+public:
+  /// Decode JSON input and append header input into destination container.
+  /// Headers are loaded in the order they appear in the JSON input.
+  ///
+  /// \param InputBuffer JSON input data.
+  /// \param Destination Container to load headers into.
+  static llvm::Error
+  loadHeaders(std::unique_ptr InputBuffer,
+  HeaderSeq );
+
+  ~FileListReader();
+
+  FileListReader(const FileListReader &) = delete;
+  FileListReader =(const FileListReader &) = delete;
+};
+
+} // namespace installapi
+} // namespace clang
+
+#endif // LLVM_CLANG_INSTALLAPI_FILELIST_H
diff --git a/clang/include/clang/InstallAPI/HeaderFile.h 
b/clang/include/clang/InstallAPI/HeaderFile.h
new file mode 100644
index 00..6ccd944f8b01be
--- /dev/null
+++ b/clang/include/clang/InstallAPI/HeaderFile.h
@@ -0,0 +1,72 @@
+//===- InstallAPI/HeaderFile.h --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// Representations of a library's headers for InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_HEADERFILE_H
+#define LLVM_CLANG_INSTALLAPI_HEADERFILE_H
+
+#include "clang/Basic/LangStandard.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Regex.h"
+#include 
+#include 
+
+namespace clang::installapi {
+enum class HeaderType {
+  /// Represents declarations accessible to all clients.
+  Public,
+  /// Represents declarations accessible to a disclosed set of clients.
+  Private,
+  /// Represents declarations only accessible as implementation details to the
+  /// input library.
+  Project,
+};
+
+class HeaderFile {
+  /// Full 

[clang] [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (PR #81343)

2024-02-14 Thread Artem Dergachev via cfe-commits


@@ -848,6 +852,60 @@ class PointerAssignmentGadget : public FixableGadget {
   }
 };
 
+/// An assignment expression of the form:
+///  \code
+///  ptr = array;
+///  \endcode
+/// where `p` is a pointer and `array` is a constant size array.
+class CArrayToPtrAssignmentGadget : public FixableGadget {
+private:
+  static constexpr const char *const PointerAssignLHSTag = "ptrLHS";
+  static constexpr const char *const PointerAssignRHSTag = "ptrRHS";
+  const DeclRefExpr *PtrLHS; // the LHS pointer expression in `PA`
+  const DeclRefExpr *PtrRHS; // the RHS pointer expression in `PA`
+
+public:
+  CArrayToPtrAssignmentGadget(const MatchFinder::MatchResult )
+  : FixableGadget(Kind::CArrayToPtrAssignment),
+PtrLHS(Result.Nodes.getNodeAs(PointerAssignLHSTag)),
+PtrRHS(Result.Nodes.getNodeAs(PointerAssignRHSTag)) {}
+
+  static bool classof(const Gadget *G) {
+return G->getKind() == Kind::CArrayToPtrAssignment;
+  }
+
+  static Matcher matcher() {
+auto PtrAssignExpr = binaryOperator(
+allOf(hasOperatorName("="),
+  hasRHS(ignoringParenImpCasts(
+  declRefExpr(hasType(hasCanonicalType(constantArrayType())),
+  toSupportedVariable())
+  .bind(PointerAssignRHSTag))),
+  hasLHS(declRefExpr(hasPointerType(), toSupportedVariable())
+ .bind(PointerAssignLHSTag;
+
+return stmt(isInUnspecifiedUntypedContext(PtrAssignExpr));
+  }
+
+  virtual std::optional
+  getFixits(const FixitStrategy ) const override;
+
+  virtual const Stmt *getBaseStmt() const override {
+// FIXME: This should be the binary operator, assuming that this method
+// makes sense at all on a FixableGadget.
+return PtrLHS;
+  }
+
+  virtual DeclUseList getClaimedVarUseSites() const override {
+return DeclUseList{PtrLHS, PtrRHS};
+  }
+
+  virtual std::optional>
+  getStrategyImplications() const override {
+return {};
+  }

haoNoQ wrote:

This is probably the default behavior 樂

https://github.com/llvm/llvm-project/pull/81343
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81808

>From 857decc27550e2b15938a7846a03561f9ad73f48 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Wed, 14 Feb 2024 16:21:33 -0800
Subject: [PATCH 1/5] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore
 trivial function calls.

This PR introduces the concept of a "trivial function" which applies to a 
function
that only calls other trivial functions and contain literals and expressions 
that
don't result in heap mutations (specifically it does not call deref). This is
implemented using ConstStmtVisitor and checking each statement and expression's
trivialness.

This PR also introduces the concept of a "ingleton function", which is a static
member function or a free standing function which ends with the suffix 
"singleton".
Such a function's return value is understood to be safe to call any function 
with.
---
 .../Checkers/WebKit/ASTUtils.cpp  |   4 +
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 207 
 .../Checkers/WebKit/PtrTypesSemantics.h   |  21 ++
 .../WebKit/UncountedCallArgsChecker.cpp   |   8 +-
 .../Analysis/Checkers/WebKit/call-args.cpp|  33 +--
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 231 ++
 6 files changed, 487 insertions(+), 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index b76c0551c77bb0..94eaa81af51772 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -66,9 +66,13 @@ tryToFindPtrOrigin(const Expr *E, bool 
StopAtFirstRefCountedObj) {
   E = call->getArg(0);
   continue;
 }
+
 if (isReturnValueRefCounted(callee))
   return {E, true};
 
+if (isSingleton(callee))
+  return {E, true};
+
 if (isPtrConversion(callee)) {
   E = call->getArg(0);
   continue;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 907244013d0871..17f59c2d304ddc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include 
 
 using namespace clang;
@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+return false;
+  }
+
+  bool VisitBinaryOperator(const BinaryOperator *BO) {
+// Binary operators are trivial if their operands are trivial.
+return Visit(BO->getLHS()) && Visit(BO->getRHS());
+  }

[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-14 Thread via cfe-commits

https://github.com/gulfemsavrun updated 
https://github.com/llvm/llvm-project/pull/75425

>From ee88c6e666759c27587f900c99a4aba23c0d4cf4 Mon Sep 17 00:00:00 2001
From: Gulfem Savrun Yeniceri 
Date: Thu, 14 Dec 2023 03:40:57 +
Subject: [PATCH] [InstrProf] Single byte counters in coverage

This patch inserts 1-byte counters instead of an 8-byte counters
into llvm profiles for source-based code coverage. The origial idea
was proposed as block-cov for PGO, and this patch repurposes that
idea for coverage.

The current 8-byte counters mechanism add counters to minimal regions,
and infer the counters in the remaining regions via adding or
subtracting counters. For example, it infers the counter in the if.else
region by subtracting the counters between if.entry and if.then regions
in an if statement. Whenever there is a control-flow merge, it adds
the counters from all the incoming regions. However, we are not going to
be able to infer counters by subtracting two execution counts when using
single-byte counters. Therefore, this patch conservatively inserts
additional counters for the cases where we need to add or subtract counters.

RFC:
https://discourse.llvm.org/t/rfc-single-byte-counters-for-source-based-code-coverage/75685
---
 clang/lib/CodeGen/CGExprAgg.cpp   |  13 +-
 clang/lib/CodeGen/CGExprComplex.cpp   |  14 +-
 clang/lib/CodeGen/CGExprScalar.cpp|  32 ++-
 clang/lib/CodeGen/CGStmt.cpp  |  73 ++-
 clang/lib/CodeGen/CodeGenFunction.cpp |   9 +-
 clang/lib/CodeGen/CodeGenFunction.h   |   2 +-
 clang/lib/CodeGen/CodeGenModule.cpp   |   1 +
 clang/lib/CodeGen/CodeGenPGO.cpp  | 150 -
 clang/lib/CodeGen/CodeGenPGO.h|   6 +-
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 206 +-
 .../CoverageMapping/single-byte-counters.cpp  | 169 ++
 compiler-rt/lib/profile/InstrProfiling.h  |   3 +-
 .../ProfileData/Coverage/CoverageMapping.h|  20 +-
 .../llvm/ProfileData/InstrProfWriter.h|   4 +
 .../ProfileData/Coverage/CoverageMapping.cpp  |  13 +-
 15 files changed, 623 insertions(+), 92 deletions(-)
 create mode 100644 clang/test/CoverageMapping/single-byte-counters.cpp

diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 22f55fe9aac904..377bf413c857cb 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -33,6 +33,10 @@ using namespace CodeGen;
 //Aggregate Expression Emitter
 
//===--===//
 
+namespace llvm {
+extern cl::opt EnableSingleByteCoverage;
+} // namespace llvm
+
 namespace  {
 class AggExprEmitter : public StmtVisitor {
   CodeGenFunction 
@@ -1278,7 +1282,10 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(LHSBlock);
-  CGF.incrementProfileCounter(E);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getTrueExpr());
+  else
+CGF.incrementProfileCounter(E);
   Visit(E->getTrueExpr());
   eval.end(CGF);
 
@@ -1293,6 +1300,8 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(RHSBlock);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getFalseExpr());
   Visit(E->getFalseExpr());
   eval.end(CGF);
 
@@ -1301,6 +1310,8 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 E->getType());
 
   CGF.EmitBlock(ContBlock);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E);
 }
 
 void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp 
b/clang/lib/CodeGen/CGExprComplex.cpp
index 9ddf0e763f139b..683097eea5e76a 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -28,6 +28,10 @@ using namespace CodeGen;
 //Complex Expression Emitter
 
//===--===//
 
+namespace llvm {
+extern cl::opt EnableSingleByteCoverage;
+} // namespace llvm
+
 typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
 
 /// Return the complex type that we are meant to emit.
@@ -1329,7 +1333,11 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(LHSBlock);
-  CGF.incrementProfileCounter(E);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getTrueExpr());
+  else
+CGF.incrementProfileCounter(E);
+
   ComplexPairTy LHS = Visit(E->getTrueExpr());
   LHSBlock = Builder.GetInsertBlock();
   CGF.EmitBranch(ContBlock);
@@ -1337,9 +1345,13 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(RHSBlock);
+  if (llvm::EnableSingleByteCoverage)
+

[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread Artem Dergachev via cfe-commits


@@ -406,6 +406,39 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) 
{
   }
   return false;
 }
+
+AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
+  // FIXME: Proper solution:
+  //  - refactor Sema::CheckArrayAccess
+  //- split safe/OOB/unknown decision logic from diagnostics emitting code
+  //-  e. g. "Try harder to find a NamedDecl to point at in the note."
+  //already duplicated
+  //  - call both from Sema and from here
+
+  const DeclRefExpr *BaseDRE =
+  dyn_cast_or_null(Node.getBase()->IgnoreParenImpCasts());

haoNoQ wrote:

I don't think `IgnoreParenImpCasts()` can ever return null.
```suggestion
  const auto *BaseDRE =
  dyn_cast(Node.getBase()->IgnoreParenImpCasts());
```

https://github.com/llvm/llvm-project/pull/80504
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81808

>From 857decc27550e2b15938a7846a03561f9ad73f48 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Wed, 14 Feb 2024 16:21:33 -0800
Subject: [PATCH 1/4] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore
 trivial function calls.

This PR introduces the concept of a "trivial function" which applies to a 
function
that only calls other trivial functions and contain literals and expressions 
that
don't result in heap mutations (specifically it does not call deref). This is
implemented using ConstStmtVisitor and checking each statement and expression's
trivialness.

This PR also introduces the concept of a "ingleton function", which is a static
member function or a free standing function which ends with the suffix 
"singleton".
Such a function's return value is understood to be safe to call any function 
with.
---
 .../Checkers/WebKit/ASTUtils.cpp  |   4 +
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 207 
 .../Checkers/WebKit/PtrTypesSemantics.h   |  21 ++
 .../WebKit/UncountedCallArgsChecker.cpp   |   8 +-
 .../Analysis/Checkers/WebKit/call-args.cpp|  33 +--
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 231 ++
 6 files changed, 487 insertions(+), 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index b76c0551c77bb0..94eaa81af51772 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -66,9 +66,13 @@ tryToFindPtrOrigin(const Expr *E, bool 
StopAtFirstRefCountedObj) {
   E = call->getArg(0);
   continue;
 }
+
 if (isReturnValueRefCounted(callee))
   return {E, true};
 
+if (isSingleton(callee))
+  return {E, true};
+
 if (isPtrConversion(callee)) {
   E = call->getArg(0);
   continue;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 907244013d0871..17f59c2d304ddc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include 
 
 using namespace clang;
@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+return false;
+  }
+
+  bool VisitBinaryOperator(const BinaryOperator *BO) {
+// Binary operators are trivial if their operands are trivial.
+return Visit(BO->getLHS()) && Visit(BO->getRHS());
+  }

[clang] [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (PR #81343)

2024-02-14 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: None (jkorous-apple)


Changes

depends on
https://github.com/llvm/llvm-project/pull/80347

---
Full diff: https://github.com/llvm/llvm-project/pull/81343.diff


4 Files Affected:

- (modified) clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def 
(+2-1) 
- (modified) clang/lib/Analysis/UnsafeBufferUsage.cpp (+99-15) 
- (modified) clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp (+1-1) 
- (added) 
clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-array-assign-to-ptr.cpp 
(+43) 


``diff
diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def 
b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
index 07f805ebb11013..3273c642eed517 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
@@ -45,7 +45,8 @@ FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in 
an Unspecified Poin
 FIXABLE_GADGET(UPCStandalonePointer)
 FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified 
Pointer Context
 FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified 
Untyped Context
-FIXABLE_GADGET(PointerAssignment)
+FIXABLE_GADGET(PtrToPtrAssignment)
+FIXABLE_GADGET(CArrayToPtrAssignment)
 FIXABLE_GADGET(PointerInit)
 
 #undef FIXABLE_GADGET
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index a74c113e29f1cf..8e810876950c81 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -7,11 +7,14 @@
 
//===--===//
 
 #include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Basic/CharInfo.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Lex/Lexer.h"
@@ -799,7 +802,8 @@ class PointerInitGadget : public FixableGadget {
 ///  \code
 ///  p = q;
 ///  \endcode
-class PointerAssignmentGadget : public FixableGadget {
+/// where both `p` and `q` are pointers.
+class PtrToPtrAssignmentGadget : public FixableGadget {
 private:
   static constexpr const char *const PointerAssignLHSTag = "ptrLHS";
   static constexpr const char *const PointerAssignRHSTag = "ptrRHS";
@@ -807,13 +811,13 @@ class PointerAssignmentGadget : public FixableGadget {
   const DeclRefExpr * PtrRHS; // the RHS pointer expression in `PA`
 
 public:
-  PointerAssignmentGadget(const MatchFinder::MatchResult )
-  : FixableGadget(Kind::PointerAssignment),
-PtrLHS(Result.Nodes.getNodeAs(PointerAssignLHSTag)),
-PtrRHS(Result.Nodes.getNodeAs(PointerAssignRHSTag)) {}
+  PtrToPtrAssignmentGadget(const MatchFinder::MatchResult )
+  : FixableGadget(Kind::PtrToPtrAssignment),
+PtrLHS(Result.Nodes.getNodeAs(PointerAssignLHSTag)),
+PtrRHS(Result.Nodes.getNodeAs(PointerAssignRHSTag)) {}
 
   static bool classof(const Gadget *G) {
-return G->getKind() == Kind::PointerAssignment;
+return G->getKind() == Kind::PtrToPtrAssignment;
   }
 
   static Matcher matcher() {
@@ -848,6 +852,60 @@ class PointerAssignmentGadget : public FixableGadget {
   }
 };
 
+/// An assignment expression of the form:
+///  \code
+///  ptr = array;
+///  \endcode
+/// where `p` is a pointer and `array` is a constant size array.
+class CArrayToPtrAssignmentGadget : public FixableGadget {
+private:
+  static constexpr const char *const PointerAssignLHSTag = "ptrLHS";
+  static constexpr const char *const PointerAssignRHSTag = "ptrRHS";
+  const DeclRefExpr *PtrLHS; // the LHS pointer expression in `PA`
+  const DeclRefExpr *PtrRHS; // the RHS pointer expression in `PA`
+
+public:
+  CArrayToPtrAssignmentGadget(const MatchFinder::MatchResult )
+  : FixableGadget(Kind::CArrayToPtrAssignment),
+PtrLHS(Result.Nodes.getNodeAs(PointerAssignLHSTag)),
+PtrRHS(Result.Nodes.getNodeAs(PointerAssignRHSTag)) {}
+
+  static bool classof(const Gadget *G) {
+return G->getKind() == Kind::CArrayToPtrAssignment;
+  }
+
+  static Matcher matcher() {
+auto PtrAssignExpr = binaryOperator(
+allOf(hasOperatorName("="),
+  hasRHS(ignoringParenImpCasts(
+  declRefExpr(hasType(hasCanonicalType(constantArrayType())),
+  toSupportedVariable())
+  .bind(PointerAssignRHSTag))),
+  hasLHS(declRefExpr(hasPointerType(), toSupportedVariable())
+ .bind(PointerAssignLHSTag;
+
+return stmt(isInUnspecifiedUntypedContext(PtrAssignExpr));
+  }
+
+  virtual std::optional
+  getFixits(const FixitStrategy ) const override;
+
+  

[clang] [-Wunsafe-buffer-usage] Add fixits for array to pointer assignment (PR #81343)

2024-02-14 Thread via cfe-commits

https://github.com/jkorous-apple updated 
https://github.com/llvm/llvm-project/pull/81343

>From 791130c5c5de31084c168db33531a5d856104506 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Thu, 8 Feb 2024 14:30:20 -0800
Subject: [PATCH 1/4] [-Wunsafe-buffer-usage][NFC] Factor out .data() fixit to
 a function

---
 clang/lib/Analysis/UnsafeBufferUsage.cpp | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index a74c113e29f1cf..cc49876779ece2 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -1490,6 +1490,9 @@ PointerAssignmentGadget::getFixits(const FixitStrategy 
) const {
   return std::nullopt;
 }
 
+/// \returns fixit that adds .data() call after \DRE.
+static inline std::optional createDataFixit(const ASTContext& Ctx, 
const DeclRefExpr * DRE);
+
 std::optional
 PointerInitGadget::getFixits(const FixitStrategy ) const {
   const auto *LeftVD = PtrInitLHS;
@@ -1907,6 +1910,18 @@ PointerDereferenceGadget::getFixits(const FixitStrategy 
) const {
   return std::nullopt;
 }
 
+static inline std::optional createDataFixit(const ASTContext& Ctx, 
const DeclRefExpr * DRE) {
+  const SourceManager  = Ctx.getSourceManager();
+  // Inserts the .data() after the DRE
+  std::optional EndOfOperand =
+  getPastLoc(DRE, SM, Ctx.getLangOpts());
+
+  if (EndOfOperand)
+return FixItList{{FixItHint::CreateInsertion(*EndOfOperand, ".data()")}};
+
+  return std::nullopt;
+}
+
 // Generates fix-its replacing an expression of the form UPC(DRE) with
 // `DRE.data()`
 std::optional
@@ -1915,14 +1930,7 @@ UPCStandalonePointerGadget::getFixits(const 
FixitStrategy ) const {
   switch (S.lookup(VD)) {
   case FixitStrategy::Kind::Array:
   case FixitStrategy::Kind::Span: {
-ASTContext  = VD->getASTContext();
-SourceManager  = Ctx.getSourceManager();
-// Inserts the .data() after the DRE
-std::optional EndOfOperand =
-getPastLoc(Node, SM, Ctx.getLangOpts());
-
-if (EndOfOperand)
-  return FixItList{{FixItHint::CreateInsertion(*EndOfOperand, ".data()")}};
+return createDataFixit(VD->getASTContext(), Node);
 // FIXME: Points inside a macro expansion.
 break;
   }

>From 1b12f7413288b01d1806b98fb90c2d44e53b7437 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Thu, 8 Feb 2024 14:33:03 -0800
Subject: [PATCH 2/4] [-Wunsafe-buffer-usage][NFC] Rename PointerAssignment
 gadget to PtrToPtrAssignment

---
 .../Analysis/Analyses/UnsafeBufferUsageGadgets.def|  2 +-
 clang/lib/Analysis/UnsafeBufferUsage.cpp  | 11 ++-
 clang/test/SemaCXX/warn-unsafe-buffer-usage-debug.cpp |  2 +-
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def 
b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
index 07f805ebb11013..2babc1df93d515 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def
@@ -45,7 +45,7 @@ FIXABLE_GADGET(UPCAddressofArraySubscript) // '[any]' in 
an Unspecified Poin
 FIXABLE_GADGET(UPCStandalonePointer)
 FIXABLE_GADGET(UPCPreIncrement)// '++Ptr' in an Unspecified 
Pointer Context
 FIXABLE_GADGET(UUCAddAssign)// 'Ptr += n' in an Unspecified 
Untyped Context
-FIXABLE_GADGET(PointerAssignment)
+FIXABLE_GADGET(PtrToPtrAssignment)
 FIXABLE_GADGET(PointerInit)
 
 #undef FIXABLE_GADGET
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index cc49876779ece2..927baef2fffa39 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -799,7 +799,8 @@ class PointerInitGadget : public FixableGadget {
 ///  \code
 ///  p = q;
 ///  \endcode
-class PointerAssignmentGadget : public FixableGadget {
+/// where both `p` and `q` are pointers.
+class PtrToPtrAssignmentGadget : public FixableGadget {
 private:
   static constexpr const char *const PointerAssignLHSTag = "ptrLHS";
   static constexpr const char *const PointerAssignRHSTag = "ptrRHS";
@@ -807,13 +808,13 @@ class PointerAssignmentGadget : public FixableGadget {
   const DeclRefExpr * PtrRHS; // the RHS pointer expression in `PA`
 
 public:
-  PointerAssignmentGadget(const MatchFinder::MatchResult )
-  : FixableGadget(Kind::PointerAssignment),
+  PtrToPtrAssignmentGadget(const MatchFinder::MatchResult )
+  : FixableGadget(Kind::PtrToPtrAssignment),
 PtrLHS(Result.Nodes.getNodeAs(PointerAssignLHSTag)),
 PtrRHS(Result.Nodes.getNodeAs(PointerAssignRHSTag)) {}
 
   static bool classof(const Gadget *G) {
-return G->getKind() == Kind::PointerAssignment;
+return G->getKind() == Kind::PtrToPtrAssignment;
   }
 
   static Matcher matcher() {
@@ -1471,7 +1472,7 @@ bool clang::internal::anyConflict(const 
SmallVectorImpl ,
 }
 
 

[clang-tools-extra] 8ce1448 - [clangd][test] Fix -Wmissing-field-initializers in DiagnosticsTests.cpp (NFC)

2024-02-14 Thread Jie Fu via cfe-commits

Author: Jie Fu
Date: 2024-02-15T10:17:58+08:00
New Revision: 8ce144800a7ed7c1e42343b3a9ac5e0ffdbfddbf

URL: 
https://github.com/llvm/llvm-project/commit/8ce144800a7ed7c1e42343b3a9ac5e0ffdbfddbf
DIFF: 
https://github.com/llvm/llvm-project/commit/8ce144800a7ed7c1e42343b3a9ac5e0ffdbfddbf.diff

LOG: [clangd][test] Fix -Wmissing-field-initializers in DiagnosticsTests.cpp 
(NFC)

llvm-project/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp:921:45:
error: missing field 'Annotations' initializer 
[-Werror,-Wmissing-field-initializers]
   TextEdit{Main.range("virtual1"), ""}}};
^
llvm-project/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp:926:45:
error: missing field 'Annotations' initializer 
[-Werror,-Wmissing-field-initializers]
   TextEdit{Main.range("virtual2"), ""}}};
^
2 errors generated.

Added: 


Modified: 
clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp 
b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
index 4839879e1b78c8..2f6dd0611b6621 100644
--- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -918,12 +918,14 @@ TEST(DiagnosticTest, 
ClangTidySelfContainedDiagsFormatting) {
   "prefer using 'override' or (rarely) 'final' "
   "instead of 'virtual'",
   {TextEdit{Main.range("override1"), " override"},
-   TextEdit{Main.range("virtual1"), ""}}};
+   TextEdit{Main.range("virtual1"), ""}},
+  {}};
   clangd::Fix const ExpectedFix2{
   "prefer using 'override' or (rarely) 'final' "
   "instead of 'virtual'",
   {TextEdit{Main.range("override2"), " override"},
-   TextEdit{Main.range("virtual2"), ""}}};
+   TextEdit{Main.range("virtual2"), ""}},
+  {}};
   // Note that in the Fix we expect the "virtual" keyword and the following
   // whitespace to be deleted
   EXPECT_THAT(TU.build().getDiagnostics(),



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


[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread via cfe-commits

https://github.com/jkorous-apple closed 
https://github.com/llvm/llvm-project/pull/80504
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 9a1e637 - [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (#80504)

2024-02-14 Thread via cfe-commits

Author: jkorous-apple
Date: 2024-02-14T18:16:44-08:00
New Revision: 9a1e6373ab3edc38486af504154db2d804e72d3d

URL: 
https://github.com/llvm/llvm-project/commit/9a1e6373ab3edc38486af504154db2d804e72d3d
DIFF: 
https://github.com/llvm/llvm-project/commit/9a1e6373ab3edc38486af504154db2d804e72d3d.diff

LOG: [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts 
(#80504)

[-Wunsafe-buffer-usage] Ignore safe array subscripts
Don't emit warnings for array subscripts on constant size arrays where the 
index is constant and within bounds.

Example:
int arr[10];
arr[5] = 0; //safe, no warning

This patch recognizes only array indices that are integer literals - it doesn't 
understand more complex expressions (arithmetic on constants, etc.).

-Warray-bounds implemented in Sema::CheckArrayAccess() already solves a similar
(opposite) problem, handles complex expressions and is battle-tested.

Adding -Wunsafe-buffer-usage diagnostics to Sema is a non-starter as we need to 
emit
both the warnings and fixits and the performance impact of the fixit machine is
unacceptable for Sema.

CheckArrayAccess() as is doesn't distinguish between "safe" and "unknown" array
accesses. It also mixes the analysis that decides if an index is out of bounds
with crafting the diagnostics.

A refactor of CheckArrayAccess() might serve both the original purpose
and help us avoid false-positive with -Wunsafe-buffer-usage on constant
size arrrays.

Added: 


Modified: 
clang/lib/Analysis/UnsafeBufferUsage.cpp
clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp

clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-arg-to-func-ptr-call.cpp
clang/test/SemaCXX/warn-unsafe-buffer-usage.cpp

Removed: 




diff  --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index ca346444e047e5..a74c113e29f1cf 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -406,6 +406,39 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) 
{
   }
   return false;
 }
+
+AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
+  // FIXME: Proper solution:
+  //  - refactor Sema::CheckArrayAccess
+  //- split safe/OOB/unknown decision logic from diagnostics emitting code
+  //-  e. g. "Try harder to find a NamedDecl to point at in the note."
+  //already duplicated
+  //  - call both from Sema and from here
+
+  const auto *BaseDRE =
+  dyn_cast(Node.getBase()->IgnoreParenImpCasts());
+  if (!BaseDRE)
+return false;
+  if (!BaseDRE->getDecl())
+return false;
+  const auto *CATy = Finder->getASTContext().getAsConstantArrayType(
+  BaseDRE->getDecl()->getType());
+  if (!CATy)
+return false;
+  const APInt ArrSize = CATy->getSize();
+
+  if (const auto *IdxLit = dyn_cast(Node.getIdx())) {
+const APInt ArrIdx = IdxLit->getValue();
+// FIXME: ArrIdx.isNegative() we could immediately emit an error as that's 
a
+// bug
+if (ArrIdx.isNonNegative() &&
+ArrIdx.getLimitedValue() < ArrSize.getLimitedValue())
+  return true;
+  }
+
+  return false;
+}
+
 } // namespace clang::ast_matchers
 
 namespace {
@@ -598,16 +631,16 @@ class ArraySubscriptGadget : public WarningGadget {
   }
 
   static Matcher matcher() {
-// FIXME: What if the index is integer literal 0? Should this be
-// a safe gadget in this case?
-  // clang-format off
+// clang-format off
   return stmt(arraySubscriptExpr(
 hasBase(ignoringParenImpCasts(
   anyOf(hasPointerType(), hasArrayType(,
-unless(hasIndex(
-anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
- )))
-.bind(ArraySubscrTag));
+unless(anyOf(
+  isSafeArraySubscript(),
+  hasIndex(
+  anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
+  )
+))).bind(ArraySubscrTag));
 // clang-format on
   }
 

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
index 90c11b1be95c25..8b2f103ec66708 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \
+// RUN: %clang_cc1 -std=c++20 -Wno-everything -Wunsafe-buffer-usage \
 // RUN:-fsafe-buffer-usage-suggestions \
 // RUN:-verify %s
 
@@ -22,3 +22,19 @@ struct Foo {
 void foo2(Foo& f, unsigned idx) {
   f.member_buffer[idx] = 0; // expected-warning{{unsafe buffer access}}
 }
+
+void constant_idx_safe(unsigned idx) {
+  int buffer[10];
+  buffer[9] = 0;
+}
+
+void constant_idx_safe0(unsigned idx) {
+  int buffer[10];
+  buffer[0] = 0;
+}
+

[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread via cfe-commits

https://github.com/jkorous-apple updated 
https://github.com/llvm/llvm-project/pull/80504

>From e075dc3ac10c0cd2e12b223988ec4821b40b55d2 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Fri, 2 Feb 2024 14:46:59 -0800
Subject: [PATCH 1/7] [-Wunsafe-buffer-usage] Ignore safe array subscripts

Don't emit warnings for array subscripts on constant size arrays where the 
index is constant and within bounds.

Example:
int arr[10];
arr[5] = 0; //safe, no warning

This patch recognizes only array indices that are integer literals - it doesn't 
understand more complex expressions (arithmetic on constants, etc.).
---
 clang/lib/Analysis/UnsafeBufferUsage.cpp  | 39 +++
 .../warn-unsafe-buffer-usage-array.cpp| 18 -
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index ca346444e047e5..d150a679597a92 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -406,6 +406,31 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) 
{
   }
   return false;
 }
+
+AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
+  const DeclRefExpr * BaseDRE = 
dyn_cast_or_null(Node.getBase()->IgnoreParenImpCasts());
+  if (!BaseDRE)
+return false;
+  if (!BaseDRE->getDecl())
+return false;
+  auto BaseVarDeclTy = BaseDRE->getDecl()->getType();
+  if (!BaseVarDeclTy->isConstantArrayType())
+return false;
+  const auto * CATy = dyn_cast_or_null(BaseVarDeclTy);
+  if (!CATy)
+return false;
+  const APInt ArrSize = CATy->getSize();
+
+  if (const auto * IdxLit = dyn_cast(Node.getIdx())) {
+const APInt ArrIdx = IdxLit->getValue();
+// FIXME: ArrIdx.isNegative() we could immediately emit an error as that's 
a bug
+if (ArrIdx.isNonNegative() && ArrIdx.getLimitedValue() < 
ArrSize.getLimitedValue())
+  return true;
+  }
+
+  return false;
+}
+
 } // namespace clang::ast_matchers
 
 namespace {
@@ -598,16 +623,16 @@ class ArraySubscriptGadget : public WarningGadget {
   }
 
   static Matcher matcher() {
-// FIXME: What if the index is integer literal 0? Should this be
-// a safe gadget in this case?
-  // clang-format off
+// clang-format off
   return stmt(arraySubscriptExpr(
 hasBase(ignoringParenImpCasts(
   anyOf(hasPointerType(), hasArrayType(,
-unless(hasIndex(
-anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
- )))
-.bind(ArraySubscrTag));
+unless(anyOf(
+  isSafeArraySubscript(),
+  hasIndex(
+  anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
+  )
+))).bind(ArraySubscrTag));
 // clang-format on
   }
 
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
index 90c11b1be95c25..4804223e8be058 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \
+// RUN: %clang_cc1 -std=c++20 -Wno-everything -Wunsafe-buffer-usage \
 // RUN:-fsafe-buffer-usage-suggestions \
 // RUN:-verify %s
 
@@ -22,3 +22,19 @@ struct Foo {
 void foo2(Foo& f, unsigned idx) {
   f.member_buffer[idx] = 0; // expected-warning{{unsafe buffer access}}
 }
+
+void constant_idx_safe(unsigned idx) {
+  int buffer[10];
+  buffer[9] = 0;
+}
+
+void constant_idx_safe0(unsigned idx) {
+  int buffer[10];
+  buffer[0] = 0;
+}
+
+void constant_idx_unsafe(unsigned idx) {
+  int buffer[10];   // expected-warning{{'buffer' is an unsafe buffer that 
does not perform bounds checks}}
+// expected-note@-1{{change type of 'buffer' to 
'std::array' to harden it}}
+  buffer[10] = 0;   // expected-note{{used in buffer access here}}
+}

>From 9f3940e5e1a8555a784521999d296ed46b1ae0c2 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Fri, 2 Feb 2024 14:48:41 -0800
Subject: [PATCH 2/7] [-Wunsafe-buffer-usage][NFC] Update existing tests after
 constant safe index is ignored

---
 ...afe-buffer-usage-fixits-pointer-access.cpp |  8 +--
 ...ge-fixits-pointer-arg-to-func-ptr-call.cpp |  3 +-
 .../test/SemaCXX/warn-unsafe-buffer-usage.cpp | 53 ++-
 3 files changed, 33 insertions(+), 31 deletions(-)

diff --git 
a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
index f94072015ff87d..b3c64f1b0d085e 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
@@ -83,11 +83,11 @@ void unsafe_method_invocation_single_param() {
 
 }
 
-void unsafe_method_invocation_single_param_array() {
+void 

[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ approved this pull request.

LGTM!

https://github.com/llvm/llvm-project/pull/80504
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread Artem Dergachev via cfe-commits


@@ -598,16 +623,16 @@ class ArraySubscriptGadget : public WarningGadget {
   }
 
   static Matcher matcher() {
-// FIXME: What if the index is integer literal 0? Should this be
-// a safe gadget in this case?
-  // clang-format off
+// clang-format off
   return stmt(arraySubscriptExpr(
 hasBase(ignoringParenImpCasts(
   anyOf(hasPointerType(), hasArrayType(,
-unless(hasIndex(
-anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
- )))
-.bind(ArraySubscrTag));
+unless(anyOf(
+  isSafeArraySubscript(),
+  hasIndex(
+  anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())

haoNoQ wrote:

So you want to suppress the warning here right? In this case yeah makes sense.

It's also somewhat covered by
```
warning: zero size arrays are an extension [-Wzero-length-array]
```

https://github.com/llvm/llvm-project/pull/80504
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81808

>From 857decc27550e2b15938a7846a03561f9ad73f48 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Wed, 14 Feb 2024 16:21:33 -0800
Subject: [PATCH 1/3] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore
 trivial function calls.

This PR introduces the concept of a "trivial function" which applies to a 
function
that only calls other trivial functions and contain literals and expressions 
that
don't result in heap mutations (specifically it does not call deref). This is
implemented using ConstStmtVisitor and checking each statement and expression's
trivialness.

This PR also introduces the concept of a "ingleton function", which is a static
member function or a free standing function which ends with the suffix 
"singleton".
Such a function's return value is understood to be safe to call any function 
with.
---
 .../Checkers/WebKit/ASTUtils.cpp  |   4 +
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 207 
 .../Checkers/WebKit/PtrTypesSemantics.h   |  21 ++
 .../WebKit/UncountedCallArgsChecker.cpp   |   8 +-
 .../Analysis/Checkers/WebKit/call-args.cpp|  33 +--
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 231 ++
 6 files changed, 487 insertions(+), 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index b76c0551c77bb0..94eaa81af51772 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -66,9 +66,13 @@ tryToFindPtrOrigin(const Expr *E, bool 
StopAtFirstRefCountedObj) {
   E = call->getArg(0);
   continue;
 }
+
 if (isReturnValueRefCounted(callee))
   return {E, true};
 
+if (isSingleton(callee))
+  return {E, true};
+
 if (isPtrConversion(callee)) {
   E = call->getArg(0);
   continue;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 907244013d0871..17f59c2d304ddc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include 
 
 using namespace clang;
@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+return false;
+  }
+
+  bool VisitBinaryOperator(const BinaryOperator *BO) {
+// Binary operators are trivial if their operands are trivial.
+return Visit(BO->getLHS()) && Visit(BO->getRHS());
+  }

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-14 Thread Kees Cook via cfe-commits

kees wrote:

> Sure -fwrapv makes wraparound defined, but it doesn't prevent us from making 
> -fsanitize=signed-integer-overflow useful. "-fwrapv => no 
> signed-integer-overflow" is not a solid argument.
> 
> I think we can try making -fsanitize=signed-integer-overflow effective even 
> when -fwrapv if specified. -fsanitize=signed-integer-overflow is rare in the 
> wild, probably rarer when combined with -fwrapv.
.

In earlier GCC discussions, it seemed very much like the 
`-fsanitize=signed-integer-overflow` was meant for UB only, but maybe I 
misunderstood. See replies leading up to this:
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630578.html

https://github.com/llvm/llvm-project/pull/80089
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread via cfe-commits


@@ -598,16 +623,16 @@ class ArraySubscriptGadget : public WarningGadget {
   }
 
   static Matcher matcher() {
-// FIXME: What if the index is integer literal 0? Should this be
-// a safe gadget in this case?
-  // clang-format off
+// clang-format off
   return stmt(arraySubscriptExpr(
 hasBase(ignoringParenImpCasts(
   anyOf(hasPointerType(), hasArrayType(,
-unless(hasIndex(
-anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
- )))
-.bind(ArraySubscrTag));
+unless(anyOf(
+  isSafeArraySubscript(),
+  hasIndex(
+  anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())

jkorous-apple wrote:

Actually, it is still necessary - we need to somehow cover:
```
int arr[0];
arr[0] = 5;
```
And that has been defined as out of scope for the warning. I don't feel like 
calling it "safe" and I'd rather have it visible in the top-level matcher.

https://github.com/llvm/llvm-project/pull/80504
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Ryosuke Niwa via cfe-commits


@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+return false;
+  }
+
+  bool VisitBinaryOperator(const BinaryOperator *BO) {
+// Binary operators are trivial if their operands are trivial.
+return Visit(BO->getLHS()) && Visit(BO->getRHS());
+  }
+
+  bool VisitConditionalOperator(const ConditionalOperator *CO) {
+// Ternary operators are trivial if their conditions & values are trivial.
+return VisitChildren(CO);
+  }
+
+  bool VisitDeclRefExpr(const DeclRefExpr *DRE) {
+if (auto *decl = DRE->getDecl()) {
+  if (isa(decl))
+return true;
+}
+return false;
+  }
+
+  bool VisitStaticAssertDecl(const StaticAssertDecl *SAD) {
+// Any static_assert is considered trivial.
+return true;
+  }
+
+  bool VisitCallExpr(const CallExpr *CE) {
+if (auto *MCE = dyn_cast(CE))
+  return VisitCXXMemberCallExpr(MCE);

rniwa wrote:

Good point. Refactored.

https://github.com/llvm/llvm-project/pull/81808
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Ryosuke Niwa via cfe-commits


@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());

rniwa wrote:

Fixed! This as indeed the cause of the crash.

https://github.com/llvm/llvm-project/pull/81808
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread via cfe-commits

https://github.com/jkorous-apple updated 
https://github.com/llvm/llvm-project/pull/80504

>From e075dc3ac10c0cd2e12b223988ec4821b40b55d2 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Fri, 2 Feb 2024 14:46:59 -0800
Subject: [PATCH 1/6] [-Wunsafe-buffer-usage] Ignore safe array subscripts

Don't emit warnings for array subscripts on constant size arrays where the 
index is constant and within bounds.

Example:
int arr[10];
arr[5] = 0; //safe, no warning

This patch recognizes only array indices that are integer literals - it doesn't 
understand more complex expressions (arithmetic on constants, etc.).
---
 clang/lib/Analysis/UnsafeBufferUsage.cpp  | 39 +++
 .../warn-unsafe-buffer-usage-array.cpp| 18 -
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index ca346444e047e5..d150a679597a92 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -406,6 +406,31 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) 
{
   }
   return false;
 }
+
+AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
+  const DeclRefExpr * BaseDRE = 
dyn_cast_or_null(Node.getBase()->IgnoreParenImpCasts());
+  if (!BaseDRE)
+return false;
+  if (!BaseDRE->getDecl())
+return false;
+  auto BaseVarDeclTy = BaseDRE->getDecl()->getType();
+  if (!BaseVarDeclTy->isConstantArrayType())
+return false;
+  const auto * CATy = dyn_cast_or_null(BaseVarDeclTy);
+  if (!CATy)
+return false;
+  const APInt ArrSize = CATy->getSize();
+
+  if (const auto * IdxLit = dyn_cast(Node.getIdx())) {
+const APInt ArrIdx = IdxLit->getValue();
+// FIXME: ArrIdx.isNegative() we could immediately emit an error as that's 
a bug
+if (ArrIdx.isNonNegative() && ArrIdx.getLimitedValue() < 
ArrSize.getLimitedValue())
+  return true;
+  }
+
+  return false;
+}
+
 } // namespace clang::ast_matchers
 
 namespace {
@@ -598,16 +623,16 @@ class ArraySubscriptGadget : public WarningGadget {
   }
 
   static Matcher matcher() {
-// FIXME: What if the index is integer literal 0? Should this be
-// a safe gadget in this case?
-  // clang-format off
+// clang-format off
   return stmt(arraySubscriptExpr(
 hasBase(ignoringParenImpCasts(
   anyOf(hasPointerType(), hasArrayType(,
-unless(hasIndex(
-anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
- )))
-.bind(ArraySubscrTag));
+unless(anyOf(
+  isSafeArraySubscript(),
+  hasIndex(
+  anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
+  )
+))).bind(ArraySubscrTag));
 // clang-format on
   }
 
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
index 90c11b1be95c25..4804223e8be058 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \
+// RUN: %clang_cc1 -std=c++20 -Wno-everything -Wunsafe-buffer-usage \
 // RUN:-fsafe-buffer-usage-suggestions \
 // RUN:-verify %s
 
@@ -22,3 +22,19 @@ struct Foo {
 void foo2(Foo& f, unsigned idx) {
   f.member_buffer[idx] = 0; // expected-warning{{unsafe buffer access}}
 }
+
+void constant_idx_safe(unsigned idx) {
+  int buffer[10];
+  buffer[9] = 0;
+}
+
+void constant_idx_safe0(unsigned idx) {
+  int buffer[10];
+  buffer[0] = 0;
+}
+
+void constant_idx_unsafe(unsigned idx) {
+  int buffer[10];   // expected-warning{{'buffer' is an unsafe buffer that 
does not perform bounds checks}}
+// expected-note@-1{{change type of 'buffer' to 
'std::array' to harden it}}
+  buffer[10] = 0;   // expected-note{{used in buffer access here}}
+}

>From 9f3940e5e1a8555a784521999d296ed46b1ae0c2 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Fri, 2 Feb 2024 14:48:41 -0800
Subject: [PATCH 2/6] [-Wunsafe-buffer-usage][NFC] Update existing tests after
 constant safe index is ignored

---
 ...afe-buffer-usage-fixits-pointer-access.cpp |  8 +--
 ...ge-fixits-pointer-arg-to-func-ptr-call.cpp |  3 +-
 .../test/SemaCXX/warn-unsafe-buffer-usage.cpp | 53 ++-
 3 files changed, 33 insertions(+), 31 deletions(-)

diff --git 
a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
index f94072015ff87d..b3c64f1b0d085e 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
@@ -83,11 +83,11 @@ void unsafe_method_invocation_single_param() {
 
 }
 
-void unsafe_method_invocation_single_param_array() {
+void 

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81808

>From 857decc27550e2b15938a7846a03561f9ad73f48 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Wed, 14 Feb 2024 16:21:33 -0800
Subject: [PATCH 1/2] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore
 trivial function calls.

This PR introduces the concept of a "trivial function" which applies to a 
function
that only calls other trivial functions and contain literals and expressions 
that
don't result in heap mutations (specifically it does not call deref). This is
implemented using ConstStmtVisitor and checking each statement and expression's
trivialness.

This PR also introduces the concept of a "ingleton function", which is a static
member function or a free standing function which ends with the suffix 
"singleton".
Such a function's return value is understood to be safe to call any function 
with.
---
 .../Checkers/WebKit/ASTUtils.cpp  |   4 +
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 207 
 .../Checkers/WebKit/PtrTypesSemantics.h   |  21 ++
 .../WebKit/UncountedCallArgsChecker.cpp   |   8 +-
 .../Analysis/Checkers/WebKit/call-args.cpp|  33 +--
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 231 ++
 6 files changed, 487 insertions(+), 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index b76c0551c77bb0..94eaa81af51772 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -66,9 +66,13 @@ tryToFindPtrOrigin(const Expr *E, bool 
StopAtFirstRefCountedObj) {
   E = call->getArg(0);
   continue;
 }
+
 if (isReturnValueRefCounted(callee))
   return {E, true};
 
+if (isSingleton(callee))
+  return {E, true};
+
 if (isPtrConversion(callee)) {
   E = call->getArg(0);
   continue;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 907244013d0871..17f59c2d304ddc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include 
 
 using namespace clang;
@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+return false;
+  }
+
+  bool VisitBinaryOperator(const BinaryOperator *BO) {
+// Binary operators are trivial if their operands are trivial.
+return Visit(BO->getLHS()) && Visit(BO->getRHS());
+  }

[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-14 Thread via cfe-commits


@@ -821,15 +822,23 @@ void InstrProfRecord::merge(InstrProfRecord , 
uint64_t Weight,
 
   for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
 bool Overflowed;
-uint64_t Value =
-SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], );
-if (Value > getInstrMaxCountValue()) {
-  Value = getInstrMaxCountValue();
-  Overflowed = true;
+uint64_t Value;
+// When a profile has single byte coverage, use || to merge counters.
+if (HasSingleByteCoverage)
+  Value = Other.Counts[I] || Counts[I];

gulfemsavrun wrote:

Ok, there is a valid use case then. So, I removed this code.

https://github.com/llvm/llvm-project/pull/75425
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-14 Thread via cfe-commits

https://github.com/gulfemsavrun updated 
https://github.com/llvm/llvm-project/pull/75425

>From 5553825da82306a3bb0b959f4cbfadc624b1d14f Mon Sep 17 00:00:00 2001
From: Gulfem Savrun Yeniceri 
Date: Thu, 14 Dec 2023 03:40:57 +
Subject: [PATCH] [InstrProf] Single byte counters in coverage

This patch inserts 1-byte counters instead of an 8-byte counters
into llvm profiles for source-based code coverage. The origial idea
was proposed as block-cov for PGO, and this patch repurposes that
idea for coverage.

The current 8-byte counters mechanism add counters to minimal regions,
and infer the counters in the remaining regions via adding or
subtracting counters. For example, it infers the counter in the if.else
region by subtracting the counters between if.entry and if.then regions
in an if statement. Whenever there is a control-flow merge, it adds
the counters from all the incoming regions. However, we are not going to
be able to infer counters by subtracting two execution counts when using
single-byte counters. Therefore, this patch conservatively inserts
additional counters for the cases where we need to add or subtract counters.

RFC:
https://discourse.llvm.org/t/rfc-single-byte-counters-for-source-based-code-coverage/75685
---
 clang/lib/CodeGen/CGExprAgg.cpp   |  13 +-
 clang/lib/CodeGen/CGExprComplex.cpp   |  14 +-
 clang/lib/CodeGen/CGExprScalar.cpp|  32 ++-
 clang/lib/CodeGen/CGStmt.cpp  |  73 ++-
 clang/lib/CodeGen/CodeGenFunction.cpp |   9 +-
 clang/lib/CodeGen/CodeGenFunction.h   |   2 +-
 clang/lib/CodeGen/CodeGenModule.cpp   |   1 +
 clang/lib/CodeGen/CodeGenPGO.cpp  | 150 -
 clang/lib/CodeGen/CodeGenPGO.h|   6 +-
 clang/lib/CodeGen/CoverageMappingGen.cpp  | 206 +-
 .../CoverageMapping/single-byte-counters.cpp  | 169 ++
 compiler-rt/lib/profile/InstrProfiling.h  |   3 +-
 .../ProfileData/Coverage/CoverageMapping.h|  20 +-
 .../llvm/ProfileData/InstrProfWriter.h|   4 +
 .../ProfileData/Coverage/CoverageMapping.cpp  |  13 +-
 llvm/lib/ProfileData/InstrProf.cpp|  10 +-
 16 files changed, 630 insertions(+), 95 deletions(-)
 create mode 100644 clang/test/CoverageMapping/single-byte-counters.cpp

diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 22f55fe9aac904..377bf413c857cb 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -33,6 +33,10 @@ using namespace CodeGen;
 //Aggregate Expression Emitter
 
//===--===//
 
+namespace llvm {
+extern cl::opt EnableSingleByteCoverage;
+} // namespace llvm
+
 namespace  {
 class AggExprEmitter : public StmtVisitor {
   CodeGenFunction 
@@ -1278,7 +1282,10 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(LHSBlock);
-  CGF.incrementProfileCounter(E);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getTrueExpr());
+  else
+CGF.incrementProfileCounter(E);
   Visit(E->getTrueExpr());
   eval.end(CGF);
 
@@ -1293,6 +1300,8 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(RHSBlock);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getFalseExpr());
   Visit(E->getFalseExpr());
   eval.end(CGF);
 
@@ -1301,6 +1310,8 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 E->getType());
 
   CGF.EmitBlock(ContBlock);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E);
 }
 
 void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp 
b/clang/lib/CodeGen/CGExprComplex.cpp
index 9ddf0e763f139b..683097eea5e76a 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -28,6 +28,10 @@ using namespace CodeGen;
 //Complex Expression Emitter
 
//===--===//
 
+namespace llvm {
+extern cl::opt EnableSingleByteCoverage;
+} // namespace llvm
+
 typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
 
 /// Return the complex type that we are meant to emit.
@@ -1329,7 +1333,11 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   CGF.EmitBlock(LHSBlock);
-  CGF.incrementProfileCounter(E);
+  if (llvm::EnableSingleByteCoverage)
+CGF.incrementProfileCounter(E->getTrueExpr());
+  else
+CGF.incrementProfileCounter(E);
+
   ComplexPairTy LHS = Visit(E->getTrueExpr());
   LHSBlock = Builder.GetInsertBlock();
   CGF.EmitBranch(ContBlock);
@@ -1337,9 +1345,13 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
 
   eval.begin(CGF);
   

[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-14 Thread Kees Cook via cfe-commits

kees wrote:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102317

https://github.com/llvm/llvm-project/pull/80089
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] bad error message on incorrect string literal #18079 (PR #81670)

2024-02-14 Thread Jon Roelofs via cfe-commits


@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -E -fsyntax-only -verify %s
+
+// expected-error@+2{{invalid character ')' character in raw string delimiter; 
use PREFIX( )PREFIX to delimit raw string}}

jroelofs wrote:

This has the old spelling of that diagnostic.

Also, might be a little nicer to combine the two tests in one file, since 
they're testing _almost_ the same thing.

https://github.com/llvm/llvm-project/pull/81670
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Artem Dergachev via cfe-commits


@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());

haoNoQ wrote:

This probably needs a null check. (But I don't think it's the root cause of the 
crash you mentioned offline.)

https://github.com/llvm/llvm-project/pull/81808
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [InstrProf] Single byte counters in coverage (PR #75425)

2024-02-14 Thread via cfe-commits

https://github.com/gulfemsavrun edited 
https://github.com/llvm/llvm-project/pull/75425
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread via cfe-commits

https://github.com/jkorous-apple updated 
https://github.com/llvm/llvm-project/pull/80504

>From e075dc3ac10c0cd2e12b223988ec4821b40b55d2 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Fri, 2 Feb 2024 14:46:59 -0800
Subject: [PATCH 1/4] [-Wunsafe-buffer-usage] Ignore safe array subscripts

Don't emit warnings for array subscripts on constant size arrays where the 
index is constant and within bounds.

Example:
int arr[10];
arr[5] = 0; //safe, no warning

This patch recognizes only array indices that are integer literals - it doesn't 
understand more complex expressions (arithmetic on constants, etc.).
---
 clang/lib/Analysis/UnsafeBufferUsage.cpp  | 39 +++
 .../warn-unsafe-buffer-usage-array.cpp| 18 -
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index ca346444e047e5..d150a679597a92 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -406,6 +406,31 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) 
{
   }
   return false;
 }
+
+AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
+  const DeclRefExpr * BaseDRE = 
dyn_cast_or_null(Node.getBase()->IgnoreParenImpCasts());
+  if (!BaseDRE)
+return false;
+  if (!BaseDRE->getDecl())
+return false;
+  auto BaseVarDeclTy = BaseDRE->getDecl()->getType();
+  if (!BaseVarDeclTy->isConstantArrayType())
+return false;
+  const auto * CATy = dyn_cast_or_null(BaseVarDeclTy);
+  if (!CATy)
+return false;
+  const APInt ArrSize = CATy->getSize();
+
+  if (const auto * IdxLit = dyn_cast(Node.getIdx())) {
+const APInt ArrIdx = IdxLit->getValue();
+// FIXME: ArrIdx.isNegative() we could immediately emit an error as that's 
a bug
+if (ArrIdx.isNonNegative() && ArrIdx.getLimitedValue() < 
ArrSize.getLimitedValue())
+  return true;
+  }
+
+  return false;
+}
+
 } // namespace clang::ast_matchers
 
 namespace {
@@ -598,16 +623,16 @@ class ArraySubscriptGadget : public WarningGadget {
   }
 
   static Matcher matcher() {
-// FIXME: What if the index is integer literal 0? Should this be
-// a safe gadget in this case?
-  // clang-format off
+// clang-format off
   return stmt(arraySubscriptExpr(
 hasBase(ignoringParenImpCasts(
   anyOf(hasPointerType(), hasArrayType(,
-unless(hasIndex(
-anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
- )))
-.bind(ArraySubscrTag));
+unless(anyOf(
+  isSafeArraySubscript(),
+  hasIndex(
+  anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
+  )
+))).bind(ArraySubscrTag));
 // clang-format on
   }
 
diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
index 90c11b1be95c25..4804223e8be058 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-array.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \
+// RUN: %clang_cc1 -std=c++20 -Wno-everything -Wunsafe-buffer-usage \
 // RUN:-fsafe-buffer-usage-suggestions \
 // RUN:-verify %s
 
@@ -22,3 +22,19 @@ struct Foo {
 void foo2(Foo& f, unsigned idx) {
   f.member_buffer[idx] = 0; // expected-warning{{unsafe buffer access}}
 }
+
+void constant_idx_safe(unsigned idx) {
+  int buffer[10];
+  buffer[9] = 0;
+}
+
+void constant_idx_safe0(unsigned idx) {
+  int buffer[10];
+  buffer[0] = 0;
+}
+
+void constant_idx_unsafe(unsigned idx) {
+  int buffer[10];   // expected-warning{{'buffer' is an unsafe buffer that 
does not perform bounds checks}}
+// expected-note@-1{{change type of 'buffer' to 
'std::array' to harden it}}
+  buffer[10] = 0;   // expected-note{{used in buffer access here}}
+}

>From 9f3940e5e1a8555a784521999d296ed46b1ae0c2 Mon Sep 17 00:00:00 2001
From: Jan Korous 
Date: Fri, 2 Feb 2024 14:48:41 -0800
Subject: [PATCH 2/4] [-Wunsafe-buffer-usage][NFC] Update existing tests after
 constant safe index is ignored

---
 ...afe-buffer-usage-fixits-pointer-access.cpp |  8 +--
 ...ge-fixits-pointer-arg-to-func-ptr-call.cpp |  3 +-
 .../test/SemaCXX/warn-unsafe-buffer-usage.cpp | 53 ++-
 3 files changed, 33 insertions(+), 31 deletions(-)

diff --git 
a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
index f94072015ff87d..b3c64f1b0d085e 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-access.cpp
@@ -83,11 +83,11 @@ void unsafe_method_invocation_single_param() {
 
 }
 
-void unsafe_method_invocation_single_param_array() {
+void 

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Artem Dergachev via cfe-commits


@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+return false;
+  }
+
+  bool VisitBinaryOperator(const BinaryOperator *BO) {
+// Binary operators are trivial if their operands are trivial.
+return Visit(BO->getLHS()) && Visit(BO->getRHS());
+  }
+
+  bool VisitConditionalOperator(const ConditionalOperator *CO) {
+// Ternary operators are trivial if their conditions & values are trivial.
+return VisitChildren(CO);
+  }
+
+  bool VisitDeclRefExpr(const DeclRefExpr *DRE) {
+if (auto *decl = DRE->getDecl()) {
+  if (isa(decl))
+return true;
+}
+return false;
+  }
+
+  bool VisitStaticAssertDecl(const StaticAssertDecl *SAD) {
+// Any static_assert is considered trivial.
+return true;
+  }
+
+  bool VisitCallExpr(const CallExpr *CE) {
+if (auto *MCE = dyn_cast(CE))
+  return VisitCXXMemberCallExpr(MCE);

haoNoQ wrote:

This happens automatically, you don't need to do that manually. The visitor 
calls the most specialized user-defined method. (If it's not user-defined, it's 
defined by default to call the slightly less specialized method.)

On the other hand, it might make sense to call `VisitCallExpr()` from inside 
`VisitCXXMemberCallExpr()` to reuse some code. (Or you can define a common 
method called by both.)

https://github.com/llvm/llvm-project/pull/81808
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ commented:

LGTM! Just one nitpick.

https://github.com/llvm/llvm-project/pull/81808
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ edited https://github.com/llvm/llvm-project/pull/81808
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Fixits for unsafe arguments of function pointer calls (PR #80358)

2024-02-14 Thread via cfe-commits

https://github.com/jkorous-apple closed 
https://github.com/llvm/llvm-project/pull/80358
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 4cd7616 - [-Wunsafe-buffer-usage] Fixits for array args of func-ptr calls (#80358)

2024-02-14 Thread via cfe-commits

Author: jkorous-apple
Date: 2024-02-14T17:19:39-08:00
New Revision: 4cd7616f6b13513bb13f2b6dd14d140a4c62c937

URL: 
https://github.com/llvm/llvm-project/commit/4cd7616f6b13513bb13f2b6dd14d140a4c62c937
DIFF: 
https://github.com/llvm/llvm-project/commit/4cd7616f6b13513bb13f2b6dd14d140a4c62c937.diff

LOG: [-Wunsafe-buffer-usage] Fixits for array args of func-ptr calls (#80358)

Currently we ignore calls on function pointers (unlike direct calls of
functions and class methods). This patch adds support for function pointers as
well.

The change is to simply replace use of forEachArgumentWithParam matcher in UPC
gadget with forEachArgumentWithParamType.

from the documentation of forEachArgumentWithParamType:
/// Matches all arguments and their respective types for a \c CallExpr or
/// \c CXXConstructExpr. It is very similar to \c forEachArgumentWithParam but
/// it works on calls through function pointers as well.

Currently the matcher also uses hasPointerType() which checks that the
canonical type of an argument is pointer and won't match on arrays decayed to
pointer. Replacing hasPointerType() with isAnyPointerType() which allows
implicit casts allows for the arrays to be matched as well and this way we get
fixits for array arguments to function pointer calls too.

Added: 

clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-arg-to-func-ptr-call.cpp

Modified: 
clang/lib/Analysis/UnsafeBufferUsage.cpp

Removed: 




diff  --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp 
b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index d00c598c4b9de3..ca346444e047e5 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -281,10 +281,13 @@ isInUnspecifiedPointerContext(internal::Matcher 
InnerMatcher) {
   // 4. the operand of a pointer subtraction operation
   //(i.e., computing the distance between two pointers); or ...
 
-  auto CallArgMatcher =
-  callExpr(forEachArgumentWithParam(InnerMatcher,
-  hasPointerType() /* array also decays to pointer type*/),
-  unless(callee(functionDecl(hasAttr(attr::UnsafeBufferUsage);
+  // clang-format off
+  auto CallArgMatcher = callExpr(
+forEachArgumentWithParamType(
+  InnerMatcher, 
+  isAnyPointer() /* array also decays to pointer type*/),
+unless(callee(
+  functionDecl(hasAttr(attr::UnsafeBufferUsage);
 
   auto CastOperandMatcher =
   castExpr(anyOf(hasCastKind(CastKind::CK_PointerToIntegral),
@@ -306,6 +309,7 @@ isInUnspecifiedPointerContext(internal::Matcher 
InnerMatcher) {
   hasRHS(hasPointerType())),
 eachOf(hasLHS(InnerMatcher),
hasRHS(InnerMatcher)));
+  // clang-format on
 
   return stmt(anyOf(CallArgMatcher, CastOperandMatcher, CompOperandMatcher,
PtrSubtractionMatcher));

diff  --git 
a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-arg-to-func-ptr-call.cpp
 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-arg-to-func-ptr-call.cpp
new file mode 100644
index 00..0459d6549fd86f
--- /dev/null
+++ 
b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-pointer-arg-to-func-ptr-call.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \
+// RUN:-fsafe-buffer-usage-suggestions \
+// RUN:-fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+void unsafe_array_func_ptr_call(void (*fn_ptr)(int *param)) {
+  int p[32];
+  // CHECK-DAG: 
fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::array p"
+
+  p[5] = 10;
+  fn_ptr(p);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:11}:".data()"
+}
+
+void unsafe_ptr_func_ptr_call(void (*fn_ptr)(int *param)) {
+  int *p;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"std::span 
p"
+
+  p[5] = 10;
+  fn_ptr(p);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:11}:".data()"
+}
+
+void addr_of_unsafe_ptr_func_ptr_call(void (*fn_ptr)(int *param)) {
+  int *p;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"std::span 
p"
+
+  p[5] = 10;
+  fn_ptr([0]);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:15}:"p.data()"
+}
+
+void addr_of_unsafe_ptr_w_offset_func_ptr_call(void (*fn_ptr)(int *param)) {
+  int *p;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"std::span 
p"
+
+  p[5] = 10;
+  fn_ptr([3]);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:15}:"()[3]"
+}
+
+void preincrement_unsafe_ptr_func_ptr_call(void (*fn_ptr)(int *param)) {
+  int *p;
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:9}:"std::span 
p"
+
+  p[5] = 10;
+  fn_ptr(++p);
+  // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:10-[[@LINE-1]]:13}:"(p = 
p.subspan(1)).data()"
+}



___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[clang] [-Wunsafe-buffer-usage] Fixits for unsafe arguments of function pointer calls (PR #80358)

2024-02-14 Thread via cfe-commits

jkorous-apple wrote:

Currently we ignore calls on function pointers (unlike direct calls of
functions and class methods). This patch adds support for function pointers as
well.

The change is to simply replace use of forEachArgumentWithParam matcher in UPC
gadget with forEachArgumentWithParamType.

from the documentation of forEachArgumentWithParamType:
/// Matches all arguments and their respective types for a \c CallExpr or
/// \c CXXConstructExpr. It is very similar to \c forEachArgumentWithParam but
/// it works on calls through function pointers as well.

Currently the matcher also uses hasPointerType() which checks that the
canonical type of an argument is pointer and won't match on arrays decayed to
pointer. Replacing hasPointerType() with isAnyPointerType() which allows
implicit casts allows for the arrays to be matched as well and this way we get
fixits for array arguments to function pointer calls too.

https://github.com/llvm/llvm-project/pull/80358
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Fixits for unsafe arguments of function pointer calls (PR #80358)

2024-02-14 Thread via cfe-commits


@@ -282,8 +282,8 @@ isInUnspecifiedPointerContext(internal::Matcher 
InnerMatcher) {
   //(i.e., computing the distance between two pointers); or ...
 
   auto CallArgMatcher =
-  callExpr(forEachArgumentWithParam(InnerMatcher,
-  hasPointerType() /* array also decays to pointer type*/),
+  callExpr(forEachArgumentWithParamType(InnerMatcher,
+  isAnyPointer() /* array also decays to pointer type*/),

jkorous-apple wrote:

Summary of an offline discussion: Actually, the above is wrong because we're 
talking about the parameter type, not argument type but it also voids the 
concern.

https://github.com/llvm/llvm-project/pull/80358
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [Sanitizer] add signed-integer-wrap sanitizer (PR #80089)

2024-02-14 Thread Fangrui Song via cfe-commits

MaskRay wrote:

This is a UI discussion about how command line options should behave.
Some folks prefer simpler rules while some prefer smart rules (guessing what 
the user intends).

A 
[-fwrapv](https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fwrapv)
 user may either:

* rely on the wraparound behavior
* or prevent certain optimizations that would raise security concerns

Our -fsanitize=signed-integer-overflow design have been assuming that -fwrapv 
users don't need the check.
This PR suggests that an important user does want overflow checks.
It seems very confusing to have two options doing the same thing.

I think we can try -fsanitize=signed-integer-overflow effective when -fwrapv.

There is a precedent that -fsanitize=undefined enables different checks for 
different targets.
We could make -fsanitize=undefined not imply -fsanitize=signed-integer-overflow 
when -fwrapv is specified, if we do want to guess the user intention.
Personally I'd prefer moving away from such behaviors and be more orthogonal.


https://github.com/llvm/llvm-project/pull/80089
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81808

>From 857decc27550e2b15938a7846a03561f9ad73f48 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Wed, 14 Feb 2024 16:21:33 -0800
Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore
 trivial function calls.

This PR introduces the concept of a "trivial function" which applies to a 
function
that only calls other trivial functions and contain literals and expressions 
that
don't result in heap mutations (specifically it does not call deref). This is
implemented using ConstStmtVisitor and checking each statement and expression's
trivialness.

This PR also introduces the concept of a "ingleton function", which is a static
member function or a free standing function which ends with the suffix 
"singleton".
Such a function's return value is understood to be safe to call any function 
with.
---
 .../Checkers/WebKit/ASTUtils.cpp  |   4 +
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 207 
 .../Checkers/WebKit/PtrTypesSemantics.h   |  21 ++
 .../WebKit/UncountedCallArgsChecker.cpp   |   8 +-
 .../Analysis/Checkers/WebKit/call-args.cpp|  33 +--
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 231 ++
 6 files changed, 487 insertions(+), 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index b76c0551c77bb0..94eaa81af51772 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -66,9 +66,13 @@ tryToFindPtrOrigin(const Expr *E, bool 
StopAtFirstRefCountedObj) {
   E = call->getArg(0);
   continue;
 }
+
 if (isReturnValueRefCounted(callee))
   return {E, true};
 
+if (isSingleton(callee))
+  return {E, true};
+
 if (isPtrConversion(callee)) {
   E = call->getArg(0);
   continue;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 907244013d0871..17f59c2d304ddc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include 
 
 using namespace clang;
@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+return false;
+  }
+
+  bool VisitBinaryOperator(const BinaryOperator *BO) {
+// Binary operators are trivial if their operands are trivial.
+return Visit(BO->getLHS()) && Visit(BO->getRHS());
+  }
+
+ 

[clang] bad error message on incorrect string literal #18079 (PR #81670)

2024-02-14 Thread via cfe-commits

https://github.com/akshaykumars614 updated 
https://github.com/llvm/llvm-project/pull/81670

>From c2f716ee5f787ec3df63511fd5f565a3deee4d6e Mon Sep 17 00:00:00 2001
From: akshaykumars614 
Date: Tue, 13 Feb 2024 16:29:51 -0500
Subject: [PATCH 1/6] issue: #18079 (bad errwqor message on incorrect string
 literal)

Fixed the error message for incorrect string literal
---
 clang/include/clang/Basic/DiagnosticLexKinds.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 75ca2fa16d3485..c5a2096d02b39d 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -100,7 +100,7 @@ def err_raw_delim_too_long : Error<
   "raw string delimiter longer than 16 characters"
   "; use PREFIX( )PREFIX to delimit raw string">;
 def err_invalid_char_raw_delim : Error<
-  "invalid character '%0' character in raw string delimiter"
+  "invalid newline character in raw string delimiter"
   "; use PREFIX( )PREFIX to delimit raw string">;
 def err_unterminated_raw_string : Error<
   "raw string missing terminating delimiter )%0\"">;

>From ac8b99309b07b6c7114dfbf784a46d2fb5d9dcc4 Mon Sep 17 00:00:00 2001
From: akshaykumars614 
Date: Wed, 14 Feb 2024 14:04:52 -0500
Subject: [PATCH 2/6] bad error message on incorrect string literal #18079

Introduced new error code for \n delimiter in raw string delimiter. Added 
testcase to test the same.
---
 clang/include/clang/Basic/DiagnosticLexKinds.td | 3 +++
 clang/lib/Lex/Lexer.cpp | 6 --
 clang/test/Lexer/raw-string-dlim-newline.cpp| 5 +
 3 files changed, 12 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Lexer/raw-string-dlim-newline.cpp

diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index c5a2096d02b39d..0bc684a9db5793 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -102,6 +102,9 @@ def err_raw_delim_too_long : Error<
 def err_invalid_char_raw_delim : Error<
   "invalid newline character in raw string delimiter"
   "; use PREFIX( )PREFIX to delimit raw string">;
+def err_invalid_nexline_raw_delim : Error<
+  "invalid newline character in raw string delimiter"
+  "; use PREFIX( )PREFIX to delimit raw string">;
 def err_unterminated_raw_string : Error<
   "raw string missing terminating delimiter )%0\"">;
 def warn_cxx98_compat_raw_string_literal : Warning<
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index d927f28b47c270..95f39df7a4628a 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -2270,10 +2270,12 @@ bool Lexer::LexRawStringLiteral(Token , const 
char *CurPtr,
   const char *PrefixEnd = [PrefixLen];
   if (PrefixLen == 16) {
 Diag(PrefixEnd, diag::err_raw_delim_too_long);
-  } else {
+  } else if (*PrefixEnd != '\n') {
 Diag(PrefixEnd, diag::err_invalid_char_raw_delim)
   << StringRef(PrefixEnd, 1);
-  }
+  } else {
+Diag(PrefixEnd, diag::err_invalid_nexline_raw_delim);
+   }
 }
 
 // Search for the next '"' in hopes of salvaging the lexer. Unfortunately,
diff --git a/clang/test/Lexer/raw-string-dlim-newline.cpp 
b/clang/test/Lexer/raw-string-dlim-newline.cpp
new file mode 100644
index 00..36939ed864ecae
--- /dev/null
+++ b/clang/test/Lexer/raw-string-dlim-newline.cpp
@@ -0,0 +1,5 @@
+// RUN: not  %clang_cc1 -E %s 2>&1 | grep 'error: invalid newline character in 
raw string delimiter; use PREFIX( )PREFIX to delimit raw string'
+
+// Introduced new error code err_invalid_nexline_raw_delim for code which has 
\n as delimiter.
+char const* str1 = R"
+";

>From f8ede1571c5678aa6cdbce7cc0d5b30f191b4e92 Mon Sep 17 00:00:00 2001
From: akshaykumars614 <88362922+akshaykumars...@users.noreply.github.com>
Date: Wed, 14 Feb 2024 14:15:34 -0500
Subject: [PATCH 3/6] Update clang/include/clang/Basic/DiagnosticLexKinds.td

Co-authored-by: Jon Roelofs 
---
 clang/include/clang/Basic/DiagnosticLexKinds.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 0bc684a9db5793..1db34adf6bee61 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -102,7 +102,7 @@ def err_raw_delim_too_long : Error<
 def err_invalid_char_raw_delim : Error<
   "invalid newline character in raw string delimiter"
   "; use PREFIX( )PREFIX to delimit raw string">;
-def err_invalid_nexline_raw_delim : Error<
+def err_invalid_newline_raw_delim : Error<
   "invalid newline character in raw string delimiter"
   "; use PREFIX( )PREFIX to delimit raw string">;
 def err_unterminated_raw_string : Error<

>From baa768ebc8f5a5359a8921c110a39d3ff8739747 Mon Sep 17 00:00:00 2001
From: 

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/81808

>From 5a5b26fc3ed2c1c263cd3495b8844e2daeb2e54b Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Wed, 14 Feb 2024 16:21:33 -0800
Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore
 trivial function calls.

This PR introduces the concept of a "trivial function" which applies to a 
function
that only calls other trivial functions and contain literals and expressions 
that
don't result in heap mutations (specifically it does not call deref). This is
implemented using ConstStmtVisitor and checking each statement and expression's
trivialness.

This PR also introduces the concept of a "ingleton function", which is a static
member function or a free standing function which ends with the suffix 
"singleton".
Such a function's return value is understood to be safe to call any function 
with.
---
 .../Checkers/WebKit/ASTUtils.cpp  |   4 +
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 208 
 .../Checkers/WebKit/PtrTypesSemantics.h   |  21 ++
 .../WebKit/UncountedCallArgsChecker.cpp   |   8 +-
 .../Analysis/Checkers/WebKit/call-args.cpp|  33 +--
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 231 ++
 6 files changed, 488 insertions(+), 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index b76c0551c77bb0..94eaa81af51772 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -66,9 +66,13 @@ tryToFindPtrOrigin(const Expr *E, bool 
StopAtFirstRefCountedObj) {
   E = call->getArg(0);
   continue;
 }
+
 if (isReturnValueRefCounted(callee))
   return {E, true};
 
+if (isSingleton(callee))
+  return {E, true};
+
 if (isPtrConversion(callee)) {
   E = call->getArg(0);
   continue;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 907244013d0871..ba02c7a786871d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include 
 
 using namespace clang;
@@ -222,4 +223,211 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+return false;
+  }
+
+  bool VisitBinaryOperator(const BinaryOperator *BO) {
+// Binary operators are trivial if their operands are trivial.
+return Visit(BO->getLHS()) && Visit(BO->getRHS());
+  }
+

[clang] [RISCV] Disable generation of asynchronous unwind tables for RISCV baremetal (PR #81727)

2024-02-14 Thread Fangrui Song via cfe-commits

MaskRay wrote:

I wonder whether GCC considers using `-fno-asynchronous-unwind-tables` for all 
RISC-V configurations.

https://github.com/llvm/llvm-project/pull/81727
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][InstallAPI] Add input file support to library (PR #81701)

2024-02-14 Thread Juergen Ributzka via cfe-commits

https://github.com/ributzka approved this pull request.

LGTM

https://github.com/llvm/llvm-project/pull/81701
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][InstallAPI] Add input file support to library (PR #81701)

2024-02-14 Thread Cyndy Ishida via cfe-commits

https://github.com/cyndyishida updated 
https://github.com/llvm/llvm-project/pull/81701

>From 9d0da0010f145b23ce2b7e5b6183558609600789 Mon Sep 17 00:00:00 2001
From: Cyndy Ishida 
Date: Tue, 13 Feb 2024 18:22:23 -0800
Subject: [PATCH 1/3] [clang][InstallAPI] Add input file support to library

This patch adds support for expected InstallAPI inputs.
InstallAPI  accepts a well defined filelist of headers and how those headers
represent a single library.

InstallAPI captures header files to determine linkable symbols
to then compare against what was compiled in a binary dylib and
generate TBD files.
---
 clang/include/clang/InstallAPI/FileList.h |  53 +
 clang/include/clang/InstallAPI/HeaderFile.h   |  72 +++
 clang/lib/ExtractAPI/CMakeLists.txt   |   1 +
 clang/lib/ExtractAPI/ExtractAPIConsumer.cpp   |   7 +-
 clang/lib/InstallAPI/CMakeLists.txt   |   2 +
 clang/lib/InstallAPI/FileList.cpp | 196 ++
 clang/lib/InstallAPI/HeaderFile.cpp   |  37 
 clang/unittests/CMakeLists.txt|   1 +
 clang/unittests/InstallAPI/CMakeLists.txt |   9 +
 clang/unittests/InstallAPI/FileListTest.cpp   | 140 +
 clang/unittests/InstallAPI/HeaderFileTest.cpp |  89 
 11 files changed, 603 insertions(+), 4 deletions(-)
 create mode 100644 clang/include/clang/InstallAPI/FileList.h
 create mode 100644 clang/include/clang/InstallAPI/HeaderFile.h
 create mode 100644 clang/lib/InstallAPI/FileList.cpp
 create mode 100644 clang/lib/InstallAPI/HeaderFile.cpp
 create mode 100644 clang/unittests/InstallAPI/CMakeLists.txt
 create mode 100644 clang/unittests/InstallAPI/FileListTest.cpp
 create mode 100644 clang/unittests/InstallAPI/HeaderFileTest.cpp

diff --git a/clang/include/clang/InstallAPI/FileList.h 
b/clang/include/clang/InstallAPI/FileList.h
new file mode 100644
index 00..01ec9b35e31490
--- /dev/null
+++ b/clang/include/clang/InstallAPI/FileList.h
@@ -0,0 +1,53 @@
+//===- InstallAPI/FileList.h *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// The JSON file list parser is used to communicate input to InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_FILELIST_H
+#define LLVM_CLANG_INSTALLAPI_FILELIST_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/InstallAPI/HeaderFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace clang {
+namespace installapi {
+
+/// JSON decoder for InstallAPI Inputs.
+class FileListReader {
+
+  class Implementation;
+  Implementation 
+
+  FileListReader(std::unique_ptr InputBuffer,
+ llvm::Error );
+
+public:
+  /// Decode JSON input and append header input into destination container.
+  /// Headers are loaded in the order they appear in the JSON input.
+  ///
+  /// \param InputBuffer JSON input data.
+  /// \param Destination Container to load headers into.
+  static llvm::Error
+  loadHeaders(std::unique_ptr InputBuffer,
+  HeaderSeq );
+
+  ~FileListReader();
+
+  FileListReader(const FileListReader &) = delete;
+  FileListReader =(const FileListReader &) = delete;
+};
+
+} // namespace installapi
+} // namespace clang
+
+#endif // LLVM_CLANG_INSTALLAPI_FILELIST_H
diff --git a/clang/include/clang/InstallAPI/HeaderFile.h 
b/clang/include/clang/InstallAPI/HeaderFile.h
new file mode 100644
index 00..6ccd944f8b01be
--- /dev/null
+++ b/clang/include/clang/InstallAPI/HeaderFile.h
@@ -0,0 +1,72 @@
+//===- InstallAPI/HeaderFile.h --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// Representations of a library's headers for InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_HEADERFILE_H
+#define LLVM_CLANG_INSTALLAPI_HEADERFILE_H
+
+#include "clang/Basic/LangStandard.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Regex.h"
+#include 
+#include 
+
+namespace clang::installapi {
+enum class HeaderType {
+  /// Represents declarations accessible to all clients.
+  Public,
+  /// Represents declarations accessible to a disclosed set of clients.
+  Private,
+  /// Represents declarations only accessible as implementation details to the
+  /// input library.
+  Project,
+};
+
+class HeaderFile {
+  /// Full 

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff fe20a759fcd20e1755ea1b34c5e6447a787925dc 
26f7904095ddd54ab54a94b3ae84db61d2135833 -- 
clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h 
clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp 
clang/test/Analysis/Checkers/WebKit/call-args.cpp 
clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index b2169bf023..528ca77c49 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -233,10 +233,10 @@ bool isSingleton(const FunctionDecl *F) {
   const auto  = safeGetName(F);
   std::string SingletonStr = "singleton";
   auto index = Name.find(SingletonStr);
-  return index != std::string::npos && index == Name.size() - 
SingletonStr.size();
+  return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
 }
 
-
 // We only care about statements so let's use the simple
 // (non-recursive) visitor.
 class TrivialFunctionAnalysisVisitor
@@ -255,7 +255,7 @@ class TrivialFunctionAnalysisVisitor
 public:
   using CacheTy = TrivialFunctionAnalysis::CacheTy;
 
-  TrivialFunctionAnalysisVisitor(CacheTy ): Cache(Cache) {}
+  TrivialFunctionAnalysisVisitor(CacheTy ) : Cache(Cache) {}
 
   bool VisitStmt(const Stmt *S) {
 // All statements are non-trivial unless overriden later.
@@ -263,9 +263,7 @@ public:
 return false;
   }
 
-  bool VisitDeclStmt(const DeclStmt *DS) {
-return VisitChildren(DS);
-  }
+  bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
 
   bool VisitCompoundStmt(const CompoundStmt *CS) {
 // A compound statement is allowed as long each individual sub-statement
@@ -278,25 +276,15 @@ public:
 return Visit(RS->getRetValue());
   }
 
-  bool VisitDoStmt(const DoStmt *DS) {
-return VisitChildren(DS);
-  }
+  bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
 
-  bool VisitIfStmt(const IfStmt *IS) {
-return VisitChildren(IS);
-  }
+  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
 
-  bool VisitSwitchStmt(const SwitchStmt *SS) {
-return VisitChildren(SS);
-  }
-  
-  bool VisitCaseStmt(const CaseStmt* CS) {
-return VisitChildren(CS);
-  }
+  bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
 
-  bool VisitDefaultStmt(const DefaultStmt* DS) {
-return VisitChildren(DS);
-  }
+  bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+
+  bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
 
   bool VisitUnaryOperator(const UnaryOperator *UO) {
 // Operator '*' and '!' are allowed as long as the operand is trivial.
@@ -316,7 +304,7 @@ public:
 // Ternary operators are trivial if their conditions & values are trivial.
 return VisitChildren(CO);
   }
-  
+
   bool VisitDeclRefExpr(const DeclRefExpr *DRE) {
 if (auto *decl = DRE->getDecl()) {
   if (isa(decl))
@@ -336,7 +324,7 @@ public:
 
 for (const Expr *Arg : CE->arguments()) {
   if (Arg && !Visit(Arg))
-return false;  
+return false;
 }
 
 auto *Callee = CE->getDirectCallee();
@@ -344,8 +332,8 @@ public:
   return false;
 const auto  = safeGetName(Callee);
 
-if (Name == "WTFCrashWithInfo" || Name == "WTFBreakpointTrap"
-|| Name == "compilerFenceForCrash" || Name == "__builtin_unreachable")
+if (Name == "WTFCrashWithInfo" || Name == "WTFBreakpointTrap" ||
+Name == "compilerFenceForCrash" || Name == "__builtin_unreachable")
   return true;
 
 return TrivialFunctionAnalysis::isTrivialImpl(Callee, Cache);
@@ -354,7 +342,7 @@ public:
   bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE) {
 for (const Expr *Arg : MCE->arguments()) {
   if (Arg && !Visit(Arg))
-return false;  
+return false;
 }
 
 bool TrivialThis = Visit(MCE->getImplicitObjectArgument());
@@ -366,7 +354,6 @@ public:
 if (IsGetterOfRefCounted && *IsGetterOfRefCounted)
   return true;
 
-
 // Recursively descend into the callee to confirm that it's trivial as 
well.
 return TrivialFunctionAnalysis::isTrivialImpl(MCE->getDirectCallee(),
   Cache);
@@ -378,27 +365,20 @@ public:
 return false;
 
 // Recursively descend into the callee to confirm that it's trivial.
-return TrivialFunctionAnalysis::isTrivialImpl(CE->getConstructor(),
- 

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Ryosuke Niwa (rniwa)


Changes

This PR introduces the concept of a "trivial function" which applies to a 
function that only calls other trivial functions and contain literals and 
expressions that don't result in heap mutations (specifically it does not call 
deref). This is implemented using ConstStmtVisitor and checking each statement 
and expression's trivialness.

This PR also introduces the concept of a "ingleton function", which is a static 
member function or a free standing function which ends with the suffix 
"singleton". Such a function's return value is understood to be safe to call 
any function with.

---

Patch is 21.82 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/81808.diff


6 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp (+4) 
- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
(+246) 
- (modified) clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h (+23) 
- (modified) 
clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp (+7-1) 
- (modified) clang/test/Analysis/Checkers/WebKit/call-args.cpp (+17-16) 
- (modified) clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp (+231) 


``diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index b76c0551c77bb0..94eaa81af51772 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -66,9 +66,13 @@ tryToFindPtrOrigin(const Expr *E, bool 
StopAtFirstRefCountedObj) {
   E = call->getArg(0);
   continue;
 }
+
 if (isReturnValueRefCounted(callee))
   return {E, true};
 
+if (isSingleton(callee))
+  return {E, true};
+
 if (isPtrConversion(callee)) {
   E = call->getArg(0);
   continue;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 907244013d0871..b2169bf023c6e9 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include 
 
 using namespace clang;
@@ -222,4 +223,249 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos && index == Name.size() - 
SingletonStr.size();
+}
+
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ): Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) {
+return VisitChildren(DS);
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDoStmt(const DoStmt *DS) {
+return VisitChildren(DS);
+  }
+
+  bool VisitIfStmt(const IfStmt *IS) {
+return VisitChildren(IS);
+  }
+
+  bool VisitSwitchStmt(const SwitchStmt *SS) {
+return VisitChildren(SS);
+  }
+  
+  bool VisitCaseStmt(const CaseStmt* CS) {
+return VisitChildren(CS);
+  }
+
+  bool VisitDefaultStmt(const DefaultStmt* DS) {
+return VisitChildren(DS);
+  }
+
+  bool VisitUnaryOperator(const UnaryOperator *UO) {
+// Operator '*' and '!' are allowed as long as the operand is trivial.
+if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+  return Visit(UO->getSubExpr());
+
+// Other operators are non-trivial.
+return false;
+  }
+
+  bool VisitBinaryOperator(const BinaryOperator *BO) {
+// Binary operators are trivial if their operands are trivial.
+return 

[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)

2024-02-14 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa created https://github.com/llvm/llvm-project/pull/81808

This PR introduces the concept of a "trivial function" which applies to a 
function that only calls other trivial functions and contain literals and 
expressions that don't result in heap mutations (specifically it does not call 
deref). This is implemented using ConstStmtVisitor and checking each statement 
and expression's trivialness.

This PR also introduces the concept of a "ingleton function", which is a static 
member function or a free standing function which ends with the suffix 
"singleton". Such a function's return value is understood to be safe to call 
any function with.

>From 26f7904095ddd54ab54a94b3ae84db61d2135833 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Wed, 14 Feb 2024 16:21:33 -0800
Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore
 trivial function calls.

This PR introduces the concept of a "trivial function" which applies to a 
function
that only calls other trivial functions and contain literals and expressions 
that
don't result in heap mutations (specifically it does not call deref). This is
implemented using ConstStmtVisitor and checking each statement and expression's
trivialness.

This PR also introduces the concept of a "ingleton function", which is a static
member function or a free standing function which ends with the suffix 
"singleton".
Such a function's return value is understood to be safe to call any function 
with.
---
 .../Checkers/WebKit/ASTUtils.cpp  |   4 +
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 246 ++
 .../Checkers/WebKit/PtrTypesSemantics.h   |  23 ++
 .../WebKit/UncountedCallArgsChecker.cpp   |   8 +-
 .../Analysis/Checkers/WebKit/call-args.cpp|  33 +--
 .../Checkers/WebKit/uncounted-obj-arg.cpp | 231 
 6 files changed, 528 insertions(+), 17 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index b76c0551c77bb0..94eaa81af51772 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -66,9 +66,13 @@ tryToFindPtrOrigin(const Expr *E, bool 
StopAtFirstRefCountedObj) {
   E = call->getArg(0);
   continue;
 }
+
 if (isReturnValueRefCounted(callee))
   return {E, true};
 
+if (isSingleton(callee))
+  return {E, true};
+
 if (isPtrConversion(callee)) {
   E = call->getArg(0);
   continue;
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 907244013d0871..b2169bf023c6e9 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -12,6 +12,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
 #include 
 
 using namespace clang;
@@ -222,4 +223,249 @@ bool isPtrConversion(const FunctionDecl *F) {
   return false;
 }
 
+bool isSingleton(const FunctionDecl *F) {
+  assert(F);
+  // FIXME: check # of params == 1
+  if (auto *MethodDecl = dyn_cast(F)) {
+if (!MethodDecl->isStatic())
+  return false;
+  }
+  const auto  = safeGetName(F);
+  std::string SingletonStr = "singleton";
+  auto index = Name.find(SingletonStr);
+  return index != std::string::npos && index == Name.size() - 
SingletonStr.size();
+}
+
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+: public ConstStmtVisitor {
+
+  // Returns false if at least one child is non-trivial.
+  bool VisitChildren(const Stmt *S) {
+for (const Stmt *Child : S->children()) {
+  if (Child && !Visit(Child))
+return false;
+}
+
+return true;
+  }
+
+public:
+  using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+  TrivialFunctionAnalysisVisitor(CacheTy ): Cache(Cache) {}
+
+  bool VisitStmt(const Stmt *S) {
+// All statements are non-trivial unless overriden later.
+// Don't even recurse into children by default.
+return false;
+  }
+
+  bool VisitDeclStmt(const DeclStmt *DS) {
+return VisitChildren(DS);
+  }
+
+  bool VisitCompoundStmt(const CompoundStmt *CS) {
+// A compound statement is allowed as long each individual sub-statement
+// is trivial.
+return VisitChildren(CS);
+  }
+
+  bool VisitReturnStmt(const ReturnStmt *RS) {
+// A return statement is allowed as long as the return value is trivial.
+return Visit(RS->getRetValue());
+  }
+
+  bool VisitDoStmt(const DoStmt *DS) {
+return VisitChildren(DS);
+  }
+
+  bool VisitIfStmt(const IfStmt *IS) {
+return VisitChildren(IS);
+  }
+
+  bool VisitSwitchStmt(const SwitchStmt *SS) {
+return VisitChildren(SS);
+  }
+  
+  bool 

[clang] [clang][InstallAPI] Add input file support to library (PR #81701)

2024-02-14 Thread Cyndy Ishida via cfe-commits


@@ -0,0 +1,53 @@
+//===- InstallAPI/FileList.h *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// The JSON file list parser is used to communicate input to InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_FILELIST_H
+#define LLVM_CLANG_INSTALLAPI_FILELIST_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/InstallAPI/HeaderFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace clang {
+namespace installapi {
+
+/// JSON decoder for InstallAPI Inputs.
+class FileListReader {
+
+  class Implementation;
+  Implementation 
+
+  FileListReader(std::unique_ptr InputBuffer,
+ llvm::Error );
+
+public:
+  /// Decode JSON input and append header input into destination container.
+  /// Headers are loaded in the order they appear in the JSON input.
+  ///
+  /// \param InputBuffer JSON input data.
+  /// \param Destination Container to load headers into.
+  static llvm::Error
+  loadHeaders(std::unique_ptr InputBuffer,

cyndyishida wrote:

I want to keep the signature because the driver will accept multiple file lists 
but hold a single `HeaderSeq` and it's easier to handle continuous insertion.  

https://github.com/llvm/llvm-project/pull/81701
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [IRPGO][ValueProfile] Instrument virtual table address that could be used to do virtual table address comparision for indirect-call-promotion. (PR #66825)

2024-02-14 Thread Mingming Liu via cfe-commits

https://github.com/minglotus-6 edited 
https://github.com/llvm/llvm-project/pull/66825
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [compiler-rt] [llvm] [IRPGO][ValueProfile] Instrument virtual table address that could be used to do virtual table address comparision for indirect-call-promotion. (PR #66825)

2024-02-14 Thread Mingming Liu via cfe-commits

https://github.com/minglotus-6 edited 
https://github.com/llvm/llvm-project/pull/66825
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][InstallAPI] Add input file support to library (PR #81701)

2024-02-14 Thread Juergen Ributzka via cfe-commits


@@ -0,0 +1,53 @@
+//===- InstallAPI/FileList.h *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// The JSON file list parser is used to communicate input to InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_FILELIST_H
+#define LLVM_CLANG_INSTALLAPI_FILELIST_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/InstallAPI/HeaderFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace clang {
+namespace installapi {
+
+/// JSON decoder for InstallAPI Inputs.
+class FileListReader {
+
+  class Implementation;
+  Implementation 
+
+  FileListReader(std::unique_ptr InputBuffer,
+ llvm::Error );
+
+public:
+  /// Decode JSON input and append header input into destination container.
+  /// Headers are loaded in the order they appear in the JSON input.
+  ///
+  /// \param InputBuffer JSON input data.
+  /// \param Destination Container to load headers into.
+  static llvm::Error
+  loadHeaders(std::unique_ptr InputBuffer,

ributzka wrote:

This could be now changed to `Expected` and return the `HeaderSeq`.

https://github.com/llvm/llvm-project/pull/81701
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][InstallAPI] Add input file support to library (PR #81701)

2024-02-14 Thread Juergen Ributzka via cfe-commits


@@ -0,0 +1,53 @@
+//===- InstallAPI/FileList.h *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// The JSON file list parser is used to communicate input to InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_FILELIST_H
+#define LLVM_CLANG_INSTALLAPI_FILELIST_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/InstallAPI/HeaderFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace clang {
+namespace installapi {
+
+/// JSON decoder for InstallAPI Inputs.
+class FileListReader {
+
+  class Implementation;
+  Implementation 

ributzka wrote:

Since everything has now moved into the `loadHeaders` method, you can now even 
remove `Impl`.

https://github.com/llvm/llvm-project/pull/81701
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][InstallAPI] Add input file support to library (PR #81701)

2024-02-14 Thread Cyndy Ishida via cfe-commits

https://github.com/cyndyishida updated 
https://github.com/llvm/llvm-project/pull/81701

>From 9d0da0010f145b23ce2b7e5b6183558609600789 Mon Sep 17 00:00:00 2001
From: Cyndy Ishida 
Date: Tue, 13 Feb 2024 18:22:23 -0800
Subject: [PATCH 1/2] [clang][InstallAPI] Add input file support to library

This patch adds support for expected InstallAPI inputs.
InstallAPI  accepts a well defined filelist of headers and how those headers
represent a single library.

InstallAPI captures header files to determine linkable symbols
to then compare against what was compiled in a binary dylib and
generate TBD files.
---
 clang/include/clang/InstallAPI/FileList.h |  53 +
 clang/include/clang/InstallAPI/HeaderFile.h   |  72 +++
 clang/lib/ExtractAPI/CMakeLists.txt   |   1 +
 clang/lib/ExtractAPI/ExtractAPIConsumer.cpp   |   7 +-
 clang/lib/InstallAPI/CMakeLists.txt   |   2 +
 clang/lib/InstallAPI/FileList.cpp | 196 ++
 clang/lib/InstallAPI/HeaderFile.cpp   |  37 
 clang/unittests/CMakeLists.txt|   1 +
 clang/unittests/InstallAPI/CMakeLists.txt |   9 +
 clang/unittests/InstallAPI/FileListTest.cpp   | 140 +
 clang/unittests/InstallAPI/HeaderFileTest.cpp |  89 
 11 files changed, 603 insertions(+), 4 deletions(-)
 create mode 100644 clang/include/clang/InstallAPI/FileList.h
 create mode 100644 clang/include/clang/InstallAPI/HeaderFile.h
 create mode 100644 clang/lib/InstallAPI/FileList.cpp
 create mode 100644 clang/lib/InstallAPI/HeaderFile.cpp
 create mode 100644 clang/unittests/InstallAPI/CMakeLists.txt
 create mode 100644 clang/unittests/InstallAPI/FileListTest.cpp
 create mode 100644 clang/unittests/InstallAPI/HeaderFileTest.cpp

diff --git a/clang/include/clang/InstallAPI/FileList.h 
b/clang/include/clang/InstallAPI/FileList.h
new file mode 100644
index 00..01ec9b35e31490
--- /dev/null
+++ b/clang/include/clang/InstallAPI/FileList.h
@@ -0,0 +1,53 @@
+//===- InstallAPI/FileList.h *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// The JSON file list parser is used to communicate input to InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_FILELIST_H
+#define LLVM_CLANG_INSTALLAPI_FILELIST_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/InstallAPI/HeaderFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace clang {
+namespace installapi {
+
+/// JSON decoder for InstallAPI Inputs.
+class FileListReader {
+
+  class Implementation;
+  Implementation 
+
+  FileListReader(std::unique_ptr InputBuffer,
+ llvm::Error );
+
+public:
+  /// Decode JSON input and append header input into destination container.
+  /// Headers are loaded in the order they appear in the JSON input.
+  ///
+  /// \param InputBuffer JSON input data.
+  /// \param Destination Container to load headers into.
+  static llvm::Error
+  loadHeaders(std::unique_ptr InputBuffer,
+  HeaderSeq );
+
+  ~FileListReader();
+
+  FileListReader(const FileListReader &) = delete;
+  FileListReader =(const FileListReader &) = delete;
+};
+
+} // namespace installapi
+} // namespace clang
+
+#endif // LLVM_CLANG_INSTALLAPI_FILELIST_H
diff --git a/clang/include/clang/InstallAPI/HeaderFile.h 
b/clang/include/clang/InstallAPI/HeaderFile.h
new file mode 100644
index 00..6ccd944f8b01be
--- /dev/null
+++ b/clang/include/clang/InstallAPI/HeaderFile.h
@@ -0,0 +1,72 @@
+//===- InstallAPI/HeaderFile.h --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// Representations of a library's headers for InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_HEADERFILE_H
+#define LLVM_CLANG_INSTALLAPI_HEADERFILE_H
+
+#include "clang/Basic/LangStandard.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Regex.h"
+#include 
+#include 
+
+namespace clang::installapi {
+enum class HeaderType {
+  /// Represents declarations accessible to all clients.
+  Public,
+  /// Represents declarations accessible to a disclosed set of clients.
+  Private,
+  /// Represents declarations only accessible as implementation details to the
+  /// input library.
+  Project,
+};
+
+class HeaderFile {
+  /// Full 

[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread via cfe-commits


@@ -406,6 +406,31 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) 
{
   }
   return false;
 }
+
+AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
+  const DeclRefExpr * BaseDRE = 
dyn_cast_or_null(Node.getBase()->IgnoreParenImpCasts());
+  if (!BaseDRE)
+return false;
+  if (!BaseDRE->getDecl())
+return false;
+  auto BaseVarDeclTy = BaseDRE->getDecl()->getType();
+  if (!BaseVarDeclTy->isConstantArrayType())
+return false;
+  const auto * CATy = dyn_cast_or_null(BaseVarDeclTy);

jkorous-apple wrote:

Use `getAsArrayType` instead of `dyn_cast`.

https://github.com/llvm/llvm-project/pull/80504
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread via cfe-commits


@@ -406,6 +406,31 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) 
{
   }
   return false;
 }
+
+AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
+  const DeclRefExpr * BaseDRE = 
dyn_cast_or_null(Node.getBase()->IgnoreParenImpCasts());
+  if (!BaseDRE)
+return false;
+  if (!BaseDRE->getDecl())
+return false;
+  auto BaseVarDeclTy = BaseDRE->getDecl()->getType();
+  if (!BaseVarDeclTy->isConstantArrayType())
+return false;
+  const auto * CATy = dyn_cast_or_null(BaseVarDeclTy);

jkorous-apple wrote:

Take a look getAsConstantArrayType().

https://github.com/llvm/llvm-project/pull/80504
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [-Wunsafe-buffer-usage] Ignore constant safe indices in array subscripts (PR #80504)

2024-02-14 Thread via cfe-commits


@@ -598,16 +623,16 @@ class ArraySubscriptGadget : public WarningGadget {
   }
 
   static Matcher matcher() {
-// FIXME: What if the index is integer literal 0? Should this be
-// a safe gadget in this case?
-  // clang-format off
+// clang-format off
   return stmt(arraySubscriptExpr(
 hasBase(ignoringParenImpCasts(
   anyOf(hasPointerType(), hasArrayType(,
-unless(hasIndex(
-anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())
- )))
-.bind(ArraySubscrTag));
+unless(anyOf(
+  isSafeArraySubscript(),
+  hasIndex(
+  anyOf(integerLiteral(equals(0)), arrayInitIndexExpr())

jkorous-apple wrote:

This is unnecessary now.

https://github.com/llvm/llvm-project/pull/80504
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][InstallAPI] Add input file support to library (PR #81701)

2024-02-14 Thread Cyndy Ishida via cfe-commits

https://github.com/cyndyishida updated 
https://github.com/llvm/llvm-project/pull/81701

>From 9d0da0010f145b23ce2b7e5b6183558609600789 Mon Sep 17 00:00:00 2001
From: Cyndy Ishida 
Date: Tue, 13 Feb 2024 18:22:23 -0800
Subject: [PATCH] [clang][InstallAPI] Add input file support to library

This patch adds support for expected InstallAPI inputs.
InstallAPI  accepts a well defined filelist of headers and how those headers
represent a single library.

InstallAPI captures header files to determine linkable symbols
to then compare against what was compiled in a binary dylib and
generate TBD files.
---
 clang/include/clang/InstallAPI/FileList.h |  53 +
 clang/include/clang/InstallAPI/HeaderFile.h   |  72 +++
 clang/lib/ExtractAPI/CMakeLists.txt   |   1 +
 clang/lib/ExtractAPI/ExtractAPIConsumer.cpp   |   7 +-
 clang/lib/InstallAPI/CMakeLists.txt   |   2 +
 clang/lib/InstallAPI/FileList.cpp | 196 ++
 clang/lib/InstallAPI/HeaderFile.cpp   |  37 
 clang/unittests/CMakeLists.txt|   1 +
 clang/unittests/InstallAPI/CMakeLists.txt |   9 +
 clang/unittests/InstallAPI/FileListTest.cpp   | 140 +
 clang/unittests/InstallAPI/HeaderFileTest.cpp |  89 
 11 files changed, 603 insertions(+), 4 deletions(-)
 create mode 100644 clang/include/clang/InstallAPI/FileList.h
 create mode 100644 clang/include/clang/InstallAPI/HeaderFile.h
 create mode 100644 clang/lib/InstallAPI/FileList.cpp
 create mode 100644 clang/lib/InstallAPI/HeaderFile.cpp
 create mode 100644 clang/unittests/InstallAPI/CMakeLists.txt
 create mode 100644 clang/unittests/InstallAPI/FileListTest.cpp
 create mode 100644 clang/unittests/InstallAPI/HeaderFileTest.cpp

diff --git a/clang/include/clang/InstallAPI/FileList.h 
b/clang/include/clang/InstallAPI/FileList.h
new file mode 100644
index 00..01ec9b35e31490
--- /dev/null
+++ b/clang/include/clang/InstallAPI/FileList.h
@@ -0,0 +1,53 @@
+//===- InstallAPI/FileList.h *- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// The JSON file list parser is used to communicate input to InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_FILELIST_H
+#define LLVM_CLANG_INSTALLAPI_FILELIST_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/InstallAPI/HeaderFile.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace clang {
+namespace installapi {
+
+/// JSON decoder for InstallAPI Inputs.
+class FileListReader {
+
+  class Implementation;
+  Implementation 
+
+  FileListReader(std::unique_ptr InputBuffer,
+ llvm::Error );
+
+public:
+  /// Decode JSON input and append header input into destination container.
+  /// Headers are loaded in the order they appear in the JSON input.
+  ///
+  /// \param InputBuffer JSON input data.
+  /// \param Destination Container to load headers into.
+  static llvm::Error
+  loadHeaders(std::unique_ptr InputBuffer,
+  HeaderSeq );
+
+  ~FileListReader();
+
+  FileListReader(const FileListReader &) = delete;
+  FileListReader =(const FileListReader &) = delete;
+};
+
+} // namespace installapi
+} // namespace clang
+
+#endif // LLVM_CLANG_INSTALLAPI_FILELIST_H
diff --git a/clang/include/clang/InstallAPI/HeaderFile.h 
b/clang/include/clang/InstallAPI/HeaderFile.h
new file mode 100644
index 00..6ccd944f8b01be
--- /dev/null
+++ b/clang/include/clang/InstallAPI/HeaderFile.h
@@ -0,0 +1,72 @@
+//===- InstallAPI/HeaderFile.h --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+///
+/// Representations of a library's headers for InstallAPI.
+///
+//===--===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_HEADERFILE_H
+#define LLVM_CLANG_INSTALLAPI_HEADERFILE_H
+
+#include "clang/Basic/LangStandard.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Regex.h"
+#include 
+#include 
+
+namespace clang::installapi {
+enum class HeaderType {
+  /// Represents declarations accessible to all clients.
+  Public,
+  /// Represents declarations accessible to a disclosed set of clients.
+  Private,
+  /// Represents declarations only accessible as implementation details to the
+  /// input library.
+  Project,
+};
+
+class HeaderFile {
+  /// Full input 

  1   2   3   4   >