[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-06-27 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 58df542edf7d1a9f65fc804f23a2b209a49f5c5f Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   | 10 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/AST/Type.h|  2 +
 clang/include/clang/Basic/Attr.td |  7 ++
 clang/include/clang/Basic/AttrDocs.td | 68 +++
 clang/include/clang/Basic/DiagnosticGroups.td |  6 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 ++
 clang/lib/AST/Expr.cpp|  9 +++
 clang/lib/AST/ExprConstant.cpp|  4 +-
 clang/lib/AST/Type.cpp|  4 ++
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 47 +
 clang/lib/Sema/Sema.cpp   |  3 +
 clang/lib/Sema/SemaChecking.cpp   | 33 -
 clang/lib/Sema/SemaDeclAttr.cpp   |  8 ++-
 clang/lib/Sema/SemaType.cpp   | 15 
 clang/test/CodeGen/integer-overflow.c | 66 ++
 clang/test/CodeGen/unsigned-overflow.c| 63 ++---
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/attr-wraps.c  | 43 
 20 files changed, 376 insertions(+), 26 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7ebfc87144269..404f80405639a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -526,6 +526,16 @@ Attribute Changes in Clang
   The attributes declare constraints about a function's behavior pertaining to 
blocking and
   heap memory allocation.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is only valid for C, as there are built-in language
+  alternatives for other languages.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 59e174954fdbf..7318f08eb7af7 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4066,6 +4066,9 @@ class BinaryOperator : public Expr {
 return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
   }
 
+  /// Does one of the subexpressions have the wraps attribute?
+  bool hasWrappingOperand(const ASTContext ) const;
+
 protected:
   BinaryOperator(const ASTContext , Expr *lhs, Expr *rhs, Opcode opc,
  QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index a98899f7f4222..a0e308daa1053 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1454,6 +1454,8 @@ class QualType {
 return getQualifiers().hasStrongOrWeakObjCLifetime();
   }
 
+  bool hasWrapsAttr() const;
+
   // true when Type is objc's weak and weak is enabled but ARC isn't.
   bool isNonWeakInMRRWithObjCWeak(const ASTContext ) const;
 
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 452cd1810f653..129422fe157eb 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4659,3 +4659,10 @@ def ClspvLibclcBuiltin: InheritableAttr {
   let Documentation = [ClspvLibclcBuiltinDoc];
   let SimpleHandler = 1;
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+  let LangOpts = [COnly];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index ab4bd003541fa..dee73d12e6499 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8173,3 +8173,71 @@ of ``nonallocating`` by the compiler.
   }];
 }
 
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-06-27 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From af16c497b1323983d55f92d6cfb9ab2c99a21639 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   | 10 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/AST/Type.h|  2 +
 clang/include/clang/Basic/Attr.td |  7 ++
 clang/include/clang/Basic/AttrDocs.td | 68 +++
 clang/include/clang/Basic/DiagnosticGroups.td |  6 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 ++
 clang/lib/AST/Expr.cpp|  9 +++
 clang/lib/AST/ExprConstant.cpp|  4 +-
 clang/lib/AST/Type.cpp|  4 ++
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 47 +
 clang/lib/Sema/Sema.cpp   |  3 +
 clang/lib/Sema/SemaChecking.cpp   | 33 -
 clang/lib/Sema/SemaDeclAttr.cpp   |  8 ++-
 clang/lib/Sema/SemaType.cpp   | 15 
 clang/test/CodeGen/integer-overflow.c | 66 ++
 clang/test/CodeGen/unsigned-overflow.c| 63 ++---
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/attr-wraps.c  | 43 
 20 files changed, 376 insertions(+), 26 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index df579ae398c5e..1c8abb79a8a9a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -525,6 +525,16 @@ Attribute Changes in Clang
   The attributes declare constraints about a function's behavior pertaining to 
blocking and
   heap memory allocation.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is only valid for C, as there are built-in language
+  alternatives for other languages.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 3bc8cae4d8c86..acd2645720217 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4061,6 +4061,9 @@ class BinaryOperator : public Expr {
 return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
   }
 
+  /// Does one of the subexpressions have the wraps attribute?
+  bool hasWrappingOperand(const ASTContext ) const;
+
 protected:
   BinaryOperator(const ASTContext , Expr *lhs, Expr *rhs, Opcode opc,
  QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 62836ec5c6312..9de19094298da 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1457,6 +1457,8 @@ class QualType {
 return getQualifiers().hasStrongOrWeakObjCLifetime();
   }
 
+  bool hasWrapsAttr() const;
+
   // true when Type is objc's weak and weak is enabled but ARC isn't.
   bool isNonWeakInMRRWithObjCWeak(const ASTContext ) const;
 
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 0c469e389eff0..81e48a7638ea6 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4630,3 +4630,10 @@ def ClspvLibclcBuiltin: InheritableAttr {
   let Documentation = [ClspvLibclcBuiltinDoc];
   let SimpleHandler = 1;
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+  let LangOpts = [COnly];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 8d8f058281684..cf34bba7dea7f 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8176,3 +8176,71 @@ of ``nonallocating`` by the compiler.
   }];
 }
 
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-06-13 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 6152bd26438a32711589424f705281291475d548 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   | 10 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/AST/Type.h|  2 +
 clang/include/clang/Basic/Attr.td |  7 ++
 clang/include/clang/Basic/AttrDocs.td | 69 +++
 clang/include/clang/Basic/DiagnosticGroups.td |  6 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 ++
 clang/lib/AST/Expr.cpp|  9 +++
 clang/lib/AST/ExprConstant.cpp|  4 +-
 clang/lib/AST/Type.cpp|  4 ++
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 47 +
 clang/lib/Sema/Sema.cpp   |  3 +
 clang/lib/Sema/SemaChecking.cpp   | 33 -
 clang/lib/Sema/SemaDeclAttr.cpp   |  8 ++-
 clang/lib/Sema/SemaType.cpp   | 15 
 clang/test/CodeGen/integer-overflow.c | 66 ++
 clang/test/CodeGen/unsigned-overflow.c| 63 ++---
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/attr-wraps.c  | 43 
 20 files changed, 377 insertions(+), 26 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8c2f737836a9d..675d33d67cb97 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -472,6 +472,16 @@ Attribute Changes in Clang
  };
 
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is only valid for C, as there are built-in language
+  alternatives for other languages.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index f2bf667636dc9..48968cbbbaf7e 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4061,6 +4061,9 @@ class BinaryOperator : public Expr {
 return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
   }
 
+  /// Does one of the subexpressions have the wraps attribute?
+  bool hasWrappingOperand(const ASTContext ) const;
+
 protected:
   BinaryOperator(const ASTContext , Expr *lhs, Expr *rhs, Opcode opc,
  QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index fab233b62d8d1..9bb468ee96646 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1455,6 +1455,8 @@ class QualType {
 return getQualifiers().hasStrongOrWeakObjCLifetime();
   }
 
+  bool hasWrapsAttr() const;
+
   // true when Type is objc's weak and weak is enabled but ARC isn't.
   bool isNonWeakInMRRWithObjCWeak(const ASTContext ) const;
 
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index b70b0c8b836a5..8d3bd6f5e9949 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4606,3 +4606,10 @@ def ClspvLibclcBuiltin: InheritableAttr {
   let Documentation = [ClspvLibclcBuiltinDoc];
   let SimpleHandler = 1;
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+  let LangOpts = [COnly];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 70d5dfa8aaf86..87f8ca855d2af 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8106,3 +8106,72 @@ Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V 
compiler) to identify func
 .. _`libclc`: https://libclc.llvm.org
 }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-05-29 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

Hi, gentle ping. 

@efriedma-quic, do you still have concerns with the current implementation (as 
an attribute attached to typedefs)? After limiting `wraps` to C and adding 
warnings to let users know when the attribute may be stripped, I think it's in 
a good spot.

```c
typedef int __attribute__((wraps)) wrap_int;

extern void foo(int b);

int main(void) {
  wrap_int a;
  foo(a); // wraps.c:12:7: warning: 'wraps' attribute may be implicitly 
discarded \
  // when converted to 'int' [-Wimplicitly-discarded-wraps-attribute]

}
```

This feature is obviously niche and requires opting in with actual source 
modifications, this is not something people will use accidentally. However, 
Eli, I hear your concerns about some of the non-obvious ways attributes can get 
lost. I've tried to remedy this with some warnings (as seen above) but, of 
course, the semantics of attribute persistence are what they are. Eli, if you 
think this is not good enough then I will try and redesign the feature as an 
extended type. Although, I reckon the C type system has just as many quirks and 
foot-guns as the Clang attribute system.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-05-24 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 1df2f520f6a8ab0e45b80f7a1d680d34f8ab37c9 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   | 10 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/AST/Type.h|  2 +
 clang/include/clang/Basic/Attr.td |  7 ++
 clang/include/clang/Basic/AttrDocs.td | 69 +++
 clang/include/clang/Basic/DiagnosticGroups.td |  6 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 ++
 clang/lib/AST/Expr.cpp|  9 +++
 clang/lib/AST/ExprConstant.cpp|  4 +-
 clang/lib/AST/Type.cpp|  4 ++
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 47 +
 clang/lib/Sema/Sema.cpp   |  3 +
 clang/lib/Sema/SemaChecking.cpp   | 33 -
 clang/lib/Sema/SemaDeclAttr.cpp   |  8 ++-
 clang/lib/Sema/SemaType.cpp   | 15 
 clang/test/CodeGen/integer-overflow.c | 66 ++
 clang/test/CodeGen/unsigned-overflow.c| 63 ++---
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/attr-wraps.c  | 43 
 20 files changed, 377 insertions(+), 26 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ba4637d98197f..a1fc18523936f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -407,6 +407,16 @@ Attribute Changes in Clang
   (`OpenCL-C to Vulkan SPIR-V compiler `_) to 
