From f78c4e57122dad4430329135b966dfc241a6425b Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 30 Jul 2011 08:57:03 +0000 Subject: [PATCH] Introduce a Fix-It for the "missing sentinel" warning, adding an appropriate sentinel at the end of the argument list. Also, put the sentinel warnings under -Wsentinel. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136566 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 1 + include/clang/Basic/DiagnosticSemaKinds.td | 6 ++++-- lib/Sema/SemaExpr.cpp | 21 ++++++++++++++++----- test/FixIt/fixit-objc.m | 14 ++++++++++++++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index af31baf627..c4ba82aab6 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -109,6 +109,7 @@ def ReturnType : DiagGroup<"return-type">; def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy">; def SelfAssignment : DiagGroup<"self-assign">; def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; +def Sentinel : DiagGroup<"sentinel">; def MissingMethodReturnType : DiagGroup<"missing-method-return-type">; def : DiagGroup<"sequence-point">; def Shadow : DiagGroup<"shadow">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4f776c42c6..cd27636fca 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2299,9 +2299,11 @@ def note_unavailable_here : Note< "%select{declaration|function}0 has been explicitly marked " "%select{unavailable|deleted|deprecated}1 here">; def warn_not_enough_argument : Warning< - "not enough variable arguments in %0 declaration to fit a sentinel">; + "not enough variable arguments in %0 declaration to fit a sentinel">, + InGroup; def warn_missing_sentinel : Warning < - "missing sentinel in %select{function call|method dispatch|block call}0">; + "missing sentinel in %select{function call|method dispatch|block call}0">, + InGroup; def note_sentinel_here : Note< "%select{function|method|block}0 has been explicitly marked sentinel here">; def warn_missing_prototype : Warning< diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 966fcbffcf..43e3807e21 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -156,13 +156,9 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, if (!attr) return; - // FIXME: In C++0x, if any of the arguments are parameter pack - // expansions, we can't check for the sentinel now. int sentinelPos = attr->getSentinel(); int nullPos = attr->getNullPos(); - // FIXME. ObjCMethodDecl and FunctionDecl need be derived from the same common - // base class. Then we won't be needing two versions of the same code. unsigned int i = 0; bool warnNotEnoughArgs = false; int isMethod = 0; @@ -247,7 +243,22 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, // Unfortunately, __null has type 'int'. if (isa(sentinelExpr)) return; - Diag(Loc, diag::warn_missing_sentinel) << isMethod; + SourceLocation MissingNilLoc + = PP.getLocForEndOfToken(sentinelExpr->getLocEnd()); + std::string NullValue; + if (isMethod && PP.getIdentifierInfo("nil")->hasMacroDefinition()) + NullValue = "nil"; + else if (PP.getIdentifierInfo("NULL")->hasMacroDefinition()) + NullValue = "NULL"; + else if (Context.getTypeSize(Context.IntTy) + == Context.getTypeSize(Context.getSizeType())) + NullValue = "0"; + else + NullValue = "0L"; + + Diag(MissingNilLoc, diag::warn_missing_sentinel) + << isMethod + << FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue); Diag(D->getLocation(), diag::note_sentinel_here) << isMethod; } diff --git a/test/FixIt/fixit-objc.m b/test/FixIt/fixit-objc.m index 2e8bfaea6a..df591c7922 100644 --- a/test/FixIt/fixit-objc.m +++ b/test/FixIt/fixit-objc.m @@ -53,3 +53,17 @@ int f0(Radar7861841 *a) { return a.x; } // expected-error {{property 'x' not fou int f1(Radar7861841 *a) { return a->y; } // expected-error {{property 'y' found on object of type 'Radar7861841 *'; did you mean to access it with the "." operator?}} + +#define nil ((void*)0) +#define NULL ((void*)0) + +void sentinel(int x, ...) __attribute__((sentinel)); // expected-note{{function has been explicitly marked sentinel here}} + +@interface Sentinel +- (void)sentinel:(int)x, ... __attribute__((sentinel)); // expected-note{{method has been explicitly marked sentinel here}} +@end + +void sentinel_test(Sentinel *a) { + sentinel(1, 2, 3); // expected-warning{{missing sentinel in function call}} + [a sentinel:1, 2, 3]; // expected-warning{{missing sentinel in method dispatch}} +} -- 2.40.0