summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2013-12-07 00:34:23 +0000
committerFariborz Jahanian <fjahanian@apple.com>2013-12-07 00:34:23 +0000
commit1f0b3bfd75029463625643b1650e097afe227b5c (patch)
tree455bc593d9918c54c6c7575676f74a8180802490 /clang/lib
parent32c3f17d3655fa97817c697e8e2456e9283567ae (diff)
downloadbcm5719-llvm-1f0b3bfd75029463625643b1650e097afe227b5c.tar.gz
bcm5719-llvm-1f0b3bfd75029463625643b1650e097afe227b5c.zip
ObjectiveC. Continuing implementation of objc_bridge_related
attribute in sema and issuing a variety of diagnostics lazily for misuse of this attribute (and what to do) when converting from CF types to ObjectiveC types (and vice versa). // rdar://15499111 llvm-svn: 196629
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp6
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp114
-rw-r--r--clang/lib/Sema/SemaInit.cpp3
3 files changed, 123 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 3db3e383482..8efdffaf090 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -10639,6 +10639,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
MayHaveConvFixit = true;
break;
case IncompatiblePointer:
+ if (getLangOpts().ObjC1 &&
+ CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType))
+ return false;
MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString);
DiagKind =
(Action == AA_Passing_CFAudited ?
@@ -10718,6 +10721,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
DiagKind = diag::err_arc_weak_unavailable_assign;
break;
case Incompatible:
+ if (getLangOpts().ObjC1 &&
+ CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType))
+ return true;
DiagKind = diag::err_typecheck_convert_incompatible;
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
MayHaveConvFixit = true;
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index ba3c5e375df..3e547fdebfd 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -3341,6 +3341,120 @@ void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) {
}
}
+
+bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ ObjCInterfaceDecl *&RelatedClass,
+ ObjCMethodDecl *&ClassMethod,
+ ObjCMethodDecl *&InstanceMethod,
+ TypedefNameDecl *&TDNDecl,
+ bool CfToNs) {
+ QualType T = CfToNs ? SrcType : DestType;
+ while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
+ TDNDecl = TD->getDecl();
+ if (ObjCBridgeRelatedAttr *ObjCBAttr =
+ getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD)) {
+ IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();
+ IdentifierInfo *CMId = ObjCBAttr->getClassMethod();
+ IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();
+ if (!RCId)
+ return false;
+ NamedDecl *Target = 0;
+ // Check for an existing type with this name.
+ LookupResult R(*this, DeclarationName(RCId), SourceLocation(),
+ Sema::LookupOrdinaryName);
+ if (!LookupName(R, TUScope)) {
+ Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId
+ << SrcType << DestType;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+ Target = R.getFoundDecl();
+ if (Target && isa<ObjCInterfaceDecl>(Target))
+ RelatedClass = cast<ObjCInterfaceDecl>(Target);
+ else {
+ Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId
+ << SrcType << DestType;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ if (Target)
+ Diag(Target->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+
+ // Check for an existing class method with the given selector name.
+ if (CfToNs && CMId) {
+ Selector Sel = Context.Selectors.getUnarySelector(CMId);
+ ClassMethod = RelatedClass->lookupMethod(Sel, false);
+ if (!ClassMethod) {
+ Diag(Loc, diag::err_objc_bridged_related_class_method)
+ << Sel << SrcType << DestType;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+ }
+
+ // Check for an existing instance method with the given selector name.
+ if (!CfToNs && IMId) {
+ Selector Sel = Context.Selectors.getNullarySelector(IMId);
+ InstanceMethod = RelatedClass->lookupMethod(Sel, true);
+ if (!InstanceMethod) {
+ Diag(Loc, diag::err_objc_bridged_related_instance_method)
+ << Sel << SrcType << DestType;
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return false;
+ }
+ }
+ return true;
+ }
+ T = TDNDecl->getUnderlyingType();
+ }
+ return false;
+}
+
+bool
+Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
+ QualType DestType, QualType SrcType) {
+ ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType);
+ ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType);
+ bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable);
+ bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);
+ if (!CfToNs && !NsToCf)
+ return false;
+
+ ObjCInterfaceDecl *RelatedClass;
+ ObjCMethodDecl *ClassMethod = 0;
+ ObjCMethodDecl *InstanceMethod = 0;
+ TypedefNameDecl *TDNDecl = 0;
+ if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,
+ ClassMethod, InstanceMethod, TDNDecl, CfToNs))
+ return false;
+
+ if (CfToNs) {
+ // Implicit conversion from CF to ObjC object is needed.
+ if (ClassMethod)
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << ClassMethod->getSelector() << 0;
+ else
+ Diag(Loc, diag::err_objc_bridged_related_unknown_method)
+ << SrcType << DestType << RelatedClass->getName() << 0;
+ Diag(RelatedClass->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ }
+ else {
+ // Implicit conversion from ObjC type to CF object is needed.
+ if (InstanceMethod)
+ Diag(Loc, diag::err_objc_bridged_related_known_method)
+ << SrcType << DestType << InstanceMethod->getSelector() << 1;
+ else
+ Diag(Loc, diag::err_objc_bridged_related_unknown_method)
+ << SrcType << DestType << RelatedClass->getName() << 1;
+ Diag(RelatedClass->getLocStart(), diag::note_declared_at);
+ Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ }
+
+ return true;
+}
+
Sema::ARCConversionResult
Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
Expr *&castExpr, CheckedConversionKind CCK,
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 4188005c762..50ea42714fa 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6482,6 +6482,9 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_ConversionFailed: {
QualType FromType = Args[0]->getType();
+ if (S.getLangOpts().ObjC1)
+ S.CheckObjCBridgeRelatedConversions(Kind.getLocation(),
+ DestType, FromType);
PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
<< (int)Entity.getKind()
<< DestType
OpenPOWER on IntegriCloud