aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-06-11 01:09:30 +0000
committerDouglas Gregor <dgregor@apple.com>2011-06-11 01:09:30 +0000
commit926df6cfabf3eaa4afc990c097fa4619b76a9b57 (patch)
treef48a5ca74fa783c76ae30e190d130881fc5febe8 /include/clang
parent45937ae10a0f70f74508165aab4f2b63e18ea747 (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.h16
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td17
-rw-r--r--include/clang/Basic/IdentifierTable.h3
-rw-r--r--include/clang/Basic/LangOptions.h3
-rw-r--r--include/clang/Driver/CC1Options.td2
-rw-r--r--include/clang/Driver/Options.td4
-rw-r--r--include/clang/Sema/Sema.h30
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