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 @@ -3653,6 +3653,27 @@ } } + if (FDecl && FDecl->hasAttr()) { + auto *AA = FDecl->getAttr(); + const Expr *Arg = Args[AA->getParamIndex().getASTIndex()]; + 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) + << Arg->getSourceRange(); + return; + } + + // Alignment calculations can wrap around if it's greater than 2**29. + unsigned MaximumAlignment = 536870912; + if (I > MaximumAlignment) + Diag(Arg->getExprLoc(), diag::warn_assume_aligned_too_great) + << Arg->getSourceRange() << MaximumAlignment; + } + } + } + if (FD) diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc); } 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 @@ -17,3 +17,15 @@ void *test_no_fn_proto(int x, int y) __attribute__((alloc_align())); // expected-error {{'alloc_align' attribute takes one argument}} void *test_no_fn_proto(int x, int y) __attribute__((alloc_align(32, 45, 37))); // expected-error {{'alloc_align' attribute takes one argument}} +void *passthrought(int a) { + return test_ptr_alloc_align(a); +} +void *align16() { + return test_ptr_alloc_align(16); +} +void *align15() { + return test_ptr_alloc_align(15); // expected-error {{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/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 @@ -23,13 +23,19 @@ template void* illegal_align_param(int p) __attribute__((alloc_align(T))); // expected-error {{'alloc_align' attribute requires parameter 1 to be an integer constant}} -void dependent_impl() { +void dependent_impl(int align) { dependent_ret a; // expected-note {{in instantiation of template class 'dependent_ret' requested here}} a.Foo(1); a.Foo2(1); - dependent_ret b; - a.Foo(1); - a.Foo2(1); + 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(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 c; c.Foo(1);