lebedev.ri updated this revision to Diff 245622.
lebedev.ri added a comment.

Rebased, NFC.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D73996

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/non-power-of-2-alignment-assumptions.c
  clang/test/Sema/alloc-align-attr.c
  clang/test/SemaCXX/alloc-align-attr.cpp

Index: clang/test/SemaCXX/alloc-align-attr.cpp
===================================================================
--- clang/test/SemaCXX/alloc-align-attr.cpp
+++ clang/test/SemaCXX/alloc-align-attr.cpp
@@ -30,14 +30,14 @@
   dependent_ret<int *> b;
   b.Foo(1);
   b.Foo2(1);
-  b.Foo(3);           // expected-error {{requested alignment is not a power of 2}}
-  b.Foo2(3);          // expected-error {{requested alignment is not a power of 2}}
+  b.Foo(3);           // expected-warning {{requested alignment is not a power of 2}}
+  b.Foo2(3);          // expected-warning {{requested alignment is not a power of 2}}
   b.Foo(1073741824);  // expected-warning {{requested alignment must be 536870912 bytes or smaller; maximum alignment assumed}}
   b.Foo2(1073741824); // expected-warning {{requested alignment must be 536870912 bytes or smaller; maximum alignment assumed}}
   b.Foo(align);
   b.Foo2(align);
 
-  dependent_param_struct<int> c; 
+  dependent_param_struct<int> c;
   c.Foo(1);
   dependent_param_struct<float> d; // expected-note {{in instantiation of template class 'dependent_param_struct<float>' requested here}}
   d.Foo(1.0);
Index: clang/test/Sema/alloc-align-attr.c
===================================================================
--- clang/test/Sema/alloc-align-attr.c
+++ clang/test/Sema/alloc-align-attr.c
@@ -24,7 +24,7 @@
   return test_ptr_alloc_align(16);
 }
 void *align15() {
-  return test_ptr_alloc_align(15); // expected-error {{requested alignment is not a power of 2}}
+  return test_ptr_alloc_align(15); // expected-warning {{requested alignment is not a power of 2}}
 }
 void *align536870912() {
   return test_ptr_alloc_align(1073741824); // expected-warning {{requested alignment must be 536870912 bytes or smaller; maximum alignment assumed}}
Index: clang/test/CodeGen/non-power-of-2-alignment-assumptions.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/non-power-of-2-alignment-assumptions.c
@@ -0,0 +1,46 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+void *__attribute__((alloc_align(1))) alloc(int align);
+
+// CHECK-LABEL: @t0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ALIGN_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ALIGN_ADDR]], align 4
+// CHECK-NEXT:    [[CALL:%.*]] = call i8* @alloc(i32 [[TMP0]])
+// CHECK-NEXT:    [[ALIGNMENTCAST:%.*]] = zext i32 [[TMP0]] to i64
+// CHECK-NEXT:    [[MASK:%.*]] = sub i64 [[ALIGNMENTCAST]], 1
+// CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i8* [[CALL]] to i64
+// CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]]
+// CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
+// CHECK-NEXT:    call void @llvm.assume(i1 [[MASKCOND]])
+// CHECK-NEXT:    ret void
+//
+void t0(int align) {
+  alloc(align);
+}
+// CHECK-LABEL: @t1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ALIGN_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4
+// CHECK-NEXT:    [[CALL:%.*]] = call i8* @alloc(i32 7)
+// CHECK-NEXT:    [[PTRINT:%.*]] = ptrtoint i8* [[CALL]] to i64
+// CHECK-NEXT:    [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 6
+// CHECK-NEXT:    [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0
+// CHECK-NEXT:    call void @llvm.assume(i1 [[MASKCOND]])
+// CHECK-NEXT:    ret void
+//
+void t1(int align) {
+  alloc(7);
+}
+// CHECK-LABEL: @t2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[ALIGN_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4
+// CHECK-NEXT:    [[CALL:%.*]] = call align 8 i8* @alloc(i32 8)
+// CHECK-NEXT:    ret void
+//
+void t2(int align) {
+  alloc(8);
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -3898,11 +3898,9 @@
     if (!Arg->isValueDependent()) {
       llvm::APSInt I(64);
       if (Arg->isIntegerConstantExpr(I, Context)) {
-        if (!I.isPowerOf2()) {
-          Diag(Arg->getExprLoc(), diag::err_alignment_not_power_of_two)
+        if (!I.isPowerOf2())
+          Diag(Arg->getExprLoc(), diag::warn_alignment_not_power_of_two)
               << Arg->getSourceRange();
-          return;
-        }
 
         if (I > Sema::MaximumAlignment)
           Diag(Arg->getExprLoc(), diag::warn_assume_aligned_too_great)
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -3892,6 +3892,10 @@
     const auto *AlignmentCI = dyn_cast<llvm::ConstantInt>(Alignment);
     if (!AlignmentCI)
       return Attrs;
+    // We may legitimately have non-power-of-2 alignment here.
+    // If so, this is UB land, emit it via `@llvm.assume` instead.
+    if (!AlignmentCI->getValue().isPowerOf2())
+      return Attrs;
     llvm::AttributeList NewAttrs = maybeRaiseRetAlignmentAttribute(
         CGF.getLLVMContext(), Attrs,
         llvm::Align(
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3033,6 +3033,9 @@
   "requested alignment must be %0 or smaller">;
 def err_alignment_not_power_of_two : Error<
   "requested alignment is not a power of 2">;
+def warn_alignment_not_power_of_two : Warning<
+  err_alignment_not_power_of_two.Text>,
+  InGroup<DiagGroup<"non-power-of-two-alignment">>;
 def err_alignment_dependent_typedef_name : Error<
   "requested alignment is dependent but declaration is not dependent">;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to