aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclAttr.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-05-15 23:15:03 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-05-15 23:15:03 +0000
commit620d89ca4eb5dcb6be13a42aafa4849eaa9b834b (patch)
tree5fcc2a29de581cdf8fd8899222d513119e97a280 /lib/Sema/SemaDeclAttr.cpp
parentffce2df6ae280d354d51371282a579df1eb86876 (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.cpp36
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;