diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-06-11 01:09:30 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-06-11 01:09:30 +0000 |
commit | 926df6cfabf3eaa4afc990c097fa4619b76a9b57 (patch) | |
tree | f48a5ca74fa783c76ae30e190d130881fc5febe8 /include/clang | |
parent | 45937ae10a0f70f74508165aab4f2b63e18ea747 (diff) |
Implement Objective-C Related Result Type semantics.
Related result types apply Cocoa conventions to the type of message
sends and property accesses to Objective-C methods that are known to
always return objects whose type is the same as the type of the
receiving class (or a subclass thereof), such as +alloc and
-init. This tightens up static type safety for Objective-C, so that we
now diagnose mistakes like this:
t.m:4:10: warning: incompatible pointer types initializing 'NSSet *'
with an
expression of type 'NSArray *' [-Wincompatible-pointer-types]
NSSet *array = [[NSArray alloc] init];
^ ~~~~~~~~~~~~~~~~~~~~~~
/System/Library/Frameworks/Foundation.framework/Headers/NSObject.h:72:1:
note:
instance method 'init' is assumed to return an instance of its
receiver
type ('NSArray *')
- (id)init;
^
It also means that we get decent type inference when writing code in
Objective-C++0x:
auto array = [[NSMutableArray alloc] initWithObjects:@"one", @"two",nil];
// ^ now infers NSMutableArray* rather than id
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132868 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r-- | include/clang/AST/DeclObjC.h | 16 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 17 | ||||
-rw-r--r-- | include/clang/Basic/IdentifierTable.h | 3 | ||||
-rw-r--r-- | include/clang/Basic/LangOptions.h | 3 | ||||
-rw-r--r-- | include/clang/Driver/CC1Options.td | 2 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 4 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 30 |
7 files changed, 69 insertions, 6 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 0a4d864cd8..0e698607db 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -135,6 +135,9 @@ private: /// in, inout, etc. unsigned objcDeclQualifier : 6; + /// \brief Indicates whether this method has a related result type. + unsigned RelatedResultType : 1; + // Number of args separated by ':' in a method declaration. unsigned NumSelectorArgs; @@ -171,6 +174,7 @@ private: bool isSynthesized = false, bool isDefined = false, ImplementationControl impControl = None, + bool HasRelatedResultType = false, unsigned numSelectorArgs = 0) : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), @@ -178,8 +182,8 @@ private: IsSynthesized(isSynthesized), IsDefined(isDefined), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), - NumSelectorArgs(numSelectorArgs), MethodDeclType(T), - ResultTInfo(ResultTInfo), + RelatedResultType(HasRelatedResultType), NumSelectorArgs(numSelectorArgs), + MethodDeclType(T), ResultTInfo(ResultTInfo), EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} /// \brief A definition will return its interface declaration. @@ -199,6 +203,7 @@ public: bool isSynthesized = false, bool isDefined = false, ImplementationControl impControl = None, + bool HasRelatedResultType = false, unsigned numSelectorArgs = 0); virtual ObjCMethodDecl *getCanonicalDecl(); @@ -211,6 +216,13 @@ public: } void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; } + /// \brief Determine whether this method has a result type that is related + /// to the message receiver's type. + bool hasRelatedResultType() const { return RelatedResultType; } + + /// \brief Note whether this method has a related result type. + void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; } + unsigned getNumSelectorArgs() const { return NumSelectorArgs; } void setNumSelectorArgs(unsigned numSelectorArgs) { NumSelectorArgs = numSelectorArgs; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 17356b963d..7890aefc50 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4117,5 +4117,22 @@ def err_invalid_astype_of_different_size : Error< } // end of sema category +let CategoryName = "Related Result Type Issue" in { +// Objective-C related result type compatibility +def warn_related_result_type_compatibility_class : Warning< + "method is expected to return an instance of its class type %0, but " + "is declared to return %1">; +def warn_related_result_type_compatibility_protocol : Warning< + "protocol method is expected to return an instance of the implementing " + "class, but is declared to return %0">; +def note_related_result_type_overridden : Note< + "overridden method is part of the '%select{|alloc|copy|init|mutableCopy|" + "new|autorelease|dealloc|release|retain|retainCount|self}0' method family">; +def note_related_result_type_inferred : Note< + "%select{class|instance}0 method %1 is assumed to return an instance of " + "its receiver type (%2)">; + +} + } // end of sema component. diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 683ec8312e..b4eca6d8fb 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -498,7 +498,8 @@ enum ObjCMethodFamily { OMF_dealloc, OMF_release, OMF_retain, - OMF_retainCount + OMF_retainCount, + OMF_self }; /// Enough bits to store any enumerator in ObjCMethodFamily or diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index a5f6789b7d..f0f1432ca0 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -46,6 +46,8 @@ public: unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled unsigned ObjCNonFragileABI2 : 1; // Objective-C enhanced modern abi enabled unsigned ObjCDefaultSynthProperties : 1; // Objective-C auto-synthesized properties. + unsigned ObjCInferRelatedResultType : 1; // Infer Objective-C related return + // types unsigned AppleKext : 1; // Allow apple kext features. unsigned PascalStrings : 1; // Allow Pascal strings @@ -173,6 +175,7 @@ public: GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0; AppleKext = 0; ObjCDefaultSynthProperties = 0; + ObjCInferRelatedResultType = 0; NoConstantCFStrings = 0; InlineVisibilityHidden = 0; C99 = C1X = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 155ecae579..14d8f67b9d 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -493,6 +493,8 @@ def print_ivar_layout : Flag<"-print-ivar-layout">, HelpText<"Enable Objective-C Ivar layout bitmap print trace">; def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, HelpText<"enable objective-c's nonfragile abi">; +def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">, + HelpText<"infer Objective-C related result type based on method family">; def ftrapv : Flag<"-ftrapv">, HelpText<"Trap on integer overflow">; def ftrapv_handler : Separate<"-ftrapv-handler">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 23b351c78a..72039766d9 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -392,6 +392,10 @@ def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>; def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>; def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group<f_Group>; def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>; +def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">, + Group<f_Group>; +def fno_objc_infer_related_result_type : Flag< + "-fno-objc-infer-related-result-type">, Group<f_Group>; // Objective-C ABI options. def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a1c0ba9dcf..bb3ec2dbed 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4981,7 +4981,7 @@ public: SourceLocation EndLoc, // location of the ; or {. tok::TokenKind MethodType, Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - Selector Sel, + SourceLocation SelectorStartLoc, Selector Sel, // optional arguments. The number of types/arguments is obtained // from the Sel.getNumArgs(). ObjCArgInfo *ArgInfo, @@ -5079,7 +5079,18 @@ public: SourceLocation RBracLoc, MultiExprArg Args); - + /// \brief Check whether the given new method is a valid override of the + /// given overridden method, and set any properties that should be inherited. + /// + /// \returns True if an error occurred. + bool CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, + const ObjCMethodDecl *Overridden, + bool IsImplementation); + + /// \brief Check whether the given method overrides any methods in its class, + /// calling \c CheckObjCMethodOverride for each overridden method. + bool CheckObjCMethodOverrides(ObjCMethodDecl *NewMethod, DeclContext *DC); + enum PragmaOptionsAlignKind { POAK_Native, // #pragma options align=native POAK_Natural, // #pragma options align=natural @@ -5501,11 +5512,24 @@ public: /// \param Method - May be null. /// \param [out] ReturnType - The return type of the send. /// \return true iff there were any incompatible types. - bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel, + bool CheckMessageArgumentTypes(QualType ReceiverType, + Expr **Args, unsigned NumArgs, Selector Sel, ObjCMethodDecl *Method, bool isClassMessage, + bool isSuperMessage, SourceLocation lbrac, SourceLocation rbrac, QualType &ReturnType, ExprValueKind &VK); + /// \brief Determine the result of a message send expression based on + /// the type of the receiver, the method expected to receive the message, + /// and the form of the message send. + QualType getMessageSendResultType(QualType ReceiverType, + ObjCMethodDecl *Method, + bool isClassMessage, bool isSuperMessage); + + /// \brief If the given expression involves a message send to a method + /// with a related result type, emit a note describing what happened. + void EmitRelatedResultTypeNote(const Expr *E); + /// CheckBooleanCondition - Diagnose problems involving the use of /// the given expression as a boolean condition (e.g. in an if /// statement). Also performs the standard function and array |