diff options
-rw-r--r-- | include/clang/Basic/DiagnosticGroups.td | 4 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | lib/Sema/SemaCast.cpp | 20 | ||||
-rw-r--r-- | test/SemaObjC/warn-cast-of-sel-expr.m | 21 |
4 files changed, 46 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index ead596cc05..cc234dd5bf 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -156,6 +156,7 @@ def ObjCReceiver : DiagGroup<"receiver-expr">; def OverlengthStrings : DiagGroup<"overlength-strings">; def OverloadedVirtual : DiagGroup<"overloaded-virtual">; def PrivateExtern : DiagGroup<"private-extern">; +def SelTypeCast : DiagGroup<"cast-of-sel-type">; def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">; def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">; def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">; @@ -373,7 +374,8 @@ def Most : DiagGroup<"most", [ VolatileRegisterVar, ObjCMissingSuperCalls, OverloadedVirtual, - PrivateExtern + PrivateExtern, + SelTypeCast ]>; // Thread Safety warnings diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index cd73dca05f..2d47db9e83 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4962,6 +4962,9 @@ def err_typecheck_cast_to_union_no_type : Error< "cast to union type from type %0 not present in union">; def err_cast_pointer_from_non_pointer_int : Error< "operand of type %0 cannot be cast to a pointer type">; +def warn_cast_pointer_from_sel : Warning< + "cast of type %0 to %1 is deprecated; use sel_getName instead">, + InGroup<SelTypeCast>, DefaultIgnore; def err_cast_pointer_to_non_pointer_int : Error< "pointer cannot be cast to type %0">; def err_typecheck_expect_scalar_operand : Error< diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 819975143d..d8d51e77ee 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -1477,6 +1477,21 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range; } +static void DiagnoseCastOfObjCSEL(Sema &Self, const ExprResult &SrcExpr, + QualType DestType) { + QualType SrcType = SrcExpr.get()->getType(); + if (const PointerType *SrcPtrTy = SrcType->getAs<PointerType>()) + if (SrcPtrTy->isObjCSelType()) { + QualType DT = DestType; + if (isa<PointerType>(DestType)) + DT = DestType->getPointeeType(); + if (!DT.getUnqualifiedType()->isVoidType()) + Self.Diag(SrcExpr.get()->getExprLoc(), + diag::warn_cast_pointer_from_sel) + << SrcType << DestType << SrcExpr.get()->getSourceRange(); + } +} + static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, @@ -1721,7 +1736,9 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, if (CStyle && DestType->isObjCObjectPointerType()) { return TC_Success; } - + if (CStyle) + DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType); + // Not casting away constness, so the only remaining check is for compatible // pointer categories. @@ -2058,6 +2075,7 @@ void CastOperation::CheckCStyleCast() { return; } } + DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType); Kind = Self.PrepareScalarCast(SrcExpr, DestType); if (SrcExpr.isInvalid()) diff --git a/test/SemaObjC/warn-cast-of-sel-expr.m b/test/SemaObjC/warn-cast-of-sel-expr.m new file mode 100644 index 0000000000..d2f243cc03 --- /dev/null +++ b/test/SemaObjC/warn-cast-of-sel-expr.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wcast-of-sel-type -Wno-unused-value %s +// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -verify -Wcast-of-sel-type -Wno-unused-value %s +// rdar://12107381 + +SEL s; + +SEL sel_registerName(const char *); + +int main() { +(char *)s; // expected-warning {{cast of type 'SEL' to 'char *' is deprecated; use sel_getName instead}} +(void *)s; // ok +(const char *)sel_registerName("foo"); // expected-warning {{cast of type 'SEL' to 'const char *' is deprecated; use sel_getName instead}} + +(const void *)sel_registerName("foo"); // ok + +(void) s; // ok + +(void *const)s; // ok + +(const void *const)s; // ok +} |