forked from OSchip/llvm-project
PR13811: Add a FunctionParmPackExpr node to handle references to function
parameter packs where the reference is not being expanded but the pack has been. Previously, Clang would segfault in such cases. llvm-svn: 163672
This commit is contained in:
parent
b28179bb80
commit
b15fe3a5e4
|
@ -3616,6 +3616,73 @@ public:
|
|||
child_range children() { return child_range(); }
|
||||
};
|
||||
|
||||
/// \brief Represents a reference to a function parameter pack that has been
|
||||
/// substituted but not yet expanded.
|
||||
///
|
||||
/// When a pack expansion contains multiple parameter packs at different levels,
|
||||
/// this node is used to represent a function parameter pack at an outer level
|
||||
/// which we have already substituted to refer to expanded parameters, but where
|
||||
/// the containing pack expansion cannot yet be expanded.
|
||||
///
|
||||
/// \code
|
||||
/// template<typename...Ts> struct S {
|
||||
/// template<typename...Us> auto f(Ts ...ts) -> decltype(g(Us(ts)...));
|
||||
/// };
|
||||
/// template struct S<int, int>;
|
||||
/// \endcode
|
||||
class FunctionParmPackExpr : public Expr {
|
||||
/// \brief The function parameter pack which was referenced.
|
||||
ParmVarDecl *ParamPack;
|
||||
|
||||
/// \brief The location of the function parameter pack reference.
|
||||
SourceLocation NameLoc;
|
||||
|
||||
/// \brief The number of expansions of this pack.
|
||||
unsigned NumParameters;
|
||||
|
||||
FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
|
||||
SourceLocation NameLoc, unsigned NumParams,
|
||||
Decl * const *Params);
|
||||
|
||||
friend class ASTReader;
|
||||
friend class ASTStmtReader;
|
||||
|
||||
public:
|
||||
static FunctionParmPackExpr *Create(ASTContext &Context, QualType T,
|
||||
ParmVarDecl *ParamPack,
|
||||
SourceLocation NameLoc,
|
||||
llvm::ArrayRef<Decl*> Params);
|
||||
static FunctionParmPackExpr *CreateEmpty(ASTContext &Context,
|
||||
unsigned NumParams);
|
||||
|
||||
/// \brief Get the parameter pack which this expression refers to.
|
||||
ParmVarDecl *getParameterPack() const { return ParamPack; }
|
||||
|
||||
/// \brief Get the location of the parameter pack.
|
||||
SourceLocation getParameterPackLocation() const { return NameLoc; }
|
||||
|
||||
/// \brief Iterators over the parameters which the parameter pack expanded
|
||||
/// into.
|
||||
typedef ParmVarDecl * const *iterator;
|
||||
iterator begin() const { return reinterpret_cast<iterator>(this+1); }
|
||||
iterator end() const { return begin() + NumParameters; }
|
||||
|
||||
/// \brief Get the number of parameters in this parameter pack.
|
||||
unsigned getNumExpansions() const { return NumParameters; }
|
||||
|
||||
/// \brief Get an expansion of the parameter pack by index.
|
||||
ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; }
|
||||
|
||||
SourceRange getSourceRange() const LLVM_READONLY { return NameLoc; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == FunctionParmPackExprClass;
|
||||
}
|
||||
static bool classof(const FunctionParmPackExpr *) { return true; }
|
||||
|
||||
child_range children() { return child_range(); }
|
||||
};
|
||||
|
||||
/// \brief Represents a prvalue temporary that written into memory so that
|
||||
/// a reference can bind to it.
|
||||
///
|
||||
|
|
|
@ -2221,6 +2221,7 @@ DEF_TRAVERSE_STMT(PackExpansionExpr, { })
|
|||
DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
|
||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
|
||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { })
|
||||
DEF_TRAVERSE_STMT(FunctionParmPackExpr, { })
|
||||
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { })
|
||||
DEF_TRAVERSE_STMT(AtomicExpr, { })
|
||||
|
||||
|
|
|
@ -131,6 +131,7 @@ def PackExpansionExpr : DStmt<Expr>;
|
|||
def SizeOfPackExpr : DStmt<Expr>;
|
||||
def SubstNonTypeTemplateParmExpr : DStmt<Expr>;
|
||||
def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>;
|
||||
def FunctionParmPackExpr : DStmt<Expr>;
|
||||
def MaterializeTemporaryExpr : DStmt<Expr>;
|
||||
def LambdaExpr : DStmt<Expr>;
|
||||
|
||||
|
|
|
@ -1193,6 +1193,7 @@ namespace clang {
|
|||
EXPR_SIZEOF_PACK, // SizeOfPackExpr
|
||||
EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
|
||||
EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
|
||||
EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr
|
||||
EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
|
||||
|
||||
// CUDA
|
||||
|
|
|
@ -2646,6 +2646,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx) const {
|
|||
case UnresolvedMemberExprClass:
|
||||
case PackExpansionExprClass:
|
||||
case SubstNonTypeTemplateParmPackExprClass:
|
||||
case FunctionParmPackExprClass:
|
||||
llvm_unreachable("shouldn't see dependent / unresolved nodes here");
|
||||
|
||||
case DeclRefExprClass:
|
||||
|
|
|
@ -1299,6 +1299,34 @@ TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
|
|||
return TemplateArgument(Arguments, NumArguments);
|
||||
}
|
||||
|
||||
FunctionParmPackExpr::FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack,
|
||||
SourceLocation NameLoc,
|
||||
unsigned NumParams,
|
||||
Decl * const *Params)
|
||||
: Expr(FunctionParmPackExprClass, T, VK_LValue, OK_Ordinary,
|
||||
true, true, true, true),
|
||||
ParamPack(ParamPack), NameLoc(NameLoc), NumParameters(NumParams) {
|
||||
if (Params)
|
||||
std::uninitialized_copy(Params, Params + NumParams,
|
||||
reinterpret_cast<Decl**>(this+1));
|
||||
}
|
||||
|
||||
FunctionParmPackExpr *
|
||||
FunctionParmPackExpr::Create(ASTContext &Context, QualType T,
|
||||
ParmVarDecl *ParamPack, SourceLocation NameLoc,
|
||||
llvm::ArrayRef<Decl*> Params) {
|
||||
return new (Context.Allocate(sizeof(FunctionParmPackExpr) +
|
||||
sizeof(ParmVarDecl*) * Params.size()))
|
||||
FunctionParmPackExpr(T, ParamPack, NameLoc, Params.size(), Params.data());
|
||||
}
|
||||
|
||||
FunctionParmPackExpr *
|
||||
FunctionParmPackExpr::CreateEmpty(ASTContext &Context, unsigned NumParams) {
|
||||
return new (Context.Allocate(sizeof(FunctionParmPackExpr) +
|
||||
sizeof(ParmVarDecl*) * NumParams))
|
||||
FunctionParmPackExpr(QualType(), 0, SourceLocation(), 0, 0);
|
||||
}
|
||||
|
||||
TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
|
||||
ArrayRef<TypeSourceInfo *> Args,
|
||||
SourceLocation RParenLoc,
|
||||
|
|
|
@ -134,6 +134,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
|
|||
// ObjC instance variables are lvalues
|
||||
// FIXME: ObjC++0x might have different rules
|
||||
case Expr::ObjCIvarRefExprClass:
|
||||
case Expr::FunctionParmPackExprClass:
|
||||
return Cl::CL_LValue;
|
||||
|
||||
// C99 6.5.2.5p5 says that compound literals are lvalues.
|
||||
|
|
|
@ -6480,6 +6480,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
|||
case Expr::OpaqueValueExprClass:
|
||||
case Expr::PackExpansionExprClass:
|
||||
case Expr::SubstNonTypeTemplateParmPackExprClass:
|
||||
case Expr::FunctionParmPackExprClass:
|
||||
case Expr::AsTypeExprClass:
|
||||
case Expr::ObjCIndirectCopyRestoreExprClass:
|
||||
case Expr::MaterializeTemporaryExprClass:
|
||||
|
|
|
@ -2809,7 +2809,15 @@ recurse:
|
|||
// };
|
||||
Out << "_SUBSTPACK_";
|
||||
break;
|
||||
|
||||
|
||||
case Expr::FunctionParmPackExprClass: {
|
||||
// FIXME: not clear how to mangle this!
|
||||
const FunctionParmPackExpr *FPPE = cast<FunctionParmPackExpr>(E);
|
||||
Out << "v110_SUBSTPACK";
|
||||
mangleFunctionParam(FPPE->getParameterPack());
|
||||
break;
|
||||
}
|
||||
|
||||
case Expr::DependentScopeDeclRefExprClass: {
|
||||
const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
|
||||
mangleUnresolvedName(DRE->getQualifier(), 0, DRE->getDeclName(), Arity);
|
||||
|
|
|
@ -1647,6 +1647,10 @@ void StmtPrinter::VisitSubstNonTypeTemplateParmExpr(
|
|||
Visit(Node->getReplacement());
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
||||
OS << *E->getParameterPack();
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *Node){
|
||||
PrintExpr(Node->GetTemporaryExpr());
|
||||
}
|
||||
|
|
|
@ -973,6 +973,14 @@ void StmtProfiler::VisitSubstNonTypeTemplateParmExpr(
|
|||
Visit(E->getReplacement());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitFunctionParmPackExpr(const FunctionParmPackExpr *S) {
|
||||
VisitExpr(S);
|
||||
VisitDecl(S->getParameterPack());
|
||||
ID.AddInteger(S->getNumExpansions());
|
||||
for (FunctionParmPackExpr::iterator I = S->begin(), E = S->end(); I != E; ++I)
|
||||
VisitDecl(*I);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitMaterializeTemporaryExpr(
|
||||
const MaterializeTemporaryExpr *S) {
|
||||
VisitExpr(S);
|
||||
|
|
|
@ -1029,6 +1029,7 @@ CanThrowResult Sema::canThrow(const Expr *E) {
|
|||
case Expr::PseudoObjectExprClass:
|
||||
case Expr::SubstNonTypeTemplateParmExprClass:
|
||||
case Expr::SubstNonTypeTemplateParmPackExprClass:
|
||||
case Expr::FunctionParmPackExprClass:
|
||||
case Expr::UnaryExprOrTypeTraitExprClass:
|
||||
case Expr::UnresolvedLookupExprClass:
|
||||
case Expr::UnresolvedMemberExprClass:
|
||||
|
|
|
@ -802,11 +802,24 @@ namespace {
|
|||
ExprResult TransformPredefinedExpr(PredefinedExpr *E);
|
||||
ExprResult TransformDeclRefExpr(DeclRefExpr *E);
|
||||
ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
|
||||
|
||||
ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
|
||||
NonTypeTemplateParmDecl *D);
|
||||
ExprResult TransformSubstNonTypeTemplateParmPackExpr(
|
||||
SubstNonTypeTemplateParmPackExpr *E);
|
||||
|
||||
|
||||
/// \brief Rebuild a DeclRefExpr for a ParmVarDecl reference.
|
||||
ExprResult RebuildParmVarDeclRefExpr(ParmVarDecl *PD, SourceLocation Loc);
|
||||
|
||||
/// \brief Transform a reference to a function parameter pack.
|
||||
ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E,
|
||||
ParmVarDecl *PD);
|
||||
|
||||
/// \brief Transform a FunctionParmPackExpr which was built when we couldn't
|
||||
/// expand a function parameter pack reference which refers to an expanded
|
||||
/// pack.
|
||||
ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
|
||||
|
||||
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
|
||||
FunctionProtoTypeLoc TL);
|
||||
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
|
||||
|
@ -1229,9 +1242,82 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
|
|||
Arg);
|
||||
}
|
||||
|
||||
ExprResult
|
||||
TemplateInstantiator::RebuildParmVarDeclRefExpr(ParmVarDecl *PD,
|
||||
SourceLocation Loc) {
|
||||
DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
|
||||
return getSema().BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, PD);
|
||||
}
|
||||
|
||||
ExprResult
|
||||
TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
||||
if (getSema().ArgumentPackSubstitutionIndex != -1) {
|
||||
// We can expand this parameter pack now.
|
||||
ParmVarDecl *D = E->getExpansion(getSema().ArgumentPackSubstitutionIndex);
|
||||
ValueDecl *VD = cast_or_null<ValueDecl>(TransformDecl(E->getExprLoc(), D));
|
||||
if (!VD)
|
||||
return ExprError();
|
||||
return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(VD), E->getExprLoc());
|
||||
}
|
||||
|
||||
QualType T = TransformType(E->getType());
|
||||
if (T.isNull())
|
||||
return ExprError();
|
||||
|
||||
// Transform each of the parameter expansions into the corresponding
|
||||
// parameters in the instantiation of the function decl.
|
||||
llvm::SmallVector<Decl*, 8> Parms;
|
||||
Parms.reserve(E->getNumExpansions());
|
||||
for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
|
||||
I != End; ++I) {
|
||||
ParmVarDecl *D =
|
||||
cast_or_null<ParmVarDecl>(TransformDecl(E->getExprLoc(), *I));
|
||||
if (!D)
|
||||
return ExprError();
|
||||
Parms.push_back(D);
|
||||
}
|
||||
|
||||
return FunctionParmPackExpr::Create(getSema().Context, T,
|
||||
E->getParameterPack(),
|
||||
E->getParameterPackLocation(), Parms);
|
||||
}
|
||||
|
||||
ExprResult
|
||||
TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
|
||||
ParmVarDecl *PD) {
|
||||
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
|
||||
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
|
||||
= getSema().CurrentInstantiationScope->findInstantiationOf(PD);
|
||||
assert(Found && "no instantiation for parameter pack");
|
||||
|
||||
Decl *TransformedDecl;
|
||||
if (DeclArgumentPack *Pack = Found->dyn_cast<DeclArgumentPack *>()) {
|
||||
// If this is a reference to a function parameter pack which we can substitute
|
||||
// but can't yet expand, build a FunctionParmPackExpr for it.
|
||||
if (getSema().ArgumentPackSubstitutionIndex == -1) {
|
||||
QualType T = TransformType(E->getType());
|
||||
if (T.isNull())
|
||||
return ExprError();
|
||||
return FunctionParmPackExpr::Create(getSema().Context, T, PD,
|
||||
E->getExprLoc(), *Pack);
|
||||
}
|
||||
|
||||
TransformedDecl = (*Pack)[getSema().ArgumentPackSubstitutionIndex];
|
||||
} else {
|
||||
TransformedDecl = Found->get<Decl*>();
|
||||
}
|
||||
|
||||
// We have either an unexpanded pack or a specific expansion.
|
||||
return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(TransformedDecl),
|
||||
E->getExprLoc());
|
||||
}
|
||||
|
||||
ExprResult
|
||||
TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
|
||||
NamedDecl *D = E->getDecl();
|
||||
|
||||
// Handle references to non-type template parameters and non-type template
|
||||
// parameter packs.
|
||||
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
||||
if (NTTP->getDepth() < TemplateArgs.getNumLevels())
|
||||
return TransformTemplateParmRefExpr(E, NTTP);
|
||||
|
@ -1240,6 +1326,11 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
|
|||
// FindInstantiatedDecl will find it in the local instantiation scope.
|
||||
}
|
||||
|
||||
// Handle references to function parameter packs.
|
||||
if (ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D))
|
||||
if (PD->isParameterPack())
|
||||
return TransformFunctionParmPackRefExpr(E, PD);
|
||||
|
||||
return TreeTransform<TemplateInstantiator>::TransformDeclRefExpr(E);
|
||||
}
|
||||
|
||||
|
|
|
@ -3397,7 +3397,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
|
|||
if (Decl *FD = Found->dyn_cast<Decl *>())
|
||||
return cast<NamedDecl>(FD);
|
||||
|
||||
unsigned PackIdx = ArgumentPackSubstitutionIndex;
|
||||
int PackIdx = ArgumentPackSubstitutionIndex;
|
||||
assert(PackIdx != -1 && "found declaration pack but not pack expanding");
|
||||
return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]);
|
||||
}
|
||||
|
||||
|
|
|
@ -8319,6 +8319,13 @@ TreeTransform<Derived>::TransformSubstNonTypeTemplateParmExpr(
|
|||
return SemaRef.Owned(E);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
||||
// Default behavior is to do nothing with this transformation.
|
||||
return SemaRef.Owned(E);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformMaterializeTemporaryExpr(
|
||||
|
|
|
@ -1468,6 +1468,16 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
|
|||
E->NameLoc = ReadSourceLocation(Record, Idx);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
||||
VisitExpr(E);
|
||||
E->NumParameters = Record[Idx++];
|
||||
E->ParamPack = ReadDeclAs<ParmVarDecl>(Record, Idx);
|
||||
E->NameLoc = ReadSourceLocation(Record, Idx);
|
||||
ParmVarDecl **Parms = reinterpret_cast<ParmVarDecl**>(E+1);
|
||||
for (unsigned i = 0, n = E->NumParameters; i != n; ++i)
|
||||
Parms[i] = ReadDeclAs<ParmVarDecl>(Record, Idx);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
|
||||
VisitExpr(E);
|
||||
E->Temporary = Reader.ReadSubExpr();
|
||||
|
@ -2183,6 +2193,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
|||
case EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK:
|
||||
S = new (Context) SubstNonTypeTemplateParmPackExpr(Empty);
|
||||
break;
|
||||
|
||||
case EXPR_FUNCTION_PARM_PACK:
|
||||
S = FunctionParmPackExpr::CreateEmpty(Context,
|
||||
Record[ASTStmtReader::NumExprFields]);
|
||||
break;
|
||||
|
||||
case EXPR_MATERIALIZE_TEMPORARY:
|
||||
S = new (Context) MaterializeTemporaryExpr(Empty);
|
||||
|
|
|
@ -1481,6 +1481,17 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr(
|
|||
Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) {
|
||||
VisitExpr(E);
|
||||
Record.push_back(E->getNumExpansions());
|
||||
Writer.AddDeclRef(E->getParameterPack(), Record);
|
||||
Writer.AddSourceLocation(E->getParameterPackLocation(), Record);
|
||||
for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
|
||||
I != End; ++I)
|
||||
Writer.AddDeclRef(*I, Record);
|
||||
Code = serialization::EXPR_FUNCTION_PARM_PACK;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
|
||||
VisitExpr(E);
|
||||
Writer.AddStmt(E->Temporary);
|
||||
|
|
|
@ -526,6 +526,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
|||
case Stmt::CXXNoexceptExprClass:
|
||||
case Stmt::PackExpansionExprClass:
|
||||
case Stmt::SubstNonTypeTemplateParmPackExprClass:
|
||||
case Stmt::FunctionParmPackExprClass:
|
||||
case Stmt::SEHTryStmtClass:
|
||||
case Stmt::SEHExceptStmtClass:
|
||||
case Stmt::LambdaExprClass:
|
||||
|
|
|
@ -187,6 +187,30 @@ namespace PacksAtDifferentLevels {
|
|||
add_pointer<float>,
|
||||
add_const<double>>>::value == 0? 1 : -1];
|
||||
|
||||
namespace PR13811 {
|
||||
constexpr int g(int n, int m) { return n * 10 + m; }
|
||||
|
||||
template<typename...A>
|
||||
struct X6 {
|
||||
template<typename...B>
|
||||
constexpr auto f1(A ...a) -> decltype(g(A(a + B())...)) { return g(A(a + B())...); }
|
||||
|
||||
template<typename...B>
|
||||
constexpr auto f2(A ...a, B ...b) -> decltype(g((&a)[b] ...)) { return g((&a)[b] ...); } // expected-note {{past-the-end}}
|
||||
|
||||
template<typename...B> struct Inner {
|
||||
template<typename...C>
|
||||
constexpr auto f(A ...a, B ...b, C ...c) -> decltype(g(a+b+c...)) { return g(a+b+c...); }
|
||||
};
|
||||
};
|
||||
struct A { constexpr operator int() { return 2; } };
|
||||
struct B { constexpr operator int() { return 1; } };
|
||||
|
||||
static_assert(X6<unsigned char, int>().f1<A, B>(255, 1) == 12, "");
|
||||
static_assert(X6<int, int>().f2(3, 4, 0, 0) == 34, "");
|
||||
static_assert(X6<int, int>().f2(3, 4, 0, 1) == 34, ""); // expected-error {{constant expression}} expected-note {{in call}}
|
||||
static_assert(X6<int, int>::Inner<int, int>().f(1, 2, 3, 4, 5, 6) == 102, "");
|
||||
}
|
||||
}
|
||||
|
||||
namespace ExpandingNonTypeTemplateParameters {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Test this without pch.
|
||||
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h -verify %s -ast-dump -o -
|
||||
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h %s -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h -verify %s -ast-dump -o -
|
||||
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include %S/cxx-templates.h %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// Test with pch.
|
||||
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h
|
||||
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include-pch %t -verify %s -ast-dump -o -
|
||||
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -x c++-header -emit-pch -o %t %S/cxx-templates.h
|
||||
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t -verify %s -ast-dump -o -
|
||||
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// CHECK: define weak_odr void @_ZN2S4IiE1mEv
|
||||
// CHECK: define linkonce_odr void @_ZN2S3IiE1mEv
|
||||
|
@ -68,3 +68,12 @@ Foo< D >& Foo< D >::operator=( const Foo& other )
|
|||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
namespace TestNestedExpansion {
|
||||
struct Int {
|
||||
Int(int);
|
||||
friend Int operator+(Int, Int);
|
||||
};
|
||||
Int &g(Int, int, double);
|
||||
Int &test = NestedExpansion<char, char, char>().f(0, 1, 2, Int(3), 4, 5.0);
|
||||
}
|
||||
|
|
|
@ -215,3 +215,8 @@ class Foo : protected T
|
|||
public:
|
||||
Foo& operator=( const Foo& other );
|
||||
};
|
||||
|
||||
template<typename...A> struct NestedExpansion {
|
||||
template<typename...B> auto f(A...a, B...b) -> decltype(g(a + b...));
|
||||
};
|
||||
template struct NestedExpansion<char, char, char>;
|
||||
|
|
|
@ -432,6 +432,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
|
|||
case Stmt::DependentScopeDeclRefExprClass:
|
||||
case Stmt::SubstNonTypeTemplateParmExprClass:
|
||||
case Stmt::SubstNonTypeTemplateParmPackExprClass:
|
||||
case Stmt::FunctionParmPackExprClass:
|
||||
case Stmt::UnresolvedLookupExprClass:
|
||||
K = CXCursor_DeclRefExpr;
|
||||
break;
|
||||
|
|
|
@ -2141,6 +2141,7 @@ DEF_TRAVERSE_STMT(PackExpansionExpr, { })
|
|||
DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
|
||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
|
||||
DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { })
|
||||
DEF_TRAVERSE_STMT(FunctionParmPackExpr, { })
|
||||
DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { })
|
||||
DEF_TRAVERSE_STMT(AtomicExpr, { })
|
||||
|
||||
|
|
Loading…
Reference in New Issue