aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/AttributeList.cpp1
-rw-r--r--lib/Sema/SemaDeclAttr.cpp34
2 files changed, 35 insertions, 0 deletions
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp
index d9f17b42da..5cd21a645d 100644
--- a/lib/Sema/AttributeList.cpp
+++ b/lib/Sema/AttributeList.cpp
@@ -171,6 +171,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("analyzer_noreturn", AT_analyzer_noreturn)
.Case("warn_unused_result", AT_warn_unused_result)
.Case("carries_dependency", AT_carries_dependency)
+ .Case("ns_bridged", AT_ns_bridged)
.Case("ns_consumed", AT_ns_consumed)
.Case("ns_consumes_self", AT_ns_consumes_self)
.Case("ns_returns_autoreleased", AT_ns_returns_autoreleased)
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 435507f9d7..eca6874b36 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -22,6 +22,7 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Lookup.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace sema;
@@ -3262,6 +3263,36 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context));
}
+static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,
+ const AttributeList &Attr) {
+ RecordDecl *RD = dyn_cast<RecordDecl>(D);
+ if (!RD || RD->isUnion()) {
+ S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
+ << Attr.getRange() << Attr.getName() << 14 /*struct */;
+ }
+
+ IdentifierInfo *ParmName = Attr.getParameterName();
+
+ // In Objective-C, verify that the type names an Objective-C type.
+ // We don't want to check this outside of ObjC because people sometimes
+ // do crazy C declarations of Objective-C types.
+ if (ParmName && S.getLangOptions().ObjC1) {
+ // Check for an existing type with this name.
+ LookupResult R(S, DeclarationName(ParmName), Attr.getParameterLoc(),
+ Sema::LookupOrdinaryName);
+ if (S.LookupName(R, Sc)) {
+ NamedDecl *Target = R.getFoundDecl();
+ if (Target && !isa<ObjCInterfaceDecl>(Target)) {
+ S.Diag(D->getLocStart(), diag::err_ns_bridged_not_interface);
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
+ }
+ }
+ }
+
+ D->addAttr(::new (S.Context) NSBridgedAttr(Attr.getRange(), S.Context,
+ ParmName));
+}
+
static void handleObjCOwnershipAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (hasDeclarator(D)) return;
@@ -3465,6 +3496,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_objc_returns_inner_pointer:
handleObjCReturnsInnerPointerAttr(S, D, Attr); break;
+ case AttributeList::AT_ns_bridged:
+ handleNSBridgedAttr(S, scope, D, Attr); break;
+
// Checker-specific.
case AttributeList::AT_cf_consumed:
case AttributeList::AT_ns_consumed: handleNSConsumedAttr (S, D, Attr); break;