Author: StoeckOverflow Date: 2026-07-13T14:36:11+01:00 New Revision: ee71eb831b6090897df8ae4f843f4b14370131d5
URL: https://github.com/llvm/llvm-project/commit/ee71eb831b6090897df8ae4f843f4b14370131d5 DIFF: https://github.com/llvm/llvm-project/commit/ee71eb831b6090897df8ae4f843f4b14370131d5.diff LOG: [APINotes] Match function-like Where.Parameters in Sema (#205307) This PR teaches Sema to apply function-like `Where.Parameters` selectors for API notes. It builds on #204147 by using the serialized `Where.Parameters` selector keys in Sema. For each `FunctionDecl` / `CXXMethodDecl`, Sema derives an exact parameter selector from the declaration’s `FunctionProtoType`. Broad name-only API notes lookup still runs first, preserving existing behavior. If Clang can form a parameter selector, Sema then performs an exact selector lookup and applies that result second, allowing overload-specific notes to refine same-name broad notes. Tests: - Adds end-to-end module APINotes Sema coverage (`.apinotes` source -> binary APINotes -> reader lookup -> Sema matching -> AST result) - Covers core matching behavior for global functions and C++ methods, including same-name overloads, exact empty selectors, broad-plus-exact coexistence and mismatched selectors - Covers important edge cases: default arguments, static methods, alias spellings remaining non-canonicalized, by-value `const`, namespaced functions, and overloaded operators. This PR does not add duplicate-selector or unmatched-selector diagnostics. Those remain for a follow-up diagnostics PR. **Note**: this PR was originally stacked on top of #204147. It has now been rebased on top of main containing those changes, so the remaining diff should reflect only the top commit specific to this PR. Reviewers: @Xazax-hun @j-hui @egorzhdan --------- Co-authored-by: John Hui <[email protected]> Added: clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes clang/test/APINotes/Inputs/Headers/WhereParametersSema.h clang/test/APINotes/where-parameters-sema.cpp Modified: clang/include/clang/APINotes/APINotesReader.h clang/lib/APINotes/APINotesFormat.h clang/lib/APINotes/APINotesReader.cpp clang/lib/Sema/SemaAPINotes.cpp clang/test/APINotes/Inputs/Headers/module.modulemap Removed: ################################################################################ diff --git a/clang/include/clang/APINotes/APINotesReader.h b/clang/include/clang/APINotes/APINotesReader.h index 8e748b5803189..761745e20b61a 100644 --- a/clang/include/clang/APINotes/APINotesReader.h +++ b/clang/include/clang/APINotes/APINotesReader.h @@ -22,6 +22,7 @@ #include "llvm/Support/VersionTuple.h" #include <memory> #include <optional> +#include <string> namespace clang { namespace api_notes { @@ -166,7 +167,7 @@ class APINotesReader { /// key, and a non-empty list uses an exact ordered parameter key. VersionedInfo<CXXMethodInfo> lookupCXXMethod(ContextID CtxID, llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters); + llvm::ArrayRef<std::string> Parameters); /// Look for information regarding the given global variable. /// @@ -191,7 +192,7 @@ class APINotesReader { /// key, and a non-empty list uses an exact ordered parameter key. VersionedInfo<GlobalFunctionInfo> lookupGlobalFunction(llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters, + llvm::ArrayRef<std::string> Parameters, std::optional<Context> Ctx = std::nullopt); /// Look for information regarding the given enumerator. @@ -242,15 +243,17 @@ class APINotesReader { private: VersionedInfo<CXXMethodInfo> lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name); + template <typename ParameterT> VersionedInfo<CXXMethodInfo> lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters); + llvm::ArrayRef<ParameterT> Parameters); VersionedInfo<GlobalFunctionInfo> lookupGlobalFunctionImpl(llvm::StringRef Name, std::optional<Context> Ctx); + template <typename ParameterT> VersionedInfo<GlobalFunctionInfo> lookupGlobalFunctionImpl(llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters, + llvm::ArrayRef<ParameterT> Parameters, std::optional<Context> Ctx); }; diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index df67da0845baf..f34ca2e2e363f 100644 --- a/clang/lib/APINotes/APINotesFormat.h +++ b/clang/lib/APINotes/APINotesFormat.h @@ -417,10 +417,10 @@ getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name, return FunctionTableKey(ParentContextID, *NameID); } -template <typename GetIdentifierFn> +template <typename ParameterT, typename GetIdentifierFn> std::optional<FunctionTableKey> getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters, + llvm::ArrayRef<ParameterT> Parameters, GetIdentifierFn GetIdentifier) { std::optional<IdentifierID> NameID = GetIdentifier(Name); if (!NameID) @@ -428,8 +428,9 @@ getFunctionKeyImpl(uint32_t ParentContextID, llvm::StringRef Name, llvm::SmallVector<IdentifierID, 2> ParameterTypeIDs; ParameterTypeIDs.reserve(Parameters.size()); - for (llvm::StringRef Parameter : Parameters) { - std::optional<IdentifierID> ParameterID = GetIdentifier(Parameter); + for (const ParameterT &Parameter : Parameters) { + std::optional<IdentifierID> ParameterID = + GetIdentifier(llvm::StringRef(Parameter)); if (!ParameterID) return std::nullopt; ParameterTypeIDs.push_back(*ParameterID); diff --git a/clang/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp index 9305a5f10b4e8..888844fbb6cd9 100644 --- a/clang/lib/APINotes/APINotesReader.cpp +++ b/clang/lib/APINotes/APINotesReader.cpp @@ -857,14 +857,16 @@ class APINotesReader::Implementation { llvm::SmallVectorImpl<uint64_t> &Scratch); std::optional<FunctionTableKey> getFunctionKey(uint32_t ParentContextID, llvm::StringRef Name); + template <typename ParameterT> std::optional<FunctionTableKey> getFunctionKey(uint32_t ParentContextID, llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters); + llvm::ArrayRef<ParameterT> Parameters); std::optional<FunctionTableKey> getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name); + template <typename ParameterT> std::optional<FunctionTableKey> getFunctionKey(std::optional<Context> ParentContext, llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters); + llvm::ArrayRef<ParameterT> Parameters); llvm::Error readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch); @@ -899,9 +901,10 @@ APINotesReader::Implementation::getFunctionKey(uint32_t ParentContextID, }); } +template <typename ParameterT> std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey( uint32_t ParentContextID, llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters) { + llvm::ArrayRef<ParameterT> Parameters) { return getFunctionKeyImpl( ParentContextID, Name, Parameters, [this](llvm::StringRef S) { return getIdentifier(S); }); @@ -914,9 +917,10 @@ std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey( return getFunctionKey(ParentContextID, Name); } +template <typename ParameterT> std::optional<FunctionTableKey> APINotesReader::Implementation::getFunctionKey( std::optional<Context> ParentContext, llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters) { + llvm::ArrayRef<ParameterT> Parameters) { uint32_t ParentContextID = ParentContext ? ParentContext->id.Value : static_cast<uint32_t>(-1); return getFunctionKey(ParentContextID, Name, Parameters); @@ -2342,7 +2346,7 @@ auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name) } auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters) + llvm::ArrayRef<std::string> Parameters) -> VersionedInfo<CXXMethodInfo> { return lookupCXXMethodImpl(CtxID, Name, Parameters); } @@ -2364,9 +2368,9 @@ auto APINotesReader::lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name) return {Implementation->SwiftVersion, *Known}; } -auto APINotesReader::lookupCXXMethodImpl( - ContextID CtxID, llvm::StringRef Name, - llvm::ArrayRef<llvm::StringRef> Parameters) +template <typename ParameterT> +auto APINotesReader::lookupCXXMethodImpl(ContextID CtxID, llvm::StringRef Name, + llvm::ArrayRef<ParameterT> Parameters) -> VersionedInfo<CXXMethodInfo> { if (!Implementation->CXXMethodTable) return std::nullopt; @@ -2409,7 +2413,7 @@ auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name, } auto APINotesReader::lookupGlobalFunction( - llvm::StringRef Name, llvm::ArrayRef<llvm::StringRef> Parameters, + llvm::StringRef Name, llvm::ArrayRef<std::string> Parameters, std::optional<Context> Ctx) -> VersionedInfo<GlobalFunctionInfo> { return lookupGlobalFunctionImpl(Name, Parameters, Ctx); } @@ -2432,8 +2436,9 @@ auto APINotesReader::lookupGlobalFunctionImpl(llvm::StringRef Name, return {Implementation->SwiftVersion, *Known}; } +template <typename ParameterT> auto APINotesReader::lookupGlobalFunctionImpl( - llvm::StringRef Name, llvm::ArrayRef<llvm::StringRef> Parameters, + llvm::StringRef Name, llvm::ArrayRef<ParameterT> Parameters, std::optional<Context> Ctx) -> VersionedInfo<GlobalFunctionInfo> { if (!Implementation->GlobalFunctionTable) return std::nullopt; diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 67c08d239e758..1ab1eac4a5434 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -993,6 +993,111 @@ 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; + + bool operator==(const APINotesParameterSelector &Other) const { + return Parameters == Other.Parameters; + } + + bool operator!=(const APINotesParameterSelector &Other) const { + return !(*this == Other); + } +}; + +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) { + 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) + Candidates.Desugared = std::move(Desugared); + + return Candidates; +} + +// 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 SpecificInfo, typename SpecificDecl> +static void processExactAPINotes( + Sema &S, SpecificDecl *D, + const APINotesParameterSelectorCandidates &ParameterSelectorCandidates, + llvm::function_ref<api_notes::APINotesReader::VersionedInfo<SpecificInfo>( + ArrayRef<std::string>)> + LookupExact) { + auto ProcessSelector = [&](const APINotesParameterSelector &Selector) { + auto Info = LookupExact(Selector.Parameters); + if (Info.size() == 0) + return false; + + ProcessVersionedAPINotes(S, D, Info); + return true; + }; + + if (ProcessSelector(ParameterSelectorCandidates.Source)) + return; + + if (ParameterSelectorCandidates.Desugared) + ProcessSelector(*ParameterSelectorCandidates.Desugared); +} + /// Process API notes that are associated with this declaration, mapping them /// to attributes as appropriate. void Sema::ProcessAPINotes(Decl *D) { @@ -1024,10 +1129,20 @@ void Sema::ProcessAPINotes(Decl *D) { // Global functions. if (auto FD = dyn_cast<FunctionDecl>(D)) { if (FD->getDeclName().isIdentifier()) { + auto ParameterSelectorCandidates = + getAPINotesParameterSelectorCandidates(*this, FD); for (auto Reader : Readers) { auto Info = Reader->lookupGlobalFunction(FD->getName(), APINotesContext); ProcessVersionedAPINotes(*this, FD, Info); + + if (ParameterSelectorCandidates) + processExactAPINotes<api_notes::GlobalFunctionInfo>( + *this, FD, *ParameterSelectorCandidates, + [&](ArrayRef<std::string> Parameters) { + return Reader->lookupGlobalFunction(FD->getName(), Parameters, + APINotesContext); + }); } } @@ -1211,6 +1326,8 @@ void Sema::ProcessAPINotes(Decl *D) { if (!isa<CXXConstructorDecl>(CXXMethod) && !isa<CXXDestructorDecl>(CXXMethod) && !isa<CXXConversionDecl>(CXXMethod)) { + auto ParameterSelectorCandidates = + getAPINotesParameterSelectorCandidates(*this, CXXMethod); for (auto Reader : Readers) { if (auto Context = UnwindTagContext(TagContext, APINotes)) { std::string MethodName; @@ -1223,6 +1340,14 @@ void Sema::ProcessAPINotes(Decl *D) { auto Info = Reader->lookupCXXMethod(Context->id, MethodName); ProcessVersionedAPINotes(*this, CXXMethod, Info); + + if (ParameterSelectorCandidates) + processExactAPINotes<api_notes::CXXMethodInfo>( + *this, CXXMethod, *ParameterSelectorCandidates, + [&](ArrayRef<std::string> Parameters) { + return Reader->lookupCXXMethod(Context->id, MethodName, + Parameters); + }); } } } diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes new file mode 100644 index 0000000000000..7ffee9223f8c3 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.apinotes @@ -0,0 +1,166 @@ +--- +Name: WhereParametersSema +Functions: +- Name: makeWidget + Where: + Parameters: + - int + SwiftName: makeIntWidget(_:) +- Name: makeWidget + Where: + Parameters: + - double + SwiftName: makeDoubleWidget(_:) +- Name: makeWidget + Where: + Parameters: [] + SwiftName: makeCurrentWidget() +- Name: broadGlobal + SwiftPrivate: true +- Name: coexistGlobal + SwiftPrivate: true +- Name: coexistGlobal + Where: + Parameters: + - int + SwiftName: coexistGlobalInt(_:) +- Name: mismatchGlobal + Where: + Parameters: + - int + SwiftName: shouldNotApplyGlobal(_:) +- Name: aliasGlobal + Where: + Parameters: + - int + SwiftName: aliasGlobal(_:) +- Name: aliasPrecedenceGlobal + Where: + Parameters: + - int + SwiftName: fallbackAliasPrecedenceGlobal(_:) +- Name: aliasPrecedenceGlobal + Where: + Parameters: + - AliasInt + SwiftName: aliasPrecedenceGlobal(_:) +- Name: multiAliasGlobal + Where: + Parameters: + - int + SwiftName: multiAliasGlobal(_:) +- Name: nullableGlobal + Where: + Parameters: + - 'char *' + SwiftName: nullableGlobal(_:) +- Name: rawIntGlobal + Where: + Parameters: + - int + SwiftName: rawIntGlobal(_:) +- Name: constValueGlobal + Where: + Parameters: + - int + SwiftName: constValueGlobal(_:) +Namespaces: +- Name: SelectorNamespace + Functions: + - Name: makeNamespaced + Where: + Parameters: + - int + SwiftName: makeNamespacedInt(_:) + - Name: makeNamespaced + Where: + Parameters: + - double + SwiftName: makeNamespacedDouble(_:) +Tags: +- Name: SelectorWidget + Methods: + - Name: setValue + Where: + Parameters: + - int + SwiftName: setIntValue(_:) + - Name: setValue + Where: + Parameters: + - double + SwiftName: setDoubleValue(_:) + - Name: setValue + Where: + Parameters: [] + SwiftName: currentValue() + - Name: broad + SwiftPrivate: true + - Name: coexist + SwiftPrivate: true + - Name: coexist + Where: + Parameters: + - int + SwiftName: coexistInt(_:) + - Name: defaults + Where: + Parameters: + - int + - double + SwiftName: defaultsWithTwoParameters(_:_:) + - Name: configure + Where: + Parameters: + - int + SwiftName: configureInt(_:) + - Name: mismatch + Where: + Parameters: + - int + SwiftName: shouldNotApplyMethod(_:) + - Name: alias + Where: + Parameters: + - int + SwiftName: alias(_:) + - Name: aliasPrecedence + Where: + Parameters: + - int + SwiftName: fallbackAliasPrecedence(_:) + - Name: aliasPrecedence + Where: + Parameters: + - AliasInt + SwiftName: aliasPrecedence(_:) + - Name: multiAlias + Where: + Parameters: + - int + SwiftName: multiAlias(_:) + - Name: nullable + Where: + Parameters: + - 'char *' + SwiftName: nullable(_:) + - Name: rawInt + Where: + Parameters: + - int + SwiftName: rawInt(_:) + - Name: constValue + Where: + Parameters: + - int + SwiftName: constValue(_:) + - Name: operator+ + Where: + Parameters: + - int + SwiftName: plusInt(_:) + - Name: operator+ + Where: + Parameters: + - double + SwiftName: plusDouble(_:) diff --git a/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h new file mode 100644 index 0000000000000..8226fa287b115 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/WhereParametersSema.h @@ -0,0 +1,59 @@ +#ifndef WHERE_PARAMETERS_SEMA_H +#define WHERE_PARAMETERS_SEMA_H + +using AliasInt = int; +using AliasAliasInt = AliasInt; +using DeepAliasInt = AliasAliasInt; + +void makeWidget(int); +void makeWidget(double); +void makeWidget(); + +void broadGlobal(int); +void broadGlobal(double); + +void coexistGlobal(int); +void coexistGlobal(double); + +void mismatchGlobal(float); +void aliasGlobal(AliasInt); +void aliasPrecedenceGlobal(AliasInt); +void multiAliasGlobal(DeepAliasInt); +void nullableGlobal(char * _Nonnull); +void rawIntGlobal(int); +void constValueGlobal(const int); + +namespace SelectorNamespace { +void makeNamespaced(int); +void makeNamespaced(double); +} + +struct SelectorWidget { + void setValue(int); + void setValue(double); + void setValue(); + + void broad(int); + void broad(double); + + void coexist(int); + void coexist(double); + + void defaults(int, double = 0); + void defaults(int); + + static void configure(int); + + void mismatch(float); + void alias(AliasInt); + void aliasPrecedence(AliasInt); + void multiAlias(DeepAliasInt); + void nullable(char * _Nonnull); + void rawInt(int); + void constValue(const int); + + SelectorWidget operator+(int); + SelectorWidget operator+(double); +}; + +#endif // WHERE_PARAMETERS_SEMA_H diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap index 7bcf33644a14f..592d482ea7a57 100644 --- a/clang/test/APINotes/Inputs/Headers/module.modulemap +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -70,3 +70,8 @@ module UnsafeBufferUsage { header "UnsafeBufferUsage.h" export * } + +module WhereParametersSema { + header "WhereParametersSema.h" + export * +} diff --git a/clang/test/APINotes/where-parameters-sema.cpp b/clang/test/APINotes/where-parameters-sema.cpp new file mode 100644 index 0000000000000..fbb7cb45b9441 --- /dev/null +++ b/clang/test/APINotes/where-parameters-sema.cpp @@ -0,0 +1,136 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter makeWidget -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-OVERLOADS %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter broadGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-BROAD %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter coexistGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-COEXIST %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter mismatchGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-MISMATCH %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter aliasGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-ALIAS %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter aliasPrecedenceGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-ALIAS-PRECEDENCE %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter multiAliasGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-MULTI-ALIAS %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter nullableGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-NULLABILITY %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter rawIntGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-RAW-INT %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter constValueGlobal -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-CONST %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorNamespace::makeNamespaced -x c++ | FileCheck --check-prefix=CHECK-GLOBAL-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::setValue -x c++ | FileCheck --check-prefix=CHECK-METHOD-OVERLOADS %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::broad -x c++ | FileCheck --check-prefix=CHECK-METHOD-BROAD %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::coexist -x c++ | FileCheck --check-prefix=CHECK-METHOD-COEXIST %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::defaults -x c++ | FileCheck --check-prefix=CHECK-METHOD-DEFAULTS %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::configure -x c++ | FileCheck --check-prefix=CHECK-METHOD-STATIC %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::mismatch -x c++ | FileCheck --check-prefix=CHECK-METHOD-MISMATCH %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::alias -x c++ | FileCheck --check-prefix=CHECK-METHOD-ALIAS %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::aliasPrecedence -x c++ | FileCheck --check-prefix=CHECK-METHOD-ALIAS-PRECEDENCE %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::multiAlias -x c++ | FileCheck --check-prefix=CHECK-METHOD-MULTI-ALIAS %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::nullable -x c++ | FileCheck --check-prefix=CHECK-METHOD-NULLABILITY %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::rawInt -x c++ | FileCheck --check-prefix=CHECK-METHOD-RAW-INT %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::constValue -x c++ | FileCheck --check-prefix=CHECK-METHOD-CONST %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/WhereParametersSema -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter SelectorWidget::operator+ -x c++ | FileCheck --check-prefix=CHECK-METHOD-OPERATOR %s + +#include "WhereParametersSema.h" + +// CHECK-GLOBAL-OVERLOADS: FunctionDecl {{.+}} makeWidget 'void (int)' +// CHECK-GLOBAL-OVERLOADS-NEXT: ParmVarDecl {{.+}} 'int' +// CHECK-GLOBAL-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "makeIntWidget(_:)" +// CHECK-GLOBAL-OVERLOADS: FunctionDecl {{.+}} makeWidget 'void (double)' +// CHECK-GLOBAL-OVERLOADS-NEXT: ParmVarDecl {{.+}} 'double' +// CHECK-GLOBAL-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "makeDoubleWidget(_:)" +// CHECK-GLOBAL-OVERLOADS: FunctionDecl {{.+}} makeWidget 'void ()' +// CHECK-GLOBAL-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "makeCurrentWidget()" + +// CHECK-GLOBAL-BROAD: FunctionDecl {{.+}} broadGlobal 'void (int)' +// CHECK-GLOBAL-BROAD: SwiftPrivateAttr +// CHECK-GLOBAL-BROAD: FunctionDecl {{.+}} broadGlobal 'void (double)' +// CHECK-GLOBAL-BROAD: SwiftPrivateAttr + +// CHECK-GLOBAL-COEXIST: FunctionDecl {{.+}} coexistGlobal 'void (int)' +// CHECK-GLOBAL-COEXIST: SwiftPrivateAttr +// CHECK-GLOBAL-COEXIST: SwiftNameAttr {{.+}} "coexistGlobalInt(_:)" +// CHECK-GLOBAL-COEXIST: FunctionDecl {{.+}} coexistGlobal 'void (double)' +// CHECK-GLOBAL-COEXIST: SwiftPrivateAttr +// CHECK-GLOBAL-COEXIST-NOT: SwiftNameAttr + +// CHECK-GLOBAL-MISMATCH: FunctionDecl {{.+}} mismatchGlobal 'void (float)' +// CHECK-GLOBAL-MISMATCH-NOT: SwiftNameAttr + +// CHECK-GLOBAL-ALIAS: FunctionDecl {{.+}} aliasGlobal 'void (AliasInt)' +// CHECK-GLOBAL-ALIAS: SwiftNameAttr {{.+}} "aliasGlobal(_:)" + +// CHECK-GLOBAL-ALIAS-PRECEDENCE: FunctionDecl {{.+}} aliasPrecedenceGlobal 'void (AliasInt)' +// CHECK-GLOBAL-ALIAS-PRECEDENCE-NOT: fallbackAliasPrecedenceGlobal +// CHECK-GLOBAL-ALIAS-PRECEDENCE: SwiftNameAttr {{.+}} "aliasPrecedenceGlobal(_:)" + +// CHECK-GLOBAL-MULTI-ALIAS: FunctionDecl {{.+}} multiAliasGlobal 'void (DeepAliasInt)' +// CHECK-GLOBAL-MULTI-ALIAS: SwiftNameAttr {{.+}} "multiAliasGlobal(_:)" + +// CHECK-GLOBAL-NULLABILITY: FunctionDecl {{.+}} nullableGlobal 'void (char * _Nonnull)' +// CHECK-GLOBAL-NULLABILITY: SwiftNameAttr {{.+}} "nullableGlobal(_:)" + +// CHECK-GLOBAL-RAW-INT: FunctionDecl {{.+}} rawIntGlobal 'void (int)' +// CHECK-GLOBAL-RAW-INT: SwiftNameAttr {{.+}} "rawIntGlobal(_:)" + +// CHECK-GLOBAL-CONST: FunctionDecl {{.+}} constValueGlobal 'void (const int)' +// CHECK-GLOBAL-CONST: SwiftNameAttr {{.+}} "constValueGlobal(_:)" + +// CHECK-GLOBAL-NAMESPACE: FunctionDecl {{.+}} makeNamespaced 'void (int)' +// CHECK-GLOBAL-NAMESPACE-NEXT: ParmVarDecl {{.+}} 'int' +// CHECK-GLOBAL-NAMESPACE-NEXT: SwiftNameAttr {{.+}} "makeNamespacedInt(_:)" +// CHECK-GLOBAL-NAMESPACE: FunctionDecl {{.+}} makeNamespaced 'void (double)' +// CHECK-GLOBAL-NAMESPACE-NEXT: ParmVarDecl {{.+}} 'double' +// CHECK-GLOBAL-NAMESPACE-NEXT: SwiftNameAttr {{.+}} "makeNamespacedDouble(_:)" + +// CHECK-METHOD-OVERLOADS: CXXMethodDecl {{.+}} setValue 'void (int)' +// CHECK-METHOD-OVERLOADS-NEXT: ParmVarDecl {{.+}} 'int' +// CHECK-METHOD-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "setIntValue(_:)" +// CHECK-METHOD-OVERLOADS: CXXMethodDecl {{.+}} setValue 'void (double)' +// CHECK-METHOD-OVERLOADS-NEXT: ParmVarDecl {{.+}} 'double' +// CHECK-METHOD-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "setDoubleValue(_:)" +// CHECK-METHOD-OVERLOADS: CXXMethodDecl {{.+}} setValue 'void ()' +// CHECK-METHOD-OVERLOADS-NEXT: SwiftNameAttr {{.+}} "currentValue()" + +// CHECK-METHOD-BROAD: CXXMethodDecl {{.+}} broad 'void (int)' +// CHECK-METHOD-BROAD: SwiftPrivateAttr +// CHECK-METHOD-BROAD: CXXMethodDecl {{.+}} broad 'void (double)' +// CHECK-METHOD-BROAD: SwiftPrivateAttr + +// CHECK-METHOD-COEXIST: CXXMethodDecl {{.+}} coexist 'void (int)' +// CHECK-METHOD-COEXIST: SwiftPrivateAttr +// CHECK-METHOD-COEXIST: SwiftNameAttr {{.+}} "coexistInt(_:)" +// CHECK-METHOD-COEXIST: CXXMethodDecl {{.+}} coexist 'void (double)' +// CHECK-METHOD-COEXIST: SwiftPrivateAttr +// CHECK-METHOD-COEXIST-NOT: SwiftNameAttr + +// CHECK-METHOD-DEFAULTS: CXXMethodDecl {{.+}} defaults 'void (int, double)' +// CHECK-METHOD-DEFAULTS: SwiftNameAttr {{.+}} "defaultsWithTwoParameters(_:_:)" +// CHECK-METHOD-DEFAULTS: CXXMethodDecl {{.+}} defaults 'void (int)' +// CHECK-METHOD-DEFAULTS-NOT: SwiftNameAttr + +// CHECK-METHOD-STATIC: CXXMethodDecl {{.+}} configure 'void (int)' static +// CHECK-METHOD-STATIC: SwiftNameAttr {{.+}} "configureInt(_:)" + +// CHECK-METHOD-MISMATCH: CXXMethodDecl {{.+}} mismatch 'void (float)' +// CHECK-METHOD-MISMATCH-NOT: SwiftNameAttr + +// CHECK-METHOD-ALIAS: CXXMethodDecl {{.+}} alias 'void (AliasInt)' +// CHECK-METHOD-ALIAS: SwiftNameAttr {{.+}} "alias(_:)" + +// CHECK-METHOD-ALIAS-PRECEDENCE: CXXMethodDecl {{.+}} aliasPrecedence 'void (AliasInt)' +// CHECK-METHOD-ALIAS-PRECEDENCE-NOT: fallbackAliasPrecedence +// CHECK-METHOD-ALIAS-PRECEDENCE: SwiftNameAttr {{.+}} "aliasPrecedence(_:)" + +// CHECK-METHOD-MULTI-ALIAS: CXXMethodDecl {{.+}} multiAlias 'void (DeepAliasInt)' +// CHECK-METHOD-MULTI-ALIAS: SwiftNameAttr {{.+}} "multiAlias(_:)" + +// CHECK-METHOD-NULLABILITY: CXXMethodDecl {{.+}} nullable 'void (char * _Nonnull)' +// CHECK-METHOD-NULLABILITY: SwiftNameAttr {{.+}} "nullable(_:)" + +// CHECK-METHOD-RAW-INT: CXXMethodDecl {{.+}} rawInt 'void (int)' +// CHECK-METHOD-RAW-INT: SwiftNameAttr {{.+}} "rawInt(_:)" + +// CHECK-METHOD-CONST: CXXMethodDecl {{.+}} constValue 'void (const int)' +// CHECK-METHOD-CONST: SwiftNameAttr {{.+}} "constValue(_:)" + +// CHECK-METHOD-OPERATOR: CXXMethodDecl {{.+}} operator+ 'SelectorWidget (int)' +// CHECK-METHOD-OPERATOR-NEXT: ParmVarDecl {{.+}} 'int' +// CHECK-METHOD-OPERATOR-NEXT: SwiftNameAttr {{.+}} "plusInt(_:)" +// CHECK-METHOD-OPERATOR: CXXMethodDecl {{.+}} operator+ 'SelectorWidget (double)' +// CHECK-METHOD-OPERATOR-NEXT: ParmVarDecl {{.+}} 'double' +// CHECK-METHOD-OPERATOR-NEXT: SwiftNameAttr {{.+}} "plusDouble(_:)" _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
