From: Fariborz Jahanian Date: Thu, 14 May 2009 20:53:39 +0000 (+0000) Subject: Adds recognition of sentinel attribute on block declarations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2f7c39246a968b921a6d95c7f8037fb3429e9501;p=clang Adds recognition of sentinel attribute on block declarations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71788 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 768690aa56..514f94798e 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -440,7 +440,8 @@ def warn_attribute_weak_import_invalid_on_definition : Warning< "'weak_import' attribute cannot be specified on a definition">; def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{function|union|" - "variable and function|function or method|parameter|parameter or Objective-C method}1 types">; + "variable and function|function or method|parameter|parameter or Objective-C method |" + "function, method or block}1 types">; def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 7606e84d52..7a6a537547 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -719,10 +719,32 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!MD->isVariadic()) { S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic); return; - } + } + } else if (isa(d)) { + // Note! BlockDecl is typeless. Variadic diagnostics + // will be issued by the caller. + ; + } else if (const VarDecl *V = dyn_cast(d)) { + // FIXME: share code with case of BlockDecl. + QualType Ty = V->getType(); + if (Ty->isBlockPointerType()) { + const BlockPointerType *BPT = Ty->getAsBlockPointerType(); + QualType FnType = BPT->getPointeeType(); + const FunctionType *FT = FnType->getAsFunctionType(); + assert(FT && "Block has non-function type?"); + if (!cast(FT)->isVariadic()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic); + return; + } + } + else { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 6 /*function, method or */; + return; + } } else { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 3 /*function or method*/; + << Attr.getName() << 6 /*function, method or */; return; } d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos)); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6a7bca0165..2bc7461962 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5038,7 +5038,12 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { CurBlock->hasPrototype = true; CurBlock->isVariadic = false; - + // Check for a valid sentinel attribute on this block. + if (CurBlock->TheDecl->getAttr()) { + Diag(ParamInfo.getAttributes()->getLoc(), + diag::warn_attribute_sentinel_not_variadic); + // FIXME: remove the attribute. + } QualType RetTy = T.getTypePtr()->getAsFunctionType()->getResultType(); // Do not allow returning a objc interface by-value. @@ -5080,6 +5085,13 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { if ((*AI)->getIdentifier()) PushOnScopeChains(*AI, CurBlock->TheScope); + // Check for a valid sentinel attribute on this block. + if (!CurBlock->isVariadic && CurBlock->TheDecl->getAttr()) { + Diag(ParamInfo.getAttributes()->getLoc(), + diag::warn_attribute_sentinel_not_variadic); + // FIXME: remove the attribute. + } + // Analyze the return type. QualType T = GetTypeForDeclarator(ParamInfo, CurScope); QualType RetTy = T->getAsFunctionType()->getResultType(); diff --git a/test/Sema/sentinel-attribute.c b/test/Sema/sentinel-attribute.c index e9451b81bc..c40f8df29c 100644 --- a/test/Sema/sentinel-attribute.c +++ b/test/Sema/sentinel-attribute.c @@ -1,5 +1,5 @@ // RUN: clang-cc -fsyntax-only -verify %s -int x __attribute__((sentinel)); //expected-warning{{'sentinel' attribute only applies to function or method types}} +int x __attribute__((sentinel)); //expected-warning{{'sentinel' attribute only applies to function, method or block types}} void f1(int a, ...) __attribute__ ((sentinel)); void f2(int a, ...) __attribute__ ((sentinel(1)));