forked from OSchip/llvm-project
Refactor some attributes to use checkFunctionOrMethodArgumentIndex instead of using custom logic. No functional changes intended.
llvm-svn: 187398
This commit is contained in:
parent
e2e0548d77
commit
be50eb86e6
|
@ -251,13 +251,15 @@ static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,
|
|||
const Expr *IdxExpr,
|
||||
uint64_t &Idx)
|
||||
{
|
||||
assert(isFunctionOrMethod(D) && hasFunctionProto(D));
|
||||
assert(isFunctionOrMethod(D));
|
||||
|
||||
// In C++ the implicit 'this' function parameter also counts.
|
||||
// Parameters are counted from one.
|
||||
const bool HasImplicitThisParam = isInstanceMethod(D);
|
||||
const unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
|
||||
const unsigned FirstIdx = 1;
|
||||
bool HP = hasFunctionProto(D);
|
||||
bool HasImplicitThisParam = isInstanceMethod(D);
|
||||
bool IV = HP && isFunctionOrMethodVariadic(D);
|
||||
unsigned NumArgs = (HP ? getFunctionOrMethodNumArgs(D) : 0) +
|
||||
HasImplicitThisParam;
|
||||
|
||||
llvm::APSInt IdxInt;
|
||||
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
|
||||
|
@ -269,7 +271,7 @@ static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,
|
|||
}
|
||||
|
||||
Idx = IdxInt.getLimitedValue();
|
||||
if (Idx < FirstIdx || (!isFunctionOrMethodVariadic(D) && Idx > NumArgs)) {
|
||||
if (Idx < 1 || (!IV && Idx > NumArgs)) {
|
||||
S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds)
|
||||
<< AttrName << AttrArgNum << IdxExpr->getSourceRange();
|
||||
return false;
|
||||
|
@ -1163,70 +1165,35 @@ static void possibleTransparentUnionPointerType(QualType &T) {
|
|||
static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
||||
if (!isFunctionOrMethod(D)) {
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
|
||||
<< "alloc_size" << ExpectedFunctionOrMethod;
|
||||
<< Attr.getName() << ExpectedFunctionOrMethod;
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
if (hasFunctionProto(D))
|
||||
NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;
|
||||
else
|
||||
NumArgs = 0;
|
||||
|
||||
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();
|
||||
for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
|
||||
Expr *Ex = Attr.getArg(i);
|
||||
uint64_t Idx;
|
||||
if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
|
||||
Attr.getLoc(), i + 1, Ex, Idx))
|
||||
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();
|
||||
QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();
|
||||
if (!T->isIntegerType()) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
|
||||
<< "alloc_size" << Ex->getSourceRange();
|
||||
<< "alloc_size" << Ex->getSourceRange();
|
||||
return;
|
||||
}
|
||||
|
||||
SizeArgs.push_back(x);
|
||||
SizeArgs.push_back(Idx);
|
||||
}
|
||||
|
||||
// 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();
|
||||
<< Attr.getName() << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange();
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.Context)
|
||||
|
@ -1244,47 +1211,16 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
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;
|
||||
|
||||
// The nonnull attribute only applies to pointers.
|
||||
SmallVector<unsigned, 10> NonNullArgs;
|
||||
|
||||
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(32);
|
||||
if (Ex->isTypeDependent() || Ex->isValueDependent() ||
|
||||
!Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
|
||||
<< "nonnull" << Ex->getSourceRange();
|
||||
SmallVector<unsigned, 8> NonNullArgs;
|
||||
for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
|
||||
Expr *Ex = Attr.getArg(i);
|
||||
uint64_t Idx;
|
||||
if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
|
||||
Attr.getLoc(), i + 1, Ex, Idx))
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned x = (unsigned) ArgNum.getZExtValue();
|
||||
|
||||
if (x < 1 || x > NumArgs) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
|
||||
<< "nonnull" << I.getArgNum() << Ex->getSourceRange();
|
||||
return;
|
||||
}
|
||||
|
||||
--x;
|
||||
if (HasImplicitThisParam) {
|
||||
if (x == 0) {
|
||||
S.Diag(Attr.getLoc(),
|
||||
diag::err_attribute_invalid_implicit_this_argument)
|
||||
<< "nonnull" << Ex->getSourceRange();
|
||||
return;
|
||||
}
|
||||
--x;
|
||||
}
|
||||
|
||||
// Is the function argument a pointer type?
|
||||
QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType();
|
||||
QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();
|
||||
possibleTransparentUnionPointerType(T);
|
||||
|
||||
if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
|
||||
|
@ -1294,7 +1230,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
continue;
|
||||
}
|
||||
|
||||
NonNullArgs.push_back(x);
|
||||
NonNullArgs.push_back(Idx);
|
||||
}
|
||||
|
||||
// If no arguments were specified to __attribute__((nonnull)) then all pointer
|
||||
|
@ -1378,59 +1314,32 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
|
|||
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;
|
||||
|
||||
StringRef Module = AL.getParameterName()->getName();
|
||||
|
||||
// Normalize the argument, __foo__ becomes foo.
|
||||
if (Module.startswith("__") && Module.endswith("__"))
|
||||
Module = Module.substr(2, Module.size() - 4);
|
||||
|
||||
SmallVector<unsigned, 10> OwnershipArgs;
|
||||
|
||||
for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E;
|
||||
++I) {
|
||||
|
||||
Expr *IdxExpr = *I;
|
||||
llvm::APSInt ArgNum(32);
|
||||
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
|
||||
|| !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
|
||||
S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int)
|
||||
<< AL.getName()->getName() << IdxExpr->getSourceRange();
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned x = (unsigned) ArgNum.getZExtValue();
|
||||
|
||||
if (x > NumArgs || x < 1) {
|
||||
S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
|
||||
<< AL.getName()->getName() << x << IdxExpr->getSourceRange();
|
||||
continue;
|
||||
}
|
||||
--x;
|
||||
if (HasImplicitThisParam) {
|
||||
if (x == 0) {
|
||||
S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
|
||||
<< "ownership" << IdxExpr->getSourceRange();
|
||||
return;
|
||||
}
|
||||
--x;
|
||||
}
|
||||
SmallVector<unsigned, 8> OwnershipArgs;
|
||||
for (unsigned i = 0; i < AL.getNumArgs(); ++i) {
|
||||
Expr *Ex = AL.getArg(i);
|
||||
uint64_t Idx;
|
||||
if (!checkFunctionOrMethodArgumentIndex(S, D, AL.getName()->getName(),
|
||||
AL.getLoc(), i + 1, Ex, Idx))
|
||||
return;
|
||||
|
||||
switch (K) {
|
||||
case OwnershipAttr::Takes:
|
||||
case OwnershipAttr::Holds: {
|
||||
// Is the function argument a pointer type?
|
||||
QualType T = getFunctionOrMethodArgType(D, x);
|
||||
QualType T = getFunctionOrMethodArgType(D, Idx);
|
||||
if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
|
||||
// FIXME: Should also highlight argument in decl.
|
||||
S.Diag(AL.getLoc(), diag::err_ownership_type)
|
||||
<< ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
|
||||
<< "pointer"
|
||||
<< IdxExpr->getSourceRange();
|
||||
<< Ex->getSourceRange();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
@ -1460,14 +1369,14 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {
|
|||
if ((*i)->getOwnKind() != K) {
|
||||
for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
|
||||
I!=E; ++I) {
|
||||
if (x == *I) {
|
||||
if (Idx == *I) {
|
||||
S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
|
||||
<< AL.getName()->getName() << "ownership_*";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OwnershipArgs.push_back(x);
|
||||
OwnershipArgs.push_back(Idx);
|
||||
}
|
||||
|
||||
unsigned* start = OwnershipArgs.data();
|
||||
|
@ -3043,39 +2952,11 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
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;
|
||||
unsigned FirstIdx = 1;
|
||||
|
||||
// checks for the 2nd argument
|
||||
Expr *IdxExpr = Attr.getArg(0);
|
||||
llvm::APSInt Idx(32);
|
||||
if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||
|
||||
!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
|
||||
<< Attr.getName() << 2 << ArgumentIntegerConstant
|
||||
<< IdxExpr->getSourceRange();
|
||||
uint64_t ArgIdx;
|
||||
if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
|
||||
Attr.getLoc(), 1, IdxExpr, ArgIdx))
|
||||
return;
|
||||
}
|
||||
|
||||
if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
|
||||
<< "format" << 2 << IdxExpr->getSourceRange();
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned ArgIdx = Idx.getZExtValue() - 1;
|
||||
|
||||
if (HasImplicitThisParam) {
|
||||
if (ArgIdx == 0) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument)
|
||||
<< "format_arg" << IdxExpr->getSourceRange();
|
||||
return;
|
||||
}
|
||||
ArgIdx--;
|
||||
}
|
||||
|
||||
// make sure the format string is really a string
|
||||
QualType Ty = getFunctionOrMethodArgType(D, ArgIdx);
|
||||
|
@ -3103,8 +2984,14 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {
|
|||
return;
|
||||
}
|
||||
|
||||
// We cannot use the ArgIdx returned from checkFunctionOrMethodArgumentIndex
|
||||
// because that has corrected for the implicit this parameter, and is zero-
|
||||
// based. The attribute expects what the user wrote explicitly.
|
||||
llvm::APSInt Val;
|
||||
IdxExpr->EvaluateAsInt(Val, S.Context);
|
||||
|
||||
D->addAttr(::new (S.Context)
|
||||
FormatArgAttr(Attr.getRange(), S.Context, Idx.getZExtValue(),
|
||||
FormatArgAttr(Attr.getRange(), S.Context, Val.getZExtValue(),
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ 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* fn1(int) __attribute__((alloc_size("xpto"))); // expected-error{{'alloc_size' attribute requires parameter 1 to be an integer constant}}
|
||||
|
||||
void* fn2(void*) __attribute__((alloc_size(1))); // expected-error{{attribute requires integer constant}}
|
||||
|
||||
|
|
|
@ -78,3 +78,5 @@ extern void gcc_cxxformat (const char *, ...)
|
|||
__attribute__ ((__format__(__gcc_cxxdiag__, 1, 2)));
|
||||
extern void gcc_tformat (const char *, ...)
|
||||
__attribute__ ((__format__(__gcc_tdiag__, 1, 2)));
|
||||
|
||||
const char *foo3(const char *format) __attribute__((format_arg("foo"))); // expected-error{{'format_arg' attribute requires parameter 1 to be an integer constant}}
|
||||
|
|
|
@ -19,3 +19,4 @@ int main(void) {
|
|||
Class_init(obj, "Hello World");
|
||||
}
|
||||
|
||||
void foo(const char *str) __attribute__((nonnull("foo"))); // expected-error{{'nonnull' attribute requires parameter 1 to be an integer constant}}
|
||||
|
|
Loading…
Reference in New Issue