================
@@ -1008,47 +1009,163 @@ struct Context {
using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>;
+/// Describes optional constraints on a C++ method's implicit object parameter.
+struct FunctionObjectSelector {
+ std::optional<bool> Const;
+ std::optional<bool> Volatile;
+ std::optional<RefQualifierKind> Ref;
+
+ std::string format() const;
+};
+
+inline bool operator==(const FunctionObjectSelector &LHS,
+ const FunctionObjectSelector &RHS) {
+ return LHS.Const == RHS.Const && LHS.Volatile == RHS.Volatile &&
+ LHS.Ref == RHS.Ref;
+}
+
+inline bool operator!=(const FunctionObjectSelector &LHS,
+ const FunctionObjectSelector &RHS) {
+ return !(LHS == RHS);
+}
+
+inline std::string FunctionObjectSelector::format() const {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ llvm::SmallVector<std::string, 3> Parts;
+
+ if (Const)
+ Parts.push_back(std::string("Const: ") + (*Const ? "true" : "false"));
+ if (Volatile)
+ Parts.push_back(std::string("Volatile: ") + (*Volatile ? "true" :
"false"));
+ if (Ref) {
+ std::string Ref = "Ref: ";
+ switch (*this->Ref) {
+ case RQ_None:
+ Ref += "none";
+ break;
+ case RQ_LValue:
+ Ref += "lvalue";
+ break;
+ case RQ_RValue:
+ Ref += "rvalue";
+ break;
+ }
+ Parts.push_back(Ref);
+ }
+
+ OS << "Object{";
+ llvm::interleaveComma(Parts, OS);
+ OS << "}";
+ return Result;
+}
+
+/// Describes a C++ function selector composed from optional exact explicit
+/// parameters plus optional implicit object constraints.
+struct FunctionSelector {
+ std::optional<llvm::SmallVector<std::string, 4>> Parameters;
+ std::optional<FunctionObjectSelector> Object;
+
+ std::string format() const;
+};
+
+inline bool operator==(const FunctionSelector &LHS,
+ const FunctionSelector &RHS) {
+ return LHS.Parameters == RHS.Parameters && LHS.Object == RHS.Object;
+}
+
+inline bool operator!=(const FunctionSelector &LHS,
+ const FunctionSelector &RHS) {
+ return !(LHS == RHS);
+}
+
+inline std::string formatAPINotesFunctionSelector(
+ std::optional<llvm::ArrayRef<std::string>> Parameters,
+ std::optional<FunctionObjectSelector> Object) {
+ std::string Result;
+ if (Parameters)
+ Result = (llvm::Twine("Where.Parameters ") +
+ formatAPINotesParameterSelector(*Parameters))
+ .str();
+
+ if (Object) {
+ if (!Result.empty())
+ Result += " ";
+ else
+ Result = "Where.Object ";
+ Result += Object->format();
+ }
+
+ return Result;
+}
+
+inline std::string FunctionSelector::format() const {
+ std::optional<llvm::ArrayRef<std::string>> Parameters;
+ if (this->Parameters)
+ Parameters = llvm::ArrayRef<std::string>(*this->Parameters);
+ return formatAPINotesFunctionSelector(Parameters, Object);
+}
+
+struct FunctionTableSelectorKey {
+ std::optional<llvm::SmallVector<IdentifierID, 2>> Parameters;
+ std::optional<FunctionObjectSelector> Object;
+};
+
/// A key for a stored global-function or C++-method API notes entry.
///
/// The key is represented by the ID of its parent context, the declaration
-/// name, and optional exact parameter types.
+/// name, and optional exact parameter/object selector data.
struct FunctionTableKey {
uint32_t parentContextID;
uint32_t nameID;
std::optional<llvm::SmallVector<IdentifierID, 2>> parameterTypeIDs;
+ std::optional<FunctionObjectSelector> objectSelector;
FunctionTableKey() : parentContextID(-1), nameID(-1) {}
- FunctionTableKey(uint32_t ParentContextID, uint32_t NameID)
- : parentContextID(ParentContextID), nameID(NameID) {}
+ FunctionTableKey(uint32_t ParentContextID, uint32_t NameID,
+ FunctionTableSelectorKey Selector = {})
+ : parentContextID(ParentContextID), nameID(NameID),
+ parameterTypeIDs(std::move(Selector.Parameters)),
+ objectSelector(Selector.Object) {}
FunctionTableKey(uint32_t ParentContextID, uint32_t NameID,
const llvm::SmallVectorImpl<IdentifierID> &ParameterTypeIDs)
: parentContextID(ParentContextID), nameID(NameID) {
parameterTypeIDs.emplace(ParameterTypeIDs.begin(), ParameterTypeIDs.end());
}
- FunctionTableKey(std::optional<Context> ParentCtx, IdentifierID NameID)
- : parentContextID(ParentCtx ? ParentCtx->id.Value
- : static_cast<uint32_t>(-1)),
- nameID(NameID) {}
+ FunctionTableKey(std::optional<Context> ParentCtx, IdentifierID NameID,
+ FunctionTableSelectorKey Selector = {})
+ : FunctionTableKey(ParentCtx ? ParentCtx->id.Value
+ : static_cast<uint32_t>(-1),
+ NameID, std::move(Selector)) {}
FunctionTableKey(std::optional<Context> ParentCtx, IdentifierID NameID,
const llvm::SmallVectorImpl<IdentifierID> &ParameterTypeIDs)
- : parentContextID(ParentCtx ? ParentCtx->id.Value
- : static_cast<uint32_t>(-1)),
- nameID(NameID) {
+ : FunctionTableKey(ParentCtx ? ParentCtx->id.Value
+ : static_cast<uint32_t>(-1),
+ NameID) {
parameterTypeIDs.emplace(ParameterTypeIDs.begin(), ParameterTypeIDs.end());
}
llvm::hash_code hashValue() const {
auto Hash = llvm::hash_combine(parentContextID, nameID,
- static_cast<bool>(parameterTypeIDs));
+ static_cast<bool>(parameterTypeIDs),
+ static_cast<bool>(objectSelector));
if (parameterTypeIDs) {
Hash = llvm::hash_combine(Hash, parameterTypeIDs->size());
for (IdentifierID TypeID : *parameterTypeIDs)
Hash = llvm::hash_combine(Hash, static_cast<unsigned>(TypeID));
}
+ if (objectSelector)
+ Hash = llvm::hash_combine(
+ Hash, objectSelector->Const.value_or(false),
+ static_cast<bool>(objectSelector->Const),
+ objectSelector->Volatile.value_or(false),
+ static_cast<bool>(objectSelector->Volatile),
+ objectSelector->Ref ? static_cast<unsigned>(*objectSelector->Ref) + 1
----------------
Xazax-hun wrote:
I wonder if we should use `llvm::to_underlying` with enums.
https://github.com/llvm/llvm-project/pull/216148
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits