[clang] [Clang][Sema] clang generates incorrect fix-its for API_AVAILABLE (PR #105855)

Ian Anderson via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 23 09:54:59 PDT 2024


================
@@ -488,22 +488,43 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
       // Don't offer a fixit for declarations with availability attributes.
       if (Enclosing->hasAttr<AvailabilityAttr>())
         return;
-      if (!S.getPreprocessor().isMacroDefined("API_AVAILABLE"))
+      Preprocessor &PP = S.getPreprocessor();
+      if (!PP.isMacroDefined("API_AVAILABLE"))
         return;
       std::optional<AttributeInsertion> Insertion = createAttributeInsertion(
           Enclosing, S.getSourceManager(), S.getLangOpts());
       if (!Insertion)
         return;
-      std::string PlatformName =
-          AvailabilityAttr::getPlatformNameSourceSpelling(
-              S.getASTContext().getTargetInfo().getPlatformName())
-              .lower();
+      StringRef PlatformName =
+          S.getASTContext().getTargetInfo().getPlatformName();
+
+      // Apple's API_AVAILABLE macro expands roughly like this.
+      // API_AVAILABLE(ios(17.0))
+      // __attribute__((availability(__API_AVAILABLE_PLATFORM_ios(17.0)))
+      // __attribute__((availability(ios,introduced=17.0)))
+      // In other words, the platform name in API_AVAILABLE has to be backed by an
+      // __API_AVAILABLE_PLATFORM_ macro. The __API_AVAILABLE_PLATFORM_ macros
+      // aren't consistent with using the canonical platform name, source spelling
+      // name, or one of the other supported names (i.e. one of the keys in
+      // canonicalizePlatformName that's neither). Look for a macro matching any
+      // of the supported attribute names.
+      llvm::Twine MacroPrefix = "__API_AVAILABLE_PLATFORM_";
+      StringRef AvailabilityPlatform = {};
+      for (StringRef EquivalentPlatform :
+           AvailabilityAttr::equivalentPlatformNames(PlatformName)) {
+        if (PP.isMacroDefined((MacroPrefix + EquivalentPlatform).str())) {
+          AvailabilityPlatform = EquivalentPlatform;
+          break;
+        }
+      }
----------------
ian-twilightcoder wrote:

Is there a nicer way to get the first matching item in an ArrayRef? I feel like I'm missing a utility somewhere...

https://github.com/llvm/llvm-project/pull/105855


More information about the cfe-commits mailing list