[cfe-commits] r71737 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaExpr.cpp test/SemaObjC/method-sentinel-attr.m

Fariborz Jahanian fjahanian at apple.com
Wed May 13 16:20:53 PDT 2009


Author: fjahanian
Date: Wed May 13 18:20:50 2009
New Revision: 71737

URL: http://llvm.org/viewvc/llvm-project?rev=71737&view=rev
Log:
Look for and diagnose missing sentinel argument on message
dispatch arguments which have sentinel attribute.

Added:
    cfe/trunk/test/SemaObjC/method-sentinel-attr.m
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=71737&r1=71736&r2=71737&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed May 13 18:20:50 2009
@@ -763,6 +763,12 @@
 def warn_unavailable : Warning<"%0 is unavailable">;
 def note_unavailable_here : Note<
   "function has been explicitly marked %select{unavailable|deleted}0 here">;
+def warn_not_enough_argument : Warning<
+  "not enough variable arguments in %0 declaration to fit a sentinel">;
+def warn_missing_sentinel : Warning <
+  "missing sentinel in method dispatch">;
+def note_sentinel_here : Note<
+  "method has been explicitly marked sentinel here">;
 def warn_missing_prototype : Warning<
   "no previous prototype for function %0">,
   InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=71737&r1=71736&r2=71737&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed May 13 18:20:50 2009
@@ -725,8 +725,7 @@
       << Attr.getName() << 3 /*function or method*/;
     return;
   }
-  
-  // FIXME: Actually create the attribute.
+  d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos));
 }
 
 static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=71737&r1=71736&r2=71737&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed May 13 18:20:50 2009
@@ -95,6 +95,50 @@
 void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
                                  Expr **Args, unsigned NumArgs)
 {
+  const SentinelAttr *attr = D->getAttr<SentinelAttr>();
+  if (!attr) 
+    return;
+  ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
+  // FIXME: function calls for later.
+  if (!MD)
+    return;
+  int sentinelPos = attr->getSentinel();
+  int nullPos = attr->getNullPos();
+  // skip over named parameters.
+  ObjCMethodDecl::param_iterator P, E = MD->param_end();
+  unsigned int i = 0;
+  for (P = MD->param_begin(); (P != E && i < NumArgs); ++P) {
+    if (nullPos)
+      --nullPos;
+    else
+      ++i;
+  }
+  if (P != E || i >= NumArgs) {
+    Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
+    Diag(D->getLocation(), diag::note_sentinel_here);
+    return;
+  }
+  int sentinel = i;
+  while (sentinelPos > 0 && i < NumArgs-1) {
+    --sentinelPos;
+    ++i;
+  }
+  if (sentinelPos > 0) {
+    Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
+    Diag(D->getLocation(), diag::note_sentinel_here);
+    return;
+  }
+  while (i < NumArgs-1) {
+    ++i;
+    ++sentinel;
+  }
+  Expr *sentinelExpr = Args[sentinel];
+  if (sentinelExpr && (!sentinelExpr->getType()->isPointerType() ||
+                       !sentinelExpr->isNullPointerConstant(Context))) {
+    Diag(Loc, diag::warn_missing_sentinel);
+    Diag(D->getLocation(), diag::note_sentinel_here);
+  }
+  return;
 }
 
 SourceRange Sema::getExprRange(ExprTy *E) const {

Added: cfe/trunk/test/SemaObjC/method-sentinel-attr.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/method-sentinel-attr.m?rev=71737&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/method-sentinel-attr.m (added)
+++ cfe/trunk/test/SemaObjC/method-sentinel-attr.m Wed May 13 18:20:50 2009
@@ -0,0 +1,37 @@
+// RUN: clang-cc  -fsyntax-only -verify %s
+
+#define NULL (void*)0
+
+#define ATTR __attribute__ ((__sentinel__)) 
+
+ at interface INTF
+- (void) foo1 : (int)x, ... ATTR; // expected-note {{method has been explicitly marked sentinel here}}
+- (void) foo3 : (int)x __attribute__ ((__sentinel__)) ; // expected-warning {{'sentinel' attribute only supported for variadic functions}}
+- (void) foo5 : (int)x, ... __attribute__ ((__sentinel__(1))); // expected-note {{method has been explicitly marked sentinel here}}
+- (void) foo6 : (int)x, ... __attribute__ ((__sentinel__(5))); // expected-note {{method has been explicitly marked sentinel here}}
+- (void) foo7 : (int)x, ... __attribute__ ((__sentinel__(0))); // expected-note {{method has been explicitly marked sentinel here}}
+- (void) foo8 : (int)x, ... __attribute__ ((__sentinel__("a")));  // expected-error {{'sentinel' attribute requires parameter 1 to be an integer constant}}
+- (void) foo9 : (int)x, ... __attribute__ ((__sentinel__(-1)));  // expected-error {{'sentinel' parameter 1 less than zero}}
+- (void) foo10 : (int)x, ... __attribute__ ((__sentinel__(1,1)));
+- (void) foo11 : (int)x, ... __attribute__ ((__sentinel__(1,1,3)));  // expected-error {{attribute requires 0, 1 or 2 argument(s)}}
+- (void) foo12 : (int)x, ... ATTR; // expected-note {{method has been explicitly marked sentinel here}}
+ at end
+
+int main ()
+{
+  INTF *p;
+
+  [p foo1:1, NULL]; // OK
+  [p foo1:1, 0];  // expected-warning {{missing sentinel in method dispatch}}
+  [p foo5:1, NULL, 2]; // OK
+  [p foo5:1, 2, NULL, 1]; // OK
+  [p foo5:1, NULL, 2, 1];  // expected-warning {{missing sentinel in method dispatch}}
+
+  [p foo6:1,2,3,4,5,6,7];  // expected-warning {{missing sentinel in method dispatch}}
+  [p foo6:1,NULL,3,4,5,6,7]; // OK
+  [p foo7:1];	 // expected-warning {{not enough variable arguments in 'foo7:' declaration to fit a sentinel}}
+  [p foo7:1, NULL]; // ok
+
+  [p foo12:1]; // expected-warning {{not enough variable arguments in 'foo12:' declaration to fit a sentinel}}
+}
+ 





More information about the cfe-commits mailing list