diff options
author | John McCall <rjmccall@apple.com> | 2011-09-30 05:12:12 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-09-30 05:12:12 +0000 |
commit | 8dfac0baaf0f81d3945bcb306480e358ba8d1f08 (patch) | |
tree | 686c4b456894ceb992527fd530ed1c80776c0433 /lib/Sema/SemaDeclAttr.cpp | |
parent | e4c6675cccbaac991843def43072687bca50d989 (diff) |
Add explicit attributes to mark functions as having had their
CoreFoundation object-transfer properties audited, and add a #pragma
to cause them to be automatically applied to functions in a particular
span of code. This has to be implemented largely in the preprocessor
because of the requirement that the region be entirely contained in
a single file; that's hard to impose from the parser without registering
for a ton of callbacks.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140846 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index eca6874b36..0ffb92f00f 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3263,6 +3263,41 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, ::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context)); } +/// Handle cf_audited_transfer and cf_unknown_transfer. +static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) { + if (!isa<FunctionDecl>(D)) { + S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) + << A.getRange() << A.getName() << 0 /*function*/; + return; + } + + bool IsAudited = (A.getKind() == AttributeList::AT_cf_audited_transfer); + + // Check whether there's a conflicting attribute already present. + Attr *Existing; + if (IsAudited) { + Existing = D->getAttr<CFUnknownTransferAttr>(); + } else { + Existing = D->getAttr<CFAuditedTransferAttr>(); + } + if (Existing) { + S.Diag(D->getLocStart(), diag::err_attributes_are_not_compatible) + << A.getName() + << (IsAudited ? "cf_unknown_transfer" : "cf_audited_transfer") + << A.getRange() << Existing->getRange(); + return; + } + + // All clear; add the attribute. + if (IsAudited) { + D->addAttr( + ::new (S.Context) CFAuditedTransferAttr(A.getRange(), S.Context)); + } else { + D->addAttr( + ::new (S.Context) CFUnknownTransferAttr(A.getRange(), S.Context)); + } +} + static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, const AttributeList &Attr) { RecordDecl *RD = dyn_cast<RecordDecl>(D); @@ -3499,6 +3534,10 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ns_bridged: handleNSBridgedAttr(S, scope, D, Attr); break; + case AttributeList::AT_cf_audited_transfer: + case AttributeList::AT_cf_unknown_transfer: + handleCFTransferAttr(S, D, Attr); break; + // Checker-specific. case AttributeList::AT_cf_consumed: case AttributeList::AT_ns_consumed: handleNSConsumedAttr (S, D, Attr); break; |