<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Jun 20, 2015 at 12:04 PM, Aaron Ballman <span dir="ltr"><<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On Fri, Jun 19, 2015 at 2:14 PM, Douglas Gregor <<a href="mailto:dgregor@apple.com">dgregor@apple.com</a>> wrote:<br>
> Author: dgregor<br>
> Date: Fri Jun 19 13:14:38 2015<br>
> New Revision: 240154<br>
><br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D240154-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=Ud2IDeuuLD7iJmo7wV4B9kSiv6HbQEmRvZrgfNvtL6U&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=240154&view=rev</a><br>
> Log:<br>
> Extend type nullability qualifiers for Objective-C.<br>
><br>
> Introduce context-sensitive, non-underscored nullability specifiers<br>
> (nonnull, nullable, null_unspecified) for Objective-C method return<br>
> types, method parameter types, and properties.<br>
><br>
> Introduce Objective-C-specific semantics, including computation of the<br>
> nullability of the result of a message send, merging of nullability<br>
> information from the @interface of a class into its @implementation,<br>
> etc .<br>
><br>
> This is the Objective-C part of rdar://problem/18868820.<br>
><br>
> Added:<br>
>     cfe/trunk/test/SemaObjC/nullable-weak-property.m<br>
>     cfe/trunk/test/SemaObjC/override-nullability.m<br>
> Modified:<br>
>     cfe/trunk/include/clang/AST/ASTContext.h<br>
>     cfe/trunk/include/clang/AST/DeclBase.h<br>
>     cfe/trunk/include/clang/AST/DeclObjC.h<br>
>     cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td<br>
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
>     cfe/trunk/include/clang/Basic/Specifiers.h<br>
>     cfe/trunk/include/clang/Parse/Parser.h<br>
>     cfe/trunk/include/clang/Sema/AttributeList.h<br>
>     cfe/trunk/include/clang/Sema/DeclSpec.h<br>
>     cfe/trunk/include/clang/Sema/Sema.h<br>
>     cfe/trunk/lib/AST/ASTImporter.cpp<br>
>     cfe/trunk/lib/AST/DeclObjC.cpp<br>
>     cfe/trunk/lib/AST/DeclPrinter.cpp<br>
>     cfe/trunk/lib/Basic/IdentifierTable.cpp<br>
>     cfe/trunk/lib/Parse/ParseObjc.cpp<br>
>     cfe/trunk/lib/Parse/Parser.cpp<br>
>     cfe/trunk/lib/Sema/SemaDecl.cpp<br>
>     cfe/trunk/lib/Sema/SemaDeclObjC.cpp<br>
>     cfe/trunk/lib/Sema/SemaExprObjC.cpp<br>
>     cfe/trunk/lib/Sema/SemaObjCProperty.cpp<br>
>     cfe/trunk/lib/Sema/SemaType.cpp<br>
>     cfe/trunk/lib/Sema/TreeTransform.h<br>
>     cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br>
>     cfe/trunk/lib/Serialization/ASTWriterDecl.cpp<br>
>     cfe/trunk/test/Index/comment-objc-decls.m<br>
>     cfe/trunk/test/SemaObjC/arc-property-decl-attrs.m<br>
>     cfe/trunk/test/SemaObjC/arc-unavailable-for-weakref.m<br>
>     cfe/trunk/test/SemaObjC/nullability.m<br>
><br>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_AST_ASTContext.h-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=IhRCCrNrDlQ3G737-O6PHG2FFNBcQuvmTW3tadpv7V4&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)<br>
> +++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jun 19 13:14:38 2015<br>
> @@ -1854,6 +1854,36 @@ public:<br>
>             getCanonicalType(T2).getTypePtr();<br>
>    }<br>
><br>
> +  bool hasSameNullabilityTypeQualifier(QualType SubT, QualType SuperT,<br>
> +                                       bool IsParam) const {<br>
> +    auto SubTnullability = SubT->getNullability(*this);<br>
> +    auto SuperTnullability = SuperT->getNullability(*this);<br>
> +    if (SubTnullability.hasValue() == SuperTnullability.hasValue()) {<br>
> +      // Neither has nullability; return true<br>
> +      if (!SubTnullability)<br>
> +        return true;<br>
> +      // Both have nullability qualifier.<br>
> +      if (*SubTnullability == *SuperTnullability ||<br>
> +          *SubTnullability == NullabilityKind::Unspecified ||<br>
> +          *SuperTnullability == NullabilityKind::Unspecified)<br>
> +        return true;<br>
> +<br>
> +      if (IsParam) {<br>
> +        // Ok for the superclass method parameter to be â€œnonnull† and the subclass<br>
> +        // method parameter to be â€œnullableâ€<br>
<br>
Non-ASCII characters in the comments.<br>
<br>
> +        return (*SuperTnullability == NullabilityKind::NonNull &&<br>
> +                *SubTnullability == NullabilityKind::Nullable);<br>
> +      }<br>
> +      else {<br>
> +        // For the return type, it’s okay for the superclass method to specify<br>
> +        // â€œnullable† and the subclass method specify â€œnonnullâ€<br>
<br>
Non-ASCII characters in the comments.<br></blockquote><div><br></div><div>(chapuni fixed the two non-ASCII lines in r<span style="font-size:12.8000001907349px">240211)</span></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
> +        return (*SuperTnullability == NullabilityKind::Nullable &&<br>
> +                *SubTnullability == NullabilityKind::NonNull);<br>
> +      }<br>
> +    }<br>
> +    return true;<br>
<br>
This appears to be one of the few functions that care about the<br>
optionality of getNullability(). I find the dereferences sprinkled all<br>
over to be really distracting and kind of ugly. Is there a better<br>
approach we could use (even if it's a different code pattern when<br>
dealing with optional) so that we don't have to stare at stars all day<br>
long?<br>
<br>
> +  }<br>
> +<br>
>    bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl,<br>
>                             const ObjCMethodDecl *MethodImp);<br>
><br>
><br>
> Modified: cfe/trunk/include/clang/AST/DeclBase.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_AST_DeclBase.h-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=owAWOMIBV7SoSvFI_B6bJIQO3P-wnt-oNMSNiFuSS5M&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/DeclBase.h (original)<br>
> +++ cfe/trunk/include/clang/AST/DeclBase.h Fri Jun 19 13:14:38 2015<br>
> @@ -178,7 +178,12 @@ public:<br>
>      OBJC_TQ_Out = 0x4,<br>
>      OBJC_TQ_Bycopy = 0x8,<br>
>      OBJC_TQ_Byref = 0x10,<br>
> -    OBJC_TQ_Oneway = 0x20<br>
> +    OBJC_TQ_Oneway = 0x20,<br>
> +<br>
> +    /// The nullability qualifier is set when the nullability of the<br>
> +    /// result or parameter was expressed via a context-sensitive<br>
> +    /// keyword.<br>
> +    OBJC_TQ_CSNullability = 0x40<br>
>    };<br>
><br>
>  protected:<br>
><br>
> Modified: cfe/trunk/include/clang/AST/DeclObjC.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_AST_DeclObjC.h-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=P4AHf7JqTaMalA7OnIMsEcJdjtojl6WZQuAX7ieGNiY&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/DeclObjC.h (original)<br>
> +++ cfe/trunk/include/clang/AST/DeclObjC.h Fri Jun 19 13:14:38 2015<br>
> @@ -141,7 +141,7 @@ private:<br>
><br>
>    // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum<br>
>    /// in, inout, etc.<br>
> -  unsigned objcDeclQualifier : 6;<br>
> +  unsigned objcDeclQualifier : 7;<br>
><br>
>    /// \brief Indicates whether this method has a related result type.<br>
>    unsigned RelatedResultType : 1;<br>
> @@ -2203,13 +2203,16 @@ public:<br>
>      OBJC_PR_atomic    = 0x100,<br>
>      OBJC_PR_weak      = 0x200,<br>
>      OBJC_PR_strong    = 0x400,<br>
> -    OBJC_PR_unsafe_unretained = 0x800<br>
> +    OBJC_PR_unsafe_unretained = 0x800,<br>
> +    /// Indicates that the nullability of the type was spelled with a<br>
> +    /// property attribute rather than a type qualifier.<br>
> +    OBJC_PR_nullability = 0x1000<br>
>      // Adding a property should change NumPropertyAttrsBits<br>
>    };<br>
><br>
>    enum {<br>
>      /// \brief Number of bits fitting all the property attributes.<br>
> -    NumPropertyAttrsBits = 12<br>
> +    NumPropertyAttrsBits = 13<br>
>    };<br>
><br>
>    enum SetterKind { Assign, Retain, Copy, Weak };<br>
> @@ -2217,7 +2220,8 @@ public:<br>
>  private:<br>
>    SourceLocation AtLoc;   // location of \@property<br>
>    SourceLocation LParenLoc; // location of '(' starting attribute list or null.<br>
> -  TypeSourceInfo *DeclType;<br>
> +  QualType DeclType;<br>
> +  TypeSourceInfo *DeclTypeSourceInfo;<br>
>    unsigned PropertyAttributes : NumPropertyAttrsBits;<br>
>    unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits;<br>
>    // \@required/\@optional<br>
> @@ -2232,12 +2236,13 @@ private:<br>
><br>
>    ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,<br>
>                     SourceLocation AtLocation,  SourceLocation LParenLocation,<br>
> -                   TypeSourceInfo *T)<br>
> +                   QualType T, TypeSourceInfo *TSI,<br>
> +                   PropertyControl propControl)<br>
>      : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),<br>
> -      LParenLoc(LParenLocation), DeclType(T),<br>
> +      LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI),<br>
>        PropertyAttributes(OBJC_PR_noattr),<br>
>        PropertyAttributesAsWritten(OBJC_PR_noattr),<br>
> -      PropertyImplementation(None),<br>
> +      PropertyImplementation(propControl),<br>
>        GetterName(Selector()),<br>
>        SetterName(Selector()),<br>
>        GetterMethodDecl(nullptr), SetterMethodDecl(nullptr),<br>
> @@ -2248,7 +2253,8 @@ public:<br>
>                                    SourceLocation L,<br>
>                                    IdentifierInfo *Id, SourceLocation AtLocation,<br>
>                                    SourceLocation LParenLocation,<br>
> -                                  TypeSourceInfo *T,<br>
> +                                  QualType T,<br>
> +                                  TypeSourceInfo *TSI,<br>
>                                    PropertyControl propControl = None);<br>
><br>
>    static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);<br>
> @@ -2259,9 +2265,14 @@ public:<br>
>    SourceLocation getLParenLoc() const { return LParenLoc; }<br>
>    void setLParenLoc(SourceLocation L) { LParenLoc = L; }<br>
><br>
> -  TypeSourceInfo *getTypeSourceInfo() const { return DeclType; }<br>
> -  QualType getType() const { return DeclType->getType(); }<br>
> -  void setType(TypeSourceInfo *T) { DeclType = T; }<br>
> +  TypeSourceInfo *getTypeSourceInfo() const { return DeclTypeSourceInfo; }<br>
> +<br>
> +  QualType getType() const { return DeclType; }<br>
> +<br>
> +  void setType(QualType T, TypeSourceInfo *TSI) {<br>
> +    DeclType = T;<br>
> +    DeclTypeSourceInfo = TSI;<br>
> +  }<br>
><br>
>    PropertyAttributeKind getPropertyAttributes() const {<br>
>      return PropertyAttributeKind(PropertyAttributes);<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Basic_DiagnosticCommonKinds.td-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=WKTN4BSfDeQb5ILO3nytVJG1zTNGslCgYfuY4HYhP9Y&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)<br>
> +++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Fri Jun 19 13:14:38 2015<br>
> @@ -101,15 +101,32 @@ def err_enum_template : Error<"enumerati<br>
><br>
>  let CategoryName = "Nullability Issue" in {<br>
><br>
> -def warn_mismatched_nullability_attr : Warning<<br>
> -  "nullability specifier "<br>
> -  "'__%select{nonnull|nullable|null_unspecified}0' "<br>
> -  "conflicts with existing specifier "<br>
> -  "'__%select{nonnull|nullable|null_unspecified}1'">,<br>
> +def warn_nullability_duplicate : Warning<<br>
> +  "duplicate nullability specifier "<br>
> +  "'%select{__|}1%select{nonnull|nullable|null_unspecified}0'">,<br>
> +  InGroup<Nullability>;<br>
> +<br>
> +def warn_conflicting_nullability_attr_overriding_ret_types : Warning<<br>
> +  "conflicting nullability specifier on return types, "<br>
> +  "'%select{%select{__|}1nonnull|"<br>
> +  "%select{__|}1nullable|%select{__|}1null_unspecified}0' "<br>
> +  "conflicts with existing specifier '%select{%select{__|}3nonnull|"<br>
> +  "%select{__|}3nullable|%select{__|}3null_unspecified}2'">,<br>
>    InGroup<Nullability>;<br>
><br>
> -def note_nullability_here : Note<<br>
> -  "'%select{__nonnull|__nullable|__null_unspecified}0' specified here">;<br>
> +def warn_conflicting_nullability_attr_overriding_param_types : Warning<<br>
> +  "conflicting nullability specifier on parameter types, "<br>
> +  "'%select{%select{__|}1nonnull|"<br>
> +  "%select{__|}1nullable|%select{__|}1null_unspecified}0' "<br>
> +  "conflicts with existing specifier '%select{%select{__|}3nonnull|"<br>
> +  "%select{__|}3nullable|%select{__|}3null_unspecified}2'">,<br>
> +  InGroup<Nullability>;<br>
> +<br>
> +def err_nullability_conflicting : Error<<br>
> +  "nullability specifier "<br>
> +  "'%select{__|}1%select{nonnull|nullable|null_unspecified}0' conflicts with "<br>
> +  "existing specifier '%select{__|}3%select{nonnull|nullable|"<br>
> +  "null_unspecified}2'">;<br>
><br>
>  }<br>
><br>
><br>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Basic_DiagnosticSemaKinds.td-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=YerovH6T4OlQkZ5DywBjGevOJO9JN5nTENJ9wLMngos&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 19 13:14:38 2015<br>
> @@ -7676,9 +7676,11 @@ def warn_profile_data_unprofiled : Warni<br>
><br>
>  let CategoryName = "Nullability Issue" in {<br>
><br>
> -def warn_duplicate_nullability : Warning<<br>
> -  "duplicate nullability specifier "<br>
> -  "'%select{__nonnull|__nullable|__null_unspecified}0'">,<br>
> +def warn_mismatched_nullability_attr : Warning<<br>
> +  "nullability specifier "<br>
> +  "'%select{__|}1%select{nonnull|nullable|null_unspecified}0' "<br>
> +  "conflicts with existing specifier "<br>
> +  "'%select{__|}3%select{nonnull|nullable|null_unspecified}2'">,<br>
>    InGroup<Nullability>;<br>
><br>
>  def warn_nullability_declspec : Warning<<br>
> @@ -7690,21 +7692,28 @@ def warn_nullability_declspec : Warning<<br>
>    InGroup<NullabilityDeclSpec>,<br>
>    DefaultError;<br>
><br>
> -def err_nullability_nonpointer : Error<<br>
> -  "nullability specifier "<br>
> -  "'%select{__nonnull|__nullable|__null_unspecified}0' cannot be applied to "<br>
> -  "non-pointer type %1">;<br>
> +def note_nullability_here : Note<<br>
> +  "'%select{__nonnull|__nullable|__null_unspecified}0' specified here">;<br>
><br>
> -def err_nullability_conflicting : Error<<br>
> +def err_nullability_nonpointer : Error<<br>
>    "nullability specifier "<br>
> -  "'%select{__nonnull|__nullable|__null_unspecified}0' conflicts with existing "<br>
> -  "specifier '%select{__nonnull|__nullable|__null_unspecified}1'">;<br>
> +  "'%select{__|}1%select{nonnull|nullable|null_unspecified}0' cannot be applied "<br>
> +  "to non-pointer type %2">;<br>
><br>
>  def warn_nullability_lost : Warning<<br>
>    "implicit conversion from nullable pointer %0 to non-nullable pointer "<br>
>    "type %1">,<br>
>    InGroup<NullableToNonNullConversion>, DefaultIgnore;<br>
><br>
> +def err_nullability_cs_multilevel : Error<<br>
> +  "nullability keyword "<br>
> +  "'%select{nonnull|nullable|null_unspecified}0' cannot be applied to "<br>
> +  "multi-level pointer type %1">;<br>
> +def note_nullability_type_specifier : Note<<br>
> +  "use nullability type specifier "<br>
> +  "'%select{__nonnull|__nullable|__null_unspecified}0' to affect the innermost "<br>
> +  "pointer type of %1">;<br>
> +<br>
>  }<br>
><br>
>  } // end of sema component.<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/Specifiers.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Basic_Specifiers.h-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=NqOxZOcE-jyVEABqPWgiWqmFAjQpyFp3F0ZTGUl8e68&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/Specifiers.h (original)<br>
> +++ cfe/trunk/include/clang/Basic/Specifiers.h Fri Jun 19 13:14:38 2015<br>
> @@ -16,6 +16,7 @@<br>
>  #ifndef LLVM_CLANG_BASIC_SPECIFIERS_H<br>
>  #define LLVM_CLANG_BASIC_SPECIFIERS_H<br>
><br>
> +#include "llvm/ADT/StringRef.h"<br>
>  #include "llvm/Support/DataTypes.h"<br>
><br>
>  namespace clang {<br>
> @@ -254,6 +255,9 @@ namespace clang {<br>
>      /// though it has been considered.<br>
>      Unspecified<br>
>    };<br>
> +<br>
> +  /// Retrieve the spelling of the given nullability kind.<br>
> +  llvm::StringRef getNullabilitySpelling(NullabilityKind kind);<br>
>  } // end namespace clang<br>
><br>
>  #endif // LLVM_CLANG_BASIC_SPECIFIERS_H<br>
><br>
> Modified: cfe/trunk/include/clang/Parse/Parser.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Parse_Parser.h-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=VrAl_-GTrPYNJryarM-G9U9s9tPllUjcXg6t1kqiPUY&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Parse/Parser.h (original)<br>
> +++ cfe/trunk/include/clang/Parse/Parser.h Fri Jun 19 13:14:38 2015<br>
> @@ -139,6 +139,11 @@ class Parser : public CodeCompletionHand<br>
>    // used as type traits.<br>
>    llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertibleTypeTraits;<br>
><br>
> +  /// Nullability type specifiers.<br>
> +  IdentifierInfo *Ident___nonnull = nullptr;<br>
> +  IdentifierInfo *Ident___nullable = nullptr;<br>
> +  IdentifierInfo *Ident___null_unspecified = nullptr;<br>
> +<br>
>    std::unique_ptr<PragmaHandler> AlignHandler;<br>
>    std::unique_ptr<PragmaHandler> GCCVisibilityHandler;<br>
>    std::unique_ptr<PragmaHandler> OptionsHandler;<br>
> @@ -303,6 +308,10 @@ public:<br>
>      return true;<br>
>    }<br>
><br>
> +  /// Retrieve the underscored keyword (__nonnull, __nullable,<br>
> +  /// __null_unspecified) that corresponds to the given nullability kind.<br>
> +  IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability);<br>
> +<br>
>  private:<br>
>    //===--------------------------------------------------------------------===//<br>
>    // Low-Level token peeking and consumption methods.<br>
> @@ -1282,6 +1291,7 @@ private:<br>
>    // Definitions for Objective-c context sensitive keywords recognition.<br>
>    enum ObjCTypeQual {<br>
>      objc_in=0, objc_out, objc_inout, objc_oneway, objc_bycopy, objc_byref,<br>
> +    objc_nonnull, objc_nullable, objc_null_unspecified,<br>
>      objc_NumQuals<br>
>    };<br>
>    IdentifierInfo *ObjCTypeQuals[objc_NumQuals];<br>
><br>
> Modified: cfe/trunk/include/clang/Sema/AttributeList.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Sema_AttributeList.h-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=iAG0uSGHHOZPp9pOjKPUPiWPJucEZLpehz6jB-mI1Io&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Sema/AttributeList.h (original)<br>
> +++ cfe/trunk/include/clang/Sema/AttributeList.h Fri Jun 19 13:14:38 2015<br>
> @@ -120,6 +120,9 @@ private:<br>
>    /// True if this has a ParsedType<br>
>    unsigned HasParsedType : 1;<br>
><br>
> +  /// True when this keyword attribute is a context-sensitive keyword.<br>
> +  unsigned IsContextSensitiveKeyword : 1;<br>
<br>
This is more expensive than you might think since the bit field will<br>
now be 33 bits.<br>
<br>
> +<br>
>    unsigned AttrKind : 8;<br>
><br>
>    /// \brief The location of the 'unavailable' keyword in an<br>
> @@ -220,7 +223,8 @@ private:<br>
>        ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),<br>
>        SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),<br>
>        IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),<br>
> -      HasParsedType(false), NextInPosition(nullptr), NextInPool(nullptr) {<br>
> +      HasParsedType(false), IsContextSensitiveKeyword(false),<br>
> +      NextInPosition(nullptr), NextInPool(nullptr) {<br>
>      if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));<br>
>      AttrKind = getKind(getName(), getScopeName(), syntaxUsed);<br>
>    }<br>
> @@ -238,8 +242,8 @@ private:<br>
>        ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),<br>
>        Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),<br>
>        IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),<br>
> -      UnavailableLoc(unavailable), MessageExpr(messageExpr),<br>
> -      NextInPosition(nullptr), NextInPool(nullptr) {<br>
> +      IsContextSensitiveKeyword(false), UnavailableLoc(unavailable),<br>
> +      MessageExpr(messageExpr), NextInPosition(nullptr), NextInPool(nullptr) {<br>
>      ArgsUnion PVal(Parm);<br>
>      memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));<br>
>      new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);<br>
> @@ -259,7 +263,8 @@ private:<br>
>      ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed),<br>
>      Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),<br>
>      IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),<br>
> -    NextInPosition(nullptr), NextInPool(nullptr) {<br>
> +    IsContextSensitiveKeyword(false), NextInPosition(nullptr),<br>
> +    NextInPool(nullptr) {<br>
>      ArgsVector Args;<br>
>      Args.push_back(Parm1);<br>
>      Args.push_back(Parm2);<br>
> @@ -277,7 +282,8 @@ private:<br>
>        ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),<br>
>        Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),<br>
>        IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),<br>
> -      NextInPosition(nullptr), NextInPool(nullptr) {<br>
> +      IsContextSensitiveKeyword(false), NextInPosition(nullptr),<br>
> +      NextInPool(nullptr) {<br>
>      ArgsUnion PVal(ArgKind);<br>
>      memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));<br>
>      TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();<br>
> @@ -295,7 +301,8 @@ private:<br>
>          ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),<br>
>          Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),<br>
>          IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),<br>
> -        NextInPosition(nullptr), NextInPool(nullptr) {<br>
> +        IsContextSensitiveKeyword(false), NextInPosition(nullptr),<br>
> +        NextInPool(nullptr) {<br>
>      new (&getTypeBuffer()) ParsedType(typeArg);<br>
>      AttrKind = getKind(getName(), getScopeName(), syntaxUsed);<br>
>    }<br>
> @@ -309,7 +316,8 @@ private:<br>
>        ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),<br>
>        Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),<br>
>        IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),<br>
> -      NextInPosition(nullptr), NextInPool(nullptr) {<br>
> +      IsContextSensitiveKeyword(false), NextInPosition(nullptr),<br>
> +      NextInPool(nullptr) {<br>
>      new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);<br>
>      AttrKind = getKind(getName(), getScopeName(), syntaxUsed);<br>
>    }<br>
> @@ -352,6 +360,15 @@ public:<br>
>    }<br>
>    bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword; }<br>
><br>
> +  bool isContextSensitiveKeywordAttribute() const {<br>
> +    return IsContextSensitiveKeyword;<br>
> +  }<br>
> +<br>
> +  void setContextSensitiveKeywordAttribute() {<br>
> +    assert(SyntaxUsed == AS_Keyword);<br>
> +    IsContextSensitiveKeyword = true;<br>
> +  }<br>
> +<br>
>    bool isInvalid() const { return Invalid; }<br>
>    void setInvalid(bool b = true) const { Invalid = b; }<br>
><br>
><br>
> Modified: cfe/trunk/include/clang/Sema/DeclSpec.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Sema_DeclSpec.h-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=_zt_vW54MDvNmxURs5HOKDtlEOhVvlZm4vGTSNMz2A4&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)<br>
> +++ cfe/trunk/include/clang/Sema/DeclSpec.h Fri Jun 19 13:14:38 2015<br>
> @@ -31,6 +31,7 @@<br>
>  #include "clang/Lex/Token.h"<br>
>  #include "clang/Sema/AttributeList.h"<br>
>  #include "clang/Sema/Ownership.h"<br>
> +#include "llvm/ADT/Optional.h"<br>
>  #include "llvm/ADT/SmallVector.h"<br>
>  #include "llvm/Support/Compiler.h"<br>
>  #include "llvm/Support/ErrorHandling.h"<br>
> @@ -785,7 +786,8 @@ public:<br>
>      DQ_Out = 0x4,<br>
>      DQ_Bycopy = 0x8,<br>
>      DQ_Byref = 0x10,<br>
> -    DQ_Oneway = 0x20<br>
> +    DQ_Oneway = 0x20,<br>
> +    DQ_CSNullability = 0x40<br>
>    };<br>
><br>
>    /// PropertyAttributeKind - list of property attributes.<br>
> @@ -802,17 +804,21 @@ public:<br>
>      DQ_PR_atomic = 0x100,<br>
>      DQ_PR_weak =   0x200,<br>
>      DQ_PR_strong = 0x400,<br>
> -    DQ_PR_unsafe_unretained = 0x800<br>
> +    DQ_PR_unsafe_unretained = 0x800,<br>
> +    DQ_PR_nullability = 0x1000<br>
>    };<br>
><br>
> -<br>
>    ObjCDeclSpec()<br>
>      : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr),<br>
> -      GetterName(nullptr), SetterName(nullptr) { }<br>
> +      Nullability(0), GetterName(nullptr), SetterName(nullptr) { }<br>
> +<br>
>    ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; }<br>
>    void setObjCDeclQualifier(ObjCDeclQualifier DQVal) {<br>
>      objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal);<br>
>    }<br>
> +  void clearObjCDeclQualifier(ObjCDeclQualifier DQVal) {<br>
> +    objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier & ~DQVal);<br>
> +  }<br>
><br>
>    ObjCPropertyAttributeKind getPropertyAttributes() const {<br>
>      return ObjCPropertyAttributeKind(PropertyAttributes);<br>
> @@ -822,6 +828,28 @@ public:<br>
>        (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal);<br>
>    }<br>
><br>
> +  NullabilityKind getNullability() const {<br>
> +    assert(((getObjCDeclQualifier() & DQ_CSNullability) ||<br>
> +            (getPropertyAttributes() & DQ_PR_nullability)) &&<br>
> +           "Objective-C declspec doesn't have nullability");<br>
> +    return static_cast<NullabilityKind>(Nullability);<br>
> +  }<br>
> +<br>
> +  SourceLocation getNullabilityLoc() const {<br>
> +    assert(((getObjCDeclQualifier() & DQ_CSNullability) ||<br>
> +            (getPropertyAttributes() & DQ_PR_nullability)) &&<br>
> +           "Objective-C declspec doesn't have nullability");<br>
> +    return NullabilityLoc;<br>
> +  }<br>
> +<br>
> +  void setNullability(SourceLocation loc, NullabilityKind kind) {<br>
> +    assert(((getObjCDeclQualifier() & DQ_CSNullability) ||<br>
> +            (getPropertyAttributes() & DQ_PR_nullability)) &&<br>
> +           "Set the nullability declspec or property attribute first");<br>
> +    Nullability = static_cast<unsigned>(kind);<br>
> +    NullabilityLoc = loc;<br>
> +  }<br>
> +<br>
>    const IdentifierInfo *getGetterName() const { return GetterName; }<br>
>    IdentifierInfo *getGetterName() { return GetterName; }<br>
>    void setGetterName(IdentifierInfo *name) { GetterName = name; }<br>
> @@ -834,10 +862,15 @@ private:<br>
>    // FIXME: These two are unrelated and mutually exclusive. So perhaps<br>
>    // we can put them in a union to reflect their mutual exclusivity<br>
>    // (space saving is negligible).<br>
> -  ObjCDeclQualifier objcDeclQualifier : 6;<br>
> +  ObjCDeclQualifier objcDeclQualifier : 7;<br>
><br>
>    // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind<br>
> -  unsigned PropertyAttributes : 12;<br>
> +  unsigned PropertyAttributes : 13;<br>
> +<br>
> +  unsigned Nullability : 2;<br>
> +<br>
> +  SourceLocation NullabilityLoc;<br>
> +<br>
>    IdentifierInfo *GetterName;    // getter name or NULL if no getter<br>
>    IdentifierInfo *SetterName;    // setter name or NULL if no setter<br>
>  };<br>
><br>
> Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_include_clang_Sema_Sema.h-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=Yo7xXTF07eHr6SGqNCf1fRk8r_M3uqCwFLyIzlForpY&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
> +++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun 19 13:14:38 2015<br>
> @@ -2859,6 +2859,26 @@ public:<br>
>    /// Valid types should not have multiple attributes with different CCs.<br>
>    const AttributedType *getCallingConvAttributedType(QualType T) const;<br>
><br>
> +  /// Check whether a nullability type specifier can be added to the given<br>
> +  /// type.<br>
> +  ///<br>
> +  /// \param type The type to which the nullability specifier will be<br>
> +  /// added. On success, this type will be updated appropriately.<br>
> +  ///<br>
> +  /// \param nullability The nullability specifier to add.<br>
> +  ///<br>
> +  /// \param nullabilityLoc The location of the nullability specifier.<br>
> +  ///<br>
> +  /// \param isContextSensitive Whether this nullability specifier was<br>
> +  /// written as a context-sensitive keyword (in an Objective-C<br>
> +  /// method) or an Objective-C property attribute, rather than as an<br>
> +  /// underscored type specifier.<br>
> +  ///<br>
> +  /// \returns true if nullability cannot be applied, false otherwise.<br>
> +  bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind nullability,<br>
> +                                     SourceLocation nullabilityLoc,<br>
> +                                     bool isContextSensitive);<br>
> +<br>
>    /// \brief Stmt attributes - this routine is the top level dispatcher.<br>
>    StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs,<br>
>                                     SourceRange Range);<br>
> @@ -2934,7 +2954,8 @@ public:<br>
>                        const unsigned Attributes,<br>
>                        const unsigned AttributesAsWritten,<br>
>                        bool *isOverridingProperty,<br>
> -                      TypeSourceInfo *T,<br>
> +                      QualType T,<br>
> +                      TypeSourceInfo *TSI,<br>
>                        tok::ObjCKeywordKind MethodImplKind);<br>
><br>
>    /// Called by ActOnProperty and HandlePropertyInClassExtension to<br>
> @@ -2950,7 +2971,8 @@ public:<br>
>                                         const bool isReadWrite,<br>
>                                         const unsigned Attributes,<br>
>                                         const unsigned AttributesAsWritten,<br>
> -                                       TypeSourceInfo *T,<br>
> +                                       QualType T,<br>
> +                                       TypeSourceInfo *TSI,<br>
>                                         tok::ObjCKeywordKind MethodImplKind,<br>
>                                         DeclContext *lexicalDC = nullptr);<br>
><br>
><br>
> Modified: cfe/trunk/lib/AST/ASTImporter.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_AST_ASTImporter.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=FdQlZGubezqHhBQhMrYoy4WpYpb-dCXGiuyS9U5iSoA&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)<br>
> +++ cfe/trunk/lib/AST/ASTImporter.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -3922,8 +3922,8 @@ Decl *ASTNodeImporter::VisitObjCProperty<br>
>    }<br>
><br>
>    // Import the type.<br>
> -  TypeSourceInfo *T = Importer.Import(D->getTypeSourceInfo());<br>
> -  if (!T)<br>
> +  TypeSourceInfo *TSI = Importer.Import(D->getTypeSourceInfo());<br>
> +  if (!TSI)<br>
>      return nullptr;<br>
><br>
>    // Create the new property.<br>
> @@ -3932,7 +3932,8 @@ Decl *ASTNodeImporter::VisitObjCProperty<br>
>                                 Name.getAsIdentifierInfo(),<br>
>                                 Importer.Import(D->getAtLoc()),<br>
>                                 Importer.Import(D->getLParenLoc()),<br>
> -                               T,<br>
> +                               Importer.Import(D->getType()),<br>
> +                               TSI,<br>
>                                 D->getPropertyImplementation());<br>
>    Importer.Imported(D, ToProperty);<br>
>    ToProperty->setLexicalDeclContext(LexicalDC);<br>
><br>
> Modified: cfe/trunk/lib/AST/DeclObjC.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_AST_DeclObjC.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=ZHZu184ZbkHZNqLuhd0aqRzXedbFUQ61UvrYoPXycdw&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/AST/DeclObjC.cpp (original)<br>
> +++ cfe/trunk/lib/AST/DeclObjC.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -1862,16 +1862,18 @@ ObjCPropertyDecl *ObjCPropertyDecl::Crea<br>
>                                             IdentifierInfo *Id,<br>
>                                             SourceLocation AtLoc,<br>
>                                             SourceLocation LParenLoc,<br>
> -                                           TypeSourceInfo *T,<br>
> +                                           QualType T,<br>
> +                                           TypeSourceInfo *TSI,<br>
>                                             PropertyControl propControl) {<br>
> -  return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T);<br>
> +  return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T, TSI,<br>
> +                                      propControl);<br>
>  }<br>
><br>
>  ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,<br>
>                                                         unsigned ID) {<br>
>    return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr,<br>
>                                        SourceLocation(), SourceLocation(),<br>
> -                                      nullptr);<br>
> +                                      QualType(), nullptr, None);<br>
>  }<br>
><br>
>  //===----------------------------------------------------------------------===//<br>
><br>
> Modified: cfe/trunk/lib/AST/DeclPrinter.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_AST_DeclPrinter.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=TH1ncJwVDQ7GxMypF8hK4NYCItzMRIgQwqXApgHTO_8&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/AST/DeclPrinter.cpp (original)<br>
> +++ cfe/trunk/lib/AST/DeclPrinter.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -37,6 +37,13 @@ namespace {<br>
><br>
>      void Print(AccessSpecifier AS);<br>
><br>
> +    /// Print an Objective-C method type in parentheses.<br>
> +    ///<br>
> +    /// \param Quals The Objective-C declaration qualifiers.<br>
> +    /// \param T The type to print.<br>
> +    void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,<br>
> +                             QualType T);<br>
> +<br>
>    public:<br>
>      DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,<br>
>                  unsigned Indentation = 0, bool PrintInstantiation = false)<br>
> @@ -930,24 +937,64 @@ void DeclPrinter::VisitClassTemplateDecl<br>
>  // Objective-C declarations<br>
>  //----------------------------------------------------------------------------<br>
><br>
> +/// Strip off the top-level nullability annotation, if it's there.<br>
> +static Optional<NullabilityKind> stripOuterNullability(QualType &T) {<br>
> +  if (auto attributed = dyn_cast<AttributedType>(T.getTypePtr())) {<br>
> +    if (auto nullability = attributed->getImmediateNullability()) {<br>
> +      T = attributed->getModifiedType();<br>
> +      return nullability;<br>
> +    }<br>
> +  }<br>
> +<br>
> +  return None;<br>
> + }<br>
> +<br>
> +void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,<br>
> +                                      Decl::ObjCDeclQualifier Quals,<br>
> +                                      QualType T) {<br>
> +  Out << '(';<br>
> +  if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)<br>
> +    Out << "in ";<br>
> +  if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout)<br>
> +    Out << "inout ";<br>
> +  if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out)<br>
> +    Out << "out ";<br>
> +  if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy)<br>
> +    Out << "bycopy ";<br>
> +  if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref)<br>
> +    Out << "byref ";<br>
> +  if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)<br>
> +    Out << "oneway ";<br>
> +  if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {<br>
> +    if (auto nullability = stripOuterNullability(T)) {<br>
> +      Out << getNullabilitySpelling(*nullability).substr(2) << ' ';<br>
> +    }<br>
> +  }<br>
> +<br>
> +  Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy);<br>
> +  Out << ')';<br>
> +}<br>
> +<br>
>  void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {<br>
>    if (OMD->isInstanceMethod())<br>
>      Out << "- ";<br>
>    else<br>
>      Out << "+ ";<br>
> -  if (!OMD->getReturnType().isNull())<br>
> -    Out << '(' << OMD->getASTContext()<br>
> -                      .getUnqualifiedObjCPointerType(OMD->getReturnType())<br>
> -                      .getAsString(Policy) << ")";<br>
> +  if (!OMD->getReturnType().isNull()) {<br>
> +    PrintObjCMethodType(OMD->getASTContext(), OMD->getObjCDeclQualifier(),<br>
> +                        OMD->getReturnType());<br>
> +  }<br>
><br>
>    std::string name = OMD->getSelector().getAsString();<br>
>    std::string::size_type pos, lastPos = 0;<br>
>    for (const auto *PI : OMD->params()) {<br>
>      // FIXME: selector is missing here!<br>
>      pos = name.find_first_of(':', lastPos);<br>
> -    Out << " " << name.substr(lastPos, pos - lastPos);<br>
> -    Out << ":(" << PI->getASTContext().getUnqualifiedObjCPointerType(PI->getType()).<br>
> -                      getAsString(Policy) << ')' << *PI;<br>
> +    Out << " " << name.substr(lastPos, pos - lastPos) << ':';<br>
> +    PrintObjCMethodType(OMD->getASTContext(),<br>
> +                        PI->getObjCDeclQualifier(),<br>
> +                        PI->getType());<br>
> +    Out << *PI;<br>
>      lastPos = pos + 1;<br>
>    }<br>
><br>
> @@ -1103,6 +1150,8 @@ void DeclPrinter::VisitObjCPropertyDecl(<br>
>    else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)<br>
>      Out << "@optional\n";<br>
><br>
> +  QualType T = PDecl->getType();<br>
> +<br>
>    Out << "@property";<br>
>    if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {<br>
>      bool first = true;<br>
> @@ -1161,10 +1210,19 @@ void DeclPrinter::VisitObjCPropertyDecl(<br>
>        first = false;<br>
>      }<br>
><br>
> +    if (PDecl->getPropertyAttributes() &<br>
> +        ObjCPropertyDecl::OBJC_PR_nullability) {<br>
> +      if (auto nullability = stripOuterNullability(T)) {<br>
> +        Out << (first ? ' ' : ',')<br>
> +            << getNullabilitySpelling(*nullability).substr(2);<br>
> +        first = false;<br>
> +      }<br>
> +    }<br>
> +<br>
>      (void) first; // Silence dead store warning due to idiomatic code.<br>
>      Out << " )";<br>
>    }<br>
> -  Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(PDecl->getType()).<br>
> +  Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(T).<br>
>                    getAsString(Policy) << ' ' << *PDecl;<br>
>    if (Policy.PolishForDeclaration)<br>
>      Out << ';';<br>
><br>
> Modified: cfe/trunk/lib/Basic/IdentifierTable.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Basic_IdentifierTable.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=xt8SNWuSA_J6nPnI4h0L23HtPvLHrENWdRZk1q72piw&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/IdentifierTable.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Basic/IdentifierTable.cpp (original)<br>
> +++ cfe/trunk/lib/Basic/IdentifierTable.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -16,6 +16,7 @@<br>
>  #include "clang/Basic/IdentifierTable.h"<br>
>  #include "clang/Basic/LangOptions.h"<br>
>  #include "clang/Basic/OperatorKinds.h"<br>
> +#include "clang/Basic/Specifiers.h"<br>
>  #include "llvm/ADT/DenseMap.h"<br>
>  #include "llvm/ADT/FoldingSet.h"<br>
>  #include "llvm/ADT/SmallString.h"<br>
> @@ -645,3 +646,16 @@ const char *clang::getOperatorSpelling(O<br>
><br>
>    llvm_unreachable("Invalid OverloadedOperatorKind!");<br>
>  }<br>
> +<br>
> +StringRef clang::getNullabilitySpelling(NullabilityKind kind) {<br>
> +  switch (kind) {<br>
> +  case NullabilityKind::NonNull:<br>
> +    return "__nonnull";<br>
> +<br>
> +  case NullabilityKind::Nullable:<br>
> +    return "__nullable";<br>
> +<br>
> +  case NullabilityKind::Unspecified:<br>
> +    return "__null_unspecified";<br>
> +  }<br>
> +}<br>
><br>
> Modified: cfe/trunk/lib/Parse/ParseObjc.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Parse_ParseObjc.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=5t3VmAKwCDfdFlFyFjrjxu8t3LnfoTDr3QVi9RjEsFI&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/ParseObjc.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/ParseObjc.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -13,6 +13,7 @@<br>
><br>
>  #include "clang/Parse/Parser.h"<br>
>  #include "RAIIObjectsForParser.h"<br>
> +#include "clang/AST/ASTContext.h"<br>
>  #include "clang/Basic/CharInfo.h"<br>
>  #include "clang/Parse/ParseDiagnostic.h"<br>
>  #include "clang/Sema/DeclSpec.h"<br>
> @@ -307,6 +308,58 @@ Decl *Parser::ParseObjCAtInterfaceDeclar<br>
>    return ClsType;<br>
>  }<br>
><br>
> +IdentifierInfo *Parser::getNullabilityKeyword(NullabilityKind nullability) {<br>
> +  switch (nullability) {<br>
> +  case NullabilityKind::NonNull:<br>
> +    if (!Ident___nonnull)<br>
> +      Ident___nonnull = PP.getIdentifierInfo("__nonnull");<br>
> +    return Ident___nonnull;<br>
> +<br>
> +  case NullabilityKind::Nullable:<br>
> +    if (!Ident___nullable)<br>
> +      Ident___nullable = PP.getIdentifierInfo("__nullable");<br>
> +    return Ident___nullable;<br>
> +<br>
> +  case NullabilityKind::Unspecified:<br>
> +    if (!Ident___null_unspecified)<br>
> +      Ident___null_unspecified = PP.getIdentifierInfo("__null_unspecified");<br>
> +    return Ident___null_unspecified;<br>
> +  }<br>
> +}<br>
> +<br>
> +/// Add an attribute for a context-sensitive type nullability to the given<br>
> +/// declarator.<br>
> +static void addContextSensitiveTypeNullability(Parser &P,<br>
> +                                               Declarator &D,<br>
> +                                               NullabilityKind nullability,<br>
> +                                               SourceLocation nullabilityLoc,<br>
> +                                               bool &addedToDeclSpec) {<br>
> +  // Create the attribute.<br>
> +  auto getNullabilityAttr = [&]() -> AttributeList * {<br>
> +    auto attr = D.getAttributePool().create(<br>
> +                  P.getNullabilityKeyword(nullability),<br>
> +                  SourceRange(nullabilityLoc),<br>
> +                  nullptr, SourceLocation(),<br>
> +                  nullptr, 0,<br>
> +                  AttributeList::AS_Keyword);<br>
> +    attr->setContextSensitiveKeywordAttribute();<br>
> +    return attr;<br>
> +  };<br>
> +<br>
> +  if (D.getNumTypeObjects() > 0) {<br>
> +    // Add the attribute to the declarator chunk nearest the declarator.<br>
> +    auto nullabilityAttr = getNullabilityAttr();<br>
> +    DeclaratorChunk &chunk = D.getTypeObject(0);<br>
> +    nullabilityAttr->setNext(chunk.getAttrListRef());<br>
> +    chunk.getAttrListRef() = nullabilityAttr;<br>
> +  } else if (!addedToDeclSpec) {<br>
> +    // Otherwise, just put it on the declaration specifiers (if one<br>
> +    // isn't there already).<br>
> +    D.getMutableDeclSpec().addAttributes(getNullabilityAttr());<br>
> +    addedToDeclSpec = true;<br>
> +  }<br>
> +}<br>
> +<br>
>  ///   objc-interface-decl-list:<br>
>  ///     empty<br>
>  ///     objc-interface-decl-list objc-property-decl [OBJC2]<br>
> @@ -445,6 +498,7 @@ void Parser::ParseObjCInterfaceDeclList(<br>
>          ParseObjCPropertyAttribute(OCDS);<br>
>        }<br>
><br>
> +      bool addedToDeclSpec = false;<br>
>        auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) {<br>
>          if (FD.D.getIdentifier() == nullptr) {<br>
>            Diag(AtLoc, diag::err_objc_property_requires_field_name)<br>
> @@ -457,6 +511,13 @@ void Parser::ParseObjCInterfaceDeclList(<br>
>            return;<br>
>          }<br>
><br>
> +        // Map a nullability property attribute to a context-sensitive keyword<br>
> +        // attribute.<br>
> +        if (OCDS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)<br>
> +          addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(),<br>
> +                                             OCDS.getNullabilityLoc(),<br>
> +                                             addedToDeclSpec);<br>
> +<br>
>          // Install the property declarator into interfaceDecl.<br>
>          IdentifierInfo *SelName =<br>
>              OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();<br>
> @@ -510,6 +571,24 @@ void Parser::ParseObjCInterfaceDeclList(<br>
>    Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables);<br>
>  }<br>
><br>
> +/// Diagnose redundant or conflicting nullability information.<br>
> +static void diagnoseRedundantPropertyNullability(Parser &P,<br>
> +                                                 ObjCDeclSpec &DS,<br>
> +                                                 NullabilityKind nullability,<br>
> +                                                 SourceLocation nullabilityLoc){<br>
> +  if (DS.getNullability() == nullability) {<br>
> +    P.Diag(nullabilityLoc, diag::warn_nullability_duplicate)<br>
> +      << static_cast<unsigned>(nullability) << true<br>
> +      << SourceRange(DS.getNullabilityLoc());<br>
> +    return;<br>
> +  }<br>
> +<br>
> +  P.Diag(nullabilityLoc, diag::err_nullability_conflicting)<br>
> +    << static_cast<unsigned>(nullability) << true<br>
> +    << static_cast<unsigned>(DS.getNullability()) << true<br>
> +    << SourceRange(DS.getNullabilityLoc());<br>
> +}<br>
> +<br>
>  ///   Parse property attribute declarations.<br>
>  ///<br>
>  ///   property-attr-decl: '(' property-attrlist ')'<br>
> @@ -529,6 +608,9 @@ void Parser::ParseObjCInterfaceDeclList(<br>
>  ///     strong<br>
>  ///     weak<br>
>  ///     unsafe_unretained<br>
> +///     nonnull<br>
> +///     nullable<br>
> +///     null_unspecified<br>
>  ///<br>
>  void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {<br>
>    assert(Tok.getKind() == tok::l_paren);<br>
> @@ -614,6 +696,27 @@ void Parser::ParseObjCPropertyAttribute(<br>
>          DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);<br>
>          DS.setGetterName(SelIdent);<br>
>        }<br>
> +    } else if (II->isStr("nonnull")) {<br>
> +      if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)<br>
> +        diagnoseRedundantPropertyNullability(*this, DS,<br>
> +                                             NullabilityKind::NonNull,<br>
> +                                             Tok.getLocation());<br>
> +      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);<br>
> +      DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull);<br>
> +    } else if (II->isStr("nullable")) {<br>
> +      if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)<br>
> +        diagnoseRedundantPropertyNullability(*this, DS,<br>
> +                                             NullabilityKind::Nullable,<br>
> +                                             Tok.getLocation());<br>
> +      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);<br>
> +      DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable);<br>
> +    } else if (II->isStr("null_unspecified")) {<br>
> +      if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)<br>
> +        diagnoseRedundantPropertyNullability(*this, DS,<br>
> +                                             NullabilityKind::Unspecified,<br>
> +                                             Tok.getLocation());<br>
> +      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);<br>
> +      DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);<br>
>      } else {<br>
>        Diag(AttrName, diag::err_objc_expected_property_attr) << II;<br>
>        SkipUntil(tok::r_paren, StopAtSemi);<br>
> @@ -779,6 +882,17 @@ bool Parser::isTokIdentifier_in() const<br>
>  ///     objc-type-qualifier<br>
>  ///     objc-type-qualifiers objc-type-qualifier<br>
>  ///<br>
> +///   objc-type-qualifier:<br>
> +///     'in'<br>
> +///     'out'<br>
> +///     'inout'<br>
> +///     'oneway'<br>
> +///     'bycopy'<br>
> +///     'byref'<br>
> +///     'nonnull'<br>
> +///     'nullable'<br>
> +///     'null_unspecified'<br>
> +///<br>
>  void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,<br>
>                                          Declarator::TheContext Context) {<br>
>    assert(Context == Declarator::ObjCParameterContext ||<br>
> @@ -796,10 +910,13 @@ void Parser::ParseObjCTypeQualifierList(<br>
><br>
>      const IdentifierInfo *II = Tok.getIdentifierInfo();<br>
>      for (unsigned i = 0; i != objc_NumQuals; ++i) {<br>
> -      if (II != ObjCTypeQuals[i])<br>
> +      if (II != ObjCTypeQuals[i] ||<br>
> +          NextToken().is(tok::less) ||<br>
> +          NextToken().is(tok::coloncolon))<br>
>          continue;<br>
><br>
>        ObjCDeclSpec::ObjCDeclQualifier Qual;<br>
> +      NullabilityKind Nullability;<br>
>        switch (i) {<br>
>        default: llvm_unreachable("Unknown decl qualifier");<br>
>        case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;<br>
> @@ -808,8 +925,28 @@ void Parser::ParseObjCTypeQualifierList(<br>
>        case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;<br>
>        case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;<br>
>        case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;<br>
> +<br>
> +      case objc_nonnull:<br>
> +        Qual = ObjCDeclSpec::DQ_CSNullability;<br>
> +        Nullability = NullabilityKind::NonNull;<br>
> +        break;<br>
> +<br>
> +      case objc_nullable:<br>
> +        Qual = ObjCDeclSpec::DQ_CSNullability;<br>
> +        Nullability = NullabilityKind::Nullable;<br>
> +        break;<br>
> +<br>
> +      case objc_null_unspecified:<br>
> +        Qual = ObjCDeclSpec::DQ_CSNullability;<br>
> +        Nullability = NullabilityKind::Unspecified;<br>
> +        break;<br>
>        }<br>
> +<br>
> +      // FIXME: Diagnose redundant specifiers.<br>
>        DS.setObjCDeclQualifier(Qual);<br>
> +      if (Qual == ObjCDeclSpec::DQ_CSNullability)<br>
> +        DS.setNullability(Tok.getLocation(), Nullability);<br>
> +<br>
>        ConsumeToken();<br>
>        II = nullptr;<br>
>        break;<br>
> @@ -889,6 +1026,14 @@ ParsedType Parser::ParseObjCTypeName(Obj<br>
><br>
>      // If that's not invalid, extract a type.<br>
>      if (!declarator.isInvalidType()) {<br>
> +      // Map a nullability specifier to a context-sensitive keyword attribute.<br>
> +      bool addedToDeclSpec = false;<br>
> +      if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability)<br>
> +        addContextSensitiveTypeNullability(*this, declarator,<br>
> +                                           DS.getNullability(),<br>
> +                                           DS.getNullabilityLoc(),<br>
> +                                           addedToDeclSpec);<br>
> +<br>
>        TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator);<br>
>        if (!type.isInvalid())<br>
>          Ty = type.get();<br>
> @@ -904,8 +1049,34 @@ ParsedType Parser::ParseObjCTypeName(Obj<br>
>        Ident_instancetype = PP.getIdentifierInfo("instancetype");<br>
><br>
>      if (Tok.getIdentifierInfo() == Ident_instancetype) {<br>
> -      Ty = Actions.ActOnObjCInstanceType(Tok.getLocation());<br>
> -      ConsumeToken();<br>
> +      SourceLocation loc = ConsumeToken();<br>
> +      Ty = Actions.ActOnObjCInstanceType(loc);<br>
> +<br>
> +      // Map a nullability specifier to a context-sensitive keyword attribute.<br>
> +      if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) {<br>
> +        // Synthesize an abstract declarator so we can use Sema::ActOnTypeName.<br>
> +        bool addedToDeclSpec = false;<br>
> +        const char *prevSpec;<br>
> +        unsigned diagID;<br>
> +        DeclSpec declSpec(AttrFactory);<br>
> +        declSpec.setObjCQualifiers(&DS);<br>
> +        declSpec.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, diagID,<br>
> +                                 Ty,<br>
> +                                 Actions.getASTContext().getPrintingPolicy());<br>
> +        declSpec.SetRangeEnd(loc);<br>
> +        Declarator declarator(declSpec, context);<br>
> +<br>
> +        // Add the context-sensitive keyword attribute.<br>
> +        addContextSensitiveTypeNullability(*this, declarator,<br>
> +                                           DS.getNullability(),<br>
> +                                           DS.getNullabilityLoc(),<br>
> +                                           addedToDeclSpec);<br>
> +<br>
> +<br>
> +        TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator);<br>
> +        if (!type.isInvalid())<br>
> +          Ty = type.get();<br>
> +      }<br>
>      }<br>
>    }<br>
><br>
><br>
> Modified: cfe/trunk/lib/Parse/Parser.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Parse_Parser.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=EzrULAU33cluQ7Wv2wlgIJi4E3NUvl1gOz0vi03Dsb8&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/Parser.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/Parser.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -463,6 +463,10 @@ void Parser::Initialize() {<br>
>      ObjCTypeQuals[objc_oneway] = &PP.getIdentifierTable().get("oneway");<br>
>      ObjCTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy");<br>
>      ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");<br>
> +    ObjCTypeQuals[objc_nonnull] = &PP.getIdentifierTable().get("nonnull");<br>
> +    ObjCTypeQuals[objc_nullable] = &PP.getIdentifierTable().get("nullable");<br>
> +    ObjCTypeQuals[objc_null_unspecified]<br>
> +      = &PP.getIdentifierTable().get("null_unspecified");<br>
>    }<br>
><br>
>    Ident_instancetype = nullptr;<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Sema_SemaDecl.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=jSP0BH-szuL_Oop7nz9BdxZXh7skh8xsdX8BwhpKwos&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -2471,9 +2471,13 @@ static void mergeParamDeclTypes(ParmVarD<br>
>    if (auto Oldnullability = OldParam->getType()->getNullability(S.Context)) {<br>
>      if (auto Newnullability = NewParam->getType()->getNullability(S.Context)) {<br>
>        if (*Oldnullability != *Newnullability) {<br>
> +        unsigned unsNewnullability = static_cast<unsigned>(*Newnullability);<br>
> +        unsigned unsOldnullability = static_cast<unsigned>(*Oldnullability);<br>
>          S.Diag(NewParam->getLocation(), diag::warn_mismatched_nullability_attr)<br>
> -          << static_cast<unsigned>(*Newnullability)<br>
> -          << static_cast<unsigned>(*Oldnullability);<br>
> +          << unsNewnullability<br>
> +          << ((NewParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)<br>
> +          << unsOldnullability<br>
> +          << ((OldParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0);<br>
>          S.Diag(OldParam->getLocation(), diag::note_previous_declaration);<br>
>        }<br>
>      }<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Sema_SemaDeclObjC.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=VPaEAvT7z_CoVuJ329fMoZOGGzoPKUszgoVlLYb9Wts&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -1366,6 +1366,13 @@ static SourceRange getTypeRange(TypeSour<br>
>    return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange());<br>
>  }<br>
><br>
> +/// Determine whether two set of Objective-C declaration qualifiers conflict.<br>
> +static bool objcModifiersConflict(Decl::ObjCDeclQualifier x,<br>
> +                                  Decl::ObjCDeclQualifier y) {<br>
> +  return (x & ~Decl::OBJC_TQ_CSNullability) !=<br>
> +         (y & ~Decl::OBJC_TQ_CSNullability);<br>
> +}<br>
> +<br>
>  static bool CheckMethodOverrideReturn(Sema &S,<br>
>                                        ObjCMethodDecl *MethodImpl,<br>
>                                        ObjCMethodDecl *MethodDecl,<br>
> @@ -1373,8 +1380,8 @@ static bool CheckMethodOverrideReturn(Se<br>
>                                        bool IsOverridingMode,<br>
>                                        bool Warn) {<br>
>    if (IsProtocolMethodDecl &&<br>
> -      (MethodDecl->getObjCDeclQualifier() !=<br>
> -       MethodImpl->getObjCDeclQualifier())) {<br>
> +      objcModifiersConflict(MethodDecl->getObjCDeclQualifier(),<br>
> +                            MethodImpl->getObjCDeclQualifier())) {<br>
>      if (Warn) {<br>
>        S.Diag(MethodImpl->getLocation(),<br>
>               (IsOverridingMode<br>
> @@ -1388,7 +1395,24 @@ static bool CheckMethodOverrideReturn(Se<br>
>      else<br>
>        return false;<br>
>    }<br>
> -<br>
> +  if (Warn && IsOverridingMode &&<br>
> +      !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&<br>
> +      !S.Context.hasSameNullabilityTypeQualifier(MethodImpl->getReturnType(),<br>
> +                                                 MethodDecl->getReturnType(),<br>
> +                                                 false)) {<br>
> +    unsigned unsNullabilityMethodImpl =<br>
> +      static_cast<unsigned>(*MethodImpl->getReturnType()->getNullability(S.Context));<br>
> +    unsigned unsNullabilityMethodDecl =<br>
> +      static_cast<unsigned>(*MethodDecl->getReturnType()->getNullability(S.Context));<br>
> +      S.Diag(MethodImpl->getLocation(),<br>
> +             diag::warn_conflicting_nullability_attr_overriding_ret_types)<br>
> +        << unsNullabilityMethodImpl<br>
> +        << ((MethodImpl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)<br>
> +        << unsNullabilityMethodDecl<br>
> +        << ((MethodDecl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0);<br>
> +      S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration);<br>
> +  }<br>
> +<br>
>    if (S.Context.hasSameUnqualifiedType(MethodImpl->getReturnType(),<br>
>                                         MethodDecl->getReturnType()))<br>
>      return true;<br>
> @@ -1438,8 +1462,8 @@ static bool CheckMethodOverrideParam(Sem<br>
>                                       bool IsOverridingMode,<br>
>                                       bool Warn) {<br>
>    if (IsProtocolMethodDecl &&<br>
> -      (ImplVar->getObjCDeclQualifier() !=<br>
> -       IfaceVar->getObjCDeclQualifier())) {<br>
> +      objcModifiersConflict(ImplVar->getObjCDeclQualifier(),<br>
> +                            IfaceVar->getObjCDeclQualifier())) {<br>
>      if (Warn) {<br>
>        if (IsOverridingMode)<br>
>          S.Diag(ImplVar->getLocation(),<br>
> @@ -1459,7 +1483,19 @@ static bool CheckMethodOverrideParam(Sem<br>
><br>
>    QualType ImplTy = ImplVar->getType();<br>
>    QualType IfaceTy = IfaceVar->getType();<br>
> -<br>
> +  if (Warn && IsOverridingMode &&<br>
> +      !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&<br>
> +      !S.Context.hasSameNullabilityTypeQualifier(ImplTy, IfaceTy, true)) {<br>
> +    unsigned unsImplTy = static_cast<unsigned>(*ImplTy->getNullability(S.Context));<br>
> +    unsigned unsIfaceTy = static_cast<unsigned>(*IfaceTy->getNullability(S.Context));<br>
> +    S.Diag(ImplVar->getLocation(),<br>
> +           diag::warn_conflicting_nullability_attr_overriding_param_types)<br>
> +        << unsImplTy<br>
> +        << ((ImplVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)<br>
> +        << unsIfaceTy<br>
> +        << ((IfaceVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0);<br>
> +        S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration);<br>
> +  }<br>
>    if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))<br>
>      return true;<br>
><br>
> @@ -3121,6 +3157,89 @@ void Sema::CheckObjCMethodOverrides(ObjC<br>
>    ObjCMethod->setOverriding(hasOverriddenMethodsInBaseOrProtocol);<br>
>  }<br>
><br>
> +/// Merge type nullability from for a redeclaration of the same entity,<br>
> +/// producing the updated type of the redeclared entity.<br>
> +static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc,<br>
> +                                              QualType type,<br>
> +                                              bool usesCSKeyword,<br>
> +                                              SourceLocation prevLoc,<br>
> +                                              QualType prevType,<br>
> +                                              bool prevUsesCSKeyword) {<br>
> +  // Determine the nullability of both types.<br>
> +  auto nullability = type->getNullability(S.Context);<br>
> +  auto prevNullability = prevType->getNullability(S.Context);<br>
> +<br>
> +  // Easy case: both have nullability.<br>
> +  if (nullability.hasValue() == prevNullability.hasValue()) {<br>
> +    // Neither has nullability; continue.<br>
> +    if (!nullability)<br>
> +      return type;<br>
> +<br>
> +    // The nullabilities are equivalent; do nothing.<br>
> +    if (*nullability == *prevNullability)<br>
> +      return type;<br>
> +<br>
> +    // Complain about mismatched nullability.<br>
> +    S.Diag(loc, diag::err_nullability_conflicting)<br>
> +      << static_cast<unsigned>(*nullability) << usesCSKeyword<br>
> +      << static_cast<unsigned>(*prevNullability) << prevUsesCSKeyword;<br>
> +    return type;<br>
> +  }<br>
> +<br>
> +  // If it's the redeclaration that has nullability, don't change anything.<br>
> +  if (nullability)<br>
> +    return type;<br>
> +<br>
> +  // Otherwise, provide the result with the same nullability.<br>
> +  return S.Context.getAttributedType(<br>
> +           AttributedType::getNullabilityAttrKind(*prevNullability),<br>
> +           type, type);<br>
> +}<br>
> +<br>
> +/// Merge information from the declaration of a method in the @interface<br>
> +/// (or a category/extension) into the corresponding method in the<br>
> +/// @implementation (for a class or category).<br>
> +static void mergeInterfaceMethodToImpl(Sema &S,<br>
> +                                       ObjCMethodDecl *method,<br>
> +                                       ObjCMethodDecl *prevMethod) {<br>
> +  // Merge the objc_requires_super attribute.<br>
> +  if (prevMethod->hasAttr<ObjCRequiresSuperAttr>() &&<br>
> +      !method->hasAttr<ObjCRequiresSuperAttr>()) {<br>
> +    // merge the attribute into implementation.<br>
> +    method->addAttr(<br>
> +      ObjCRequiresSuperAttr::CreateImplicit(S.Context,<br>
> +                                            method->getLocation()));<br>
> +  }<br>
> +<br>
> +  // Merge nullability of the result type.<br>
> +  QualType newReturnType<br>
> +    = mergeTypeNullabilityForRedecl(<br>
> +        S, method->getReturnTypeSourceRange().getBegin(),<br>
> +        method->getReturnType(),<br>
> +        method->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,<br>
> +        prevMethod->getReturnTypeSourceRange().getBegin(),<br>
> +        prevMethod->getReturnType(),<br>
> +        prevMethod->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);<br>
> +  method->setReturnType(newReturnType);<br>
> +<br>
> +  // Handle each of the parameters.<br>
> +  unsigned numParams = method->param_size();<br>
> +  unsigned numPrevParams = prevMethod->param_size();<br>
> +  for (unsigned i = 0, n = std::min(numParams, numPrevParams); i != n; ++i) {<br>
> +    ParmVarDecl *param = method->param_begin()[i];<br>
> +    ParmVarDecl *prevParam = prevMethod->param_begin()[i];<br>
> +<br>
> +    // Merge nullability.<br>
> +    QualType newParamType<br>
> +      = mergeTypeNullabilityForRedecl(<br>
> +          S, param->getLocation(), param->getType(),<br>
> +          param->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,<br>
> +          prevParam->getLocation(), prevParam->getType(),<br>
> +          prevParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);<br>
> +    param->setType(newParamType);<br>
> +  }<br>
> +}<br>
> +<br>
>  Decl *Sema::ActOnMethodDeclaration(<br>
>      Scope *S,<br>
>      SourceLocation MethodLoc, SourceLocation EndLoc,<br>
> @@ -3151,7 +3270,9 @@ Decl *Sema::ActOnMethodDeclaration(<br>
>      if (CheckFunctionReturnType(resultDeclType, MethodLoc))<br>
>        return nullptr;<br>
><br>
> -    HasRelatedResultType = (resultDeclType == Context.getObjCInstanceType());<br>
> +    QualType bareResultType = resultDeclType;<br>
> +    (void)AttributedType::stripOuterNullability(bareResultType);<br>
> +    HasRelatedResultType = (bareResultType == Context.getObjCInstanceType());<br>
>    } else { // get the type for "id".<br>
>      resultDeclType = Context.getObjCIdType();<br>
>      Diag(MethodLoc, diag::warn_missing_method_return_type)<br>
> @@ -3252,22 +3373,20 @@ Decl *Sema::ActOnMethodDeclaration(<br>
>        ImpDecl->addClassMethod(ObjCMethod);<br>
>      }<br>
><br>
> -    ObjCMethodDecl *IMD = nullptr;<br>
> -    if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface())<br>
> -      IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),<br>
> -                                ObjCMethod->isInstanceMethod());<br>
> -    if (IMD && IMD->hasAttr<ObjCRequiresSuperAttr>() &&<br>
> -        !ObjCMethod->hasAttr<ObjCRequiresSuperAttr>()) {<br>
> -      // merge the attribute into implementation.<br>
> -      ObjCMethod->addAttr(ObjCRequiresSuperAttr::CreateImplicit(Context,<br>
> -                                                   ObjCMethod->getLocation()));<br>
> -    }<br>
> -    if (isa<ObjCCategoryImplDecl>(ImpDecl)) {<br>
> -      ObjCMethodFamily family =<br>
> -        ObjCMethod->getSelector().getMethodFamily();<br>
> -      if (family == OMF_dealloc && IMD && IMD->isOverriding())<br>
> -        Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category)<br>
> -          << ObjCMethod->getDeclName();<br>
> +    // Merge information from the @interface declaration into the<br>
> +    // @implementation.<br>
> +    if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) {<br>
> +      if (auto *IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),<br>
> +                                          ObjCMethod->isInstanceMethod())) {<br>
> +        mergeInterfaceMethodToImpl(*this, ObjCMethod, IMD);<br>
> +<br>
> +        // Warn about defining -dealloc in a category.<br>
> +        if (isa<ObjCCategoryImplDecl>(ImpDecl) && IMD->isOverriding() &&<br>
> +            ObjCMethod->getSelector().getMethodFamily() == OMF_dealloc) {<br>
> +          Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category)<br>
> +            << ObjCMethod->getDeclName();<br>
> +        }<br>
> +      }<br>
>      }<br>
>    } else {<br>
>      cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Sema_SemaExprObjC.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=Rnq1c12O6ArdELYPQnfCF_Axo8IbHETcGPGkzuQDl8k&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -1135,49 +1135,150 @@ ObjCMethodDecl *Sema::tryCaptureObjCSelf<br>
>  }<br>
><br>
>  static QualType stripObjCInstanceType(ASTContext &Context, QualType T) {<br>
> +  QualType origType = T;<br>
> +  if (auto nullability = AttributedType::stripOuterNullability(T)) {<br>
> +    if (T == Context.getObjCInstanceType()) {<br>
> +      return Context.getAttributedType(<br>
> +               AttributedType::getNullabilityAttrKind(*nullability),<br>
> +               Context.getObjCIdType(),<br>
> +               Context.getObjCIdType());<br>
> +    }<br>
> +<br>
> +    return origType;<br>
> +  }<br>
> +<br>
>    if (T == Context.getObjCInstanceType())<br>
>      return Context.getObjCIdType();<br>
><br>
> -  return T;<br>
> +  return origType;<br>
>  }<br>
><br>
> -QualType Sema::getMessageSendResultType(QualType ReceiverType,<br>
> -                                        ObjCMethodDecl *Method,<br>
> -                                    bool isClassMessage, bool isSuperMessage) {<br>
> +/// Determine the result type of a message send based on the receiver type,<br>
> +/// method, and the kind of message send.<br>
> +///<br>
> +/// This is the "base" result type, which will still need to be adjusted<br>
> +/// to account for nullability.<br>
> +static QualType getBaseMessageSendResultType(Sema &S,<br>
> +                                             QualType ReceiverType,<br>
> +                                             ObjCMethodDecl *Method,<br>
> +                                             bool isClassMessage,<br>
> +                                             bool isSuperMessage) {<br>
>    assert(Method && "Must have a method");<br>
>    if (!Method->hasRelatedResultType())<br>
>      return Method->getSendResultType();<br>
> -<br>
> +<br>
> +  ASTContext &Context = S.Context;<br>
> +<br>
> +  // Local function that transfers the nullability of the method's<br>
> +  // result type to the returned result.<br>
> +  auto transferNullability = [&](QualType type) -> QualType {<br>
> +    // If the method's result type has nullability, extract it.<br>
> +    if (auto nullability = Method->getSendResultType()->getNullability(Context)){<br>
> +      // Strip off any outer nullability sugar from the provided type.<br>
> +      (void)AttributedType::stripOuterNullability(type);<br>
> +<br>
> +      // Form a new attributed type using the method result type's nullability.<br>
> +      return Context.getAttributedType(<br>
> +               AttributedType::getNullabilityAttrKind(*nullability),<br>
> +               type,<br>
> +               type);<br>
> +    }<br>
> +<br>
> +    return type;<br>
> +  };<br>
> +<br>
>    // If a method has a related return type:<br>
>    //   - if the method found is an instance method, but the message send<br>
>    //     was a class message send, T is the declared return type of the method<br>
>    //     found<br>
>    if (Method->isInstanceMethod() && isClassMessage)<br>
>      return stripObjCInstanceType(Context, Method->getSendResultType());<br>
> -<br>
> -  //   - if the receiver is super, T is a pointer to the class of the<br>
> +<br>
> +  //   - if the receiver is super, T is a pointer to the class of the<br>
>    //     enclosing method definition<br>
>    if (isSuperMessage) {<br>
> -    if (ObjCMethodDecl *CurMethod = getCurMethodDecl())<br>
> -      if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface())<br>
> -        return Context.getObjCObjectPointerType(<br>
> -                                        Context.getObjCInterfaceType(Class));<br>
> +    if (ObjCMethodDecl *CurMethod = S.getCurMethodDecl())<br>
> +      if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) {<br>
> +        return transferNullability(<br>
> +                 Context.getObjCObjectPointerType(<br>
> +                   Context.getObjCInterfaceType(Class)));<br>
> +      }<br>
>    }<br>
> -<br>
> +<br>
>    //   - if the receiver is the name of a class U, T is a pointer to U<br>
>    if (ReceiverType->getAs<ObjCInterfaceType>() ||<br>
>        ReceiverType->isObjCQualifiedInterfaceType())<br>
> -    return Context.getObjCObjectPointerType(ReceiverType);<br>
> -  //   - if the receiver is of type Class or qualified Class type,<br>
> +    return transferNullability(Context.getObjCObjectPointerType(ReceiverType));<br>
> +  //   - if the receiver is of type Class or qualified Class type,<br>
>    //     T is the declared return type of the method.<br>
>    if (ReceiverType->isObjCClassType() ||<br>
>        ReceiverType->isObjCQualifiedClassType())<br>
>      return stripObjCInstanceType(Context, Method->getSendResultType());<br>
> -<br>
> +<br>
>    //   - if the receiver is id, qualified id, Class, or qualified Class, T<br>
>    //     is the receiver type, otherwise<br>
>    //   - T is the type of the receiver expression.<br>
> -  return ReceiverType;<br>
> +  return transferNullability(ReceiverType);<br>
> +}<br>
> +<br>
> +QualType Sema::getMessageSendResultType(QualType ReceiverType,<br>
> +                                        ObjCMethodDecl *Method,<br>
> +                                        bool isClassMessage,<br>
> +                                        bool isSuperMessage) {<br>
> +  // Produce the result type.<br>
> +  QualType resultType = getBaseMessageSendResultType(*this, ReceiverType,<br>
> +                                                     Method,<br>
> +                                                     isClassMessage,<br>
> +                                                     isSuperMessage);<br>
> +<br>
> +  // Map the nullability of the result into a table index.<br>
> +  unsigned receiverNullabilityIdx = 0;<br>
> +  if (auto nullability = ReceiverType->getNullability(Context))<br>
> +    receiverNullabilityIdx = 1 + static_cast<unsigned>(*nullability);<br>
> +<br>
> +  unsigned resultNullabilityIdx = 0;<br>
> +  if (auto nullability = resultType->getNullability(Context))<br>
> +    resultNullabilityIdx = 1 + static_cast<unsigned>(*nullability);<br>
> +<br>
> +  // The table of nullability mappings, indexed by the receiver's nullability<br>
> +  // and then the result type's nullability.<br>
> +  static const uint8_t None = 0;<br>
> +  static const uint8_t NonNull = 1;<br>
> +  static const uint8_t Nullable = 2;<br>
> +  static const uint8_t Unspecified = 3;<br>
> +  static const uint8_t nullabilityMap[4][4] = {<br>
> +    //                  None        NonNull       Nullable    Unspecified<br>
> +    /* None */        { None,       None,         Nullable,   None },<br>
> +    /* NonNull */     { None,       NonNull,      Nullable,   Unspecified },<br>
> +    /* Nullable */    { Nullable,   Nullable,     Nullable,   Nullable },<br>
> +    /* Unspecified */ { None,       Unspecified,  Nullable,   Unspecified }<br>
> +  };<br>
> +<br>
> +  unsigned newResultNullabilityIdx<br>
> +    = nullabilityMap[receiverNullabilityIdx][resultNullabilityIdx];<br>
> +  if (newResultNullabilityIdx == resultNullabilityIdx)<br>
> +    return resultType;<br>
> +<br>
> +  // Strip off the existing nullability. This removes as little type sugar as<br>
> +  // possible.<br>
> +  do {<br>
> +    if (auto attributed = dyn_cast<AttributedType>(resultType.getTypePtr())) {<br>
> +      resultType = attributed->getModifiedType();<br>
> +    } else {<br>
> +      resultType = resultType.getDesugaredType(Context);<br>
> +    }<br>
<br>
Elide braces (here and elsewhere).<br>
<br>
> +  } while (resultType->getNullability(Context));<br>
> +<br>
> +  // Add nullability back if needed.<br>
> +  if (newResultNullabilityIdx > 0) {<br>
> +    auto newNullability<br>
> +      = static_cast<NullabilityKind>(newResultNullabilityIdx-1);<br>
> +    return Context.getAttributedType(<br>
> +             AttributedType::getNullabilityAttrKind(newNullability),<br>
> +             resultType, resultType);<br>
> +  }<br>
> +<br>
> +  return resultType;<br>
>  }<br>
><br>
>  /// Look for an ObjC method whose result type exactly matches the given type.<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Sema_SemaObjCProperty.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=Og4EexuhWY4SXR-osWqG-tXeld4nfEO7_CSVfmxbauA&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -149,7 +149,6 @@ Decl *Sema::ActOnProperty(Scope *S, Sour<br>
>    TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);<br>
>    QualType T = TSI->getType();<br>
>    Attributes |= deduceWeakPropertyFromType(*this, T);<br>
> -<br>
>    bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||<br>
>                        // default is readwrite!<br>
>                        !(Attributes & ObjCDeclSpec::DQ_PR_readonly));<br>
> @@ -173,7 +172,7 @@ Decl *Sema::ActOnProperty(Scope *S, Sour<br>
>                                             isAssign, isReadWrite,<br>
>                                             Attributes,<br>
>                                             ODS.getPropertyAttributes(),<br>
> -                                           isOverridingProperty, TSI,<br>
> +                                           isOverridingProperty, T, TSI,<br>
>                                             MethodImplKind);<br>
>        if (!Res)<br>
>          return nullptr;<br>
> @@ -184,7 +183,7 @@ Decl *Sema::ActOnProperty(Scope *S, Sour<br>
>      Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,<br>
>                               GetterSel, SetterSel, isAssign, isReadWrite,<br>
>                               Attributes, ODS.getPropertyAttributes(),<br>
> -                             TSI, MethodImplKind);<br>
> +                             T, TSI, MethodImplKind);<br>
>      if (lexicalDC)<br>
>        Res->setLexicalDeclContext(lexicalDC);<br>
>    }<br>
> @@ -322,7 +321,8 @@ Sema::HandlePropertyInClassExtension(Sco<br>
>                                       const unsigned Attributes,<br>
>                                       const unsigned AttributesAsWritten,<br>
>                                       bool *isOverridingProperty,<br>
> -                                     TypeSourceInfo *T,<br>
> +                                     QualType T,<br>
> +                                     TypeSourceInfo *TSI,<br>
>                                       tok::ObjCKeywordKind MethodImplKind) {<br>
>    ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(CurContext);<br>
>    // Diagnose if this property is already in continuation class.<br>
> @@ -348,7 +348,7 @@ Sema::HandlePropertyInClassExtension(Sco<br>
>    // FIXME. We should really be using CreatePropertyDecl for this.<br>
>    ObjCPropertyDecl *PDecl =<br>
>      ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),<br>
> -                             PropertyId, AtLoc, LParenLoc, T);<br>
> +                             PropertyId, AtLoc, LParenLoc, T, TSI);<br>
>    PDecl->setPropertyAttributesAsWritten(<br>
>                            makePropertyAttributesAsWritten(AttributesAsWritten));<br>
>    if (Attributes & ObjCDeclSpec::DQ_PR_readonly)<br>
> @@ -359,6 +359,8 @@ Sema::HandlePropertyInClassExtension(Sco<br>
>      PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);<br>
>    if (Attributes & ObjCDeclSpec::DQ_PR_atomic)<br>
>      PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);<br>
> +  if (Attributes & ObjCDeclSpec::DQ_PR_nullability)<br>
> +    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);<br>
>    // Set setter/getter selector name. Needed later.<br>
>    PDecl->setGetterName(GetterSel);<br>
>    PDecl->setSetterName(SetterSel);<br>
> @@ -383,7 +385,8 @@ Sema::HandlePropertyInClassExtension(Sco<br>
>      ObjCPropertyDecl *PrimaryPDecl =<br>
>        CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc,<br>
>                           FD, GetterSel, SetterSel, isAssign, isReadWrite,<br>
> -                         Attributes,AttributesAsWritten, T, MethodImplKind, DC);<br>
> +                         Attributes,AttributesAsWritten, T, TSI, MethodImplKind,<br>
> +                         DC);<br>
><br>
>      // A case of continuation class adding a new property in the class. This<br>
>      // is not what it was meant for. However, gcc supports it and so should we.<br>
> @@ -531,11 +534,11 @@ ObjCPropertyDecl *Sema::CreatePropertyDe<br>
>                                             const bool isReadWrite,<br>
>                                             const unsigned Attributes,<br>
>                                             const unsigned AttributesAsWritten,<br>
> +                                           QualType T,<br>
>                                             TypeSourceInfo *TInfo,<br>
>                                             tok::ObjCKeywordKind MethodImplKind,<br>
>                                             DeclContext *lexicalDC){<br>
>    IdentifierInfo *PropertyId = FD.D.getIdentifier();<br>
> -  QualType T = TInfo->getType();<br>
><br>
>    // Issue a warning if property is 'assign' as default and its object, which is<br>
>    // gc'able conforms to NSCopying protocol<br>
> @@ -564,7 +567,8 @@ ObjCPropertyDecl *Sema::CreatePropertyDe<br>
>    DeclContext *DC = cast<DeclContext>(CDecl);<br>
>    ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,<br>
>                                                       FD.D.getIdentifierLoc(),<br>
> -                                                     PropertyId, AtLoc, LParenLoc, TInfo);<br>
> +                                                     PropertyId, AtLoc,<br>
> +                                                     LParenLoc, T, TInfo);<br>
><br>
>    if (ObjCPropertyDecl *prevDecl =<br>
>          ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {<br>
> @@ -639,6 +643,9 @@ ObjCPropertyDecl *Sema::CreatePropertyDe<br>
>    else if (MethodImplKind == tok::objc_optional)<br>
>      PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);<br>
><br>
> +  if (Attributes & ObjCDeclSpec::DQ_PR_nullability)<br>
> +    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nullability);<br>
> +<br>
>    return PDecl;<br>
>  }<br>
><br>
> @@ -2228,6 +2235,23 @@ void Sema::CheckObjCPropertyAttributes(D<br>
>        Attributes &= ~ObjCDeclSpec::DQ_PR_weak;<br>
>    }<br>
><br>
> +  if ((Attributes & ObjCDeclSpec::DQ_PR_weak) &&<br>
> +      !(Attributes & ObjCDeclSpec::DQ_PR_readonly)) {<br>
> +    // 'weak' and 'nonnull' are mutually exclusive.<br>
> +    if (auto nullability = PropertyTy->getNullability(Context)) {<br>
> +      if (*nullability == NullabilityKind::NonNull)<br>
> +        Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)<br>
> +          << "nonnull" << "weak";<br>
> +    } else {<br>
> +        PropertyTy =<br>
> +          Context.getAttributedType(<br>
> +            AttributedType::getNullabilityAttrKind(NullabilityKind::Nullable),<br>
> +            PropertyTy, PropertyTy);<br>
> +        TypeSourceInfo *TSInfo = PropertyDecl->getTypeSourceInfo();<br>
> +        PropertyDecl->setType(PropertyTy, TSInfo);<br>
> +    }<br>
> +  }<br>
> +<br>
>    if ((Attributes & ObjCDeclSpec::DQ_PR_atomic) &&<br>
>        (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) {<br>
>        Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Sema_SemaType.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=bWeaXg2pKGgL6XkJe8nudYI4tRj_SPnkCTl62fRZjvI&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaType.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -4522,34 +4522,10 @@ static bool handleMSPointerTypeQualifier<br>
>    return false;<br>
>  }<br>
><br>
> -/// Map a nullability attribute kind to a nullability kind.<br>
> -static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) {<br>
> -  switch (kind) {<br>
> -  case AttributeList::AT_TypeNonNull:<br>
> -    return NullabilityKind::NonNull;<br>
> -<br>
> -  case AttributeList::AT_TypeNullable:<br>
> -    return NullabilityKind::Nullable;<br>
> -<br>
> -  case AttributeList::AT_TypeNullUnspecified:<br>
> -    return NullabilityKind::Unspecified;<br>
> -<br>
> -  default:<br>
> -    llvm_unreachable("not a nullability attribute kind");<br>
> -  }<br>
> -}<br>
> -<br>
> -/// Handle a nullability type attribute.<br>
> -static bool handleNullabilityTypeAttr(TypeProcessingState &state,<br>
> -                                      AttributeList &attr,<br>
> -                                      QualType &type) {<br>
> -  Sema &S = state.getSema();<br>
> -  ASTContext &Context = S.Context;<br>
> -<br>
> -  // Determine the nullability.<br>
> -  AttributeList::Kind kind = attr.getKind();<br>
> -  NullabilityKind nullability = mapNullabilityAttrKind(kind);<br>
> -<br>
> +bool Sema::checkNullabilityTypeSpecifier(QualType &type,<br>
> +                                         NullabilityKind nullability,<br>
> +                                         SourceLocation nullabilityLoc,<br>
> +                                         bool isContextSensitive) {<br>
>    // Check for existing nullability attributes on the type.<br>
>    QualType desugared = type;<br>
>    while (auto attributed = dyn_cast<AttributedType>(desugared.getTypePtr())) {<br>
> @@ -4557,19 +4533,24 @@ static bool handleNullabilityTypeAttr(Ty<br>
>      if (auto existingNullability = attributed->getImmediateNullability()) {<br>
>        // Duplicated nullability.<br>
>        if (nullability == *existingNullability) {<br>
> -        S.Diag(attr.getLoc(), diag::warn_duplicate_nullability)<br>
> -          << static_cast<unsigned>(nullability);<br>
> -        return true;<br>
> -      }<br>
> +        Diag(nullabilityLoc, diag::warn_nullability_duplicate)<br>
> +          << static_cast<unsigned>(nullability)<br>
> +          << isContextSensitive<br>
> +          << FixItHint::CreateRemoval(nullabilityLoc);<br>
> +<br>
> +        break;<br>
> +      }<br>
><br>
>        // Conflicting nullability.<br>
> -      S.Diag(attr.getLoc(), diag::err_nullability_conflicting)<br>
> -        <<  static_cast<unsigned>(nullability)<br>
> -        << static_cast<unsigned>(*existingNullability);<br>
> +      Diag(nullabilityLoc, diag::err_nullability_conflicting)<br>
> +        << static_cast<unsigned>(nullability)<br>
> +        << isContextSensitive<br>
> +        << static_cast<unsigned>(*existingNullability)<br>
> +        << false;<br>
>        return true;<br>
>      }<br>
><br>
> -    desugared = attributed->getEquivalentType();<br>
> +    desugared = attributed->getModifiedType();<br>
>    }<br>
><br>
>    // If there is already a different nullability specifier, complain.<br>
> @@ -4578,8 +4559,9 @@ static bool handleNullabilityTypeAttr(Ty<br>
>    // provide a useful Fix-It.<br>
>    if (auto existingNullability = desugared->getNullability(Context)) {<br>
>      if (nullability != *existingNullability) {<br>
> -      S.Diag(attr.getLoc(), diag::err_nullability_conflicting)<br>
> +      Diag(nullabilityLoc, diag::err_nullability_conflicting)<br>
>          << static_cast<unsigned>(nullability)<br>
> +        << isContextSensitive<br>
>          << static_cast<unsigned>(*existingNullability);<br>
><br>
>        // Try to find the typedef with the existing nullability specifier.<br>
> @@ -4589,7 +4571,7 @@ static bool handleNullabilityTypeAttr(Ty<br>
>          if (auto typedefNullability<br>
>                = AttributedType::stripOuterNullability(underlyingType)) {<br>
>            if (*typedefNullability == *existingNullability) {<br>
> -            S.Diag(typedefDecl->getLocation(), diag::note_nullability_here)<br>
> +            Diag(typedefDecl->getLocation(), diag::note_nullability_here)<br>
>                << static_cast<unsigned>(*existingNullability);<br>
>            }<br>
>          }<br>
> @@ -4600,31 +4582,35 @@ static bool handleNullabilityTypeAttr(Ty<br>
>    }<br>
><br>
>    // If this definitely isn't a pointer type, reject the specifier.<br>
> -  if (!type->canHaveNullability()) {<br>
> -    S.Diag(attr.getLoc(), diag::err_nullability_nonpointer)<br>
> -      << static_cast<unsigned>(nullability) << type;<br>
> +  if (!desugared->canHaveNullability()) {<br>
> +    Diag(nullabilityLoc, diag::err_nullability_nonpointer)<br>
> +      << static_cast<unsigned>(nullability) << isContextSensitive << type;<br>
>      return true;<br>
>    }<br>
> +<br>
> +  // For the context-sensitive keywords/Objective-C property<br>
> +  // attributes, require that the type be a single-level pointer.<br>
> +  if (isContextSensitive) {<br>
> +    // Make sure that the pointee isn't itself a pointer type.<br>
> +    QualType pointeeType = desugared->getPointeeType();<br>
> +    if (pointeeType->isAnyPointerType() ||<br>
> +        pointeeType->isObjCObjectPointerType() ||<br>
> +        pointeeType->isMemberPointerType()) {<br>
> +      Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)<br>
> +        << static_cast<unsigned>(nullability)<br>
> +        << type;<br>
> +      Diag(nullabilityLoc, diag::note_nullability_type_specifier)<br>
> +        << static_cast<unsigned>(nullability)<br>
> +        << type<br>
> +        << FixItHint::CreateReplacement(nullabilityLoc,<br>
> +                                        getNullabilitySpelling(nullability));<br>
> +      return true;<br>
> +    }<br>
> +  }<br>
><br>
>    // Form the attributed type.<br>
> -  AttributedType::Kind typeAttrKind;<br>
> -  switch (kind) {<br>
> -  case AttributeList::AT_TypeNonNull:<br>
> -    typeAttrKind = AttributedType::attr_nonnull;<br>
> -    break;<br>
> -<br>
> -  case AttributeList::AT_TypeNullable:<br>
> -    typeAttrKind = AttributedType::attr_nullable;<br>
> -    break;<br>
> -<br>
> -  case AttributeList::AT_TypeNullUnspecified:<br>
> -    typeAttrKind = AttributedType::attr_null_unspecified;<br>
> -    break;<br>
> -<br>
> -  default:<br>
> -    llvm_unreachable("Not a nullability specifier");<br>
> -  }<br>
> -  type = S.Context.getAttributedType(typeAttrKind, type, type);<br>
> +  type = Context.getAttributedType(<br>
> +           AttributedType::getNullabilityAttrKind(nullability), type, type);<br>
>    return false;<br>
>  }<br>
><br>
> @@ -4642,6 +4628,23 @@ static bool hasNullabilityAttr(const Att<br>
>    return false;<br>
>  }<br>
><br>
> +/// Map a nullability attribute kind to a nullability kind.<br>
> +static NullabilityKind mapNullabilityAttrKind(AttributeList::Kind kind) {<br>
> +  switch (kind) {<br>
> +  case AttributeList::AT_TypeNonNull:<br>
> +    return NullabilityKind::NonNull;<br>
> +<br>
> +  case AttributeList::AT_TypeNullable:<br>
> +    return NullabilityKind::Nullable;<br>
> +<br>
> +  case AttributeList::AT_TypeNullUnspecified:<br>
> +    return NullabilityKind::Unspecified;<br>
> +<br>
> +  default:<br>
> +    llvm_unreachable("not a nullability attribute kind");<br>
> +  }<br>
> +}<br>
> +<br>
>  /// Distribute a nullability type attribute that cannot be applied to<br>
>  /// the type specifier to a pointer, block pointer, or member pointer<br>
>  /// declarator, complaining if necessary.<br>
> @@ -5233,7 +5236,11 @@ static void processTypeAttrs(TypeProcess<br>
>        // dependent type, because that complicates the user model.<br>
>        if (type->canHaveNullability() || type->isDependentType() ||<br>
>            !distributeNullabilityTypeAttr(state, type, attr)) {<br>
> -        if (handleNullabilityTypeAttr(state, attr, type)) {<br>
> +        if (state.getSema().checkNullabilityTypeSpecifier(<br>
> +              type,<br>
> +              mapNullabilityAttrKind(attr.getKind()),<br>
> +              attr.getLoc(),<br>
> +              attr.isContextSensitiveKeywordAttribute())) {<br>
>            attr.setInvalid();<br>
>          }<br>
><br>
><br>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Sema_TreeTransform.h-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=juBbvRIgGPFDSuFkGGbZemuh-0xu3uciBUaC1cKrTrA&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
> +++ cfe/trunk/lib/Sema/TreeTransform.h Fri Jun 19 13:14:38 2015<br>
> @@ -5392,7 +5392,7 @@ QualType TreeTransform<Derived>::Transfo<br>
>      if (auto nullability = oldType->getImmediateNullability()) {<br>
>        if (!modifiedType->canHaveNullability()) {<br>
>          SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer)<br>
> -          << static_cast<unsigned>(*nullability) << modifiedType;<br>
> +          << static_cast<unsigned>(*nullability) << false << modifiedType;<br>
>          return QualType();<br>
>        }<br>
>      }<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Serialization_ASTReaderDecl.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=BHtfOpy4GzYPBYfxNYCtUk-ZbOaZuQ7cl6UjNeI7R5Y&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -1042,7 +1042,9 @@ void ASTDeclReader::VisitObjCPropertyDec<br>
>    VisitNamedDecl(D);<br>
>    D->setAtLoc(ReadSourceLocation(Record, Idx));<br>
>    D->setLParenLoc(ReadSourceLocation(Record, Idx));<br>
> -  D->setType(GetTypeSourceInfo(Record, Idx));<br>
> +  QualType T = Reader.readType(F, Record, Idx);<br>
> +  TypeSourceInfo *TSI = GetTypeSourceInfo(Record, Idx);<br>
> +  D->setType(T, TSI);<br>
>    // FIXME: stable encoding<br>
>    D->setPropertyAttributes(<br>
>                        (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_lib_Serialization_ASTWriterDecl.cpp-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=slz9kHekn-Aksqx2P3uZyH3VJJ1DdmXEImoa9JR3JxU&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Jun 19 13:14:38 2015<br>
> @@ -542,7 +542,7 @@ void ASTDeclWriter::VisitObjCMethodDecl(<br>
><br>
>    // FIXME: stable encoding for @required/@optional<br>
>    Record.push_back(D->getImplementationControl());<br>
> -  // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway<br>
> +  // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway/nullability<br>
>    Record.push_back(D->getObjCDeclQualifier());<br>
>    Record.push_back(D->hasRelatedResultType());<br>
>    Writer.AddTypeRef(D->getReturnType(), Record);<br>
> @@ -678,6 +678,7 @@ void ASTDeclWriter::VisitObjCPropertyDec<br>
>    VisitNamedDecl(D);<br>
>    Writer.AddSourceLocation(D->getAtLoc(), Record);<br>
>    Writer.AddSourceLocation(D->getLParenLoc(), Record);<br>
> +  Writer.AddTypeRef(D->getType(), Record);<br>
>    Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);<br>
>    // FIXME: stable encoding<br>
>    Record.push_back((unsigned)D->getPropertyAttributes());<br>
><br>
> Modified: cfe/trunk/test/Index/comment-objc-decls.m<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_test_Index_comment-2Dobjc-2Ddecls.m-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=cU8wh9ROjmeswtsPEOkiPSIp7Q-k5h90moGwnPiuuMM&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/comment-objc-decls.m?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/Index/comment-objc-decls.m (original)<br>
> +++ cfe/trunk/test/Index/comment-objc-decls.m Fri Jun 19 13:14:38 2015<br>
> @@ -20,19 +20,19 @@<br>
>   * \param[in] range output value is unsigned int<br>
>   * \result return index<br>
>   */<br>
> -- (unsigned int)MethodMyProto:(id)anObject inRange:(unsigned int)range;<br>
> +- (unsigned int)MethodMyProto:(nullable id)anObject inRange:(unsigned int)range;<br>
>  /**<br>
>   * \brief PropertyMyProto - This is protocol's property.<br>
>  */<br>
> -@property (copy) id PropertyMyProto;<br>
> +@property (copy, nonnull) id PropertyMyProto;<br>
>  /**<br>
>   * \brief ClassMethodMyProto<br>
>  */<br>
>  + ClassMethodMyProto;<br>
>  @end<br>
>  // CHECK: <Declaration>@protocol MyProto\n@end</Declaration><br>
> -// CHECK: <Declaration>- (unsigned int)MethodMyProto:(id)anObject inRange:(unsigned int)range;</Declaration><br>
> -// CHECK: <Declaration>@optional\n@property(readwrite, copy, atomic) id PropertyMyProto;</Declaration><br>
> +// CHECK: <Declaration>- (unsigned int)MethodMyProto:(nullable id)anObject inRange:(unsigned int)range;</Declaration><br>
> +// CHECK: <Declaration>@optional\n@property(readwrite, copy, atomic, nonnull) id PropertyMyProto;</Declaration><br>
>  // CHECK: <Declaration>+ (id)ClassMethodMyProto;</Declaration><br>
><br>
>  /**<br>
><br>
> Modified: cfe/trunk/test/SemaObjC/arc-property-decl-attrs.m<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_test_SemaObjC_arc-2Dproperty-2Ddecl-2Dattrs.m-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=sNY5dXLnC-W5gTpX2T5y9VeRjh3PvkSJ-8KJdVdxANI&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-property-decl-attrs.m?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/SemaObjC/arc-property-decl-attrs.m (original)<br>
> +++ cfe/trunk/test/SemaObjC/arc-property-decl-attrs.m Fri Jun 19 13:14:38 2015<br>
> @@ -79,3 +79,11 @@<br>
>  @property (readwrite) id frr;<br>
>  @end<br>
><br>
> +// rdar://20152386<br>
> +@interface NSObject @end<br>
> +<br>
> +@interface rdar20152386_2: NSObject<br>
> +@property(nonatomic, weak, nonnull) id delegate; // expected-error {{property attributes 'nonnull' and 'weak' are mutually exclusive}}<br>
> +@property(nonatomic, weak, nonnull, readonly) id ReadDelegate; // no warning<br>
> +@end<br>
> +<br>
><br>
> Modified: cfe/trunk/test/SemaObjC/arc-unavailable-for-weakref.m<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_test_SemaObjC_arc-2Dunavailable-2Dfor-2Dweakref.m-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=P2lTRqpd8X4iIsU7yz5_Xq0BNH1c2AOCXhMP_SF0rqM&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-unavailable-for-weakref.m?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/SemaObjC/arc-unavailable-for-weakref.m (original)<br>
> +++ cfe/trunk/test/SemaObjC/arc-unavailable-for-weakref.m Fri Jun 19 13:14:38 2015<br>
> @@ -56,7 +56,7 @@ __attribute__((objc_arc_weak_reference_u<br>
>  @interface I<br>
>  {<br>
>  }<br>
> -@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont *', which does not support weak references}}<br>
> +@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * __nullable', which does not support weak references}}<br>
>  @end<br>
><br>
>  @implementation I // expected-note {{when implemented by class I}}<br>
> @@ -65,7 +65,7 @@ __attribute__((objc_arc_weak_reference_u<br>
><br>
>  // rdar://13676793<br>
>  @protocol MyProtocol<br>
> -@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont *', which does not support weak references}}<br>
> +@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * __nullable', which does not support weak references}}<br>
>  @end<br>
><br>
>  @interface I1 <MyProtocol><br>
> @@ -76,7 +76,7 @@ __attribute__((objc_arc_weak_reference_u<br>
>  @end<br>
><br>
>  @interface Super<br>
> -@property (weak) NSFont *font;  // expected-error {{synthesizing __weak instance variable of type 'NSFont *', which does not support weak references}}<br>
> +@property (weak) NSFont *font;  // expected-error {{synthesizing __weak instance variable of type 'NSFont * __nullable', which does not support weak references}}<br>
>  @end<br>
><br>
><br>
><br>
> Modified: cfe/trunk/test/SemaObjC/nullability.m<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_test_SemaObjC_nullability.m-3Frev-3D240154-26r1-3D240153-26r2-3D240154-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=YyNRm6u5UyGxro_ihXd_9t0Iio_eV5spovxYhvroJsQ&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/nullability.m?rev=240154&r1=240153&r2=240154&view=diff</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/SemaObjC/nullability.m (original)<br>
> +++ cfe/trunk/test/SemaObjC/nullability.m Fri Jun 19 13:14:38 2015<br>
> @@ -20,9 +20,6 @@ typedef __nonnull NSFoo * __nullable con<br>
>  void testBlocksPrinting(NSFoo * __nullable (^bp)(int)) {<br>
>    int *ip = bp; // expected-error{{'NSFoo * __nullable (^)(int)'}}<br>
>  }<br>
> -void test_accepts_nonnull_null_pointer_literal(NSFoo *foo) {<br>
> -  [foo methodTakingIntPtr: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}<br>
> -}<br>
><br>
>  // Check returning nil from a __nonnull-returning method.<br>
>  @implementation NSFoo<br>
> @@ -31,3 +28,151 @@ void test_accepts_nonnull_null_pointer_l<br>
>    return 0; // no warning<br>
>  }<br>
>  @end<br>
> +<br>
> +// Context-sensitive keywords and property attributes for nullability.<br>
> +__attribute__((objc_root_class))<br>
> +@interface NSBar<br>
> +- (nonnull NSFoo *)methodWithFoo:(nonnull NSFoo *)foo;<br>
> +<br>
> +- (nonnull NSFoo **)invalidMethod1; // expected-error{{nullability keyword 'nonnull' cannot be applied to multi-level pointer type 'NSFoo **'}}<br>
> +// expected-note@-1{{use nullability type specifier '__nonnull' to affect the innermost pointer type of 'NSFoo **'}}<br>
> +- (nonnull NSFoo * __nullable)conflictingMethod1; // expected-error{{nullability specifier '__nullable' conflicts with existing specifier '__nonnull'}}<br>
> +- (nonnull NSFoo * __nonnull)redundantMethod1; // expected-warning{{duplicate nullability specifier '__nonnull'}}<br>
> +<br>
> +@property(nonnull,retain) NSFoo *property1;<br>
> +@property(nullable,assign) NSFoo ** invalidProperty1; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}}<br>
> +// expected-note@-1{{use nullability type specifier '__nullable' to affect the innermost pointer type of 'NSFoo **'}}<br>
> +@property(null_unspecified,retain) NSFoo * __nullable conflictingProperty1; // expected-error{{nullability specifier '__nullable' conflicts with existing specifier '__null_unspecified'}}<br>
> +@property(retain,nonnull) NSFoo * __nonnull redundantProperty1; // expected-warning{{duplicate nullability specifier '__nonnull'}}<br>
> +<br>
> +@property(null_unspecified,retain,nullable) NSFoo *conflictingProperty3; // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'null_unspecified'}}<br>
> +@property(nullable,retain,nullable) NSFoo *redundantProperty3; // expected-warning{{duplicate nullability specifier 'nullable'}}<br>
> +@end<br>
> +<br>
> +@interface NSBar ()<br>
> +@property(nonnull,retain) NSFoo *property2;<br>
> +@property(nullable,assign) NSFoo ** invalidProperty2; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}}<br>
> +// expected-note@-1{{use nullability type specifier '__nullable' to affect the innermost pointer type of 'NSFoo **'}}<br>
> +@property(null_unspecified,retain) NSFoo * __nullable conflictingProperty2; // expected-error{{nullability specifier '__nullable' conflicts with existing specifier '__null_unspecified'}}<br>
> +@property(retain,nonnull) NSFoo * __nonnull redundantProperty2; // expected-warning{{duplicate nullability specifier '__nonnull'}}<br>
> +@end<br>
> +<br>
> +void test_accepts_nonnull_null_pointer_literal(NSFoo *foo, __nonnull NSBar *bar) {<br>
> +  [foo methodTakingIntPtr: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}<br>
> +  [bar methodWithFoo: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}<br>
> +  bar.property1 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}}<br>
> +  bar.property2 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}}<br>
> +  [bar setProperty1: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}<br>
> +  [bar setProperty2: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}<br>
> +  int *ptr = bar.property1; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * __nonnull'}}<br>
> +}<br>
> +<br>
> +// Check returning nil from a nonnull-returning method.<br>
> +@implementation NSBar<br>
> +- (nonnull NSFoo *)methodWithFoo:(nonnull NSFoo *)foo {<br>
> +  return 0; // no warning<br>
> +}<br>
> +<br>
> +- (NSFoo **)invalidMethod1 {<br>
> +  return 0;<br>
> +}<br>
> +<br>
> +- (NSFoo *)conflictingMethod1 {<br>
> +  return 0; // no warning<br>
> +}<br>
> +- (NSFoo *)redundantMethod1 {<br>
> +  int *ip = 0;<br>
> +  return ip; // expected-warning{{result type 'NSFoo * __nonnull'}}<br>
> +}<br>
> +@end<br>
> +<br>
> +__attribute__((objc_root_class))<br>
> +@interface NSMerge<br>
> +- (nonnull NSFoo *)methodA:(nonnull NSFoo*)foo;<br>
> +- (nonnull NSFoo *)methodB:(nonnull NSFoo*)foo;<br>
> +- (NSFoo *)methodC:(NSFoo*)foo;<br>
> +@end<br>
> +<br>
> +@implementation NSMerge<br>
> +- (NSFoo *)methodA:(NSFoo*)foo {<br>
> +  int *ptr = foo; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * __nonnull'}}<br>
> +  return ptr; // expected-warning{{result type 'NSFoo * __nonnull'}}<br>
> +}<br>
> +<br>
> +- (nullable NSFoo *)methodB:(null_unspecified NSFoo*)foo { // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'nonnull'}} \<br>
> +  // expected-error{{nullability specifier 'null_unspecified' conflicts with existing specifier 'nonnull'}}<br>
> +  return 0;<br>
> +}<br>
> +<br>
> +- (nonnull NSFoo *)methodC:(nullable NSFoo*)foo {<br>
> +  int *ip = 0;<br>
> +  return ip; // expected-warning{{result type 'NSFoo * __nonnull'}}<br>
> +}<br>
> +@end<br>
> +<br>
> +// Checking merging of nullability when sending a message.<br>
> +@interface NSMergeReceiver<br>
> +- (id)returnsNone;<br>
> +- (nonnull id)returnsNonNull;<br>
> +- (nullable id)returnsNullable;<br>
> +- (null_unspecified id)returnsNullUnspecified;<br>
> +@end<br>
> +<br>
> +void test_receiver_merge(NSMergeReceiver *none,<br>
> +                         __nonnull NSMergeReceiver *nonnull,<br>
> +                         __nullable NSMergeReceiver *nullable,<br>
> +                         __null_unspecified NSMergeReceiver *null_unspecified) {<br>
> +  int *ptr;<br>
> +<br>
> +  ptr = [nullable returnsNullable]; // expected-warning{{'id __nullable'}}<br>
> +  ptr = [nullable returnsNullUnspecified]; // expected-warning{{'id __nullable'}}<br>
> +  ptr = [nullable returnsNonNull]; // expected-warning{{'id __nullable'}}<br>
> +  ptr = [nullable returnsNone]; // expected-warning{{'id __nullable'}}<br>
> +<br>
> +  ptr = [null_unspecified returnsNullable]; // expected-warning{{'id __nullable'}}<br>
> +  ptr = [null_unspecified returnsNullUnspecified]; // expected-warning{{'id __null_unspecified'}}<br>
> +  ptr = [null_unspecified returnsNonNull]; // expected-warning{{'id __null_unspecified'}}<br>
> +  ptr = [null_unspecified returnsNone]; // expected-warning{{'id'}}<br>
> +<br>
> +  ptr = [nonnull returnsNullable]; // expected-warning{{'id __nullable'}}<br>
> +  ptr = [nonnull returnsNullUnspecified]; // expected-warning{{'id __null_unspecified'}}<br>
> +  ptr = [nonnull returnsNonNull]; // expected-warning{{'id __nonnull'}}<br>
> +  ptr = [nonnull returnsNone]; // expected-warning{{'id'}}<br>
> +<br>
> +  ptr = [none returnsNullable]; // expected-warning{{'id __nullable'}}<br>
> +  ptr = [none returnsNullUnspecified]; // expected-warning{{'id'}}<br>
> +  ptr = [none returnsNonNull]; // expected-warning{{'id'}}<br>
> +  ptr = [none returnsNone]; // expected-warning{{'id'}}<br>
> +<br>
> +}<br>
> +<br>
> +// instancetype<br>
> +@protocol Initializable<br>
> +- (instancetype)initWithBlah:(id)blah;<br>
> +@end<br>
> +<br>
> +__attribute__((objc_root_class))<br>
> +@interface InitializableClass <Initializable><br>
> +- (nonnull instancetype)initWithBlah:(nonnull id)blah;<br>
> +- (nullable instancetype)returnMe;<br>
> ++ (nullable instancetype)returnInstanceOfMe;<br>
> +@end<br>
> +<br>
> +void test_instancetype(InitializableClass * __nonnull ic, id __nonnull object) {<br>
> +  int *ip = [ic returnMe]; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'InitializableClass * __nullable'}}<br>
> +  ip = [InitializableClass returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id __nullable'}}<br>
> +  ip = [InitializableClass returnInstanceOfMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * __nullable'}}<br>
> +  ip = [object returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id __nullable'}}<br>
> +}<br>
> +// rdar://problem/19814852<br>
> +@interface MultiProp<br>
> +@property (nullable, copy) id a, b, c;<br>
> +@property (nullable, copy) MultiProp *d, *(^e)(int);<br>
> +@end<br>
> +<br>
> +void testMultiProp(MultiProp *foo) {<br>
> +  int *ip;<br>
> +  ip = foo.a; // expected-warning{{from 'id __nullable'}}<br>
> +  ip = foo.d; // expected-warning{{from 'MultiProp * __nullable'}}<br>
> +  ip = foo.e; // expected-error{{incompatible type 'MultiProp *(^ __nullable)(int)'}}<br>
> +}<br>
><br>
> Added: cfe/trunk/test/SemaObjC/nullable-weak-property.m<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_test_SemaObjC_nullable-2Dweak-2Dproperty.m-3Frev-3D240154-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=wdJRO_B2kNYhWA9CCnCMmh2b1z86IwuxPzTxTMLDzbs&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/nullable-weak-property.m?rev=240154&view=auto</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/SemaObjC/nullable-weak-property.m (added)<br>
> +++ cfe/trunk/test/SemaObjC/nullable-weak-property.m Fri Jun 19 13:14:38 2015<br>
> @@ -0,0 +1,18 @@<br>
> +// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -Wnullable-to-nonnull-conversion %s -verify<br>
> +<br>
> +<br>
> +// rdar://19985330<br>
> +@interface NSObject @end<br>
> +<br>
> +@class NSFoo;<br>
> +void foo (NSFoo * __nonnull);<br>
> +<br>
> +@interface NSBar : NSObject<br>
> +@property(weak) NSFoo *property1;<br>
> +@end<br>
> +<br>
> +@implementation NSBar<br>
> +- (void) Meth {<br>
> +   foo (self.property1); // expected-warning {{implicit conversion from nullable pointer 'NSFoo * __nullable' to non-nullable pointer type 'NSFoo * __nonnull'}}<br>
> +}<br>
> +@end<br>
><br>
> Added: cfe/trunk/test/SemaObjC/override-nullability.m<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_cfe_trunk_test_SemaObjC_override-2Dnullability.m-3Frev-3D240154-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=BSqEv9KvKMW_Ob8SyngJ70KdZISM_ASROnREeq0cCxk&m=-X3TpLMEeVoLY8YQm8xQUfpv5bR6UnFhFxMgatnWM4Q&s=2FdF5s_uC4_tfbi3KNLBC-mOCT0znDEIyf1OaBK2PB8&e=" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/override-nullability.m?rev=240154&view=auto</a><br>
> ==============================================================================<br>
> --- cfe/trunk/test/SemaObjC/override-nullability.m (added)<br>
> +++ cfe/trunk/test/SemaObjC/override-nullability.m Fri Jun 19 13:14:38 2015<br>
> @@ -0,0 +1,15 @@<br>
> +// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -Wnonnull %s -verify<br>
> +//rdar://19211059<br>
> +<br>
> +@interface NSObject @end<br>
> +<br>
> +@interface Base : NSObject<br>
> +- (nonnull id)bad:(nullable id)obj; // expected-note 2 {{previous declaration is here}}<br>
> +- (nullable id)notAsBad:(nonnull id)obj;<br>
> +@end<br>
> +<br>
> +@interface Sub : Base<br>
> +- (nullable id)bad:(nonnull id)obj; // expected-warning {{conflicting nullability specifier on return types, 'nullable' conflicts with existing specifier 'nonnull'}} \<br>
> +                                    // expected-warning {{conflicting nullability specifier on parameter types, 'nonnull' conflicts with existing specifier 'nullable'}}<br>
> +- (nonnull id)notAsBad:(nullable id)obj;<br>
> +@end<br>
><br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
<br>
~Aaron<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>