forked from OSchip/llvm-project
Added parsing/sema support for __attribute__ ((IBOutlet)), a clang-specific attribute that the static analyzer will use to recognize what ivars are IBOutlets.
llvm-svn: 53644
This commit is contained in:
parent
3879c5f6e4
commit
8e3704d35a
|
@ -37,7 +37,9 @@ public:
|
||||||
Visibility,
|
Visibility,
|
||||||
FastCall,
|
FastCall,
|
||||||
StdCall,
|
StdCall,
|
||||||
TransparentUnion
|
TransparentUnion,
|
||||||
|
IBOutletKind // Clang-specific. Use "Kind" suffix to not conflict with
|
||||||
|
// the IBOutlet macro.
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -120,6 +122,17 @@ public:
|
||||||
static bool classof(const Attr *A) { return A->getKind() == Alias; }
|
static bool classof(const Attr *A) { return A->getKind() == Alias; }
|
||||||
static bool classof(const AliasAttr *A) { return true; }
|
static bool classof(const AliasAttr *A) { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class IBOutletAttr : public Attr {
|
||||||
|
public:
|
||||||
|
IBOutletAttr() : Attr(IBOutletKind) {}
|
||||||
|
|
||||||
|
// Implement isa/cast/dyncast/etc.
|
||||||
|
static bool classof(const Attr *A) {
|
||||||
|
return A->getKind() == IBOutletKind;
|
||||||
|
}
|
||||||
|
static bool classof(const IBOutletAttr *A) { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
class NoReturnAttr : public Attr {
|
class NoReturnAttr : public Attr {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -672,6 +672,10 @@ DIAG(err_mode_wrong_type, ERROR,
|
||||||
"type of machine mode does not match type of base type")
|
"type of machine mode does not match type of base type")
|
||||||
DIAG(err_attr_wrong_decl, ERROR,
|
DIAG(err_attr_wrong_decl, ERROR,
|
||||||
"'%0' attribute invalid on this declaration, requires typedef or value")
|
"'%0' attribute invalid on this declaration, requires typedef or value")
|
||||||
|
|
||||||
|
// Clang-Specific Attributes
|
||||||
|
DIAG(err_attribute_iboutlet_non_ivar, ERROR,
|
||||||
|
"'IBOutlet' attribute can only be applied to instance variables")
|
||||||
|
|
||||||
// Function Parameter Semantic Analysis.
|
// Function Parameter Semantic Analysis.
|
||||||
DIAG(err_param_with_void_type, ERROR,
|
DIAG(err_param_with_void_type, ERROR,
|
||||||
|
|
|
@ -52,6 +52,7 @@ public:
|
||||||
AT_ext_vector_type,
|
AT_ext_vector_type,
|
||||||
AT_fastcall,
|
AT_fastcall,
|
||||||
AT_format,
|
AT_format,
|
||||||
|
AT_IBOutlet, // Clang-specific.
|
||||||
AT_malloc,
|
AT_malloc,
|
||||||
AT_mode,
|
AT_mode,
|
||||||
AT_noinline,
|
AT_noinline,
|
||||||
|
|
|
@ -49,7 +49,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
|
||||||
Str += 2;
|
Str += 2;
|
||||||
Len -= 4;
|
Len -= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Len) {
|
switch (Len) {
|
||||||
case 4:
|
case 4:
|
||||||
if (!memcmp(Str, "weak", 4)) return AT_weak;
|
if (!memcmp(Str, "weak", 4)) return AT_weak;
|
||||||
|
@ -76,6 +76,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
|
||||||
if (!memcmp(Str, "noreturn", 8)) return AT_noreturn;
|
if (!memcmp(Str, "noreturn", 8)) return AT_noreturn;
|
||||||
if (!memcmp(Str, "noinline", 8)) return AT_noinline;
|
if (!memcmp(Str, "noinline", 8)) return AT_noinline;
|
||||||
if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
|
if (!memcmp(Str, "fastcall", 8)) return AT_fastcall;
|
||||||
|
if (!memcmp(Str, "IBOutlet", 8)) return AT_IBOutlet;
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
|
if (!memcmp(Str, "dllimport", 9)) return AT_dllimport;
|
||||||
|
|
|
@ -217,6 +217,22 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
Attr.getName()->getName());
|
Attr.getName()->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
|
// check the attribute arguments.
|
||||||
|
if (Attr.getNumArgs() > 0) {
|
||||||
|
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
|
||||||
|
std::string("0"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The IBOutlet attribute only applies to instance variables of Objective-C
|
||||||
|
// classes.
|
||||||
|
if (ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(d))
|
||||||
|
ID->addAttr(new IBOutletAttr());
|
||||||
|
else
|
||||||
|
S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet_non_ivar);
|
||||||
|
}
|
||||||
|
|
||||||
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||||
// check the attribute arguments.
|
// check the attribute arguments.
|
||||||
if (Attr.getNumArgs() != 1) {
|
if (Attr.getNumArgs() != 1) {
|
||||||
|
@ -746,6 +762,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
|
||||||
case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
|
case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break;
|
||||||
case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
|
case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
|
||||||
case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
|
case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
|
||||||
|
case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break;
|
||||||
case AttributeList::AT_transparent_union:
|
case AttributeList::AT_transparent_union:
|
||||||
HandleTransparentUnionAttr(D, Attr, S);
|
HandleTransparentUnionAttr(D, Attr, S);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue