Skip to content

Commit

Permalink
Splicer template arguments.
Browse files Browse the repository at this point in the history
Closes issue #8.
  • Loading branch information
katzdm committed Mar 31, 2024
1 parent a80b44e commit 2f44ef0
Show file tree
Hide file tree
Showing 22 changed files with 659 additions and 21 deletions.
1 change: 1 addition & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -2217,6 +2217,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
const IdentifierInfo *Name) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
OverloadedOperatorKind Operator) const;
TemplateName getDependentTemplateName(CXXIndeterminateSpliceExpr *S) const;
TemplateName
getSubstTemplateTemplateParm(TemplateName replacement, Decl *AssociatedDecl,
unsigned Index,
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,9 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
case TemplateArgument::StructuralValue:
return true;

case TemplateArgument::IndeterminateSplice:
return getDerived().TraverseStmt(Arg.getAsIndeterminateSplice());

case TemplateArgument::Type:
return getDerived().TraverseType(Arg.getAsType());

Expand Down Expand Up @@ -906,6 +909,10 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
case TemplateArgument::StructuralValue:
return true;

case TemplateArgument::IndeterminateSplice:
return getDerived().TraverseStmt(
ArgLoc.getSourceIndeterminateSpliceExpression());

case TemplateArgument::Type: {
// FIXME: how can TSI ever be NULL?
if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/TemplateArgumentVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Base {
DISPATCH(NullPtr);
DISPATCH(Integral);
DISPATCH(Reflection);
DISPATCH(IndeterminateSplice);
DISPATCH(StructuralValue);
DISPATCH(Template);
DISPATCH(TemplateExpansion);
Expand All @@ -62,6 +63,7 @@ class Base {
VISIT_METHOD(NullPtr);
VISIT_METHOD(Integral);
VISIT_METHOD(Reflection);
VISIT_METHOD(IndeterminateSplice);
VISIT_METHOD(StructuralValue);
VISIT_METHOD(Template);
VISIT_METHOD(TemplateExpansion);
Expand Down
20 changes: 20 additions & 0 deletions clang/include/clang/AST/TemplateBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace clang {

class APValue;
class ASTContext;
class CXXIndeterminateSpliceExpr;
class Expr;
struct PrintingPolicy;
class TypeSourceInfo;
Expand Down Expand Up @@ -89,6 +90,10 @@ class TemplateArgument {
/// meta::info non-type template parameter.
Reflection,

/// The template argument is an indeterminate splice of a reflection, which
/// might reflect any of: a type, an expression, or a class template.
IndeterminateSplice,

/// The template argument is a non-type template argument that can't be
/// represented by the special-case Declaration, NullPtr, or Integral
/// forms. These values are only ever produced by constant evaluation,
Expand Down Expand Up @@ -232,6 +237,10 @@ class TemplateArgument {
TemplateArgument(ASTContext &Ctx, const ReflectionValue &Value,
bool IsDefaulted = false);

/// Construct an indeterminate splice template argument.
TemplateArgument(CXXIndeterminateSpliceExpr *Splice,
bool IsDefaulted = false);

/// Construct an integral constant template argument with the same
/// value as Other but a different type.
TemplateArgument(const TemplateArgument &Other, QualType Type) {
Expand Down Expand Up @@ -403,6 +412,11 @@ class TemplateArgument {
(const char *)&ReflectionArg.Value);
}

CXXIndeterminateSpliceExpr *getAsIndeterminateSplice() const {
assert(getKind() == IndeterminateSplice && "Unexpected kind");
return reinterpret_cast<CXXIndeterminateSpliceExpr *>(TypeOrValue.V);
}

/// Retrieve the type of the integral value.
QualType getIntegralType() const {
assert(getKind() == Integral && "Unexpected kind");
Expand Down Expand Up @@ -581,6 +595,7 @@ class TemplateArgumentLoc {
assert(Argument.getKind() == TemplateArgument::NullPtr ||
Argument.getKind() == TemplateArgument::Integral ||
Argument.getKind() == TemplateArgument::Reflection ||
Argument.getKind() == TemplateArgument::IndeterminateSplice ||
Argument.getKind() == TemplateArgument::Declaration ||
Argument.getKind() == TemplateArgument::StructuralValue ||
Argument.getKind() == TemplateArgument::Expression);
Expand Down Expand Up @@ -643,6 +658,11 @@ class TemplateArgumentLoc {
return LocInfo.getAsExpr();
}

Expr *getSourceIndeterminateSpliceExpression() const {
assert(Argument.getKind() == TemplateArgument::IndeterminateSplice);
return LocInfo.getAsExpr();
}

Expr *getSourceStructuralValueExpression() const {
assert(Argument.getKind() == TemplateArgument::StructuralValue);
return LocInfo.getAsExpr();
Expand Down
58 changes: 48 additions & 10 deletions clang/include/clang/AST/TemplateName.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
namespace clang {

class ASTContext;
class CXXIndeterminateSpliceExpr;
class Decl;
class DependentTemplateName;
class IdentifierInfo;
Expand Down Expand Up @@ -488,13 +489,19 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
class DependentTemplateName : public llvm::FoldingSetNode {
friend class ASTContext;

enum Kind {
DTNK_Identifier,
DTNK_Operator,
DTNK_IndeterminateSplice,
};

/// The nested name specifier that qualifies the template
/// name.
///
/// The bit stored in this qualifier describes whether the \c Name field
/// is interpreted as an IdentifierInfo pointer (when clear) or as an
/// overloaded operator kind (when set).
llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
llvm::PointerIntPair<NestedNameSpecifier *, 2, Kind> Qualifier;

/// The dependent template name.
union {
Expand All @@ -507,6 +514,11 @@ class DependentTemplateName : public llvm::FoldingSetNode {
///
/// Only valid when the bit on \c Qualifier is set.
OverloadedOperatorKind Operator;

/// The dependent splice expression.
///
/// Only valid when the NestedNameSpecifier on \c Qualifier is unset.
CXXIndeterminateSpliceExpr *SpliceExpr;
};

/// The canonical template name to which this dependent
Expand All @@ -519,32 +531,36 @@ class DependentTemplateName : public llvm::FoldingSetNode {

DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Identifier)
: Qualifier(Qualifier, false), Identifier(Identifier),
: Qualifier(Qualifier, DTNK_Identifier), Identifier(Identifier),
CanonicalTemplateName(this) {}

DependentTemplateName(NestedNameSpecifier *Qualifier,
const IdentifierInfo *Identifier,
TemplateName Canon)
: Qualifier(Qualifier, false), Identifier(Identifier),
: Qualifier(Qualifier, DTNK_Identifier), Identifier(Identifier),
CanonicalTemplateName(Canon) {}

DependentTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator)
: Qualifier(Qualifier, true), Operator(Operator),
: Qualifier(Qualifier, DTNK_Operator), Operator(Operator),
CanonicalTemplateName(this) {}

DependentTemplateName(NestedNameSpecifier *Qualifier,
OverloadedOperatorKind Operator,
TemplateName Canon)
: Qualifier(Qualifier, true), Operator(Operator),
: Qualifier(Qualifier, DTNK_Operator), Operator(Operator),
CanonicalTemplateName(Canon) {}

DependentTemplateName(CXXIndeterminateSpliceExpr *SpliceExpr)
: Qualifier(nullptr, DTNK_IndeterminateSplice), SpliceExpr(SpliceExpr),
CanonicalTemplateName(this) {}

public:
/// Return the nested name specifier that qualifies this name.
NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }

/// Determine whether this template name refers to an identifier.
bool isIdentifier() const { return !Qualifier.getInt(); }
bool isIdentifier() const { return Qualifier.getInt() == DTNK_Identifier; }

/// Returns the identifier to which this template name refers.
const IdentifierInfo *getIdentifier() const {
Expand All @@ -554,7 +570,9 @@ class DependentTemplateName : public llvm::FoldingSetNode {

/// Determine whether this template name refers to an overloaded
/// operator.
bool isOverloadedOperator() const { return Qualifier.getInt(); }
bool isOverloadedOperator() const {
return Qualifier.getInt() == DTNK_Operator;
}

/// Return the overloaded operator to which this template name refers.
OverloadedOperatorKind getOperator() const {
Expand All @@ -563,26 +581,46 @@ class DependentTemplateName : public llvm::FoldingSetNode {
return Operator;
}

/// Determine whether this template name refers to an indeterminate splice.
bool isIndeterminateSplice() const {
return Qualifier.getInt() == DTNK_IndeterminateSplice;
}

CXXIndeterminateSpliceExpr *getIndeterminateSplice() const {
assert(isIndeterminateSplice() &&
"Template name isn't an indeterminate splice?");
return SpliceExpr;
}

void Profile(llvm::FoldingSetNodeID &ID) {
if (isIdentifier())
Profile(ID, getQualifier(), getIdentifier());
else
else if (isOverloadedOperator())
Profile(ID, getQualifier(), getOperator());
else
Profile(ID, getIndeterminateSplice());
}

static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
const IdentifierInfo *Identifier) {
ID.AddPointer(NNS);
ID.AddBoolean(false);
ID.AddInteger(DTNK_Identifier);
ID.AddPointer(Identifier);
}

static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
OverloadedOperatorKind Operator) {
ID.AddPointer(NNS);
ID.AddBoolean(true);
ID.AddInteger(DTNK_Operator);
ID.AddInteger(Operator);
}

static void Profile(llvm::FoldingSetNodeID &ID,
CXXIndeterminateSpliceExpr *Splice) {
ID.AddPointer(nullptr);
ID.AddPointer(Splice);
ID.AddInteger(DTNK_IndeterminateSplice);
}
};

} // namespace clang.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3737,6 +3737,7 @@ class Parser : public CodeCompletionHandler {
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
TemplateTy Template, SourceLocation OpenLoc);
ParsedTemplateArgument ParseTemplateTemplateArgument();
ParsedTemplateArgument ParseIndeterminateSpliceTemplateArgument();
ParsedTemplateArgument ParseTemplateArgument();
ParsedTemplateArgument ParseTemplateReflectOperand();
DeclGroupPtrTy ParseExplicitInstantiation(DeclaratorContext Context,
Expand Down
10 changes: 9 additions & 1 deletion clang/include/clang/Sema/ParsedTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ namespace clang {
/// A non-type template parameter, stored as an expression.
NonType,
/// A template template argument, stored as a template name.
Template
Template,
/// An indeterminate splice argument, stored as an expression.
IndeterminateSplice,
};

/// Build an empty template argument.
Expand Down Expand Up @@ -89,6 +91,12 @@ namespace clang {
return ParsedTemplateTy::getFromOpaquePtr(Arg);
}

CXXIndeterminateSpliceExpr *getAsIndeterminateSplice() const {
assert(Kind == IndeterminateSplice &&
"Not an indeterminate splice argument");
return static_cast<CXXIndeterminateSpliceExpr*>(Arg);
}

/// Retrieve the location of the template argument.
SourceLocation getLocation() const { return Loc; }

Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -14908,6 +14908,9 @@ class Sema final {
DeclResult ActOnCXXSpliceExpectingNamespace(SourceLocation LSplice,
Expr *Operand,
SourceLocation RSplice);
ParsedTemplateArgument
ActOnTemplateIndeterminateSpliceArgument(CXXIndeterminateSpliceExpr *Splice);

bool ActOnCXXNestedNameSpecifierReflectionSplice(
CXXScopeSpec &SS, CXXIndeterminateSpliceExpr *Splice,
SourceLocation ColonColonLoc);
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6881,6 +6881,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
return TemplateArgument(Arg, getCanonicalType(Arg.getIntegralType()));

case TemplateArgument::Reflection:
case TemplateArgument::IndeterminateSplice:
return Arg;

case TemplateArgument::StructuralValue:
Expand Down Expand Up @@ -9403,6 +9404,25 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
return TemplateName(QTN);
}

/// Retrieve the template name that represents a dependent
/// template name such as \c [:R:] where \c R is dependent.
TemplateName
ASTContext::getDependentTemplateName(CXXIndeterminateSpliceExpr *Splice) const {
llvm::FoldingSetNodeID ID;
DependentTemplateName::Profile(ID, Splice);

void *InsertPos = nullptr;
DependentTemplateName *QTN
= DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);

if (!QTN) {
QTN = new (*this, alignof(DependentTemplateName))
DependentTemplateName(Splice);
DependentTemplateNames.InsertNode(QTN, InsertPos);
}
return TemplateName(QTN);
}

TemplateName ASTContext::getSubstTemplateTemplateParm(
TemplateName Replacement, Decl *AssociatedDecl, unsigned Index,
std::optional<unsigned> PackIndex) const {
Expand Down
Loading

0 comments on commit 2f44ef0

Please sign in to comment.