aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/Sema.h6
-rw-r--r--lib/Sema/SemaDecl.cpp93
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp55
-rw-r--r--test/SemaTemplate/instantiate-enum.cpp11
4 files changed, 125 insertions, 40 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 13c3e87bfe..ed6b2d4160 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -399,6 +399,12 @@ public:
/// 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,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index d34a8e7111..7eedd0b07f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3755,6 +3755,57 @@ void Sema::ActOnFields(Scope* S,
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 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
}
}
- 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;
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 25553e510f..4f0a9923bd 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -664,8 +664,7 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
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 @@ TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
// 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 @@ Sema::InstantiateClassTemplateSpecialization(
} 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());
}
}
diff --git a/test/SemaTemplate/instantiate-enum.cpp b/test/SemaTemplate/instantiate-enum.cpp
new file mode 100644
index 0000000000..665746cfd4
--- /dev/null
+++ b/test/SemaTemplate/instantiate-enum.cpp
@@ -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];