Skip to content

Commit c2a9061

Browse files
committed
[Sema] Attempt to perform call-size-specific __attribute__((alloc_align(param_idx))) validation
Summary: `alloc_align` attribute takes parameter number, not the alignment itself, so given **just** the attribute/function declaration we can't do any sanity checking for said alignment. However, at call site, given the actual `Expr` that is passed into that parameter, we //might// be able to evaluate said `Expr` as Integer Constant Expression, and perform the sanity checks. But since there is no requirement for that argument to be an immediate, we may fail, and that's okay. However if we did evaluate, we should enforce the same constraints as with `__builtin_assume_aligned()`/`__attribute__((assume_aligned(imm)))`: said alignment is a power of two, and is not greater than our magic threshold Reviewers: erichkeane, aaron.ballman, hfinkel, rsmith, jdoerfert Reviewed By: erichkeane Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D72996
1 parent a4cfb15 commit c2a9061

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

clang/lib/Sema/SemaChecking.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3653,6 +3653,27 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
36533653
}
36543654
}
36553655

3656+
if (FDecl && FDecl->hasAttr<AllocAlignAttr>()) {
3657+
auto *AA = FDecl->getAttr<AllocAlignAttr>();
3658+
const Expr *Arg = Args[AA->getParamIndex().getASTIndex()];
3659+
if (!Arg->isValueDependent()) {
3660+
llvm::APSInt I(64);
3661+
if (Arg->isIntegerConstantExpr(I, Context)) {
3662+
if (!I.isPowerOf2()) {
3663+
Diag(Arg->getExprLoc(), diag::err_alignment_not_power_of_two)
3664+
<< Arg->getSourceRange();
3665+
return;
3666+
}
3667+
3668+
// Alignment calculations can wrap around if it's greater than 2**29.
3669+
unsigned MaximumAlignment = 536870912;
3670+
if (I > MaximumAlignment)
3671+
Diag(Arg->getExprLoc(), diag::warn_assume_aligned_too_great)
3672+
<< Arg->getSourceRange() << MaximumAlignment;
3673+
}
3674+
}
3675+
}
3676+
36563677
if (FD)
36573678
diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
36583679
}

clang/test/Sema/alloc-align-attr.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,15 @@ void *test_no_fn_proto(int x, int y) __attribute__((alloc_align)); // expected-e
1717
void *test_no_fn_proto(int x, int y) __attribute__((alloc_align())); // expected-error {{'alloc_align' attribute takes one argument}}
1818
void *test_no_fn_proto(int x, int y) __attribute__((alloc_align(32, 45, 37))); // expected-error {{'alloc_align' attribute takes one argument}}
1919

20+
void *passthrought(int a) {
21+
return test_ptr_alloc_align(a);
22+
}
23+
void *align16() {
24+
return test_ptr_alloc_align(16);
25+
}
26+
void *align15() {
27+
return test_ptr_alloc_align(15); // expected-error {{requested alignment is not a power of 2}}
28+
}
29+
void *align536870912() {
30+
return test_ptr_alloc_align(1073741824); // expected-warning {{requested alignment must be 536870912 bytes or smaller; maximum alignment assumed}}
31+
}

clang/test/SemaCXX/alloc-align-attr.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,19 @@ void* dependent_param_func(T param) __attribute__((alloc_align(1)));// expected-
2323
template <int T>
2424
void* illegal_align_param(int p) __attribute__((alloc_align(T))); // expected-error {{'alloc_align' attribute requires parameter 1 to be an integer constant}}
2525

26-
void dependent_impl() {
26+
void dependent_impl(int align) {
2727
dependent_ret<int> a; // expected-note {{in instantiation of template class 'dependent_ret<int>' requested here}}
2828
a.Foo(1);
2929
a.Foo2(1);
30-
dependent_ret<int*> b;
31-
a.Foo(1);
32-
a.Foo2(1);
30+
dependent_ret<int *> b;
31+
b.Foo(1);
32+
b.Foo2(1);
33+
b.Foo(3); // expected-error {{requested alignment is not a power of 2}}
34+
b.Foo2(3); // expected-error {{requested alignment is not a power of 2}}
35+
b.Foo(1073741824); // expected-warning {{requested alignment must be 536870912 bytes or smaller; maximum alignment assumed}}
36+
b.Foo2(1073741824); // expected-warning {{requested alignment must be 536870912 bytes or smaller; maximum alignment assumed}}
37+
b.Foo(align);
38+
b.Foo2(align);
3339

3440
dependent_param_struct<int> c;
3541
c.Foo(1);

0 commit comments

Comments
 (0)