Look for and diagnose missing sentinel argument on message
dispatch arguments which have sentinel attribute.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71737 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 4d054fb..7606e84 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -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) {
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f1da408..a1c170c 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -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 {