Skip to content

Commit

Permalink
[FOLD] support type-constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
sdkrystian committed Aug 6, 2024
1 parent 63788ea commit 53684e5
Show file tree
Hide file tree
Showing 13 changed files with 300 additions and 52 deletions.
3 changes: 3 additions & 0 deletions include/mrdocs/Metadata/Template.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ struct TypeTParam
{
/** Keyword (class/typename) the parameter uses */
TParamKeyKind KeyKind = TParamKeyKind::Class;

/** The type-constraint for the parameter, if any. */
std::unique_ptr<NameInfo> Constraint;
};

struct NonTypeTParam
Expand Down
25 changes: 24 additions & 1 deletion include/mrdocs/Metadata/Type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
namespace clang {
namespace mrdocs {

enum QualifierKind : int
enum QualifierKind
{
None,
Const,
Expand All @@ -39,6 +39,7 @@ enum class TypeKind
{
Named = 1, // for bitstream
Decltype,
Auto,
LValueReference,
RValueReference,
Pointer,
Expand All @@ -49,6 +50,14 @@ enum class TypeKind

MRDOCS_DECL dom::String toString(TypeKind kind) noexcept;

enum class AutoKind
{
Auto,
DecltypeAuto
};

MRDOCS_DECL dom::String toString(AutoKind kind) noexcept;

struct TypeInfo
{
/** The kind of TypeInfo this is
Expand All @@ -63,6 +72,7 @@ struct TypeInfo

constexpr bool isNamed() const noexcept { return Kind == TypeKind::Named; }
constexpr bool isDecltype() const noexcept { return Kind == TypeKind::Decltype; }
constexpr bool isAuto() const noexcept { return Kind == TypeKind::Auto; }
constexpr bool isLValueReference() const noexcept { return Kind == TypeKind::LValueReference; }
constexpr bool isRValueReference() const noexcept { return Kind == TypeKind::RValueReference; }
constexpr bool isPointer() const noexcept { return Kind == TypeKind::Pointer; }
Expand Down Expand Up @@ -100,6 +110,7 @@ struct IsType : TypeInfo

static constexpr bool isNamed() noexcept { return K == TypeKind::Named; }
static constexpr bool isDecltype() noexcept { return K == TypeKind::Decltype; }
static constexpr bool isAuto() noexcept { return K == TypeKind::Auto; }
static constexpr bool isLValueReference() noexcept { return K == TypeKind::LValueReference; }
static constexpr bool isRValueReference() noexcept { return K == TypeKind::RValueReference; }
static constexpr bool isPointer() noexcept { return K == TypeKind::Pointer; }
Expand Down Expand Up @@ -129,6 +140,14 @@ struct DecltypeTypeInfo
ExprInfo Operand;
};

struct AutoTypeInfo
: IsType<TypeKind::Auto>
{
QualifierKind CVQualifiers = QualifierKind::None;
AutoKind Keyword = AutoKind::Auto;
std::unique_ptr<NameInfo> Constraint;
};

struct LValueReferenceTypeInfo
: IsType<TypeKind::LValueReference>
{
Expand Down Expand Up @@ -226,6 +245,10 @@ visit(
return f(static_cast<add_cv_from_t<
TypeTy, DecltypeTypeInfo>&>(II),
std::forward<Args>(args)...);
case TypeKind::Auto:
return f(static_cast<add_cv_from_t<
TypeTy, AutoTypeInfo>&>(II),
std::forward<Args>(args)...);
case TypeKind::LValueReference:
return f(static_cast<add_cv_from_t<
TypeTy, LValueReferenceTypeInfo>&>(II),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
{{#if element-type~}}{{~>declarator-before element-type nolink=nolink~}}{{/if~}}
{{#if return-type~}}{{~>declarator-before return-type nolink=nolink~}}{{/if~}}
{{#if (eq kind "named")}}{{>name-info name nolink=nolink}}{{/if~}}
{{#if (eq kind "auto")}}{{#if constraint}}{{>name-info constraint nolink=nolink}} {{/if~}}{{keyword}}{{/if~}}
{{#if cv-qualifiers~}}
{{#if pointee-type}} {{cv-qualifiers}}{{else}} {{cv-qualifiers}}{{/if~}}
{{/if~}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{{#if (eq kind "type")~}}
{{key}}{{#if is-pack}}...{{/if~}}
{{#if constraint}}{{>name-info constraint}}{{else}}{{key}}{{/if~}}
{{#if is-pack}}...{{/if~}}
{{#if name}} {{name}}{{/if~}}
{{#if default}} = {{>template-arg default~}}{{/if~}}
{{else if (eq kind "non-type")~}}
Expand Down
141 changes: 123 additions & 18 deletions src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,6 @@ class ASTVisitor
odr_hash_.AddStmt(RC);
usr_.append("@TPL#");
usr_.append(llvm::itostr(odr_hash_.CalculateHash()));
llvm::outs() << usr_ << '\n';
odr_hash_.clear();
}
}
Expand All @@ -713,7 +712,6 @@ class ASTVisitor
odr_hash_.AddStmt(RC);
usr_.append("@TRC#");
usr_.append(llvm::itostr(odr_hash_.CalculateHash()));
llvm::outs() << usr_ << '\n';
odr_hash_.clear();
}

Expand Down Expand Up @@ -1025,10 +1023,28 @@ class ASTVisitor
const NestedNameSpecifier* NNS,
ExtractMode extract_mode = ExtractMode::IndirectDependency);

#if 0
std::unique_ptr<NameInfo>
buildNameInfo(
const Decl* D,
ExtractMode extract_mode = ExtractMode::IndirectDependency);
#endif

template<typename TArgRange = ArrayRef<TemplateArgument>>
std::unique_ptr<NameInfo>
buildNameInfo(
DeclarationName Name,
std::optional<TArgRange> TArgs = std::nullopt,
const NestedNameSpecifier* NNS = nullptr,
ExtractMode extract_mode = ExtractMode::IndirectDependency);

template<typename TArgRange = ArrayRef<TemplateArgument>>
std::unique_ptr<NameInfo>
buildNameInfo(
const Decl* D,
std::optional<TArgRange> TArgs = std::nullopt,
const NestedNameSpecifier* NNS = nullptr,
ExtractMode extract_mode = ExtractMode::IndirectDependency);


template<typename Integer>
Expand Down Expand Up @@ -1149,6 +1165,15 @@ class ASTVisitor
if(P->hasDefaultArgument() && !R->Default)
R->Default = buildTemplateArg(
P->getDefaultArgument().getArgument());
if(const TypeConstraint* TC = P->getTypeConstraint())
{
const NestedNameSpecifier* NNS =
TC->getNestedNameSpecifierLoc().getNestedNameSpecifier();
std::optional<const ASTTemplateArgumentListInfo*> TArgs;
if(TC->hasExplicitTemplateArgs())
TArgs.emplace(TC->getTemplateArgsAsWritten());
R->Constraint = buildNameInfo(TC->getNamedConcept(), TArgs, NNS);
}
return;
}
else if constexpr(kind == Decl::NonTypeTemplateParm)
Expand Down Expand Up @@ -1871,12 +1896,11 @@ class ASTVisitor
return std::make_pair(param_arg->getAsType(), std::move(ControllingArgs));
}

std::string
extractName(
const NamedDecl* D)
std::string extractName(DeclarationName N)
{
std::string result;
DeclarationName N = D->getDeclName();
if(N.isEmpty())
return result;
switch(N.getNameKind())
{
case DeclarationName::Identifier:
Expand All @@ -1896,14 +1920,11 @@ class ASTVisitor
break;
case DeclarationName::CXXConversionFunctionName:
{
MRDOCS_ASSERT(isa<CXXConversionDecl>(D));
const auto* CD = cast<CXXConversionDecl>(D);
result.append("operator ");
// KRYSTIAN FIXME: we *really* should not be
// converting types to strings like this
result.append(toString(
*buildTypeInfo(
CD->getReturnType())));
*buildTypeInfo(N.getCXXNameType())));
break;
}
case DeclarationName::CXXOperatorName:
Expand All @@ -1926,16 +1947,19 @@ class ASTVisitor
return result;
}

std::string extractName(const NamedDecl* D)
{
return extractName(D->getDeclName());
}

//------------------------------------------------

const Decl*
getParentDecl(const Decl* D)
const Decl* getParentDecl(const Decl* D)
{
return getParentDecl(const_cast<Decl*>(D));
}

Decl*
getParentDecl(Decl* D)
Decl* getParentDecl(Decl* D)
{
while((D = cast_if_present<
Decl>(D->getDeclContext())))
Expand Down Expand Up @@ -3764,15 +3788,14 @@ class TerminalTypeVisitor
VisitAutoType(
const AutoType* T)
{
// KRYSTIAN TODO: we should probably add a TypeInfo
// to represent deduced types that also stores what
// it was deduced as.
#if 0
// KRYSTIAN NOTE: we don't use isDeduced because it will
// return true if the type is dependent
// if the type has been deduced, use the deduced type
if(QualType DT = T->getDeducedType(); ! DT.isNull())
return Visit(DT);
getDerived().buildTerminal(NNS_, T, Quals_, IsPack_);
#endif
getDerived().buildAuto(T, Quals_, IsPack_);
return true;
}

Expand Down Expand Up @@ -3984,6 +4007,14 @@ class TerminalTypeVisitor
{
}

void
buildAuto(
const AutoType* T,
unsigned quals,
bool pack)
{
}

void
buildTerminal(
const NestedNameSpecifier* NNS,
Expand Down Expand Up @@ -4100,6 +4131,30 @@ class TypeInfoBuilder
Result->IsPackExpansion = pack;
}

void
buildAuto(
const AutoType* T,
unsigned quals,
bool pack)
{
auto I = std::make_unique<AutoTypeInfo>();
I->CVQualifiers = convertToQualifierKind(quals);
I->Keyword = convertToAutoKind(T->getKeyword());
if(T->isConstrained())
{
std::optional<ArrayRef<TemplateArgument>> TArgs;
if(auto Args = T->getTypeConstraintArguments();
! Args.empty())
TArgs.emplace(Args);
I->Constraint = getASTVisitor().buildNameInfo(
T->getTypeConstraintConcept(), TArgs);
// Constraint->Prefix = getASTVisitor().buildNameInfo(
// cast<Decl>(CD->getDeclContext()));
}
*Inner = std::move(I);
Result->IsPackExpansion = pack;
}

void
buildTerminal(
const NestedNameSpecifier* NNS,
Expand Down Expand Up @@ -4373,6 +4428,7 @@ buildNameInfo(
return I;
}

#if 0
std::unique_ptr<NameInfo>
ASTVisitor::
buildNameInfo(
Expand All @@ -4391,6 +4447,55 @@ buildNameInfo(
I->Prefix = buildNameInfo(getParentDecl(D), extract_mode);
return I;
}
#endif

template<typename TArgRange>
std::unique_ptr<NameInfo>
ASTVisitor::
buildNameInfo(
DeclarationName Name,
std::optional<TArgRange> TArgs,
const NestedNameSpecifier* NNS,
ExtractMode extract_mode)
{
if(Name.isEmpty())
return nullptr;
std::unique_ptr<NameInfo> I = nullptr;
if(TArgs)
{
auto Specialization = std::make_unique<SpecializationNameInfo>();
buildTemplateArgs(Specialization->TemplateArgs, *TArgs);
I = std::move(Specialization);
}
else
{
I = std::make_unique<NameInfo>();
}
I->Name = extractName(Name);
if(NNS)
I->Prefix = buildNameInfo(NNS, extract_mode);
return I;
}

template<typename TArgRange>
std::unique_ptr<NameInfo>
ASTVisitor::
buildNameInfo(
const Decl* D,
std::optional<TArgRange> TArgs,
const NestedNameSpecifier* NNS,
ExtractMode extract_mode)
{
const auto* ND = dyn_cast_if_present<NamedDecl>(D);
if(! ND)
return nullptr;
auto I = buildNameInfo(ND->getDeclName(),
std::move(TArgs), NNS, extract_mode);
if(! I)
return nullptr;
getDependencyID(getInstantiatedFrom(D), I->id);
return I;
}

//------------------------------------------------

Expand Down
20 changes: 20 additions & 0 deletions src/lib/AST/ASTVisitorHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,26 @@ convertToFunctionClass(
}
}

/** Convert a Clang AutoTypeKeyword into a MrDocs AutoKind
*/
AutoKind
convertToAutoKind(
AutoTypeKeyword kind)
{
using OldKind = AutoTypeKeyword;
using NewKind = AutoKind;
switch(kind)
{
case OldKind::Auto:
case OldKind::GNUAutoType:
return NewKind::Auto;
case OldKind::DecltypeAuto:
return NewKind::DecltypeAuto;
default:
MRDOCS_UNREACHABLE();
}
}

// ----------------------------------------------------------------

/** Visit a Decl and call the appropriate visitor function.
Expand Down
Loading

0 comments on commit 53684e5

Please sign in to comment.