зеркало из https://github.com/microsoft/clang.git
Create a new expression node, SubstNonTypeTemplateParmExpr,
to represent a fully-substituted non-type template parameter. This should improve source fidelity, as well as being generically useful for diagnostics and such. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135243 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
165622faa4
Коммит
91a5755ad7
|
@ -538,6 +538,10 @@ public:
|
|||
/// the rules of C++ [expr.unary.noexcept].
|
||||
CanThrowResult CanThrow(ASTContext &C) const;
|
||||
|
||||
/// IgnoreImpCasts - Skip past any implicit casts which might
|
||||
/// surround this expression. Only skips ImplicitCastExprs.
|
||||
Expr *IgnoreImpCasts();
|
||||
|
||||
/// IgnoreImplicit - Skip past any implicit AST nodes which might
|
||||
/// surround this expression.
|
||||
Expr *IgnoreImplicit() { return cast<Expr>(Stmt::IgnoreImplicit()); }
|
||||
|
@ -596,7 +600,10 @@ public:
|
|||
|
||||
/// \brief Whether this expression is an implicit reference to 'this' in C++.
|
||||
bool isImplicitCXXThis() const;
|
||||
|
||||
|
||||
const Expr *IgnoreImpCasts() const {
|
||||
return const_cast<Expr*>(this)->IgnoreImpCasts();
|
||||
}
|
||||
const Expr *IgnoreParens() const {
|
||||
return const_cast<Expr*>(this)->IgnoreParens();
|
||||
}
|
||||
|
@ -2487,6 +2494,13 @@ public:
|
|||
static bool classof(const ImplicitCastExpr *) { return true; }
|
||||
};
|
||||
|
||||
inline Expr *Expr::IgnoreImpCasts() {
|
||||
Expr *e = this;
|
||||
while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
|
||||
e = ice->getSubExpr();
|
||||
return e;
|
||||
}
|
||||
|
||||
/// ExplicitCastExpr - An explicit cast written in the source
|
||||
/// code.
|
||||
///
|
||||
|
|
|
@ -2957,6 +2957,48 @@ public:
|
|||
child_range children() { return child_range(); }
|
||||
};
|
||||
|
||||
/// \brief Represents a reference to a non-type template parameter
|
||||
/// that has been substituted with a template argument.
|
||||
class SubstNonTypeTemplateParmExpr : public Expr {
|
||||
/// \brief The replaced parameter.
|
||||
NonTypeTemplateParmDecl *Param;
|
||||
|
||||
/// \brief The replacement expression.
|
||||
Stmt *Replacement;
|
||||
|
||||
/// \brief The location of the non-type template parameter reference.
|
||||
SourceLocation NameLoc;
|
||||
|
||||
public:
|
||||
SubstNonTypeTemplateParmExpr(QualType type,
|
||||
ExprValueKind valueKind,
|
||||
SourceLocation loc,
|
||||
NonTypeTemplateParmDecl *param,
|
||||
Expr *replacement)
|
||||
: Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary,
|
||||
replacement->isTypeDependent(), replacement->isValueDependent(),
|
||||
replacement->isInstantiationDependent(),
|
||||
replacement->containsUnexpandedParameterPack()),
|
||||
Param(param), Replacement(replacement), NameLoc(loc) {}
|
||||
|
||||
SourceLocation getNameLoc() const { return NameLoc; }
|
||||
SourceRange getSourceRange() const { return NameLoc; }
|
||||
|
||||
Expr *getReplacement() const { return cast<Expr>(Replacement); }
|
||||
|
||||
NonTypeTemplateParmDecl *getParameter() const { return Param; }
|
||||
|
||||
static bool classof(const Stmt *s) {
|
||||
return s->getStmtClass() == SubstNonTypeTemplateParmExprClass;
|
||||
}
|
||||
static bool classof(const SubstNonTypeTemplateParmExpr *) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(&Replacement, &Replacement+1); }
|
||||
};
|
||||
|
||||
/// \brief Represents a reference to a non-type template parameter pack that
|
||||
/// has been substituted with a non-template argument pack.
|
||||
///
|
||||
|
|
|
@ -1978,6 +1978,7 @@ DEF_TRAVERSE_STMT(CXXNoexceptExpr, { })
|
|||
DEF_TRAVERSE_STMT(PackExpansionExpr, { })
|
||||
DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
|
||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
|
||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { })
|
||||
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { })
|
||||
|
||||
// These literals (all of them) do not need any action.
|
||||
|
|
|
@ -120,6 +120,7 @@ def UnresolvedMemberExpr : DStmt<OverloadExpr>;
|
|||
def CXXNoexceptExpr : DStmt<Expr>;
|
||||
def PackExpansionExpr : DStmt<Expr>;
|
||||
def SizeOfPackExpr : DStmt<Expr>;
|
||||
def SubstNonTypeTemplateParmExpr : DStmt<Expr>;
|
||||
def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
|
||||
def MaterializeTemporaryExpr : DStmt<Expr>;
|
||||
|
||||
|
|
|
@ -165,6 +165,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
|
|||
return Cl::CL_PRValue;
|
||||
|
||||
// Next come the complicated cases.
|
||||
case Expr::SubstNonTypeTemplateParmExprClass:
|
||||
return ClassifyInternal(Ctx,
|
||||
cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
|
||||
|
||||
// C++ [expr.sub]p1: The result is an lvalue of type "T".
|
||||
// However, subscripting vector types is more like member access.
|
||||
|
|
|
@ -406,6 +406,8 @@ public:
|
|||
{ return StmtVisitorTy::Visit(E->getChosenSubExpr(Info.Ctx)); }
|
||||
RetTy VisitGenericSelectionExpr(const GenericSelectionExpr *E)
|
||||
{ return StmtVisitorTy::Visit(E->getResultExpr()); }
|
||||
RetTy VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
|
||||
{ return StmtVisitorTy::Visit(E->getReplacement()); }
|
||||
|
||||
RetTy VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) {
|
||||
OpaqueValueEvaluation opaque(Info, E->getOpaqueValue(), E->getCommon());
|
||||
|
@ -2806,6 +2808,10 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
|||
// GCC considers the GNU __null value to be an integral constant expression.
|
||||
return NoDiag();
|
||||
|
||||
case Expr::SubstNonTypeTemplateParmExprClass:
|
||||
return
|
||||
CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx);
|
||||
|
||||
case Expr::ParenExprClass:
|
||||
return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
|
||||
case Expr::GenericSelectionExprClass:
|
||||
|
|
|
@ -2279,6 +2279,11 @@ recurse:
|
|||
mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
|
||||
break;
|
||||
|
||||
case Expr::SubstNonTypeTemplateParmExprClass:
|
||||
mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
|
||||
Arity);
|
||||
break;
|
||||
|
||||
case Expr::CXXMemberCallExprClass: // fallthrough
|
||||
case Expr::CallExprClass: {
|
||||
const CallExpr *CE = cast<CallExpr>(E);
|
||||
|
|
|
@ -1413,6 +1413,11 @@ void StmtPrinter::VisitSubstNonTypeTemplateParmPackExpr(
|
|||
OS << Node->getParameterPack()->getNameAsString();
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitSubstNonTypeTemplateParmExpr(
|
||||
SubstNonTypeTemplateParmExpr *Node) {
|
||||
Visit(Node->getReplacement());
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
|
||||
PrintExpr(Node->GetTemporaryExpr());
|
||||
}
|
||||
|
|
|
@ -911,6 +911,12 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmPackExpr(
|
|||
VisitTemplateArgument(S->getArgumentPack());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitSubstNonTypeTemplateParmExpr(
|
||||
const SubstNonTypeTemplateParmExpr *E) {
|
||||
// Profile exactly as the replacement expression.
|
||||
Visit(E->getReplacement());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitMaterializeTemporaryExpr(
|
||||
const MaterializeTemporaryExpr *S) {
|
||||
VisitExpr(S);
|
||||
|
|
|
@ -705,6 +705,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
|
|||
return EmitLValue(cast<ChooseExpr>(E)->getChosenSubExpr(getContext()));
|
||||
case Expr::OpaqueValueExprClass:
|
||||
return EmitOpaqueValueLValue(cast<OpaqueValueExpr>(E));
|
||||
case Expr::SubstNonTypeTemplateParmExprClass:
|
||||
return EmitLValue(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
|
||||
case Expr::ImplicitCastExprClass:
|
||||
case Expr::CStyleCastExprClass:
|
||||
case Expr::CXXFunctionalCastExprClass:
|
||||
|
|
|
@ -85,6 +85,9 @@ public:
|
|||
Visit(GE->getResultExpr());
|
||||
}
|
||||
void VisitUnaryExtension(UnaryOperator *E) { Visit(E->getSubExpr()); }
|
||||
void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
|
||||
return Visit(E->getReplacement());
|
||||
}
|
||||
|
||||
// l-values.
|
||||
void VisitDeclRefExpr(DeclRefExpr *DRE) { EmitAggLoadOfLValue(DRE); }
|
||||
|
|
|
@ -112,6 +112,10 @@ public:
|
|||
return Visit(GE->getResultExpr());
|
||||
}
|
||||
ComplexPairTy VisitImaginaryLiteral(const ImaginaryLiteral *IL);
|
||||
ComplexPairTy
|
||||
VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE) {
|
||||
return Visit(PE->getReplacement());
|
||||
}
|
||||
|
||||
// l-values.
|
||||
ComplexPairTy VisitDeclRefExpr(const Expr *E) { return EmitLoadOfLValue(E); }
|
||||
|
|
|
@ -481,6 +481,11 @@ public:
|
|||
return Visit(PE->getSubExpr());
|
||||
}
|
||||
|
||||
llvm::Constant *
|
||||
VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE) {
|
||||
return Visit(PE->getReplacement());
|
||||
}
|
||||
|
||||
llvm::Constant *VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
|
||||
return Visit(GE->getResultExpr());
|
||||
}
|
||||
|
|
|
@ -161,6 +161,9 @@ public:
|
|||
Value *VisitParenExpr(ParenExpr *PE) {
|
||||
return Visit(PE->getSubExpr());
|
||||
}
|
||||
Value *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
|
||||
return Visit(E->getReplacement());
|
||||
}
|
||||
Value *VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
|
||||
return Visit(GE->getResultExpr());
|
||||
}
|
||||
|
|
|
@ -3316,8 +3316,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
|
|||
QualType ArgType = Arg->getType();
|
||||
|
||||
// See through any implicit casts we added to fix the type.
|
||||
while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
|
||||
Arg = Cast->getSubExpr();
|
||||
Arg = Arg->IgnoreImpCasts();
|
||||
|
||||
// C++ [temp.arg.nontype]p1:
|
||||
//
|
||||
|
@ -3330,7 +3329,6 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
|
|||
// expressed as & id-expression where the & is optional if
|
||||
// the name refers to a function or array, or if the
|
||||
// corresponding template-parameter is a reference; or
|
||||
DeclRefExpr *DRE = 0;
|
||||
|
||||
// In C++98/03 mode, give an extension warning on any extra parentheses.
|
||||
// See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
|
||||
|
@ -3346,29 +3344,30 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
|
|||
Arg = Parens->getSubExpr();
|
||||
}
|
||||
|
||||
while (SubstNonTypeTemplateParmExpr *subst =
|
||||
dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
|
||||
Arg = subst->getReplacement()->IgnoreImpCasts();
|
||||
|
||||
bool AddressTaken = false;
|
||||
SourceLocation AddrOpLoc;
|
||||
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
|
||||
if (UnOp->getOpcode() == UO_AddrOf) {
|
||||
// Support &__uuidof(class_with_uuid) as a non-type template argument.
|
||||
// Very common in Microsoft COM headers.
|
||||
if (S.getLangOptions().Microsoft &&
|
||||
isa<CXXUuidofExpr>(UnOp->getSubExpr())) {
|
||||
Converted = TemplateArgument(ArgIn);
|
||||
return false;
|
||||
}
|
||||
|
||||
DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
|
||||
Arg = UnOp->getSubExpr();
|
||||
AddressTaken = true;
|
||||
AddrOpLoc = UnOp->getOperatorLoc();
|
||||
}
|
||||
} else {
|
||||
if (S.getLangOptions().Microsoft && isa<CXXUuidofExpr>(Arg)) {
|
||||
Converted = TemplateArgument(ArgIn);
|
||||
return false;
|
||||
}
|
||||
DRE = dyn_cast<DeclRefExpr>(Arg);
|
||||
}
|
||||
|
||||
if (S.getLangOptions().Microsoft && isa<CXXUuidofExpr>(Arg)) {
|
||||
Converted = TemplateArgument(ArgIn);
|
||||
return false;
|
||||
}
|
||||
|
||||
while (SubstNonTypeTemplateParmExpr *subst =
|
||||
dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
|
||||
Arg = subst->getReplacement()->IgnoreImpCasts();
|
||||
|
||||
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
|
||||
if (!DRE) {
|
||||
S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
|
||||
<< Arg->getSourceRange();
|
||||
|
@ -3563,10 +3562,10 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
|
|||
// We can't perform this conversion or binding.
|
||||
if (ParamType->isReferenceType())
|
||||
S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind)
|
||||
<< ParamType << Arg->getType() << Arg->getSourceRange();
|
||||
<< ParamType << ArgIn->getType() << Arg->getSourceRange();
|
||||
else
|
||||
S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible)
|
||||
<< Arg->getType() << ParamType << Arg->getSourceRange();
|
||||
<< ArgIn->getType() << ParamType << Arg->getSourceRange();
|
||||
S.Diag(Param->getLocation(), diag::note_template_param_here);
|
||||
return true;
|
||||
}
|
||||
|
@ -3610,6 +3609,10 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
|
|||
Arg = Parens->getSubExpr();
|
||||
}
|
||||
|
||||
while (SubstNonTypeTemplateParmExpr *subst =
|
||||
dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
|
||||
Arg = subst->getReplacement()->IgnoreImpCasts();
|
||||
|
||||
// A pointer-to-member constant written &Class::member.
|
||||
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
|
||||
if (UnOp->getOpcode() == UO_AddrOf) {
|
||||
|
@ -4149,16 +4152,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
|
|||
else
|
||||
BT = T;
|
||||
|
||||
Expr *E = IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc);
|
||||
if (T->isEnumeralType()) {
|
||||
// FIXME: This is a hack. We need a better way to handle substituted
|
||||
// non-type template parameters.
|
||||
E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0,
|
||||
Context.getTrivialTypeSourceInfo(T, Loc),
|
||||
Loc, Loc);
|
||||
}
|
||||
|
||||
return Owned(E);
|
||||
return Owned(IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc));
|
||||
}
|
||||
|
||||
/// \brief Match two template parameters within template parameter lists.
|
||||
|
|
|
@ -800,6 +800,11 @@ namespace {
|
|||
getSema().CallsUndergoingInstantiation.pop_back();
|
||||
return move(Result);
|
||||
}
|
||||
|
||||
private:
|
||||
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
|
||||
SourceLocation loc,
|
||||
const TemplateArgument &arg);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1078,46 +1083,65 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
|
|||
Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
|
||||
}
|
||||
|
||||
return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg);
|
||||
}
|
||||
|
||||
ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef(
|
||||
NonTypeTemplateParmDecl *parm,
|
||||
SourceLocation loc,
|
||||
const TemplateArgument &arg) {
|
||||
ExprResult result;
|
||||
QualType type;
|
||||
|
||||
// The template argument itself might be an expression, in which
|
||||
// case we just return that expression.
|
||||
if (Arg.getKind() == TemplateArgument::Expression)
|
||||
return SemaRef.Owned(Arg.getAsExpr());
|
||||
if (arg.getKind() == TemplateArgument::Expression) {
|
||||
Expr *argExpr = arg.getAsExpr();
|
||||
result = SemaRef.Owned(argExpr);
|
||||
type = argExpr->getType();
|
||||
|
||||
if (Arg.getKind() == TemplateArgument::Declaration) {
|
||||
ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
|
||||
} else if (arg.getKind() == TemplateArgument::Declaration) {
|
||||
ValueDecl *VD = cast<ValueDecl>(arg.getAsDecl());
|
||||
|
||||
// Find the instantiation of the template argument. This is
|
||||
// required for nested templates.
|
||||
VD = cast_or_null<ValueDecl>(
|
||||
getSema().FindInstantiatedDecl(E->getLocation(),
|
||||
VD, TemplateArgs));
|
||||
getSema().FindInstantiatedDecl(loc, VD, TemplateArgs));
|
||||
if (!VD)
|
||||
return ExprError();
|
||||
|
||||
// Derive the type we want the substituted decl to have. This had
|
||||
// better be non-dependent, or these checks will have serious problems.
|
||||
QualType TargetType;
|
||||
if (NTTP->isExpandedParameterPack())
|
||||
TargetType = NTTP->getExpansionType(
|
||||
getSema().ArgumentPackSubstitutionIndex);
|
||||
else if (NTTP->isParameterPack() &&
|
||||
isa<PackExpansionType>(NTTP->getType())) {
|
||||
TargetType = SemaRef.SubstType(
|
||||
cast<PackExpansionType>(NTTP->getType())->getPattern(),
|
||||
TemplateArgs, E->getLocation(),
|
||||
NTTP->getDeclName());
|
||||
} else
|
||||
TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs,
|
||||
E->getLocation(), NTTP->getDeclName());
|
||||
assert(!TargetType.isNull() && "type substitution failed for param type");
|
||||
assert(!TargetType->isDependentType() && "param type still dependent");
|
||||
return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg,
|
||||
TargetType,
|
||||
E->getLocation());
|
||||
}
|
||||
if (parm->isExpandedParameterPack()) {
|
||||
type = parm->getExpansionType(SemaRef.ArgumentPackSubstitutionIndex);
|
||||
} else if (parm->isParameterPack() &&
|
||||
isa<PackExpansionType>(parm->getType())) {
|
||||
type = SemaRef.SubstType(
|
||||
cast<PackExpansionType>(parm->getType())->getPattern(),
|
||||
TemplateArgs, loc, parm->getDeclName());
|
||||
} else {
|
||||
type = SemaRef.SubstType(parm->getType(), TemplateArgs,
|
||||
loc, parm->getDeclName());
|
||||
}
|
||||
assert(!type.isNull() && "type substitution failed for param type");
|
||||
assert(!type->isDependentType() && "param type still dependent");
|
||||
result = SemaRef.BuildExpressionFromDeclTemplateArgument(arg, type, loc);
|
||||
|
||||
return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg,
|
||||
E->getSourceRange().getBegin());
|
||||
if (!result.isInvalid()) type = result.get()->getType();
|
||||
} else {
|
||||
result = SemaRef.BuildExpressionFromIntegralTemplateArgument(arg, loc);
|
||||
|
||||
// Note that this type can be different from the type of 'result',
|
||||
// e.g. if it's an enum type.
|
||||
type = arg.getIntegralType();
|
||||
}
|
||||
if (result.isInvalid()) return ExprError();
|
||||
|
||||
Expr *resultExpr = result.take();
|
||||
return SemaRef.Owned(new (SemaRef.Context)
|
||||
SubstNonTypeTemplateParmExpr(type,
|
||||
resultExpr->getValueKind(),
|
||||
loc, parm, resultExpr));
|
||||
}
|
||||
|
||||
ExprResult
|
||||
|
@ -1133,36 +1157,9 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
|
|||
assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
|
||||
|
||||
const TemplateArgument &Arg = ArgPack.pack_begin()[Index];
|
||||
if (Arg.getKind() == TemplateArgument::Expression)
|
||||
return SemaRef.Owned(Arg.getAsExpr());
|
||||
|
||||
if (Arg.getKind() == TemplateArgument::Declaration) {
|
||||
ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
|
||||
|
||||
// Find the instantiation of the template argument. This is
|
||||
// required for nested templates.
|
||||
VD = cast_or_null<ValueDecl>(
|
||||
getSema().FindInstantiatedDecl(E->getParameterPackLocation(),
|
||||
VD, TemplateArgs));
|
||||
if (!VD)
|
||||
return ExprError();
|
||||
|
||||
QualType T;
|
||||
NonTypeTemplateParmDecl *NTTP = E->getParameterPack();
|
||||
if (NTTP->isExpandedParameterPack())
|
||||
T = NTTP->getExpansionType(getSema().ArgumentPackSubstitutionIndex);
|
||||
else if (const PackExpansionType *Expansion
|
||||
= dyn_cast<PackExpansionType>(NTTP->getType()))
|
||||
T = SemaRef.SubstType(Expansion->getPattern(), TemplateArgs,
|
||||
E->getParameterPackLocation(), NTTP->getDeclName());
|
||||
else
|
||||
T = E->getType();
|
||||
return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, T,
|
||||
E->getParameterPackLocation());
|
||||
}
|
||||
|
||||
return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg,
|
||||
E->getParameterPackLocation());
|
||||
return transformNonTypeTemplateParmRef(E->getParameterPack(),
|
||||
E->getParameterPackLocation(),
|
||||
Arg);
|
||||
}
|
||||
|
||||
ExprResult
|
||||
|
|
|
@ -7663,6 +7663,14 @@ TreeTransform<Derived>::TransformSubstNonTypeTemplateParmPackExpr(
|
|||
return SemaRef.Owned(E);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformSubstNonTypeTemplateParmExpr(
|
||||
SubstNonTypeTemplateParmExpr *E) {
|
||||
// Default behavior is to do nothing with this transformation.
|
||||
return SemaRef.Owned(E);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
|
||||
|
|
|
@ -479,6 +479,7 @@ void ExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
|
|||
|
||||
// We don't handle default arguments either yet, but we can fake it
|
||||
// for now by just skipping them.
|
||||
case Stmt::SubstNonTypeTemplateParmExprClass:
|
||||
case Stmt::CXXDefaultArgExprClass: {
|
||||
Dst.Add(Pred);
|
||||
break;
|
||||
|
|
|
@ -183,6 +183,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent,
|
|||
|
||||
case Stmt::DeclRefExprClass:
|
||||
case Stmt::BlockDeclRefExprClass:
|
||||
case Stmt::SubstNonTypeTemplateParmExprClass:
|
||||
case Stmt::SubstNonTypeTemplateParmPackExprClass:
|
||||
// FIXME: UnresolvedLookupExpr?
|
||||
// FIXME: DependentScopeDeclRefExpr?
|
||||
|
|
Загрузка…
Ссылка в новой задаче