diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2983,8 +2983,9 @@ "requested alignment must be %0 or greater">; def err_alignment_too_big : Error< "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< + "requested alignment is not a power of 2">, + InGroup>; def err_alignment_dependent_typedef_name : Error< "requested alignment is dependent but declaration is not dependent">; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3884,6 +3884,10 @@ const auto *AlignmentCI = dyn_cast(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( diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -253,7 +253,7 @@ return true; } if (!AlignValue.isPowerOf2()) { - S.Diag(AlignOp->getExprLoc(), diag::err_alignment_not_power_of_two); + S.Diag(AlignOp->getExprLoc(), diag::warn_alignment_not_power_of_two); return true; } if (AlignValue == 1) { @@ -3885,7 +3885,7 @@ if (Arg->EvaluateAsInt(Align, Context)) { const llvm::APSInt &I = Align.Val.getInt(); if (!I.isPowerOf2()) { - Diag(Arg->getExprLoc(), diag::err_alignment_not_power_of_two) + Diag(Arg->getExprLoc(), diag::warn_alignment_not_power_of_two) << Arg->getSourceRange(); return; } @@ -5579,7 +5579,7 @@ llvm::APSInt Result = Arg->EvaluateKnownConstInt(Context); if (!Result.isPowerOf2()) - return Diag(TheCall->getBeginLoc(), diag::err_alignment_not_power_of_two) + return Diag(TheCall->getBeginLoc(), diag::warn_alignment_not_power_of_two) << Arg->getSourceRange(); if (Result < Context.getCharWidth()) @@ -5614,7 +5614,7 @@ return true; if (!Result.isPowerOf2()) - return Diag(TheCall->getBeginLoc(), diag::err_alignment_not_power_of_two) + return Diag(TheCall->getBeginLoc(), diag::warn_alignment_not_power_of_two) << Arg->getSourceRange(); if (Result > Sema::MaximumAlignment) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1621,8 +1621,8 @@ } if (!I.isPowerOf2()) { - Diag(AttrLoc, diag::err_alignment_not_power_of_two) - << E->getSourceRange(); + Diag(AttrLoc, diag::warn_alignment_not_power_of_two) + << E->getSourceRange(); return; } @@ -3691,8 +3691,8 @@ return; if (!Alignment.isPowerOf2()) { - Diag(AttrLoc, diag::err_alignment_not_power_of_two) - << E->getSourceRange(); + Diag(AttrLoc, diag::warn_alignment_not_power_of_two) + << E->getSourceRange(); return; } @@ -3808,8 +3808,8 @@ // An alignment specification of zero has no effect. if (!(TmpAttr.isAlignas() && !Alignment)) { if (!llvm::isPowerOf2_64(AlignVal)) { - Diag(AttrLoc, diag::err_alignment_not_power_of_two) - << E->getSourceRange(); + Diag(AttrLoc, diag::warn_alignment_not_power_of_two) + << E->getSourceRange(); return; } } diff --git a/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c b/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c new file mode 100644 --- /dev/null +++ b/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); +} diff --git a/clang/test/Sema/align_value.c b/clang/test/Sema/align_value.c --- a/clang/test/Sema/align_value.c +++ b/clang/test/Sema/align_value.c @@ -4,10 +4,10 @@ void foo(aligned_double x, double * y __attribute__((align_value(32)))) { }; -// expected-error@+1 {{requested alignment is not a power of 2}} +// expected-warning@+1 {{requested alignment is not a power of 2}} typedef double * __attribute__((align_value(63))) aligned_double1; -// expected-error@+1 {{requested alignment is not a power of 2}} +// expected-warning@+1 {{requested alignment is not a power of 2}} typedef double * __attribute__((align_value(-2))) aligned_double2; // expected-error@+1 {{attribute takes one argument}} diff --git a/clang/test/Sema/alignas.c b/clang/test/Sema/alignas.c --- a/clang/test/Sema/alignas.c +++ b/clang/test/Sema/alignas.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -Dalignof=__alignof %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -Dalignof=_Alignof -DUSING_C11_SYNTAX %s -_Alignas(3) int align_illegal; //expected-error {{requested alignment is not a power of 2}} +_Alignas(3) int align_illegal; //expected-warning {{requested alignment is not a power of 2}} _Alignas(int) char align_big; _Alignas(1) int align_small; // expected-error {{requested alignment is less than minimum}} _Alignas(1) unsigned _Alignas(8) int _Alignas(1) align_multiple; diff --git a/clang/test/Sema/alloc-align-attr.c b/clang/test/Sema/alloc-align-attr.c --- a/clang/test/Sema/alloc-align-attr.c +++ b/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}} diff --git a/clang/test/Sema/attr-aligned.c b/clang/test/Sema/attr-aligned.c --- a/clang/test/Sema/attr-aligned.c +++ b/clang/test/Sema/attr-aligned.c @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify %s -int x __attribute__((aligned(3))); // expected-error {{requested alignment is not a power of 2}} +int x __attribute__((aligned(3))); // expected-warning {{requested alignment is not a power of 2}} int y __attribute__((aligned(1 << 30))); // expected-error {{requested alignment must be 536870912 bytes or smaller}} // PR26444 diff --git a/clang/test/Sema/builtin-align.c b/clang/test/Sema/builtin-align.c --- a/clang/test/Sema/builtin-align.c +++ b/clang/test/Sema/builtin-align.c @@ -83,8 +83,8 @@ #else // expected-warning@-4 {{aligning a value to 1 byte is a no-op}} #endif - (void)ALIGN_BUILTIN(ptr, 3); // expected-error {{requested alignment is not a power of 2}} - (void)ALIGN_BUILTIN(x, 7); // expected-error {{requested alignment is not a power of 2}} + (void)ALIGN_BUILTIN(ptr, 3); // expected-warning {{requested alignment is not a power of 2}} + (void)ALIGN_BUILTIN(x, 7); // expected-warning {{requested alignment is not a power of 2}} // check the maximum range for smaller types: __UINT8_TYPE__ c = ' '; @@ -102,7 +102,7 @@ (void)ALIGN_BUILTIN(longptr, ((__int128)1) << 65); // expected-error {{requested alignment must be 9223372036854775808 or smaller}} const int bad_align = 8 + 1; - (void)ALIGN_BUILTIN(ptr, bad_align); // expected-error {{requested alignment is not a power of 2}} + (void)ALIGN_BUILTIN(ptr, bad_align); // expected-warning {{requested alignment is not a power of 2}} } // Check that it can be used in constant expressions: diff --git a/clang/test/Sema/builtin-alloca-with-align.c b/clang/test/Sema/builtin-alloca-with-align.c --- a/clang/test/Sema/builtin-alloca-with-align.c +++ b/clang/test/Sema/builtin-alloca-with-align.c @@ -5,7 +5,7 @@ } void test2(int a) { - __builtin_alloca_with_align(a, -32); // expected-error {{requested alignment is not a power of 2}} + __builtin_alloca_with_align(a, -32); // expected-warning {{requested alignment is not a power of 2}} } void test3(unsigned *b) { @@ -17,7 +17,7 @@ } void test5(int a) { - __builtin_alloca_with_align(a, 31); // expected-error {{requested alignment is not a power of 2}} + __builtin_alloca_with_align(a, 31); // expected-warning {{requested alignment is not a power of 2}} } void test6(int a, int j) { diff --git a/clang/test/Sema/builtin-assume-aligned.c b/clang/test/Sema/builtin-assume-aligned.c --- a/clang/test/Sema/builtin-assume-aligned.c +++ b/clang/test/Sema/builtin-assume-aligned.c @@ -16,7 +16,7 @@ } int test4(int *a) { - a = __builtin_assume_aligned(a, -32); // expected-error {{requested alignment is not a power of 2}} + a = __builtin_assume_aligned(a, -32); // expected-warning {{requested alignment is not a power of 2}} // FIXME: The line below produces {{requested alignment is not a power of 2}} // on i386-freebsd, but not on x86_64-linux (for example). // a = __builtin_assume_aligned(a, 1ULL << 63); @@ -34,7 +34,7 @@ } int test7(int *a) { - a = __builtin_assume_aligned(a, 31); // expected-error {{requested alignment is not a power of 2}} + a = __builtin_assume_aligned(a, 31); // expected-warning {{requested alignment is not a power of 2}} return a[0]; } @@ -52,7 +52,7 @@ void *test_no_fn_proto() __attribute__((assume_aligned(32))); // no-warning void *test_with_fn_proto(void) __attribute__((assume_aligned(128))); // no-warning -void *test_no_fn_proto() __attribute__((assume_aligned(31))); // expected-error {{requested alignment is not a power of 2}} +void *test_no_fn_proto() __attribute__((assume_aligned(31))); // expected-warning {{requested alignment is not a power of 2}} void *test_no_fn_proto() __attribute__((assume_aligned(32, 73))); // no-warning void *test_no_fn_proto() __attribute__((assume_aligned)); // expected-error {{'assume_aligned' attribute takes at least 1 argument}} diff --git a/clang/test/SemaCXX/align_value.cpp b/clang/test/SemaCXX/align_value.cpp --- a/clang/test/SemaCXX/align_value.cpp +++ b/clang/test/SemaCXX/align_value.cpp @@ -17,7 +17,7 @@ template struct nope { - // expected-error@+1 {{requested alignment is not a power of 2}} + // expected-warning@+1 {{requested alignment is not a power of 2}} void foo(T &b __attribute__((align_value(sizeof(T)+1)))); }; diff --git a/clang/test/SemaCXX/alloc-align-attr.cpp b/clang/test/SemaCXX/alloc-align-attr.cpp --- a/clang/test/SemaCXX/alloc-align-attr.cpp +++ b/clang/test/SemaCXX/alloc-align-attr.cpp @@ -30,8 +30,8 @@ dependent_ret 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); diff --git a/clang/test/SemaCXX/attr-cxx0x.cpp b/clang/test/SemaCXX/attr-cxx0x.cpp --- a/clang/test/SemaCXX/attr-cxx0x.cpp +++ b/clang/test/SemaCXX/attr-cxx0x.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -pedantic -std=c++11 %s -int align_illegal alignas(3); //expected-error {{requested alignment is not a power of 2}} +int align_illegal alignas(3); //expected-warning {{requested alignment is not a power of 2}} char align_big alignas(int); int align_small alignas(1); // expected-error {{requested alignment is less than minimum}} int align_multiple alignas(1) alignas(8) alignas(1); diff --git a/clang/test/SemaCXX/builtin-align-cxx.cpp b/clang/test/SemaCXX/builtin-align-cxx.cpp --- a/clang/test/SemaCXX/builtin-align-cxx.cpp +++ b/clang/test/SemaCXX/builtin-align-cxx.cpp @@ -17,7 +17,7 @@ template void test_templated_arguments() { T array[ArraySize]; // expected-error{{variable has incomplete type 'fwddecl'}} - static_assert(__is_same(decltype(__builtin_align_up(array, Alignment)), T *), // expected-error{{requested alignment is not a power of 2}} + static_assert(__is_same(decltype(__builtin_align_up(array, Alignment)), T *), // expected-warning{{requested alignment is not a power of 2}} "return type should be the decayed array type"); static_assert(__is_same(decltype(__builtin_align_down(array, Alignment)), T *), "return type should be the decayed array type"); @@ -40,16 +40,16 @@ template void test_incorrect_alignment_without_instatiation(T value) { int array[32]; - static_assert(__is_same(decltype(__builtin_align_up(array, 31)), int *), // expected-error{{requested alignment is not a power of 2}} + static_assert(__is_same(decltype(__builtin_align_up(array, 31)), int *), // expected-warning{{requested alignment is not a power of 2}} "return type should be the decayed array type"); - static_assert(__is_same(decltype(__builtin_align_down(array, 7)), int *), // expected-error{{requested alignment is not a power of 2}} + static_assert(__is_same(decltype(__builtin_align_down(array, 7)), int *), // expected-warning{{requested alignment is not a power of 2}} "return type should be the decayed array type"); static_assert(__is_same(decltype(__builtin_is_aligned(array, -1)), bool), // expected-error{{requested alignment must be 1 or greater}} "return type should be bool"); __builtin_align_up(array); // expected-error{{too few arguments to function call, expected 2, have 1}} - __builtin_align_up(array, 31); // expected-error{{requested alignment is not a power of 2}} - __builtin_align_down(array, 31); // expected-error{{requested alignment is not a power of 2}} - __builtin_align_up(array, 31); // expected-error{{requested alignment is not a power of 2}} + __builtin_align_up(array, 31); // expected-warning{{requested alignment is not a power of 2}} + __builtin_align_down(array, 31); // expected-warning{{requested alignment is not a power of 2}} + __builtin_align_up(array, 31); // expected-warning{{requested alignment is not a power of 2}} __builtin_align_up(value, 31); // This shouldn't want since the type is dependent __builtin_align_up(value); // Same here } diff --git a/clang/test/SemaCXX/builtin-assume-aligned-tmpl.cpp b/clang/test/SemaCXX/builtin-assume-aligned-tmpl.cpp --- a/clang/test/SemaCXX/builtin-assume-aligned-tmpl.cpp +++ b/clang/test/SemaCXX/builtin-assume-aligned-tmpl.cpp @@ -2,7 +2,7 @@ template int test9(int *a) { - a = (int *) __builtin_assume_aligned(a, z + 1); // expected-error {{requested alignment is not a power of 2}} + a = (int *)__builtin_assume_aligned(a, z + 1); // expected-warning {{requested alignment is not a power of 2}} return a[0]; } @@ -21,10 +21,10 @@ } template -void *atest() __attribute__((assume_aligned(q))); // expected-error {{requested alignment is not a power of 2}} +void *atest() __attribute__((assume_aligned(q))); // expected-warning {{requested alignment is not a power of 2}} template -void *atest2() __attribute__((assume_aligned(q, o))); // expected-error {{requested alignment is not a power of 2}} +void *atest2() __attribute__((assume_aligned(q, o))); // expected-warning {{requested alignment is not a power of 2}} void test20() { atest<31>(); // expected-note {{in instantiation of function template specialization 'atest<31>' requested here}} @@ -47,7 +47,7 @@ } template -T *atest3() __attribute__((assume_aligned(31, o))); // expected-error {{requested alignment is not a power of 2}} +T *atest3() __attribute__((assume_aligned(31, o))); // expected-warning {{requested alignment is not a power of 2}} template T *atest4() __attribute__((assume_aligned(32, o))); @@ -78,7 +78,7 @@ }; template -void *atest5() __attribute__((assume_aligned(X::x))); // expected-error {{requested alignment is not a power of 2}} +void *atest5() __attribute__((assume_aligned(X::x))); // expected-warning {{requested alignment is not a power of 2}} void test24() { atest5(); atest5(); diff --git a/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp b/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp --- a/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp +++ b/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp @@ -32,7 +32,7 @@ void *ptr_variable(int align) { return new (std::align_val_t(align)) A; } void *ptr_align16() { return new (std::align_val_t(16)) A; } -void *ptr_align15() { return new (std::align_val_t(15)) A; } // expected-error {{requested alignment is not a power of 2}} +void *ptr_align15() { return new (std::align_val_t(15)) A; } // expected-warning {{requested alignment is not a power of 2}} struct alignas(128) S { S() {} @@ -49,7 +49,7 @@ return new (std::align_val_t(256)) S; } void *alloc_overaligned_struct_with_extra_255_alignment(int align) { - return new (std::align_val_t(255)) S; // expected-error {{requested alignment is not a power of 2}} + return new (std::align_val_t(255)) S; // expected-warning {{requested alignment is not a power of 2}} } std::align_val_t align_variable(int align) { return std::align_val_t(align); } diff --git a/clang/test/SemaTemplate/attributes.cpp b/clang/test/SemaTemplate/attributes.cpp --- a/clang/test/SemaTemplate/attributes.cpp +++ b/clang/test/SemaTemplate/attributes.cpp @@ -4,7 +4,7 @@ namespace attribute_aligned { template struct X { - char c[1] __attribute__((__aligned__((N)))); // expected-error {{alignment is not a power of 2}} + char c[1] __attribute__((__aligned__((N)))); // expected-warning {{alignment is not a power of 2}} }; template struct check { @@ -25,7 +25,7 @@ { __attribute__((aligned(Align))) char storage[Size]; }; - + template class C { public: @@ -33,11 +33,11 @@ static_assert(sizeof(t) == sizeof(T), "my_aligned_storage size wrong"); static_assert(alignof(t) == alignof(T), "my_aligned_storage align wrong"); // expected-warning{{'alignof' applied to an expression is a GNU extension}} } - + private: my_aligned_storage t; }; - + C cd; }