diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-05-15 23:15:03 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-05-15 23:15:03 +0000 |
commit | 620d89ca4eb5dcb6be13a42aafa4849eaa9b834b (patch) | |
tree | 5fcc2a29de581cdf8fd8899222d513119e97a280 /lib/Sema/SemaDeclAttr.cpp | |
parent | ffce2df6ae280d354d51371282a579df1eb86876 (diff) |
Early support for __format__attribute on blocks.
Work in progress...
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71908 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 42a177a497..5154c66c6c 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -37,6 +37,8 @@ static const FunctionType *getFunctionType(Decl *d) { if (Ty->isFunctionPointerType()) Ty = Ty->getAsPointerType()->getPointeeType(); + else if (Ty->isBlockPointerType()) + Ty = Ty->getAsBlockPointerType()->getPointeeType(); return Ty->getAsFunctionType(); } @@ -51,13 +53,27 @@ static bool isFunctionOrMethod(Decl *d) { return getFunctionType(d) || isa<ObjCMethodDecl>(d); } +/// isFunctionOrMethodOrBlock - Return true if the given decl has function +/// type (function or function-typed variable) or an Objective-C +/// method or a block. +static bool isFunctionOrMethodOrBlock(Decl *d) { + if (isFunctionOrMethod(d)) + return true; + // check for block is more involved. + if (const VarDecl *V = dyn_cast<VarDecl>(d)) { + QualType Ty = V->getType(); + return Ty->isBlockPointerType(); + } + return false; +} + /// hasFunctionProto - Return true if the given decl has a argument /// information. This decl should have already passed -/// isFunctionOrMethod. +/// isFunctionOrMethod or isFunctionOrMethodOrBlock. static bool hasFunctionProto(Decl *d) { - if (const FunctionType *FnTy = getFunctionType(d)) { + if (const FunctionType *FnTy = getFunctionType(d)) return isa<FunctionProtoType>(FnTy); - } else { + else { assert(isa<ObjCMethodDecl>(d)); return true; } @@ -69,6 +85,17 @@ static bool hasFunctionProto(Decl *d) { static unsigned getFunctionOrMethodNumArgs(Decl *d) { if (const FunctionType *FnTy = getFunctionType(d)) return cast<FunctionProtoType>(FnTy)->getNumArgs(); + else if (VarDecl *V = dyn_cast<VarDecl>(d)) { + QualType Ty = V->getType(); + if (Ty->isBlockPointerType()) { + const FunctionType *FT = + Ty->getAsBlockPointerType()->getPointeeType()->getAsFunctionType(); + if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) + return Proto->getNumArgs(); + + } + assert(false && "getFunctionOrMethodNumArgs - caused by block mishap"); + } return cast<ObjCMethodDecl>(d)->param_size(); } @@ -76,6 +103,7 @@ static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) { if (const FunctionType *FnTy = getFunctionType(d)) return cast<FunctionProtoType>(FnTy)->getArgType(Idx); + return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType(); } @@ -1062,7 +1090,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { + if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << 0 /*function*/; return; |