[clang] [APINotes] Upstream Sema logic to apply API Notes to decls (PR #78445)

Egor Zhdan via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 22 13:03:24 PST 2024


================
@@ -0,0 +1,1014 @@
+//===--- SemaAPINotes.cpp - API Notes Handling ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the mapping from API notes to declaration attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Sema/SemaInternal.h"
+
+using namespace clang;
+
+namespace {
+enum IsActive_t : bool { IsNotActive, IsActive };
+enum IsReplacement_t : bool { IsNotReplacement, IsReplacement };
+
+struct VersionedInfoMetadata {
+  /// An empty version refers to unversioned metadata.
+  VersionTuple Version;
+  unsigned IsActive : 1;
+  unsigned IsReplacement : 1;
+
+  VersionedInfoMetadata(VersionTuple Version, IsActive_t Active,
+                        IsReplacement_t Replacement)
+      : Version(Version), IsActive(Active == IsActive_t::IsActive),
+        IsReplacement(Replacement == IsReplacement_t::IsReplacement) {}
+};
+} // end anonymous namespace
+
+/// Determine whether this is a multi-level pointer type.
+static bool isMultiLevelPointerType(QualType Type) {
+  QualType Pointee = Type->getPointeeType();
+  if (Pointee.isNull())
+    return false;
+
+  return Pointee->isAnyPointerType() || Pointee->isObjCObjectPointerType() ||
+         Pointee->isMemberPointerType();
+}
+
+/// Apply nullability to the given declaration.
+static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability,
+                             VersionedInfoMetadata Metadata) {
+  if (!Metadata.IsActive)
+    return;
+
+  QualType Type;
+
+  // Nullability for a function/method appertains to the retain type.
+  if (auto Function = dyn_cast<FunctionDecl>(D))
+    Type = Function->getReturnType();
+  else if (auto Method = dyn_cast<ObjCMethodDecl>(D))
+    Type = Method->getReturnType();
+  else if (auto Value = dyn_cast<ValueDecl>(D))
+    Type = Value->getType();
+  else if (auto Property = dyn_cast<ObjCPropertyDecl>(D))
+    Type = Property->getType();
+  else
+    return;
+
+  // Check the nullability specifier on this type.
+  QualType OrigType = Type;
+  S.CheckImplicitNullabilityTypeSpecifier(Type, Nullability, D->getLocation(),
+                                          isa<ParmVarDecl>(D),
+                                          /*overrideExisting=*/true);
+  if (Type.getTypePtr() == OrigType.getTypePtr())
+    return;
+
+  if (auto Function = dyn_cast<FunctionDecl>(D)) {
+    const FunctionType *FnType = Function->getType()->castAs<FunctionType>();
+    if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType))
+      Function->setType(S.Context.getFunctionType(Type, Proto->getParamTypes(),
+                                                  Proto->getExtProtoInfo()));
+    else
+      Function->setType(
+          S.Context.getFunctionNoProtoType(Type, FnType->getExtInfo()));
+  } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) {
+    Method->setReturnType(Type);
+
+    // Make it a context-sensitive keyword if we can.
+    if (!isMultiLevelPointerType(Type))
+      Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+          Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+
+  } else if (auto Value = dyn_cast<ValueDecl>(D)) {
+    Value->setType(Type);
+
+    // Make it a context-sensitive keyword if we can.
+    if (auto Parm = dyn_cast<ParmVarDecl>(D)) {
+      if (Parm->isObjCMethodParameter() && !isMultiLevelPointerType(Type))
+        Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier(
+            Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability));
+    }
+  } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) {
+    Property->setType(Type, Property->getTypeSourceInfo());
+
+    // Make it a property attribute if we can.
+    if (!isMultiLevelPointerType(Type))
+      Property->setPropertyAttributes(
+          ObjCPropertyAttribute::kind_null_resettable);
+
+  } else
+    llvm_unreachable("cannot handle nullability here");
+}
+
+/// Copy a string into ASTContext-allocated memory.
+static StringRef CopyString(ASTContext &Ctx, StringRef String) {
----------------
egorzhdan wrote:

Renamed it to `ASTAllocateString`.

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


More information about the cfe-commits mailing list