]> granicus.if.org Git - clang/commitdiff
fix PR9474, a crash with -fshort-enum and C++ templates: when instantiating
authorChris Lattner <sabre@nondot.org>
Mon, 25 Apr 2011 20:37:58 +0000 (20:37 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 25 Apr 2011 20:37:58 +0000 (20:37 +0000)
the enum decl, we need to use an integer type the same size as the enumerator,
which may not be the promoted type with packed enums.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130148 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplate.cpp
lib/Sema/TreeTransform.h
test/SemaCXX/short-enums.cpp [new file with mode: 0644]

index bc29a4cbdc0e47d0568c749601718e2b3b6022b4..3123f5fc675289aa0643fb4da06b7895bba80b0b 100644 (file)
@@ -3840,18 +3840,18 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
   if (T->isCharType() || T->isWideCharType())
     return Owned(new (Context) CharacterLiteral(
                                              Arg.getAsIntegral()->getZExtValue(),
-                                             T->isWideCharType(),
-                                             T,
-                                             Loc));
+                                             T->isWideCharType(), T, Loc));
   if (T->isBooleanType())
     return Owned(new (Context) CXXBoolLiteralExpr(
                                             Arg.getAsIntegral()->getBoolValue(),
-                                            T,
-                                            Loc));
+                                            T, Loc));
 
+  // If this is an enum type that we're instantiating, we need to use an integer
+  // type the same size as the enumerator.  We don't want to build an
+  // IntegerLiteral with enum type.
   QualType BT;
   if (const EnumType *ET = T->getAs<EnumType>())
-    BT = ET->getDecl()->getPromotionType();
+    BT = ET->getDecl()->getIntegerType();
   else
     BT = T;
 
@@ -3859,10 +3859,9 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
   if (T->isEnumeralType()) {
     // FIXME: This is a hack. We need a better way to handle substituted
     // non-type template parameters.
-    E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast,
-                                      E, 0, 
-                                      Context.getTrivialTypeSourceInfo(T, Loc),
-                                      Loc, Loc);
+    E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0, 
+                               Context.getTrivialTypeSourceInfo(T, Loc),
+                               Loc, Loc);
   }
   
   return Owned(E);
index c642e642cc83aa04707da8a164101f3940460900..b2aa85e7198beed14af3085dcb9963cacb896113 100644 (file)
@@ -2819,8 +2819,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
     Expr *InputExpr = Input.getSourceExpression();
     if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
 
-    ExprResult E
-      = getDerived().TransformExpr(InputExpr);
+    ExprResult E = getDerived().TransformExpr(InputExpr);
     if (E.isInvalid()) return true;
     Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take());
     return false;
diff --git a/test/SemaCXX/short-enums.cpp b/test/SemaCXX/short-enums.cpp
new file mode 100644 (file)
index 0000000..ca713b7
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fshort-enums -fsyntax-only %s
+
+// This shouldn't crash: PR9474
+
+enum E { VALUE_1 };
+
+template <typename T>
+struct A {};
+
+template <E Enum>
+struct B : A<B<Enum> > {};
+
+void bar(int x) {
+  switch (x) {
+    case sizeof(B<VALUE_1>): ;
+  }
+}
\ No newline at end of file