[cfe-commits] r67092 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiate-enum.cpp
Douglas Gregor
dgregor at apple.com
Tue Mar 17 12:06:02 PDT 2009
Author: dgregor
Date: Tue Mar 17 14:05:46 2009
New Revision: 67092
URL: http://llvm.org/viewvc/llvm-project?rev=67092&view=rev
Log:
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.
Added:
cfe/trunk/test/SemaTemplate/instantiate-enum.cpp
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=67092&r1=67091&r2=67092&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 17 14:05:46 2009
@@ -399,6 +399,12 @@
/// the definition of a tag (enumeration, class, struct, or union).
virtual void ActOnTagFinishDefinition(Scope *S, DeclTy *TagDecl);
+ EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum,
+ EnumConstantDecl *LastEnumConst,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id,
+ ExprArg val);
+
virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl,
DeclTy *LastEnumConstant,
SourceLocation IdLoc, IdentifierInfo *Id,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=67092&r1=67091&r2=67092&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar 17 14:05:46 2009
@@ -3755,6 +3755,57 @@
ProcessDeclAttributeList(Record, Attr);
}
+EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
+ EnumConstantDecl *LastEnumConst,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id,
+ ExprArg val) {
+ Expr *Val = (Expr *)val.get();
+
+ llvm::APSInt EnumVal(32);
+ QualType EltTy;
+ if (Val && !Val->isTypeDependent()) {
+ // Make sure to promote the operand type to int.
+ UsualUnaryConversions(Val);
+ if (Val != val.get()) {
+ val.release();
+ val = Val;
+ }
+
+ // C99 6.7.2.2p2: Make sure we have an integer constant expression.
+ SourceLocation ExpLoc;
+ if (!Val->isValueDependent() &&
+ VerifyIntegerConstantExpression(Val, &EnumVal)) {
+ Val = 0;
+ } else {
+ EltTy = Val->getType();
+ }
+ }
+
+ if (!Val) {
+ if (LastEnumConst) {
+ // Assign the last value + 1.
+ EnumVal = LastEnumConst->getInitVal();
+ ++EnumVal;
+
+ // Check for overflow on increment.
+ if (EnumVal < LastEnumConst->getInitVal())
+ Diag(IdLoc, diag::warn_enum_value_overflow);
+
+ EltTy = LastEnumConst->getType();
+ } else {
+ // First value, set to zero.
+ EltTy = Context.IntTy;
+ EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy)));
+ }
+ }
+
+ val.release();
+ return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
+ Val, EnumVal);
+}
+
+
Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
DeclTy *lastEnumConst,
SourceLocation IdLoc, IdentifierInfo *Id,
@@ -3794,46 +3845,12 @@
}
}
- llvm::APSInt EnumVal(32);
- QualType EltTy;
- if (Val) {
- // Make sure to promote the operand type to int.
- UsualUnaryConversions(Val);
-
- // C99 6.7.2.2p2: Make sure we have an integer constant expression.
- SourceLocation ExpLoc;
- if (VerifyIntegerConstantExpression(Val, &EnumVal)) {
- Val->Destroy(Context);
- Val = 0; // Just forget about it.
- } else {
- EltTy = Val->getType();
- }
- }
-
- if (!Val) {
- if (LastEnumConst) {
- // Assign the last value + 1.
- EnumVal = LastEnumConst->getInitVal();
- ++EnumVal;
+ EnumConstantDecl *New = CheckEnumConstant(TheEnumDecl, LastEnumConst,
+ IdLoc, Id, Owned(Val));
- // Check for overflow on increment.
- if (EnumVal < LastEnumConst->getInitVal())
- Diag(IdLoc, diag::warn_enum_value_overflow);
-
- EltTy = LastEnumConst->getType();
- } else {
- // First value, set to zero.
- EltTy = Context.IntTy;
- EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy)));
- }
- }
-
- EnumConstantDecl *New =
- EnumConstantDecl::Create(Context, TheEnumDecl, IdLoc, Id, EltTy,
- Val, EnumVal);
-
// Register this decl in the current scope stack.
- PushOnScopeChains(New, S);
+ if (New)
+ PushOnScopeChains(New, S);
return New;
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=67092&r1=67091&r2=67092&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Mar 17 14:05:46 2009
@@ -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());
}
}
Added: cfe/trunk/test/SemaTemplate/instantiate-enum.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-enum.cpp?rev=67092&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-enum.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-enum.cpp Tue Mar 17 14:05:46 2009
@@ -0,0 +1,11 @@
+// RUN: clang -fsyntax-only %s
+
+template<typename T, T I, int J>
+struct adder {
+ enum {
+ value = I + J,
+ value2
+ };
+};
+
+int array1[adder<long, 3, 4>::value == 7? 1 : -1];
More information about the cfe-commits
mailing list