diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-17 19:05:46 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-17 19:05:46 +0000 |
commit | 879fd49f99742e61965f7fefecf1f3b4ba90e197 (patch) | |
tree | 94f7603c0ae78bc3bcf9eda2701b44f9405d226c /lib/Sema/SemaDecl.cpp | |
parent | 1fd6c4b8abbbdcbae0e221f35100102112dabff2 (diff) |
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
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 93 |
1 files changed, 55 insertions, 38 deletions
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; } |