identify functions coming from libclc
   (`OpenCL-C builtin library `_).
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is only valid for C, as there are built-in language
+  alternatives for other languages.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index f2bf667636dc9..48968cbbbaf7e 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4061,6 +4061,9 @@ class BinaryOperator : public Expr {
 return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
   }
 
+  /// Does one of the subexpressions have the wraps attribute?
+  bool hasWrappingOperand(const ASTContext ) const;
+
 protected:
   BinaryOperator(const ASTContext , Expr *lhs, Expr *rhs, Opcode opc,
  QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index da3834f19ca04..641f943205891 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1441,6 +1441,8 @@ class QualType {
 return getQualifiers().hasStrongOrWeakObjCLifetime();
   }
 
+  bool hasWrapsAttr() const;
+
   // true when Type is objc's weak and weak is enabled but ARC isn't.
   bool isNonWeakInMRRWithObjCWeak(const ASTContext ) const;
 
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 7008bea483c87..922dcba29a8de 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4595,3 +4595,10 @@ def ClspvLibclcBuiltin: InheritableAttr {
   let Documentation = [ClspvLibclcBuiltinDoc];
   let SimpleHandler = 1;
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+  let LangOpts = [COnly];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 54197d588eb45..dc050e616d63a 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8106,3 +8106,72 @@ Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V 
compiler) to identify func
 .. _`libclc`: https://libclc.llvm.org
 }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-05-20 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

FYI: I've rebased and handled merge conflicts (mainly in ReleaseNotes.rst). 
This, of course, required a force push.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-05-20 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 1df2f520f6a8ab0e45b80f7a1d680d34f8ab37c9 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   | 10 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/AST/Type.h|  2 +
 clang/include/clang/Basic/Attr.td |  7 ++
 clang/include/clang/Basic/AttrDocs.td | 69 +++
 clang/include/clang/Basic/DiagnosticGroups.td |  6 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 ++
 clang/lib/AST/Expr.cpp|  9 +++
 clang/lib/AST/ExprConstant.cpp|  4 +-
 clang/lib/AST/Type.cpp|  4 ++
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 47 +
 clang/lib/Sema/Sema.cpp   |  3 +
 clang/lib/Sema/SemaChecking.cpp   | 33 -
 clang/lib/Sema/SemaDeclAttr.cpp   |  8 ++-
 clang/lib/Sema/SemaType.cpp   | 15 
 clang/test/CodeGen/integer-overflow.c | 66 ++
 clang/test/CodeGen/unsigned-overflow.c| 63 ++---
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/attr-wraps.c  | 43 
 20 files changed, 377 insertions(+), 26 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ba4637d98197f..a1fc18523936f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -407,6 +407,16 @@ Attribute Changes in Clang
   (`OpenCL-C to Vulkan SPIR-V compiler `_) to 
identify functions coming from libclc
   (`OpenCL-C builtin library `_).
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is only valid for C, as there are built-in language
+  alternatives for other languages.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index f2bf667636dc9..48968cbbbaf7e 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4061,6 +4061,9 @@ class BinaryOperator : public Expr {
 return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
   }
 
+  /// Does one of the subexpressions have the wraps attribute?
+  bool hasWrappingOperand(const ASTContext ) const;
+
 protected:
   BinaryOperator(const ASTContext , Expr *lhs, Expr *rhs, Opcode opc,
  QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index da3834f19ca04..641f943205891 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1441,6 +1441,8 @@ class QualType {
 return getQualifiers().hasStrongOrWeakObjCLifetime();
   }
 
+  bool hasWrapsAttr() const;
+
   // true when Type is objc's weak and weak is enabled but ARC isn't.
   bool isNonWeakInMRRWithObjCWeak(const ASTContext ) const;
 
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 7008bea483c87..922dcba29a8de 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4595,3 +4595,10 @@ def ClspvLibclcBuiltin: InheritableAttr {
   let Documentation = [ClspvLibclcBuiltinDoc];
   let SimpleHandler = 1;
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+  let LangOpts = [COnly];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 54197d588eb45..dc050e616d63a 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8106,3 +8106,72 @@ Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V 
compiler) to identify func
 .. _`libclc`: https://libclc.llvm.org
 }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-05-17 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 238e3242d12473a072d0d2adc51f18fbeaa927a8 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/AST/Type.h|  2 +
 clang/include/clang/Basic/Attr.td |  7 ++
 clang/include/clang/Basic/AttrDocs.td | 69 +++
 clang/include/clang/Basic/DiagnosticGroups.td |  6 ++
 .../clang/Basic/DiagnosticSemaKinds.td|  7 ++
 clang/lib/AST/Expr.cpp|  9 +++
 clang/lib/AST/ExprConstant.cpp|  4 +-
 clang/lib/AST/Type.cpp|  4 ++
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 47 +
 clang/lib/Sema/Sema.cpp   |  3 +
 clang/lib/Sema/SemaChecking.cpp   | 33 -
 clang/lib/Sema/SemaDeclAttr.cpp   |  8 ++-
 clang/lib/Sema/SemaType.cpp   | 15 
 clang/test/CodeGen/integer-overflow.c | 66 ++
 clang/test/CodeGen/unsigned-overflow.c| 63 ++---
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/Sema/attr-wraps.c  | 43 
 20 files changed, 376 insertions(+), 26 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2f83f5c6d54e9..6cf358477b4db 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -425,6 +425,15 @@ Attribute Changes in Clang
size_t count;
  };
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is only valid for C, as there are built-in language
+  alternatives for other languages.
 
 Improvements to Clang's diagnostics
 ---
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index f2bf667636dc9..48968cbbbaf7e 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4061,6 +4061,9 @@ class BinaryOperator : public Expr {
 return getFPFeaturesInEffect(LO).getAllowFEnvAccess();
   }
 
+  /// Does one of the subexpressions have the wraps attribute?
+  bool hasWrappingOperand(const ASTContext ) const;
+
 protected:
   BinaryOperator(const ASTContext , Expr *lhs, Expr *rhs, Opcode opc,
  QualType ResTy, ExprValueKind VK, ExprObjectKind OK,
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index c7a8e785913b3..d85cbfef02145 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1441,6 +1441,8 @@ class QualType {
 return getQualifiers().hasStrongOrWeakObjCLifetime();
   }
 
+  bool hasWrapsAttr() const;
+
   // true when Type is objc's weak and weak is enabled but ARC isn't.
   bool isNonWeakInMRRWithObjCWeak(const ASTContext ) const;
 
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 7a7721239a28f..52572ec96b203 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4569,3 +4569,10 @@ def ClspvLibclcBuiltin: InheritableAttr {
   let Documentation = [ClspvLibclcBuiltinDoc];
   let SimpleHandler = 1;
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+  let LangOpts = [COnly];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index b48aaf65558ac..6340703354a45 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8101,3 +8101,72 @@ Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V 
compiler) to identify func
 .. _`libclc`: https://libclc.llvm.org
 }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-05-02 Thread Bill Wendling via cfe-commits

bwendling wrote:

The code looks fine to me. But you should wait for @efriedma-quic to chime in 
as he had concerns over the feature.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

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

JustinStitt wrote:

Ping!

Any chance we could land this soon?

I know @efriedma-quic has some different ideas for the implementation of this 
feature. However, adding a new type is most likely overkill for what is needed 
out of `wraps`. I think the implementation/documentation and testing has landed 
in a pretty nice spot but am eager to hear what others have to think as well.

@bwendling as you recently implemented `__counted_by` is there anything you see 
missing with `wraps` (considering there's some overlap between the feature 
sets)?

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-29 Thread Kees Cook via cfe-commits

kees wrote:

My thinking about this attribute tends to follow from my desire not to change 
the C type system, but rather to adjust the behavior of the sanitizers. This 
means that it is possible to still build the Linux kernel without the 
sanitizers (the build just ignores the attribute), or with (where the attribute 
now has meaning). I feel like adding new types is a much larger/different 
thing, as it ends up requiring that the core language has to do something 
specific about overflow, etc. Under the sanitizers, there is a well-defined 
behavioral modification for overflow. Having the attribute augment the 
sanitizer means the semantics of regular C remain unchanged. We could even go 
so far as making it an error to encounter the attribute when the sanitizers 
aren't enabled.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-26 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 50e7b1039e514dacc05bb8cd9ff9a3e3df9ed24d Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 01/18] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2b3bafa1c30548..fa7acb894cd76f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,15 @@ Attribute Changes in Clang
 - Clang now warns that the ``exclude_from_explicit_instantiation`` attribute
   is ignored when applied to a local class or a member thereof.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index a0bbe5861c5722..5f6e5a8de79954 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8057,3 +8057,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-26 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 50e7b1039e514dacc05bb8cd9ff9a3e3df9ed24d Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 01/17] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2b3bafa1c30548..fa7acb894cd76f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,15 @@ Attribute Changes in Clang
 - Clang now warns that the ``exclude_from_explicit_instantiation`` attribute
   is ignored when applied to a local class or a member thereof.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index a0bbe5861c5722..5f6e5a8de79954 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8057,3 +8057,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-26 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

