================
@@ -993,6 +993,119 @@ UnwindTagContext(TagDecl *DC, api_notes::APINotesManager 
&APINotes) {
   return std::nullopt;
 }
 
+static void stripAPINotesParameterNullability(QualType &ParamType) {
+  while (true) {
+    if (!AttributedType::stripOuterNullability(ParamType))
+      return;
+  }
+}
+
+struct APINotesParameterSelector {
+  SmallVector<std::string, 4> Parameters;
+
+  SmallVector<StringRef, 4> getParameterRefs() const {
+    SmallVector<StringRef, 4> Refs;
+    Refs.reserve(Parameters.size());
+    for (const std::string &Parameter : Parameters)
+      Refs.push_back(Parameter);
+    return Refs;
+  }
+
+  bool operator==(const APINotesParameterSelector &Other) const {
+    return Parameters == Other.Parameters;
+  }
+};
+
+struct APINotesParameterSelectorCandidates {
+  APINotesParameterSelector Source;
+  std::optional<APINotesParameterSelector> Desugared;
+};
+
+static PrintingPolicy
+getAPINotesParameterSelectorPrintingPolicy(const ASTContext &Context) {
+  PrintingPolicy Policy(Context.getLangOpts());
+  Policy.PrintAsCanonical = false;
+  Policy.FullyQualifiedName = false;
+  Policy.SuppressScope = false;
+  Policy.UsePreferredNames = false;
+  Policy.MSVCFormatting = false;
+  Policy.SplitTemplateClosers = false;
+  Policy.IncludeNewlines = false;
+  return Policy;
+}
+
+// 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<APINotesParameterSelectorCandidates>
+getAPINotesParameterSelectorCandidates(const Sema &S, const FunctionDecl *FD) {
+  const auto *FPT = FD->getType()->getAs<FunctionProtoType>();
+  if (!FPT)
+    return std::nullopt;
+
+  APINotesParameterSelectorCandidates Candidates;
+  APINotesParameterSelector Desugared;
+  Candidates.Source.Parameters.reserve(FPT->getNumParams());
+  Desugared.Parameters.reserve(FPT->getNumParams());
+
+  const PrintingPolicy Policy =
+      getAPINotesParameterSelectorPrintingPolicy(S.Context);
+  for (QualType ParamType : FPT->param_types()) {
+    Candidates.Source.Parameters.push_back(
+        getAPINotesParameterSelectorSpelling(ParamType, S.Context, Policy,
+                                             /*Desugar=*/false));
+    Desugared.Parameters.push_back(getAPINotesParameterSelectorSpelling(
+        ParamType, S.Context, Policy, /*Desugar=*/true));
+  }
+
+  if (!(Candidates.Source == Desugared))
----------------
Xazax-hun wrote:

I wonder if it would be cleaner to define `operator!=`. 

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