forked from OSchip/llvm-project
Add parsing of the sentinel attribute. Still need to create the attribute.
llvm-svn: 57121
This commit is contained in:
parent
d27a0c2395
commit
c181b01681
|
@ -733,6 +733,12 @@ DIAG(warn_attribute_nonnull_no_pointers, WARNING,
|
|||
DIAG(warn_transparent_union_nonpointer, WARNING,
|
||||
"'transparent_union' attribute support incomplete; only supported for"
|
||||
"pointer unions")
|
||||
DIAG(warn_attribute_sentinel_not_variadic, WARNING,
|
||||
"'sentinel' attribute only supported for variadic functions")
|
||||
DIAG(err_attribute_sentinel_less_than_zero, ERROR,
|
||||
"'sentinel' parameter 1 less than zero")
|
||||
DIAG(err_attribute_sentinel_not_zero_or_one, ERROR,
|
||||
"'sentinel' parameter 2 not 0 or 1")
|
||||
|
||||
// Clang-Specific Attributes
|
||||
DIAG(err_attribute_iboutlet_non_ivar, ERROR,
|
||||
|
|
|
@ -72,6 +72,7 @@ public:
|
|||
AT_weak,
|
||||
AT_objc_gc,
|
||||
AT_blocks,
|
||||
AT_sentinel,
|
||||
UnknownAttribute
|
||||
};
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
|
|||
if (!memcmp(Str, "noinline", 8)) return AT_noinline;
|
||||
if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
|
||||
if (!memcmp(Str, "iboutlet", 8)) return AT_IBOutlet;
|
||||
if (!memcmp(Str, "sentinel", 8)) return AT_sentinel;
|
||||
break;
|
||||
case 9:
|
||||
if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
|
||||
|
|
|
@ -586,6 +586,71 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
d->addAttr(new BlocksAttr(type));
|
||||
}
|
||||
|
||||
static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||
// check the attribute arguments.
|
||||
if (Attr.getNumArgs() > 2) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments, "0, 1 or 2");
|
||||
return;
|
||||
}
|
||||
|
||||
int sentinel = 0;
|
||||
if (Attr.getNumArgs() > 0) {
|
||||
Expr *E = static_cast<Expr *>(Attr.getArg(0));
|
||||
llvm::APSInt Idx(32);
|
||||
if (!E->isIntegerConstantExpr(Idx, S.Context)) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
|
||||
"sentinel", "1", E->getSourceRange());
|
||||
return;
|
||||
}
|
||||
sentinel = Idx.getZExtValue();
|
||||
|
||||
if (sentinel < 0) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero,
|
||||
E->getSourceRange());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int nullPos = 0;
|
||||
if (Attr.getNumArgs() > 1) {
|
||||
Expr *E = static_cast<Expr *>(Attr.getArg(1));
|
||||
llvm::APSInt Idx(32);
|
||||
if (!E->isIntegerConstantExpr(Idx, S.Context)) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
|
||||
"sentinel", "2", E->getSourceRange());
|
||||
return;
|
||||
}
|
||||
nullPos = Idx.getZExtValue();
|
||||
|
||||
if (nullPos > 1 || nullPos < 0) {
|
||||
// FIXME: This error message could be improved, it would be nice
|
||||
// to say what the bounds actually are.
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one,
|
||||
E->getSourceRange());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
|
||||
QualType FT = FD->getType();
|
||||
if (!FT->getAsFunctionTypeProto()->isVariadic()) {
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic);
|
||||
return;
|
||||
}
|
||||
} else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) {
|
||||
if (!MD->isVariadic()) {
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
|
||||
"sentinel", "function or method");
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Actually create the attribute.
|
||||
}
|
||||
|
||||
static void HandleWeakAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||
// check the attribute arguments.
|
||||
if (Attr.getNumArgs() != 0) {
|
||||
|
@ -1052,6 +1117,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
|
|||
break;
|
||||
case AttributeList::AT_objc_gc: HandleObjCGCAttr (D, Attr, S); break;
|
||||
case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break;
|
||||
case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break;
|
||||
default:
|
||||
#if 0
|
||||
// TODO: when we have the full set of attributes, warn about unknown ones.
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
int x __attribute__((sentinel)); //expected-warning{{'sentinel' attribute only applies to function or method types}}
|
||||
|
||||
void f1(int a, ...) __attribute__ ((sentinel));
|
||||
void f2(int a, ...) __attribute__ ((sentinel(1)));
|
||||
|
||||
void f3(int a, ...) __attribute__ ((sentinel("hello"))); //expected-error{{'sentinel' attribute requires parameter 1 to be an integer constant}}
|
||||
void f4(int a, ...) __attribute__ ((sentinel(1, 2, 3))); //expected-error{{attribute requires 0, 1 or 2 argument(s)}}
|
||||
void f4(int a, ...) __attribute__ ((sentinel(-1))); //expected-error{{parameter 1 less than zero}}
|
||||
void f4(int a, ...) __attribute__ ((sentinel(0, 2))); // expected-error{{parameter 2 not 0 or 1}}
|
||||
|
||||
void f5(int a) __attribute__ ((sentinel)); //expected-warning{{'sentinel' attribute only supported for variadic functions}}
|
||||
|
Loading…
Reference in New Issue