Implement instantiation of enums within class templates. This isn't
quite as great as it sounds, because, while we can refer to the
enumerator values outside the template, e.g.,
adder<long, 3, 4>::value
we can't yet refer to them with dependent names, so no Fibonacci
(yet).
InstantiateClassTemplateSpecialization is getting messy; next commit
will put it into a less-ugly state.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67092 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 25553e5..4f0a992 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -664,8 +664,7 @@
Sema::OwningExprResult
TemplateExprInstantiator::VisitParenExpr(ParenExpr *E) {
- Sema::OwningExprResult SubExpr
- = SemaRef.InstantiateExpr(E->getSubExpr(), TemplateArgs, NumTemplateArgs);
+ Sema::OwningExprResult SubExpr = Visit(E->getSubExpr());
if (SubExpr.isInvalid())
return SemaRef.ExprError();
@@ -733,6 +732,7 @@
// expression.
First.release();
Second.release();
+ // FIXME: Don't reuse the callee here. We need to instantiate it.
return SemaRef.Owned(new (SemaRef.Context) CXXOperatorCallExpr(
SemaRef.Context,
E->getOperator(),
@@ -1147,6 +1147,57 @@
} else
Invalid = true;
+ } else if (EnumDecl *Enum = dyn_cast<EnumDecl>(*Member)) {
+ // FIXME: Spaghetti, anyone?
+ EnumDecl *New = EnumDecl::Create(Context, ClassTemplateSpec,
+ Enum->getLocation(),
+ Enum->getIdentifier(),
+ /*PrevDecl=*/0);
+ ClassTemplateSpec->addDecl(New);
+ New->startDefinition();
+
+ llvm::SmallVector<DeclTy *, 16> Enumerators;
+
+ EnumConstantDecl *LastEnumConst = 0;
+ for (EnumDecl::enumerator_iterator EC = Enum->enumerator_begin(),
+ ECEnd = Enum->enumerator_end();
+ EC != ECEnd; ++EC) {
+ // The specified value for the enumerator.
+ OwningExprResult Value = Owned((Expr *)0);
+ if (Expr *UninstValue = EC->getInitExpr())
+ Value = InstantiateExpr(UninstValue,
+ ClassTemplateSpec->getTemplateArgs(),
+ ClassTemplateSpec->getNumTemplateArgs());
+
+ // Drop the initial value and continue.
+ bool isInvalid = false;
+ if (Value.isInvalid()) {
+ Value = Owned((Expr *)0);
+ isInvalid = true;
+ }
+
+ EnumConstantDecl *NewEnumConst
+ = CheckEnumConstant(New, LastEnumConst,
+ EC->getLocation(),
+ EC->getIdentifier(),
+ move(Value));
+
+ if (isInvalid) {
+ if (NewEnumConst)
+ NewEnumConst->setInvalidDecl();
+ New->setInvalidDecl();
+ Invalid = true;
+ }
+
+ if (NewEnumConst) {
+ New->addDecl(NewEnumConst);
+ Enumerators.push_back(NewEnumConst);
+ LastEnumConst = NewEnumConst;
+ }
+ }
+
+ ActOnEnumBody(New->getLocation(), New,
+ &Enumerators[0], Enumerators.size());
}
}