forked from OSchip/llvm-project
implement Sema support for the alloc_size attribute
Portions of this patch by Xi Wang. Reviewed by Jordy Rose. Thank you both. Codegen support will follow soon. llvm-svn: 157360
This commit is contained in:
parent
9b43c3f0c5
commit
5c7ad16fdd
|
@ -144,6 +144,11 @@ def AlignMac68k : InheritableAttr {
|
|||
let SemaHandler = 0;
|
||||
}
|
||||
|
||||
def AllocSize : Attr {
|
||||
let Spellings = ["alloc_size"];
|
||||
let Args = [VariadicUnsignedArgument<"Args">];
|
||||
}
|
||||
|
||||
def AlwaysInline : InheritableAttr {
|
||||
let Spellings = ["always_inline"];
|
||||
}
|
||||
|
|
|
@ -1483,6 +1483,8 @@ def err_attribute_argument_outof_range : Error<
|
|||
def err_init_priority_object_attr : Error<
|
||||
"can only use 'init_priority' attribute on file-scope definitions "
|
||||
"of objects of class type">;
|
||||
def err_attribute_argument_duplicate: Error<
|
||||
"'%0' attribute parameter %1 is duplicated">;
|
||||
def err_attribute_argument_n_not_int : Error<
|
||||
"'%0' attribute requires parameter %1 to be an integer constant">;
|
||||
def err_attribute_argument_n_not_string : Error<
|
||||
|
|
|
@ -922,6 +922,81 @@ static void possibleTransparentUnionPointerType(QualType &T) {
|
|||
}
|
||||
}
|
||||
|
||||
static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
|
||||
return;
|
||||
|
||||
// In C++ the implicit 'this' function parameter also counts, and they are
|
||||
// counted from one.
|
||||
bool HasImplicitThisParam = isInstanceMethod(D);
|
||||
unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
|
||||
|
||||
SmallVector<unsigned, 8> SizeArgs;
|
||||
|
||||
for (AttributeList::arg_iterator I = Attr.arg_begin(),
|
||||
E = Attr.arg_end(); I!=E; ++I) {
|
||||
// The argument must be an integer constant expression.
|
||||
Expr *Ex = *I;
|
||||
llvm::APSInt ArgNum;
|
||||
if (Ex->isTypeDependent() || Ex->isValueDependent() ||
|
||||
!Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
|
||||
<< "alloc_size" << Ex->getSourceRange();
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t x = ArgNum.getZExtValue();
|
||||
|
||||
if (x < 1 || x > NumArgs) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
|
||||
<< "alloc_size" << I.getArgNum() << Ex->getSourceRange();
|
||||
return;
|
||||
}
|
||||
|
||||
--x;
|
||||
if (HasImplicitThisParam) {
|
||||
if (x == 0) {
|
||||
S.Diag(Attr.getLoc(),
|
||||
diag::err_attribute_invalid_implicit_this_argument)
|
||||
<< "alloc_size" << Ex->getSourceRange();
|
||||
return;
|
||||
}
|
||||
--x;
|
||||
}
|
||||
|
||||
// check if the function argument is of an integer type
|
||||
QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType();
|
||||
if (!T->isIntegerType()) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
|
||||
<< "alloc_size" << Ex->getSourceRange();
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the argument is a duplicate
|
||||
SmallVectorImpl<unsigned>::iterator Pos;
|
||||
Pos = std::find(SizeArgs.begin(), SizeArgs.end(), x);
|
||||
if (Pos != SizeArgs.end()) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_duplicate)
|
||||
<< "alloc_size" << I.getArgNum() << Ex->getSourceRange();
|
||||
return;
|
||||
}
|
||||
|
||||
SizeArgs.push_back(x);
|
||||
}
|
||||
|
||||
// check if the function returns a pointer
|
||||
if (!getFunctionType(D)->getResultType()->isAnyPointerType()) {
|
||||
S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type)
|
||||
<< "alloc_size" << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange();
|
||||
}
|
||||
|
||||
unsigned size = SizeArgs.size();
|
||||
unsigned* start = &SizeArgs[0];
|
||||
llvm::array_pod_sort(start, start + size);
|
||||
D->addAttr(::new (S.Context) AllocSizeAttr(Attr.getRange(), S.Context, start,
|
||||
size));
|
||||
}
|
||||
|
||||
static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||
// GCC ignores the nonnull attribute on K&R style function prototypes, so we
|
||||
// ignore it as well
|
||||
|
@ -3844,6 +3919,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
|
|||
break;
|
||||
case AttributeList::AT_alias: handleAliasAttr (S, D, Attr); break;
|
||||
case AttributeList::AT_aligned: handleAlignedAttr (S, D, Attr); break;
|
||||
case AttributeList::AT_alloc_size: handleAllocSizeAttr (S, D, Attr); break;
|
||||
case AttributeList::AT_always_inline:
|
||||
handleAlwaysInlineAttr (S, D, Attr); break;
|
||||
case AttributeList::AT_analyzer_noreturn:
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
void* my_malloc(unsigned char) __attribute__((alloc_size(1)));
|
||||
void* my_calloc(unsigned char, short) __attribute__((alloc_size(1,2)));
|
||||
void* my_realloc(void*, unsigned) __attribute__((alloc_size(2)));
|
||||
|
||||
|
||||
void* fn1(int) __attribute__((alloc_size("xpto"))); // expected-error{{attribute requires integer constant}}
|
||||
|
||||
void* fn2(void*) __attribute__((alloc_size(1))); // expected-error{{attribute requires integer constant}}
|
||||
|
||||
void* fn3(unsigned) __attribute__((alloc_size(0))); // expected-error{{attribute parameter 1 is out of bounds}}
|
||||
void* fn4(unsigned) __attribute__((alloc_size(2))); // expected-error{{attribute parameter 1 is out of bounds}}
|
||||
|
||||
void fn5(unsigned) __attribute__((alloc_size(1))); // expected-warning{{only applies to functions that return a pointer}}
|
||||
char fn6(unsigned) __attribute__((alloc_size(1))); // expected-warning{{only applies to functions that return a pointer}}
|
||||
|
||||
void* fn7(unsigned) __attribute__((alloc_size)); // expected-error {{attribute takes at least 1 argument}}
|
||||
|
||||
void *fn8(int, int) __attribute__((alloc_size(1, 1))); // expected-error {{attribute parameter 2 is duplicated}}
|
||||
|
||||
void* fn9(unsigned) __attribute__((alloc_size(12345678901234567890123))); // expected-warning {{integer constant is too large for its type}} // expected-error {{attribute parameter 1 is out of bounds}}
|
Loading…
Reference in New Issue