aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2008-10-05 18:05:59 +0000
committerAnders Carlsson <andersca@mac.com>2008-10-05 18:05:59 +0000
commit770918281c5bdc7b5b3942285c407e3d62270053 (patch)
tree8098d6fb2d8b845d738df9bc8655df11e3502c0d /lib
parent9a9683b585696119ea8f57598634f647468f41aa (diff)
Add parsing of the sentinel attribute. Still need to create the attribute.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57121 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Parse/AttributeList.cpp1
-rw-r--r--lib/Sema/SemaDeclAttr.cpp66
2 files changed, 67 insertions, 0 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index b39dbe8c01..825570dce2 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -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;
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 2bdb885f53..fd79a10bf4 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -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.