]> granicus.if.org Git - clang/commitdiff
Fix the handling of dependent enums per C++ DR 502.
authorEli Friedman <eli.friedman@gmail.com>
Fri, 11 Dec 2009 01:34:50 +0000 (01:34 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Fri, 11 Dec 2009 01:34:50 +0000 (01:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91089 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/SemaTemplate/instantiate-enum-2.cpp [new file with mode: 0644]

index fa0d3cef65867a4aa37fd6c056d0d56b0ae75768..64305b443ec5c152b6d1aad17f003a4c8a3a517e 100644 (file)
@@ -5663,7 +5663,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
   llvm::APSInt EnumVal(32);
   QualType EltTy;
   if (Val) {
-    if (Val->isTypeDependent())
+    if (Enum->isDependentType())
       EltTy = Context.DependentTy;
     else {
       // Make sure to promote the operand type to int.
@@ -5675,8 +5675,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
 
       // C99 6.7.2.2p2: Make sure we have an integer constant expression.
       SourceLocation ExpLoc;
-      if (!Val->isValueDependent() &&
-          VerifyIntegerConstantExpression(Val, &EnumVal)) {
+      if (VerifyIntegerConstantExpression(Val, &EnumVal)) {
         Val = 0;
       } else {
         EltTy = Val->getType();
@@ -5685,7 +5684,9 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
   }
 
   if (!Val) {
-    if (LastEnumConst) {
+    if (Enum->isDependentType())
+      EltTy = Context.DependentTy;
+    else if (LastEnumConst) {
       // Assign the last value + 1.
       EnumVal = LastEnumConst->getInitVal();
       ++EnumVal;
@@ -5771,6 +5772,19 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
   if (Attr)
     ProcessDeclAttributeList(S, Enum, Attr);
 
+  if (Enum->isDependentType()) {
+    for (unsigned i = 0; i != NumElements; ++i) {
+      EnumConstantDecl *ECD =
+        cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>());
+      if (!ECD) continue;
+
+      ECD->setType(EnumType);
+    }
+
+    Enum->completeDefinition(Context, Context.DependentTy, Context.DependentTy);
+    return;
+  }
+
   // TODO: If the result value doesn't fit in an int, it must be a long or long
   // long value.  ISO C does not support this, but GCC does as an extension,
   // emit a warning.
diff --git a/test/SemaTemplate/instantiate-enum-2.cpp b/test/SemaTemplate/instantiate-enum-2.cpp
new file mode 100644 (file)
index 0000000..2b56a03
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: clang-cc %s -fsyntax-only -verify
+
+template<int IntBits> struct X {
+  enum {
+    IntShift = (unsigned long long)IntBits,
+    ShiftedIntMask = (1 << IntShift)
+  };
+};
+X<1> x;