================
@@ -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