[clang] [clang][ExtractAPI] Compute inherited availability information (PR #103040)
Cyndy Ishida via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 13 16:20:48 PDT 2024
================
@@ -16,33 +16,101 @@
#include "clang/AST/Decl.h"
#include "clang/Basic/TargetInfo.h"
-namespace clang {
+namespace {
+
+struct AvailabilitySet {
+ llvm::SmallVector<clang::AvailabilityInfo> Availabilities;
+ bool UnconditionallyDeprecated = false;
+ bool UnconditionallyUnavailable = false;
-AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *Decl) {
- ASTContext &Context = Decl->getASTContext();
- StringRef PlatformName = Context.getTargetInfo().getPlatformName();
- AvailabilityInfo Availability;
+ void insert(clang::AvailabilityInfo &&Availability) {
+ auto *Found = getForPlatform(Availability.Domain);
+ if (Found)
+ Found->mergeWith(std::move(Availability));
+ else
+ Availabilities.emplace_back(std::move(Availability));
+ }
+
+ clang::AvailabilityInfo *getForPlatform(llvm::StringRef Domain) {
+ auto *It = llvm::find_if(Availabilities,
+ [Domain](const clang::AvailabilityInfo &Info) {
+ return Domain.compare(Info.Domain) == 0;
+ });
+ return It == Availabilities.end() ? nullptr : It;
+ }
+};
+static void createInfoForDecl(const clang::Decl *Decl,
+ AvailabilitySet &Availabilities) {
// Collect availability attributes from all redeclarations.
for (const auto *RD : Decl->redecls()) {
- for (const auto *A : RD->specific_attrs<AvailabilityAttr>()) {
- if (A->getPlatform()->getName() != PlatformName)
- continue;
- Availability = AvailabilityInfo(
+ for (const auto *A : RD->specific_attrs<clang::AvailabilityAttr>()) {
+ Availabilities.insert(clang::AvailabilityInfo(
A->getPlatform()->getName(), A->getIntroduced(), A->getDeprecated(),
- A->getObsoleted(), A->getUnavailable(), false, false);
- break;
+ A->getObsoleted(), A->getUnavailable(), false, false));
}
- if (const auto *A = RD->getAttr<UnavailableAttr>())
+ if (const auto *A = RD->getAttr<clang::UnavailableAttr>())
if (!A->isImplicit())
- Availability.UnconditionallyUnavailable = true;
+ Availabilities.UnconditionallyUnavailable = true;
- if (const auto *A = RD->getAttr<DeprecatedAttr>())
+ if (const auto *A = RD->getAttr<clang::DeprecatedAttr>())
if (!A->isImplicit())
- Availability.UnconditionallyDeprecated = true;
+ Availabilities.UnconditionallyDeprecated = true;
+ }
+}
+
+} // namespace
+
+namespace clang {
+
+void AvailabilityInfo::mergeWith(AvailabilityInfo Other) {
+ if (isDefault() && Other.isDefault())
+ return;
+
+ if (Domain.empty())
+ Domain = Other.Domain;
+
+ UnconditionallyUnavailable |= Other.UnconditionallyUnavailable;
+ UnconditionallyDeprecated |= Other.UnconditionallyDeprecated;
+ Unavailable |= Other.Unavailable;
+
+ Introduced = std::max(Introduced, Other.Introduced);
+
+ // Default VersionTuple is 0.0.0 so if both are non default let's pick the
+ // smallest version number, otherwise select the one that is non-zero if there
+ // is one.
+ if (!Deprecated.empty() && !Other.Deprecated.empty())
+ Deprecated = std::min(Deprecated, Other.Deprecated);
+ else
+ Deprecated = std::max(Deprecated, Other.Deprecated);
+
+ if (!Obsoleted.empty() && !Other.Obsoleted.empty())
+ Obsoleted = std::min(Obsoleted, Other.Obsoleted);
+ else
+ Obsoleted = std::max(Obsoleted, Other.Obsoleted);
+}
+
+AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *D) {
+ AvailabilitySet Availabilities;
+ createInfoForDecl(D, Availabilities);
+ // Traverse
----------------
cyndyishida wrote:
nit: I think this can be removed
https://github.com/llvm/llvm-project/pull/103040
More information about the cfe-commits
mailing list