================
@@ -993,6 +993,87 @@ UnwindTagContext(TagDecl *DC, api_notes::APINotesManager 
&APINotes) {
   return std::nullopt;
 }
 
+static void stripAPINotesParameterNullability(QualType &ParamType) {
+  while (true) {
+    if (!AttributedType::stripOuterNullability(ParamType))
+      return;
+  }
+}
+
+// Print the APINotes selector spelling for one parameter. The source-spelled
+// selector is tried first. The desugared spelling is only a permissive
+// fallback.
+static std::string getAPINotesParameterSelectorSpelling(
+    QualType ParamType, const ASTContext &Context, const PrintingPolicy 
&Policy,
+    bool Desugar) {
+  ParamType.removeLocalConst();
+  stripAPINotesParameterNullability(ParamType);
+
+  if (Desugar) {
+    ParamType = ParamType.getDesugaredType(Context);
+    ParamType.removeLocalConst();
+    stripAPINotesParameterNullability(ParamType);
+  }
+
+  return ParamType.getAsString(Policy);
+}
+
+static std::optional<SmallVector<SmallVector<std::string, 4>, 2>>
+getAPINotesParameterSelectorCandidates(const Sema &S, const FunctionDecl *FD) {
+  const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
+  if (!FPT)
+    return std::nullopt;
+
+  SmallVector<std::string, 4> SourceParameters;
+  SmallVector<std::string, 4> DesugaredParameters;
+  SourceParameters.reserve(FPT->getNumParams());
+  DesugaredParameters.reserve(FPT->getNumParams());
+
+  const PrintingPolicy &Policy = S.Context.getPrintingPolicy();
+  for (QualType ParamType : FPT->param_types()) {
+    SourceParameters.push_back(getAPINotesParameterSelectorSpelling(
+        ParamType, S.Context, Policy, /*Desugar=*/false));
+    DesugaredParameters.push_back(getAPINotesParameterSelectorSpelling(
+        ParamType, S.Context, Policy, /*Desugar=*/true));
+  }
+
+  SmallVector<SmallVector<std::string, 4>, 2> Candidates;
+  Candidates.push_back(std::move(SourceParameters));
+  if (Candidates.front() != DesugaredParameters)
+    Candidates.push_back(std::move(DesugaredParameters));
+
+  return Candidates;
+}
+
+static SmallVector<StringRef, 4>
+getAPINotesParameterSelectorRefs(ArrayRef<std::string> Strings) {
+  SmallVector<StringRef, 4> Refs;
+  Refs.reserve(Strings.size());
+  for (const std::string &String : Strings)
+    Refs.push_back(String);
+  return Refs;
+}
+
+// Apply the first exact selector entry found. This preserves source-spelling
+// precedence over the desugared fallback and avoids applying multiple exact
+// entries for the same declaration.
+template <typename SpecificDecl, typename LookupExactFn>
+static void processExactAPINotes(
+    Sema &S, SpecificDecl *D,
+    ArrayRef<SmallVector<std::string, 4>> ParameterSelectorCandidates,
+    LookupExactFn LookupExact) {
----------------
j-hui wrote:

I know this is just an internal helper function, but I think that 
`LookupExactFn` type parameter is too broad and should be constrained more. In 
particular, I think it should be narrowed to `SpecificInfo` (to mirror the 
parameterization of `ProcessVersionedAPINotes()`), and the `LookupExactFn` 
should be given as a `llvm::function_ref<const VersionedInfo<SpecificInfo> 
(ArrayRef<StringRef>)>`, so that the "shape" of the lambda being passed in is 
clearer.

https://github.com/llvm/llvm-project/pull/205307
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to