In an effort to appease the build bot, I am adding a `-W` flag to turn of 
`warn_wraps_attr_var_decl_type_not_integer` which yells at users for trying to 
add `__attribute__((wraps))` to things that don't really wrap in the 
traditional sense.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-26 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 50e7b1039e514dacc05bb8cd9ff9a3e3df9ed24d Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 01/16] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2b3bafa1c30548..fa7acb894cd76f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,15 @@ Attribute Changes in Clang
 - Clang now warns that the ``exclude_from_explicit_instantiation`` attribute
   is ignored when applied to a local class or a member thereof.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index a0bbe5861c5722..5f6e5a8de79954 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8057,3 +8057,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-25 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

@efriedma-quic:
> Attributes mostly do modify the type. The few that don't, like "aligned" and 
> "may_alias", are a constant source of problems because they get accidentally 
> stripped off. (I don't have any personal experience with "noderef".)

So do you believe the current approach is a no-go? I am happy to do whatever it 
takes to get this feature over the line but hear me out:

Any way of implementing this feature is subject to corner cases and can be 
broken -- like a lot of stuff in C. For its specific use case, this attribute 
provides immense power and clarity to existing code bases; the Linux Kernel 
would benefit massively as we could then enable multiple arithmetic sanitizers. 
With my custom wraps-enabled compiler and a syzkaller instance I've already 
located [dozens of potential 
bugs](https://gist.github.com/JustinStitt/51f988421522d9ab7d5dbf1c2025e7a0) 
that could be fixed with this attribute! (and ~hundreds of others with the 
`unsigned-integer-overflow` and `implicit-integer-truncation` sanitizers -- 
which I have yet to fuzz with).

The tests made by @kees (mostly kernel-tailored) and the tests I've checked in 
with this PR all pass without regression to existing integer sanitizer uses.

I'd love to hear more folk's opinions, too. With more feedback, we can make 
this feature and its documentation/testing as solid as possible.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-25 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 50e7b1039e514dacc05bb8cd9ff9a3e3df9ed24d Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 01/15] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2b3bafa1c30548..fa7acb894cd76f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,15 @@ Attribute Changes in Clang
 - Clang now warns that the ``exclude_from_explicit_instantiation`` attribute
   is ignored when applied to a local class or a member thereof.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index a0bbe5861c5722..5f6e5a8de79954 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8057,3 +8057,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-25 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

Attributes mostly do modify the type.  The few that don't, like "aligned" and 
"may_alias", are a constant source of problems because they get accidentally 
stripped off.  (I don't have any personal experience with "noderef".)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-25 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

@efriedma-quic:
> This is declaring, then defining, a global variable; sorry if that wasn't 
> clear.

Gotcha. 

> Probably should be an error? It'll be confusing no matter what we do.

I think it's OK for a global variable to be declared then later defined with 
additional attributes on it. There is some precedence with this (with deref and 
other type attributes):

```c
extern int* a;
int __attribute__((noderef)) *a = 0x0;
// no warnings/errors
```

This is really just letting the developer and compiler know that we shouldn't 
dereference `a` in this module. (same concept with `wraps`).
 
> I assume for your usage, you want the result of the arithmetic to be the same 
> whether or not the compiler supports the "wraps" attribute, which constrains 
> your choices.

Right, I'll make the necessary changes to allow for the attribute to persist 
through implicit integer promotions without changing arithmetic results.

> If you had a distinct canonical type, you would have had to make explicit 
> decisions about a bunch of these things... and the rest would be stable 
> independent of details of non-canonical type propagation.

Couldn't we say this about all the existing [Type 
Attributes](https://clang.llvm.org/docs/AttributeReference.html#type-attributes)?
 Should `noderef` have it's own type in clang? I think this would be a bit 
overkill. These attributes (and the proposed `wraps`) are just meant to give 
hints to developers and compilers. Specifically for wraps, the goal is to hint 
to readers of code that some arithmetic containing certain types or variables 
may wrap (and won't warn when doing so, so we can safely enable sanitizers).

I really don't see new types in the type system as being the most developer 
friendly option.



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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-25 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

> No. But I am confused, isn't this just shadowing a global variable with a 
> lesser-scoped one. Are they the same? What behavior do we want here?

This is declaring, then defining, a global variable; sorry if that wasn't clear.

Probably should be an error?  It'll be confusing no matter what we do.

> However, after making the patch and testing it I am not sure what we want. Do 
> we want to cancel implicit promotions for less-than-ints that possess the 
> wraps attribute (doesn't sound spec compliant)? Or, should wrapping things 
> still undergo promotion but now wrap at different bounds than what their 
> original type specified?

I assume for your usage, you want the result of the arithmetic to be the same 
whether or not the compiler supports the "wraps" attribute, which constrains 
your choices.

> More on this, I don't see how changing implementation from attribute-based to 
> type-based resolves any of these design decisions. Neither approach is 
> necessarily easier to implement or to understand for developers, if the right 
> decisions are made in terms of behavior then the attribute approach can be 
> just as useful and predictable.

If you had a distinct canonical type, you would have had to make explicit 
decisions about a bunch of these things... and the rest would be stable 
independent of details of non-canonical type propagation.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-24 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> > > If you declare a variable as both wrapping and non-wrapping, is it 
> > > wrapping?
> > 
> > 
> > I am not sure how to do this. I am sure that with the magic of C anything 
> > is possible but I can't conceive a way to have a variable both have the 
> > attribute and not have the attribute (to be clear, there doesn't exist a 
> > `__attribute__((no-wraps))` currently)
> 
> Say you declare a global variable like the following:
> 
> ```
> typedef int wrapint __attribute((wraps));
> extern wrapint x;
> int x = 0;
> ```
> 
> Is "x" wrapping?

No. But I am confused, isn't this just shadowing a global variable with a 
lesser-scoped one. Are they the same? What behavior do we want here?

> 
> > > If you mark a `short` wrapping, is the type after promotion wrapping?
> > 
> > 
> > This concerns the `-fsanitize=implicit-signed-integer-truncation` sanitizer 
> > which the wraps attribute disables. So the type boundaries pre- and 
> > post-promotion are not enforced by this sanitizer for wrapping types.
> 
> There are cases that don't involve truncation:
> 
> ```
> typedef short wrapshort __attribute((wraps));
> wrapshort x = 0x7FFF;
> int y = x*x*x*x;
> ```

Arithmetic cannot be performed on less-than-ints so the implicit promotions are 
put in place which lose the attribute. I just worked on an update to carry the 
wraps attribute through implicit integer promotion. 

However, after making the patch and testing it I am not sure what we want. Do 
we want to cancel implicit promotions for less-than-ints that possess the wraps 
attribute (doesn't sound spec compliant)? Or, should wrapping things still 
undergo promotion but now wrap at different bounds than what their original 
type specified?

If I make a wrapping char [-128, 127] and do some arithmetic on it it will be 
promoted to int (and still have the wraps attribute, with my patch) then 
proceed.

In the example below, `x*x*x*x*x` is `33,038,369,407` which is greater than 
INT_MAX `2,147,483,647` and will thus overflow (a few times). However, this 
overflow is happening at the integer boundaries not at the char boundaries.

```c
wrapchar x = 127;
int y = x*x*x*x*x; // result: -1321368961
```

The options are:
1) don't carry the wraps attribute through implicit promotions
2) carry the wraps attribute but use promoted-to-type's boundaries for wrapping
3) carry attribute and use the pre-promotion type's boundaries

More on this, I don't see how changing implementation from attribute-based to 
type-based resolves any of these design decisions. Neither approach is 
necessarily easier to implement or to understand for developers, if the right 
decisions are made in terms of behavior then the attribute approach can be just 
as useful and predictable.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-24 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

> > If you declare a variable as both wrapping and non-wrapping, is it wrapping?
> 
> I am not sure how to do this. I am sure that with the magic of C anything is 
> possible but I can't conceive a way to have a variable both have the 
> attribute and not have the attribute (to be clear, there doesn't exist a 
> `__attribute__((no-wraps))` currently)

Say you declare a global variable like the following:

```
typedef int wrapint __attribute((wraps));
extern wrapint x;
int x = 0;
```

Is "x" wrapping?

> > If you mark a `short` wrapping, is the type after promotion wrapping?
> 
> This concerns the `-fsanitize=implicit-signed-integer-truncation` sanitizer 
> which the wraps attribute disables. So the type boundaries pre- and 
> post-promotion are not enforced by this sanitizer for wrapping types.

There are cases that don't involve truncation:

```
typedef short wrapshort __attribute((wraps));
short x = 0x7FFF;
int y = x*x*x*x;
```

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-24 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

Hi @efriedma-quic, thanks for dumping all these cases! I will respond to each 
one individually.

I understand you think adding a type would be better so I am exploring that 
option (I am thinking something similar to [extended 
vectors](https://clang.llvm.org/docs/LanguageExtensions.html#vectors-and-extended-vectors)).
 But for now, I am trying to make this attribute as useful and compatible as 
possible.

> If you have a select with both wrapping and non-wrapping operands, is the 
> result wrapping? 

I assume you're referring to a ternary statement? Currently, no. Although, I 
should add support for this similar to how BinaryOperators are considered 
wrapping if any of their operands are.
```
`-ConditionalOperator 0x559ddad37998  'int'
  |-ImplicitCastExpr 0x559ddad37950  'int' 
  | `-ImplicitCastExpr 0x559ddad37938  '_Bool' 
  |   `-DeclRefExpr 0x559ddad378d8  'volatile _Bool' lvalue Var 
0x559ddad7a350 'cond' 'volatile _Bool'
  |-ImplicitCastExpr 0x559ddad37968  'wrap_int':'int' 
  | `-DeclRefExpr 0x559ddad378f8  'const wrap_int':'const int' lvalue 
Var 0x559ddad37780 'a' 'const wrap_int':'const int'
  `-ImplicitCastExpr 0x559ddad37980  'int' 
`-DeclRefExpr 0x559ddad37918  'const int' lvalue Var 0x559ddad37838 
'b' 'const int'
```
---

> If you declare a variable as both wrapping and non-wrapping, is it wrapping? 

I am not sure how to do this. I am sure that with the magic of C anything is 
possible but I can't conceive a way to have a variable both have the attribute 
and not have the attribute (to be clear, there doesn't exist a 
`__attribute__((no-wraps))` currently)


> If you declare a function parameter both wrapping and non-wrapping, is it 
> wrapping? 

Same here, not sure what you mean.


> If you assign to a wrapping variable, is the result wrapping? 

It depends on the type of the assignee, which I discuss later with a `const` 
analogy.

```c
wrap_int a;

int b = a; // b is not wrapping

wrap_int c = a; // c is wrapping
```

---

> If you mark a `short` wrapping, is the type after promotion wrapping? 

This concerns the `-fsanitize=implicit-signed-integer-truncation` sanitizer 
which the wraps attribute disables. So the type boundaries pre-promotion are 
not enforced by this sanitizer for wrapping types (e.g. for short, 
[-32768,32767]).

> If the operands of an equality operation are wrapping, is the resulting 
> boolean wrapping? 

I don't think you can get a less-than-int from an equality operator as the 
result. With that being said, and for all BinaryOperators, the resulting type 
will be wrapping if any of the operands are wrapping.

```
`-IfStmt 0x56518e85e710 
  |-BinaryOperator 0x56518e85e6e0  'int 
__attribute__((wraps))':'int' '=='
  | |-ImplicitCastExpr 0x56518e85e6b0  'wrap_int':'int' 

  | | `-DeclRefExpr 0x56518e85e670  'wrap_int':'int' lvalue Var 
0x56518e85e560 'a' 'wrap_int':'int'
  | `-ImplicitCastExpr 0x56518e85e6c8  'wrap_int':'int' 

  |   `-DeclRefExpr 0x56518e85e690  'wrap_int':'int' lvalue Var 
0x56518e85e5d8 'b' 'wrap_int':'int'
  `-CompoundStmt 0x56518e85e700 

```
---
> If you mark a bitfield wrapping, does it wrap?

Ah, nice corner case. This concerns the 
`-fsanitize=implicit-bitfield-conversion` sanitizer and is something I did not 
consider. So, currently the wraps attribute won't do anything on bitfields. I 
could add support for disabling this sanitizer for wrapping bitfields.

> The fact that with this patch, a wrapping int is "just" an int is both the 
> strength and weakness: you don't need to write out all these interactions... 
> but the result is just based on clang's internal preferences for preserving 
> type sugar, which are not documented.

In the cases where the attribute is "lost" it is similar to how `const` 
qualifiers disappear during assignments/type changes.

```c
const int a;
int b = a; // b is not const
// or 
extern void foo(int some);
foo(a); // const-ness is stripped, @some is not const
```

In the cases where the attribute sticks around, it follows these rules:

* Persists through Unary operators 
* If any operand within a BinaryOperator expression are wrapping then the 
entire expression result is considered wrapping.
* When used in assignments or passed as arguments to a function, the wrapping 
attribute will be present if the left-hand side or the function argument is 
wrapping. (similar to `const`, I suppose).


---

So, after reading all your cases my TODO list is:
* add support for ternary operator results gaining the wrapping attribute if 
any of its operands have it
* add support for disabling `-fsanitize=implicit-bitfield-conversion` when 
bitfields are marked as wrapping.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-23 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

The C standard is small enough that if you comb through the C grammar 
carefully, you can probably come up with explicitly rules for all the important 
constructs, and verify they work.  There's probably still a long tail of weird 
interactions with current and future clang extensions, and the whole thing is 
still sort of fragile because it's built on undocumented rules for type sugar 
propagation, but maybe if we're careful enough with testing, we can solve most 
of the compatibility?

I'd still prefer to have a distinct canonical type.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-23 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

If you have a select with both wrapping and non-wrapping operands, is the 
result wrapping?  If you declare a variable as both wrapping and non-wrapping, 
is it wrapping?  If you declare a function parameter both wrapping and 
non-wrapping, is it wrapping?  If you assign to a wrapping variable, is the 
result wrapping?  If you mark a `short` wrapping, is the type after promotion 
wrapping?  If the operands of an equality operation are wrapping, is the 
resulting boolean wrapping?  If you mark a bitfield wrapping, does it wrap?

The fact that with this patch, a wrapping int is "just" an int is both the 
strength and weakness: you don't need to write out all these interactions... 
but the result is just based on clang's internal preferences for preserving 
type sugar, which are not documented.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

@efriedma-quic said:
> I'm still not happy with the AST representation here. The current 
> representation is likely to cause unpredictable results in edge cases, and 
> compatibility constraints mean whatever result the current version happens to 
> produce for those cases is locked in forever. And there isn't really any good 
> way to mitigate those issues under the current representation.
> 
> I don't want to block progress here, but I think in its current form, we're 
> likely to end up with reported issues we can't fix.

The current design is heavily opt-in. So much so that this isn't just some 
compiler flag that you turn on. You have to go out of your way to design your 
code around this attribute, specifically marking things as wrapping with named 
types, etc.

So I guess the questions are: Is the current description of this attribute not 
clear enough? Do we think users will be confused/surprised by its behavior? 
What edge cases are there (in C)? Can they be fixed right now so we don't have 
these compatibility issues in the future?

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits


@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -triple x86_64-pc-linux-gnu
+// expected-no-diagnostics
+typedef int __attribute__((wraps)) wrapping_int;
+
+void foo(void) {
+  const wrapping_int A = 1;
+  int D = 2147483647 + A;

JustinStitt wrote:

OK, fixed in 1aa85e159d5768a7059bb35e457af28a3753bf66

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 50e7b1039e514dacc05bb8cd9ff9a3e3df9ed24d Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 01/13] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2b3bafa1c30548..fa7acb894cd76f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,15 @@ Attribute Changes in Clang
 - Clang now warns that the ``exclude_from_explicit_instantiation`` attribute
   is ignored when applied to a local class or a member thereof.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index a0bbe5861c5722..5f6e5a8de79954 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8057,3 +8057,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits


@@ -4249,6 +4270,10 @@ Value *ScalarExprEmitter::EmitFixedPointBinOp(const 
BinOpInfo ) {
 Value *ScalarExprEmitter::EmitSub(const BinOpInfo ) {
   // The LHS is always a pointer if either side is.
   if (!op.LHS->getType()->isPointerTy()) {
+if ((op.Ty->isSignedIntegerOrEnumerationType() ||

JustinStitt wrote:

Yep, fixed with 
[872e5d6](https://github.com/llvm/llvm-project/pull/86618/commits/872e5d6a2791c7de1268ff3d0bc090578f42067c)
 alongside a fix to EmitMul

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits


@@ -4455,6 +4455,14 @@ void Sema::AddAlignValueAttr(Decl *D, const 
AttributeCommonInfo , Expr *E) {
   D->addAttr(::new (Context) AlignValueAttr(Context, CI, E));
 }
 
+static void handleWrapsAttr(Sema , Decl *D, const ParsedAttr ) {
+  S.AddWrapsAttr(D, AL);
+}
+
+void Sema::AddWrapsAttr(Decl *D, const AttributeCommonInfo ) {

JustinStitt wrote:

gotcha, fixed in 
[872e5d6](https://github.com/llvm/llvm-project/pull/86618/commits/872e5d6a2791c7de1268ff3d0bc090578f42067c)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits


@@ -4093,6 +4109,11 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo ) {
   op.RHS->getType()->isPointerTy())
 return emitPointerArithmetic(CGF, op, CodeGenFunction::NotSubtraction);
 
+  if ((op.Ty->isSignedIntegerOrEnumerationType() ||

JustinStitt wrote:

fixed in 
[872e5d6](https://github.com/llvm/llvm-project/pull/86618/commits/872e5d6a2791c7de1268ff3d0bc090578f42067c)
 (I went with just removing the early return clauses)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits


@@ -2831,6 +2840,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const 
UnaryOperator *E, LValue LV,
   } else if (type->isIntegerType()) {
 QualType promotedType;
 bool canPerformLossyDemotionCheck = false;
+BinOpInfo Ops = (createBinOpInfoFromIncDec(

JustinStitt wrote:

fixed in 
[872e5d6](https://github.com/llvm/llvm-project/pull/86618/commits/872e5d6a2791c7de1268ff3d0bc090578f42067c)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits


@@ -156,6 +156,10 @@ struct BinOpInfo {
 }
 return false;
   }
+
+  /// Does the BinaryOperator have the wraps attribute?
+  /// If so, we can ellide overflow sanitizer checks.

JustinStitt wrote:

fixed in 
[872e5d6](https://github.com/llvm/llvm-project/pull/86618/commits/872e5d6a2791c7de1268ff3d0bc090578f42067c)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits


@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?

JustinStitt wrote:

fixed in 
[872e5d6](https://github.com/llvm/llvm-project/pull/86618/commits/872e5d6a2791c7de1268ff3d0bc090578f42067c)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 50e7b1039e514dacc05bb8cd9ff9a3e3df9ed24d Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 01/12] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2b3bafa1c30548..fa7acb894cd76f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,15 @@ Attribute Changes in Clang
 - Clang now warns that the ``exclude_from_explicit_instantiation`` attribute
   is ignored when applied to a local class or a member thereof.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index a0bbe5861c5722..5f6e5a8de79954 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8057,3 +8057,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits


@@ -4093,6 +4109,11 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo ) {
   op.RHS->getType()->isPointerTy())
 return emitPointerArithmetic(CGF, op, CodeGenFunction::NotSubtraction);
 
+  if ((op.Ty->isSignedIntegerOrEnumerationType() ||

JustinStitt wrote:

It can't just be flat out removed, if that's what you're asking. An alternative 
would be a few additions to existing if-statements resulting in about the same 
level of readability.

Specifically a diff like this should perform the same:

```diff
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 70b3849240cd..3f6bac748506 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4109,12 +4109,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo ) {
   op.RHS->getType()->isPointerTy())
 return emitPointerArithmetic(CGF, op, CodeGenFunction::NotSubtraction);
 
-  if ((op.Ty->isSignedIntegerOrEnumerationType() ||
-   op.Ty->isUnsignedIntegerType()) &&
-  op.hasWrappingOperand())
-return Builder.CreateAdd(op.LHS, op.RHS, "add");
-
-  if (op.Ty->isSignedIntegerOrEnumerationType()) {
+  if (op.Ty->isSignedIntegerOrEnumerationType() && !op.hasWrappingOperand()) {
 switch (CGF.getLangOpts().getSignedOverflowBehavior()) {
 case LangOptions::SOB_Defined:
   if (!CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow))
@@ -4147,7 +4142,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo ) {
 
   if (op.Ty->isUnsignedIntegerType() &&
   CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
-  !CanElideOverflowCheck(CGF.getContext(), op))
+  !CanElideOverflowCheck(CGF.getContext(), op) && !op.hasWrappingOperand())
 return EmitOverflowCheckedBinOp(op);
 
   if (op.LHS->getType()->isFPOrFPVectorTy()) {

```


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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Bill Wendling via cfe-commits


@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?

bwendling wrote:

s/Do/Does/

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Bill Wendling via cfe-commits


@@ -4249,6 +4270,10 @@ Value *ScalarExprEmitter::EmitFixedPointBinOp(const 
BinOpInfo ) {
 Value *ScalarExprEmitter::EmitSub(const BinOpInfo ) {
   // The LHS is always a pointer if either side is.
   if (!op.LHS->getType()->isPointerTy()) {
+if ((op.Ty->isSignedIntegerOrEnumerationType() ||

bwendling wrote:

Same question here, re-early creation of subtraction.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Bill Wendling via cfe-commits


@@ -2831,6 +2840,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const 
UnaryOperator *E, LValue LV,
   } else if (type->isIntegerType()) {
 QualType promotedType;
 bool canPerformLossyDemotionCheck = false;
+BinOpInfo Ops = (createBinOpInfoFromIncDec(

bwendling wrote:

You probably don't need parens around the `createBinOpInforFromIncDec` call.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Bill Wendling via cfe-commits


@@ -4455,6 +4455,14 @@ void Sema::AddAlignValueAttr(Decl *D, const 
AttributeCommonInfo , Expr *E) {
   D->addAttr(::new (Context) AlignValueAttr(Context, CI, E));
 }
 
+static void handleWrapsAttr(Sema , Decl *D, const ParsedAttr ) {
+  S.AddWrapsAttr(D, AL);
+}
+
+void Sema::AddWrapsAttr(Decl *D, const AttributeCommonInfo ) {

bwendling wrote:

It looks like this is called only by `handleWrapsAttr`. Maybe just inline it?

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Bill Wendling via cfe-commits


@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -triple x86_64-pc-linux-gnu
+// expected-no-diagnostics
+typedef int __attribute__((wraps)) wrapping_int;
+
+void foo(void) {
+  const wrapping_int A = 1;
+  int D = 2147483647 + A;

bwendling wrote:

How about instead:

```c
int foo(void) {
  const wrapping_int A = 1;
  return 2147483647 + A;
}
```

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Bill Wendling via cfe-commits


@@ -4093,6 +4109,11 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo ) {
   op.RHS->getType()->isPointerTy())
 return emitPointerArithmetic(CGF, op, CodeGenFunction::NotSubtraction);
 
+  if ((op.Ty->isSignedIntegerOrEnumerationType() ||

bwendling wrote:

Is this early-exit necessary, or does the following processing not work?

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Bill Wendling via cfe-commits


@@ -156,6 +156,10 @@ struct BinOpInfo {
 }
 return false;
   }
+
+  /// Does the BinaryOperator have the wraps attribute?
+  /// If so, we can ellide overflow sanitizer checks.

bwendling wrote:

s/ellide/elide/

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

I'm still not happy with the AST representation here.  The current 
representation is likely to cause unpredictable results in edge cases, and 
compatibility constraints mean whatever result the current version happens to 
produce for those cases is locked in forever.  And there isn't really any good 
way to mitigate those issues under the current representation.

I don't want to block progress here, but I think in its current form, we're 
likely to end up with reported issues we can't fix.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

Ping!

I've rebased this PR onto bcd150d2906ac83ea0ab680e981770a71c021a03 and fixed 
the issues with the docs not building because of faulty code-blocks.

Bigger picture, for the Linux Kernel, the current plan is to only enable 
certain integer sanitizers if support for this wraps attribute exists -- so it 
currently stands as a blocker for further arithmetic safety in the Kernel. 
(paraphrasing @kees)

With that being said, we're looking for more review on for this PR or a 
maintainer with push-access to merge :>)



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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 50e7b1039e514dacc05bb8cd9ff9a3e3df9ed24d Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 01/11] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2b3bafa1c30548..fa7acb894cd76f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,15 @@ Attribute Changes in Clang
 - Clang now warns that the ``exclude_from_explicit_instantiation`` attribute
   is ignored when applied to a local class or a member thereof.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index a0bbe5861c5722..5f6e5a8de79954 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8057,3 +8057,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-22 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 01/11] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-11 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 01/10] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-11 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> > Forbidding usage in C++ probably avoids the worst of the canonical-type 
> > issues, but there's still some potential for weird results. Particularly 
> > with type merging; for example, if you write `a ? (wrap_int)x : 1`, is the 
> > result a wrapping type?
> 
> I had a similar question in the general case: is the annotation contagious?
> 
> ```
> int foo(wrap_int x, int a, int b, int c) {
>   if (x + a + b < c)
> return 0;
>   return 1;
> }
> ```
> 
> The `x + a` is checked, but is that result checked when added to `b`?

Yes, it's "contagious":

```
|-FunctionDecl 0x55f64065a5d8  line:6:5 foo 'int 
(wrap_int, int, int, int)'
| |-ParmVarDecl 0x55f64065a300  col:18 used x 'wrap_int':'int'
| |-ParmVarDecl 0x55f64065a380  col:25 used a 'int'
| |-ParmVarDecl 0x55f64065a400  col:32 used b 'int'
| |-ParmVarDecl 0x55f64065a480  col:39 used c 'int'
| `-CompoundStmt 0x55f64065a8a8 
|   |-IfStmt 0x55f64065a858 
|   | |-BinaryOperator 0x55f64065a808  'int 
__attribute__((wraps))':'int' '<'
|   | | |-BinaryOperator 0x55f64065a7b0  'int 
__attribute__((wraps))':'int' '+'
|   | | | |-BinaryOperator 0x55f64065a758  'int 
__attribute__((wraps))':'int' '+'
|   | | | | |-ImplicitCastExpr 0x55f64065a728  'wrap_int':'int' 

|   | | | | | `-DeclRefExpr 0x55f64065a6e8  'wrap_int':'int' lvalue 
ParmVar 0x55f64065a300 'x' 'wrap_int':'int'
|   | | | | `-ImplicitCastExpr 0x55f64065a740  'int' 
|   | | | |   `-DeclRefExpr 0x55f64065a708  'int' lvalue ParmVar 
0x55f64065a380 'a' 'int'
|   | | | `-ImplicitCastExpr 0x55f64065a798  'int' 
|   | | |   `-DeclRefExpr 0x55f64065a778  'int' lvalue ParmVar 
0x55f64065a400 'b' 'int'
|   | | `-ImplicitCastExpr 0x55f64065a7f0  'int' 
|   | |   `-DeclRefExpr 0x55f64065a7d0  'int' lvalue ParmVar 
0x55f64065a480 'c' 'int'
|   | `-ReturnStmt 0x55f64065a848 
|   |   `-IntegerLiteral 0x55f64065a828  'int' 0
|   `-ReturnStmt 0x55f64065a898 
| `-IntegerLiteral 0x55f64065a878  'int' 1
```

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-11 Thread Bill Wendling via cfe-commits

bwendling wrote:

> Forbidding usage in C++ probably avoids the worst of the canonical-type 
> issues, but there's still some potential for weird results. Particularly with 
> type merging; for example, if you write `a ? (wrap_int)x : 1`, is the result 
> a wrapping type?

I had a similar question in the general case: is the annotation contagious?

```
int foo(wrap_int x, int a, int b, int c) {
  if (x + a + b < c)
return 0;
  return 1;
}
```

The `x + a` is checked, but is that result checked when added to `b`?

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-11 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

Forbidding usage in C++ probably avoids the worst of the canonical-type issues, 
but there's still some potential for weird results.  Particularly with type 
merging; for example, if you write `a ? (wrap_int)x : 1`, is the result a 
wrapping type?

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-11 Thread Bill Wendling via cfe-commits

bwendling wrote:

> Hi, I've made some changes and am looking for some more review on this PR:
> 
> * This attribute no longer supports C++ as there are other solutions for that 
> language [1](https://godbolt.org/z/7qPve6cWq) that allow for the same 
> fine-grained wrapping control without changing syntax patterns.
> * Add bypass for implicit-(un)signed-integer-truncation sanitizers
> * Rebased onto 
> [eec41d2](https://github.com/llvm/llvm-project/commit/eec41d2f8d81b546d7b97648cca6b2d656104bd3)

Does this list address all of @efriedma-quic's concerns about adding an 
attribute to a type?

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/9] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

The most recent commits have massively simplified checking for the wrapping 
attributes.

FWIW, the tests I am running are:
✅ `$ llvm-lit clang/test/CodeGen/integer-overflow.c -v`
✅ `$ llvm-lit clang/test/CodeGen/unsigned-overflow.c -v`
✅ `$ llvm-lit clang/test/Sema/attr-wraps.c -v`
...and some hand-rolled stuff I have.


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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/8] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 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 eec41d2f8d81b546d7b97648cca6b2d656104bd3 
a2f63982920f22d795c4971800bcc5cb55356570 -- clang/test/Sema/attr-wraps.c 
clang/include/clang/AST/Expr.h clang/include/clang/AST/Type.h 
clang/include/clang/Sema/Sema.h clang/lib/AST/Expr.cpp 
clang/lib/AST/ExprConstant.cpp clang/lib/AST/Type.cpp 
clang/lib/AST/TypePrinter.cpp clang/lib/CodeGen/CGExprScalar.cpp 
clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaDeclAttr.cpp 
clang/lib/Sema/SemaType.cpp clang/test/CodeGen/integer-overflow.c 
clang/test/CodeGen/unsigned-overflow.c
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index a001cdc7b5..4d996b4c57 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -150,9 +150,7 @@ struct BinOpInfo {
 
   /// Does the BinaryOperator have the wraps attribute?
   /// If so, we can ellide overflow sanitizer checks.
-  bool hasWrappingOperand() const {
-return E->getType().hasWrapsAttr();
-  }
+  bool hasWrappingOperand() const { return E->getType().hasWrapsAttr(); }
 };
 
 static bool MustVisitNullValue(const Expr *E) {
@@ -4418,7 +4416,8 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo ) {
   bool SanitizeSignedBase = CGF.SanOpts.has(SanitizerKind::ShiftBase) &&
 Ops.Ty->hasSignedIntegerRepresentation() &&
 !CGF.getLangOpts().isSignedOverflowDefined() &&
-!CGF.getLangOpts().CPlusPlus20 && 
!Ops.hasWrappingOperand();
+!CGF.getLangOpts().CPlusPlus20 &&
+!Ops.hasWrappingOperand();
   bool SanitizeUnsignedBase =
   CGF.SanOpts.has(SanitizerKind::UnsignedShiftBase) &&
   Ops.Ty->hasUnsignedIntegerRepresentation();

``




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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -6954,6 +6954,23 @@ static void HandleBTFTypeTagAttribute(QualType , 
const ParsedAttr ,
   ::new (Ctx) BTFTypeTagAttr(Ctx, Attr, BTFTypeTag), Type);
 }
 
+static void handleWrapsAttr(QualType , const ParsedAttr ,
+TypeProcessingState ) {
+  Sema  = State.getSema();
+  ASTContext  = S.Context;
+
+  // No need to warn here, that is handled by SemaDeclAttr.
+  // Simply disable applying this attribute.
+  if (S.getLangOpts().CPlusPlus)

JustinStitt wrote:

Right! I missed this. Fixed!

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -147,6 +147,15 @@ struct BinOpInfo {
   return UnOp->getSubExpr()->getType()->isFixedPointType();
 return false;
   }
+
+  /// Does the BinaryOperator have the wraps attribute?
+  /// If so, we can ellide overflow sanitizer checks.
+  bool oneOfWraps() const {
+const Type *TyPtr = E->getType().getTypePtrOrNull();
+if (TyPtr)

JustinStitt wrote:

Gotcha, checkout a2f63982920f22d795c4971800bcc5cb55356570

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -2237,6 +2237,21 @@ bool 
BinaryOperator::isNullPointerArithmeticExtension(ASTContext ,
   return true;
 }
 
+bool BinaryOperator::oneOfWraps(const ASTContext ) const {
+  llvm::SmallVector Both = {getLHS(), getRHS()};

JustinStitt wrote:

I had trouble with your code snippet because `children()` gives `Stmt` 
iterators and I would have to add in a cast or two. I went with a simpler 
approach in a2f63982920f22d795c4971800bcc5cb55356570 (with 
QualType::hasWrapsAttr())

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [GNU<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}

JustinStitt wrote:

0d7566777f06b3f2058d93dd77624ab2c66f1127

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [GNU<"wraps">];

JustinStitt wrote:

Right, I had that originally. I shouldn't have changed it :)

Anyways, fixed in 0d7566777f06b3f2058d93dd77624ab2c66f1127

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits


@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;

JustinStitt wrote:

Hi, fixed with 5e6d926532c2cff3288f25e9b8f872e7f2ec9b65

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/7] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Erich Keane via cfe-commits


@@ -6954,6 +6954,23 @@ static void HandleBTFTypeTagAttribute(QualType , 
const ParsedAttr ,
   ::new (Ctx) BTFTypeTagAttr(Ctx, Attr, BTFTypeTag), Type);
 }
 
+static void handleWrapsAttr(QualType , const ParsedAttr ,
+TypeProcessingState ) {
+  Sema  = State.getSema();
+  ASTContext  = S.Context;
+
+  // No need to warn here, that is handled by SemaDeclAttr.
+  // Simply disable applying this attribute.
+  if (S.getLangOpts().CPlusPlus)

erichkeane wrote:

This shouldn't be required at all with the 'lang opts' suggestion.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Erich Keane via cfe-commits


@@ -147,6 +147,15 @@ struct BinOpInfo {
   return UnOp->getSubExpr()->getType()->isFixedPointType();
 return false;
   }
+
+  /// Does the BinaryOperator have the wraps attribute?
+  /// If so, we can ellide overflow sanitizer checks.
+  bool oneOfWraps() const {
+const Type *TyPtr = E->getType().getTypePtrOrNull();
+if (TyPtr)

erichkeane wrote:

Also would be simplified with the above suggestion.  Also, since `QualType` has 
an operator -> and *, we typically don't fall to `Type*` unless we REALLY have 
to.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Erich Keane via cfe-commits


@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;

erichkeane wrote:

The name here is pretty annoyingly vague here, and even with the comment, had I 
not been in this in this review, wouldn't have known what this means. Feel free 
to come up with a better name, but for now, I am suggesting:

```suggestion
  bool hasWrappingOperand(const ASTContext ) const;
```

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Erich Keane via cfe-commits


@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [GNU<"wraps">];

erichkeane wrote:

Typically we'd want to do a `Clang` spelling here, which will allow the 
`[[clang::wraps]]` variant.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Erich Keane via cfe-commits


@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [GNU<"wraps">];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}

erichkeane wrote:

```suggestion
let LangOpts = [COnly];
}
```

??

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Erich Keane via cfe-commits


@@ -2237,6 +2237,21 @@ bool 
BinaryOperator::isNullPointerArithmeticExtension(ASTContext ,
   return true;
 }
 
+bool BinaryOperator::oneOfWraps(const ASTContext ) const {
+  llvm::SmallVector Both = {getLHS(), getRHS()};

erichkeane wrote:

Suggest instead:

```
return children().end() != llvm::find_if(children(), [](const Expr *E) {
return E && !E->IgnoreParenImpCasts()->getType().isNull() && 
E->IgnoreParenImpCasts()->getType()->hasAttr(attr::Wraps);
 });
```

Alternatively, you could make that significantly easier by implementing 
`hasWrapAttr` on `QualType` which could just do `return !isNull() && 
getTypePtr()->hasAttr(attr::Wraps);`.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-10 Thread Erich Keane via cfe-commits


@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.

erichkeane wrote:

```suggestion
  This attribute is only valid for C, as there are built-in language 
alternatives for other languages.
```

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Kees Cook via cfe-commits

kees wrote:

This now passes my behavioral testing suite for wrapping; yay! (The earlier 
version didn't cover truncate, so this is very nice now.)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/4] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

Hi, I've made some changes and am looking for some more review on this PR:

* This attribute no longer supports C++ as there are other solutions for that 
language [1] that allow for the same fine-grained wrapping control without 
changing syntax patterns.
* Add bypass for implicit-(un)signed-integer-truncation sanitizers
* Rebased onto eec41d2f8d81b546d7b97648cca6b2d656104bd3

[1]: https://godbolt.org/z/7qPve6cWq (simple example)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 10ee32826fc2acb6bd993c88bdb7142360b6f263 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/3] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  9 +++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 298 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f96cebbde3d825..cb02af7e948989 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -282,6 +282,15 @@ Attribute Changes in Clang
   This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to
   apply to this class.
 
+- Introduced ``__attribute((wraps))__`` which can be added to type or variable
+  declarations. Using an attributed type or variable in an arithmetic
+  expression will define the overflow behavior for that expression as having
+  two's complement wrap-around. These expressions cannot trigger integer
+  overflow warnings or sanitizer warnings. They also cannot be optimized away
+  by some eager UB optimizations.
+
+  This attribute is ignored in C++.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2bfefeabc348be..68cd7d7c0fac3b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4077,6 +4077,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index dc87a8c6f022dc..06e41fcee206c4 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4506,3 +4506,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 0ca4ea377fc36a..a2adb923e3c47c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8044,3 +8044,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-04-09 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 0fa8f07c722f9d7f80a90824f961ae6e9c5bdef7 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/4] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  7 ++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 296 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7fbe2fec6ca065..20bb9815830592 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -248,6 +248,13 @@ Attribute Changes in Clang
   added a new extension query ``__has_extension(swiftcc)`` corresponding to the
   ``__attribute__((swiftcc))`` attribute.
 
+- Introduced ``__attribute((wraps))`` or ``[[wraps]]`` which can be added to
+  type or variable declarations. Using an attributed type or variable in an
+  arithmetic expression will define the overflow behavior for that expression
+  as having two's complement wrap-around. These expressions cannot trigger
+  integer overflow warnings or sanitizer warnings. They also cannot be
+  optimized away by some eager UB optimizations.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6e153ebe024b42..934146e8a182bc 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4084,6 +4084,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 3e03e55612645b..0ea7755791d82e 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4496,3 +4496,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 9de14f608fd114..af662702edcffa 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8005,3 +8005,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int offset) {

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-27 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll commented:

`Sema.h` changes look good to me.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-27 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

Because we're dealing specifically with integers, which are a pretty limited 
class, you could consider introducing new types into the type system instead.  
Similar to how ext_vector_type works.  That's maybe easier than qualifiers in 
the sense that the code already deals with a bunch of arithmetic types... but 
you probably still have to touch a lot of places to get everything working.

Attributes on typedefs that don't correspond to a canonical type, like 
noderef/aligned/may_alias, are a constant source of issues; the user can't 
really tell if the attribute is actually working, or the compiler silently ate 
it.  My team spent a lot of time dealing with a user having trouble with the 
aligned attribute... they way they were using it was completely broken, but 
they didn't know it was broken until a new compiler started optimizing more 
aggressively.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-27 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

> Adding attributes to types as type sugar (not part of the canonical type) is 
> generally problematic: non-canonical types are not reliably preserved 
> throughout the compiler, particularly in cases involving templates.

I see, here's an example that currently breaks my attribute (without any 
special handling):

```c++
typedef int __attribute__((wraps)) wrapping_int;

template 
void foo(T a) {
  ++a; // this will throw a sanitizer error because the generic method 
   // created for this templated type is generic
}

int main(void) {
  wrapping_int A = INT_MAX;
  foo(A);
}
```


> 
> Can we use a type qualifier here?

FWICT, qualifiers are extremely sparse with only a handful existing at all. 
```
Type.h +142:
/// The collection of all-type qualifiers we support.
/// Clang supports five independent qualifiers:
/// * C99: const, volatile, and restrict
/// * MS: __unaligned
/// * Embedded C (TR18037): address spaces
/// * Objective C: the GC attributes (none, weak, or strong)
```

Most if not all type qualifiers are strongly associated with how the storage 
memory of a type is handled. For the behavior needed out of `wraps`, I was 
thinking this kind of thing is typically done via an attribute. Something like 
[noderef](https://clang.llvm.org/docs/AttributeReference.html#noderef) is 
similar. You apply it to types which then adjusts Clang's handling of variables 
of that type.

If it comes down to it, we can make this attribute only available for C under 
``__attribute__(())`` or I can try to add support for templates to be made 
aware of specific type attributes.

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-26 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

Adding attributes to types as type sugar (not part of the canonical type) is 
generally problematic: non-canonical types are not reliably preserved 
throughout the compiler, particularly in cases involving templates.

Can we use a type qualifier here?

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-26 Thread Justin Stitt via cfe-commits

JustinStitt wrote:

cc: @MaskRay (since they also reviewed 
https://github.com/llvm/llvm-project/pull/82432)

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


[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-25 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt updated 
https://github.com/llvm/llvm-project/pull/86618

>From 0fa8f07c722f9d7f80a90824f961ae6e9c5bdef7 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar 2024 03:14:49 +
Subject: [PATCH 1/2] implement wraps attribute

Signed-off-by: Justin Stitt 
---
 clang/docs/ReleaseNotes.rst   |  7 ++
 clang/include/clang/AST/Expr.h|  3 +
 clang/include/clang/Basic/Attr.td |  6 ++
 clang/include/clang/Basic/AttrDocs.td | 66 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  3 +
 clang/include/clang/Sema/Sema.h   |  4 ++
 clang/lib/AST/Expr.cpp| 19 ++
 clang/lib/AST/ExprConstant.cpp|  6 +-
 clang/lib/AST/TypePrinter.cpp |  3 +
 clang/lib/CodeGen/CGExprScalar.cpp| 40 +--
 clang/lib/Sema/SemaDeclAttr.cpp   | 12 +++-
 clang/lib/Sema/SemaType.cpp   | 15 +
 clang/test/CodeGen/integer-overflow.c | 56 
 clang/test/CodeGen/unsigned-overflow.c| 63 +++---
 clang/test/Sema/attr-wraps.c  |  9 +++
 15 files changed, 296 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/Sema/attr-wraps.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7fbe2fec6ca065..20bb9815830592 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -248,6 +248,13 @@ Attribute Changes in Clang
   added a new extension query ``__has_extension(swiftcc)`` corresponding to the
   ``__attribute__((swiftcc))`` attribute.
 
+- Introduced ``__attribute((wraps))`` or ``[[wraps]]`` which can be added to
+  type or variable declarations. Using an attributed type or variable in an
+  arithmetic expression will define the overflow behavior for that expression
+  as having two's complement wrap-around. These expressions cannot trigger
+  integer overflow warnings or sanitizer warnings. They also cannot be
+  optimized away by some eager UB optimizations.
+
 Improvements to Clang's diagnostics
 ---
 - Clang now applies syntax highlighting to the code snippets it
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 6e153ebe024b42..934146e8a182bc 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4084,6 +4084,9 @@ class BinaryOperator : public Expr {
   static unsigned sizeOfTrailingObjects(bool HasFPFeatures) {
 return HasFPFeatures * sizeof(FPOptionsOverride);
   }
+
+  /// Do one of the subexpressions have the wraps attribute?
+  bool oneOfWraps(const ASTContext ) const;
 };
 
 /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 3e03e55612645b..0ea7755791d82e 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4496,3 +4496,9 @@ def CodeAlign: StmtAttr {
 static constexpr int MaximumAlignment = 4096;
   }];
 }
+
+def Wraps : DeclOrTypeAttr {
+  let Spellings = [Clang<"wraps">, CXX11<"", "wraps", 202403>];
+  let Subjects = SubjectList<[Var, TypedefName, Field]>;
+  let Documentation = [WrapsDocs];
+}
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 9de14f608fd114..af662702edcffa 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8005,3 +8005,69 @@ requirement:
   }
   }];
 }
+
+def WrapsDocs : Documentation {
+  let Category = DocCatField;
+  let Content = [{
+This attribute can be used with type or variable declarations to denote that
+arithmetic containing these marked components have defined overflow behavior.
+Specifically, the behavior is defined as being consistent with two's complement
+wrap-around. For the purposes of sanitizers or warnings that concern themselves
+with the definedness of integer arithmetic, they will cease to instrument or
+warn about arithmetic that directly involves a "wrapping" component.
+
+For example, ``-fsanitize=signed-integer-overflow`` or ``-Winteger-overflow``
+will not warn about suspicious overflowing arithmetic -- assuming correct usage
+of the wraps attribute.
+
+This example shows some basic usage of ``__attribute__((wraps))`` on a type
+definition when building with ``-fsanitize=signed-integer-overflow``
+
+.. code-block:: c
+  typedef int __attribute__((wraps)) wrapping_int;
+
+  void foo() {
+wrapping_int a = INT_MAX;
+++a; // no sanitizer warning
+  }
+
+  int main() { foo(); }
+
+In the following example, we use ``__attribute__((wraps))`` on a variable to
+disable overflow instrumentation for arithmetic expressions it appears in. We
+do so with a popular overflow-checking pattern which we might not want to trip
+sanitizers (like ``-fsanitize=unsigned-integer-overflow``).
+
+.. code-block:: c
+  void foo(int offset) {

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-25 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: Justin Stitt (JustinStitt)


Changes

## Intro

This attribute would allow for more granular control over what expressions can 
emit integer overflow warnings or integer overflow sanitizer errors.

 Here are some examples:

_copy-pasted from my 
[RFC.](https://discourse.llvm.org/t/rfc-add-wraps-attribute-for-granular-integer-overflow-handling/77670)_


When compiling with 
`-fsanitize=signed-integer-overflow,unsigned-integer-overflow`:

```c
typedef int __attribute__((wraps)) wrapping_int;

wrapping_int A = INT_MAX;
++A; /* This will not trigger a runtime sanitizer error */
```

```c
unsigned long addr __attribute__((wraps)); /* wraps can be added to variables */
unsigned long size; /* both operands don't need wraps, just one */
...
if (addr + size  addr) {
  // handle overflow gracefully, because the overflow sanitizer won't trip
}
...
```

```c
typedef int __attribute__((wraps)) wrapping_int;

int a = (wrapping_int) INT_MAX + 1; // no sanitizer trip (or -Winteger-overflow)
```

The next few examples will show some cases where sanitizers will still trip (by 
design):

```c
wrapping_int A = INT_MAX;
int B = 1;

A = INT_MAX + 1; // overflow sanitizer trips! (INT_MAX + 1) is computed and 
trips the sanitizer before assignment to A

B = (INT_MAX+B) * A; // overflow sanitizer trips!

B =  INT_MAX + B * A; // overflow sanitizer does NOT trip!
// This is because B * A is computed first, the result type carries the wraps 
attribute
// with it from A, then that result is used in summation with INT_MAX.
```

## Reasoning
The root cause of many security vulnerabilities in the Linux kernel is 
[arithmetic overflow](https://cwe.mitre.org/data/definitions/190.html). 

The currently available choices to control arithmetic overflow behavior are 
very limited. The instrumentation is "all or nothing" which lacks the 
granularity required for many cases.

Enabling or disabling a sanitizer like ``-fsanitize=unsigned-integer-overflow`` 
completely opts you in or out of instrumentation for __all__ unsigned 
arithmetic. For functions where intentional wrap-around is performed you could 
use ``__attribute__((no_sanitize("unsigned-integer-overflow")))`` to completely 
disable sanitizer instrumentation. This, however, is not ideal if your function 
is large and multi-purposed -- perhaps even containing loads of arithmetic that 
you don't want to disable instrumentation for. Getting more granular, we have 
compiler built-ins like ``__builtin_add_overflow()`` or similar. However, in 
some codebases, refactoring existing arithmetic to utilize these overflow 
builtins may only serve to complicate code. For example, the Linux Kernel has, 
like lots of other projects, some agreed upon idioms which are understood by 
its developers and changing these patterns is [frowned 
upon](https://lore.kernel.org/all/CAHk-=whS7FSbBoo1gxe+83twO2JeGNsUKMhAcfWymw9auqBvjg@mail.gmail.com):


"if there's some unsigned wrap-around checker that doesn't
understand this traditional way of doing overflow checking, that piece
of crap needs fixing." - Linus 


This was in response to a patch that was trying to change the commonly accepted 
idiom: `base + offset  base` to utilize a builtin (via a macro) to silence 
sanitizer errors.

Recently, there's been some effort by Kees, myself and others to reintroduce 
the signed and unsigned integer overflow sanitizers in the Linux Kernel. Upon 
turning these sanitizers back on (or for the case of signed-integer-overflow, 
[making it work at all](https://github.com/llvm/llvm-project/pull/82432)) we 
encountered plently of existing instances of integer overflow in the Kernel. 
However, there's some pushback when trying to alter the "traditional" way of 
doing things.

With this new wrapping attribute we can specifically craft types that disable 
overflow instrumentation, without modifying traditional and widely understood 
code patterns -- resulting in easier to read code.

### To summarize the behavior:

Using ``__attribute__((wraps))`` on a typedef or variable declaration makes it 
a "wrapping" type or variable thereby disabling overflow instrumentation for 
either 1) arithmetic performed directly on wrapping variables or types or 2) 
arithmetic performed on the result of calculations containing a wrapping 
variable or type. Instrumentation is not disabled for calculations containing 
subexpressions wherein no wrapping variables are present.


## Other Notes

* ``[[wraps]]`` and ``[[clang::wraps]]`` are supported for C++11

* The wraps attribute cannot be applied to functions

* The wraps attribute _can_ be applied to member variables

* Constant expressions containing a wrapping type or variable should not result 
in `-Winteger-overflow` warnings either.

### CCs
@kees @nickdesaulniers @bwendling @erichkeane 
@haoNoQ @apple-fcloutier @FlashSheridan 




---

Patch is 25.42 KiB, truncated to 20.00 KiB below, full version: 

[clang] [Clang] Add wraps attribute (for granular integer overflow handling) (PR #86618)

2024-03-25 Thread Justin Stitt via cfe-commits

https://github.com/JustinStitt created 
https://github.com/llvm/llvm-project/pull/86618

## Intro

This attribute would allow for more granular control over what expressions can 
emit integer overflow warnings or integer overflow sanitizer errors.

 Here are some examples:

_copy-pasted from my 
[RFC.](https://discourse.llvm.org/t/rfc-add-wraps-attribute-for-granular-integer-overflow-handling/77670)_


When compiling with 
`-fsanitize=signed-integer-overflow,unsigned-integer-overflow`:

```c
typedef int __attribute__((wraps)) wrapping_int;

wrapping_int A = INT_MAX;
++A; /* This will not trigger a runtime sanitizer error */
```

```c
unsigned long addr __attribute__((wraps)); /* wraps can be added to variables */
unsigned long size; /* both operands don't need wraps, just one */
...
if (addr + size < addr) {
  // handle overflow gracefully, because the overflow sanitizer won't trip
}
...
```

```c
typedef int __attribute__((wraps)) wrapping_int;

int a = (wrapping_int) INT_MAX + 1; // no sanitizer trip (or -Winteger-overflow)
```

The next few examples will show some cases where sanitizers will still trip (by 
design):

```c
wrapping_int A = INT_MAX;
int B = 1;

A = INT_MAX + 1; // overflow sanitizer trips! (INT_MAX + 1) is computed and 
trips the sanitizer before assignment to A

B = (INT_MAX+B) * A; // overflow sanitizer trips!

B =  INT_MAX + B * A; // overflow sanitizer does NOT trip!
// This is because B * A is computed first, the result type carries the wraps 
attribute
// with it from A, then that result is used in summation with INT_MAX.
```

## Reasoning
The root cause of many security vulnerabilities in the Linux kernel is 
[arithmetic overflow](https://cwe.mitre.org/data/definitions/190.html). 

The currently available choices to control arithmetic overflow behavior are 
very limited. The instrumentation is "all or nothing" which lacks the 
granularity required for many cases.

Enabling or disabling a sanitizer like ``-fsanitize=unsigned-integer-overflow`` 
completely opts you in or out of instrumentation for __all__ unsigned 
arithmetic. For functions where intentional wrap-around is performed you could 
use ``__attribute__((no_sanitize("unsigned-integer-overflow")))`` to completely 
disable sanitizer instrumentation. This, however, is not ideal if your function 
is large and multi-purposed -- perhaps even containing loads of arithmetic that 
you don't want to disable instrumentation for. Getting more granular, we have 
compiler built-ins like ``__builtin_add_overflow()`` or similar. However, in 
some codebases, refactoring existing arithmetic to utilize these overflow 
builtins may only serve to complicate code. For example, the Linux Kernel has, 
like lots of other projects, some agreed upon idioms which are understood by 
its developers and changing these patterns is [frowned 
upon](https://lore.kernel.org/all/CAHk-=whs7fsbboo1gxe+83two2jegnsukmhacfwymw9auqb...@mail.gmail.com):


"if there's some unsigned wrap-around checker that doesn't
understand this traditional way of doing overflow checking, that piece
of crap needs fixing." - Linus 


This was in response to a patch that was trying to change the commonly accepted 
idiom: `base + offset < base` to utilize a builtin (via a macro) to silence 
sanitizer errors.

Recently, there's been some effort by Kees, myself and others to reintroduce 
the signed and unsigned integer overflow sanitizers in the Linux Kernel. Upon 
turning these sanitizers back on (or for the case of signed-integer-overflow, 
[making it work at all](https://github.com/llvm/llvm-project/pull/82432)) we 
encountered plently of existing instances of integer overflow in the Kernel. 
However, there's some pushback when trying to alter the "traditional" way of 
doing things.

With this new wrapping attribute we can specifically craft types that disable 
overflow instrumentation, without modifying traditional and widely understood 
code patterns -- resulting in easier to read code.

### To summarize the behavior:

Using ``__attribute__((wraps))`` on a typedef or variable declaration makes it 
a "wrapping" type or variable thereby disabling overflow instrumentation for 
either 1) arithmetic performed directly on wrapping variables or types or 2) 
arithmetic performed on the result of calculations containing a wrapping 
variable or type. Instrumentation is not disabled for calculations containing 
subexpressions wherein no wrapping variables are present.


## Other Notes

* ``[[wraps]]`` and ``[[clang::wraps]]`` are supported for C++11

* The wraps attribute cannot be applied to functions

* The wraps attribute _can_ be applied to member variables

* Constant expressions containing a wrapping type or variable should not result 
in `-Winteger-overflow` warnings either.

### CCs
@kees @nickdesaulniers @bwendling @erichkeane @haoNoQ @apple-fcloutier 
@FlashSheridan 




>From 0fa8f07c722f9d7f80a90824f961ae6e9c5bdef7 Mon Sep 17 00:00:00 2001
From: Justin Stitt 
Date: Tue, 5 Mar