[cfe-commits] r172567 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaDeclObjC.cpp test/SemaObjC/attr-availability.m

Jordan Rose jordan_rose at apple.com
Tue Jan 15 15:25:46 PST 2013


On Jan 15, 2013, at 14:43 , Douglas Gregor <dgregor at apple.com> wrote:

> Author: dgregor
> Date: Tue Jan 15 16:43:08 2013
> New Revision: 172567
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=172567&view=rev
> Log:
> When checking availability attributes for consistency between an
> overriding and overridden method, allow the overridden method to have
> a narrower contract (introduced earlier, deprecated/obsoleted later)
> than the overriding method. Fixes <rdar://problem/12992023>.

I think you mean "allow the overridding method…" I spent five minutes trying to figure out if the comment as written really made sense. Unfortunately, the test case seems backwards as well for warn_mismatched_availability_override_unavail, but correct for both variants of warn_mismatched_availability_override.


> Modified:
>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>    cfe/trunk/include/clang/Sema/Sema.h
>    cfe/trunk/lib/Sema/SemaDecl.cpp
>    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
>    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
>    cfe/trunk/test/SemaObjC/attr-availability.m
> 
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=172567&r1=172566&r2=172567&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jan 15 16:43:08 2013
> @@ -1879,6 +1879,16 @@
>   "attribute ignored">, InGroup<Availability>;
> def warn_mismatched_availability: Warning<
>   "availability does not match previous declaration">, InGroup<Availability>;
> +def warn_mismatched_availability_override : Warning<
> +  "overriding method %select{introduced after|"
> +  "deprecated before|obsoleted before}0 overridden method on %1 (%2 vs. %3)">, 
> +  InGroup<Availability>;
> +def warn_mismatched_availability_override_unavail : Warning<
> +  "overriding method cannot be unavailable on %0 when its overridden method is "
> +  "available">,
> +  InGroup<Availability>;
> +def note_overridden_method : Note<
> +  "overridden method is here">;
> 
> // Thread Safety Attributes
> def warn_thread_attribute_ignored : Warning<
> 
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=172567&r1=172566&r2=172567&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Jan 15 16:43:08 2013
> @@ -1677,7 +1677,8 @@
>                                           VersionTuple Deprecated,
>                                           VersionTuple Obsoleted,
>                                           bool IsUnavailable,
> -                                          StringRef Message);
> +                                          StringRef Message,
> +                                          bool Override);
>   VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range,
>                                       VisibilityAttr::VisibilityType Vis);
>   DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range);
> @@ -1685,10 +1686,24 @@
>   FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format,
>                               int FormatIdx, int FirstArg);
>   SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name);
> -  bool mergeDeclAttribute(NamedDecl *New, InheritableAttr *Attr);
> +  bool mergeDeclAttribute(NamedDecl *New, InheritableAttr *Attr,
> +                          bool Override);
> +
> +  /// \brief Describes the kind of merge to perform for availability
> +  /// attributes (including "deprecated", "unavailable", and "availability").
> +  enum AvailabilityMergeKind {
> +    /// \brief Don't merge availability attributes at all.
> +    AMK_None,
> +    /// \brief Merge availability attributes for a redeclaration, which requires
> +    /// an exact match.
> +    AMK_Redeclaration,
> +    /// \brief Merge availability attributes for an override, which requires
> +    /// an exact match or a weakening of constraints.
> +    AMK_Override
> +  };
> 
>   void mergeDeclAttributes(NamedDecl *New, Decl *Old,
> -                           bool MergeDeprecation = true);
> +                           AvailabilityMergeKind AMK = AMK_Redeclaration);
>   void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls);
>   bool MergeFunctionDecl(FunctionDecl *New, Decl *Old, Scope *S);
>   bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
> @@ -6383,8 +6398,7 @@
>   /// \brief Check whether the given new method is a valid override of the
>   /// given overridden method, and set any properties that should be inherited.
>   void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
> -                               const ObjCMethodDecl *Overridden,
> -                               bool IsImplementation);
> +                               const ObjCMethodDecl *Overridden);
> 
>   /// \brief Describes the compatibility of a result type with its method.
>   enum ResultTypeCompatibilityKind {
> 
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=172567&r1=172566&r2=172567&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jan 15 16:43:08 2013
> @@ -1822,13 +1822,14 @@
>   return false;
> }
> 
> -bool Sema::mergeDeclAttribute(NamedDecl *D, InheritableAttr *Attr) {
> +bool Sema::mergeDeclAttribute(NamedDecl *D, InheritableAttr *Attr,
> +                              bool Override) {
>   InheritableAttr *NewAttr = NULL;
>   if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr))
>     NewAttr = mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(),
>                                     AA->getIntroduced(), AA->getDeprecated(),
>                                     AA->getObsoleted(), AA->getUnavailable(),
> -                                    AA->getMessage());
> +                                    AA->getMessage(), Override);
>   else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr))
>     NewAttr = mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility());
>   else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr))
> @@ -1902,7 +1903,7 @@
> 
> /// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
> void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
> -                               bool MergeDeprecation) {
> +                               AvailabilityMergeKind AMK) {
>   // attributes declared post-definition are currently ignored
>   checkNewAttributesAfterDef(*this, New, Old);
> 
> @@ -1919,14 +1920,25 @@
>          i = Old->specific_attr_begin<InheritableAttr>(),
>          e = Old->specific_attr_end<InheritableAttr>(); 
>        i != e; ++i) {
> +    bool Override = false;
>     // Ignore deprecated/unavailable/availability attributes if requested.
> -    if (!MergeDeprecation &&
> -        (isa<DeprecatedAttr>(*i) || 
> -         isa<UnavailableAttr>(*i) ||
> -         isa<AvailabilityAttr>(*i)))
> -      continue;
> +    if (isa<DeprecatedAttr>(*i) ||
> +        isa<UnavailableAttr>(*i) ||
> +        isa<AvailabilityAttr>(*i)) {
> +      switch (AMK) {
> +      case AMK_None:
> +        continue;
> +
> +      case AMK_Redeclaration:
> +        break;
> +
> +      case AMK_Override:
> +        Override = true;
> +        break;
> +      }
> +    }
> 
> -    if (mergeDeclAttribute(New, *i))
> +    if (mergeDeclAttribute(New, *i, Override))
>       foundAny = true;
>   }
> 
> @@ -2475,7 +2487,7 @@
>                                 ObjCMethodDecl *oldMethod) {
> 
>   // Merge the attributes, including deprecated/unavailable
> -  mergeDeclAttributes(newMethod, oldMethod, /* mergeDeprecation */true);
> +  mergeDeclAttributes(newMethod, oldMethod, AMK_Override);
> 
>   // Merge attributes from the parameters.
>   ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(),
> @@ -2485,7 +2497,7 @@
>        ni != ne && oi != oe; ++ni, ++oi)
>     mergeParamDeclAttributes(*ni, *oi, Context);
> 
> -  CheckObjCMethodOverride(newMethod, oldMethod, true);
> +  CheckObjCMethodOverride(newMethod, oldMethod);
> }
> 
> /// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and
> 
> Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=172567&r1=172566&r2=172567&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Jan 15 16:43:08 2013
> @@ -2001,13 +2001,32 @@
>   return false;
> }
> 
> +/// \brief Check whether the two versions match.
> +///
> +/// If either version tuple is empty, then they are assumed to match. If
> +/// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y.
> +static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y,
> +                          bool BeforeIsOkay) {
> +  if (X.empty() || Y.empty())
> +    return true;
> +
> +  if (X == Y)
> +    return true;
> +
> +  if (BeforeIsOkay && X < Y)
> +    return true;
> +
> +  return false;
> +}
> +
> AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,
>                                               IdentifierInfo *Platform,
>                                               VersionTuple Introduced,
>                                               VersionTuple Deprecated,
>                                               VersionTuple Obsoleted,
>                                               bool IsUnavailable,
> -                                              StringRef Message) {
> +                                              StringRef Message,
> +                                              bool Override) {
>   VersionTuple MergedIntroduced = Introduced;
>   VersionTuple MergedDeprecated = Deprecated;
>   VersionTuple MergedObsoleted = Obsoleted;
> @@ -2033,18 +2052,47 @@
>       VersionTuple OldDeprecated = OldAA->getDeprecated();
>       VersionTuple OldObsoleted = OldAA->getObsoleted();
>       bool OldIsUnavailable = OldAA->getUnavailable();
> -      StringRef OldMessage = OldAA->getMessage();
> 
> -      if ((!OldIntroduced.empty() && !Introduced.empty() &&
> -           OldIntroduced != Introduced) ||
> -          (!OldDeprecated.empty() && !Deprecated.empty() &&
> -           OldDeprecated != Deprecated) ||
> -          (!OldObsoleted.empty() && !Obsoleted.empty() &&
> -           OldObsoleted != Obsoleted) ||
> -          (OldIsUnavailable != IsUnavailable) ||
> -          (OldMessage != Message)) {
> -        Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
> -        Diag(Range.getBegin(), diag::note_previous_attribute);
> +      if (!versionsMatch(OldIntroduced, Introduced, Override) ||
> +          !versionsMatch(Deprecated, OldDeprecated, Override) ||
> +          !versionsMatch(Obsoleted, OldObsoleted, Override) ||
> +          !(OldIsUnavailable == IsUnavailable ||
> +            (Override && OldIsUnavailable && !IsUnavailable))) {
> +        if (Override) {
> +          int Which = -1;
> +          VersionTuple FirstVersion;
> +          VersionTuple SecondVersion;
> +          if (!versionsMatch(OldIntroduced, Introduced, Override)) {
> +            Which = 0;
> +            FirstVersion = OldIntroduced;
> +            SecondVersion = Introduced;
> +          } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) {
> +            Which = 1;
> +            FirstVersion = Deprecated;
> +            SecondVersion = OldDeprecated;
> +          } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) {
> +            Which = 2;
> +            FirstVersion = Obsoleted;
> +            SecondVersion = OldObsoleted;
> +          }
> +
> +          if (Which == -1) {
> +            Diag(OldAA->getLocation(),
> +                 diag::warn_mismatched_availability_override_unavail)
> +              << AvailabilityAttr::getPrettyPlatformName(Platform->getName());
> +          } else {
> +            Diag(OldAA->getLocation(),
> +                 diag::warn_mismatched_availability_override)
> +              << Which
> +              << AvailabilityAttr::getPrettyPlatformName(Platform->getName())
> +              << FirstVersion.getAsString() << SecondVersion.getAsString();
> +          }
> +          Diag(Range.getBegin(), diag::note_overridden_method);
> +        } else {
> +          Diag(OldAA->getLocation(), diag::warn_mismatched_availability);
> +          Diag(Range.getBegin(), diag::note_previous_attribute);
> +        }
> +
>         Attrs.erase(Attrs.begin() + i);
>         --e;
>         continue;
> @@ -2121,7 +2169,8 @@
>                                                       Introduced.Version,
>                                                       Deprecated.Version,
>                                                       Obsoleted.Version,
> -                                                      IsUnavailable, Str);
> +                                                      IsUnavailable, Str,
> +                                                      /*Override=*/false);
>   if (NewAttr)
>     D->addAttr(NewAttr);
> }
> 
> Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=172567&r1=172566&r2=172567&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Jan 15 16:43:08 2013
> @@ -109,8 +109,7 @@
> }
> 
> void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, 
> -                                   const ObjCMethodDecl *Overridden,
> -                                   bool IsImplementation) {
> +                                   const ObjCMethodDecl *Overridden) {
>   if (Overridden->hasRelatedResultType() && 
>       !NewMethod->hasRelatedResultType()) {
>     // This can only happen when the method follows a naming convention that
> 
> Modified: cfe/trunk/test/SemaObjC/attr-availability.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/attr-availability.m?rev=172567&r1=172566&r2=172567&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/attr-availability.m (original)
> +++ cfe/trunk/test/SemaObjC/attr-availability.m Tue Jan 15 16:43:08 2013
> @@ -6,11 +6,24 @@
> 
> @interface A <P>
> - (void)method __attribute__((availability(macosx,introduced=10.1,deprecated=10.2))); // expected-note {{method 'method' declared here}}
> +
> +- (void)overridden __attribute__((availability(macosx,introduced=10.3))); // expected-note{{overridden method is here}}
> +- (void)overridden2 __attribute__((availability(macosx,introduced=10.3)));
> +- (void)overridden3 __attribute__((availability(macosx,deprecated=10.3)));
> +- (void)overridden4 __attribute__((availability(macosx,deprecated=10.3))); // expected-note{{overridden method is here}}
> +- (void)overridden5 __attribute__((availability(macosx,unavailable))); // expected-note{{overridden method is here}}
> +- (void)overridden6 __attribute__((availability(macosx,introduced=10.3)));
> @end
> 
> // rdar://11475360
> @interface B : A
> - (void)method; // expected-note {{method 'method' declared here}}
> +- (void)overridden __attribute__((availability(macosx,introduced=10.4))); // expected-warning{{overriding method introduced after overridden method on OS X (10.4 vs. 10.3)}}
> +- (void)overridden2 __attribute__((availability(macosx,introduced=10.2)));
> +- (void)overridden3 __attribute__((availability(macosx,deprecated=10.4)));
> +- (void)overridden4 __attribute__((availability(macosx,deprecated=10.2))); // expected-warning{{overriding method deprecated before overridden method on OS X (10.3 vs. 10.2)}}
> +- (void)overridden5 __attribute__((availability(macosx,introduced=10.3))); // expected-warning{{overriding method cannot be unavailable on OS X when its overridden method is available}}
> +- (void)overridden6 __attribute__((availability(macosx,unavailable)));
> @end
> 
> void f(A *a, B *b) {
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130115/d991b21a/attachment.html>


More information about the cfe-commits mailing list