]> granicus.if.org Git - clang/commitdiff
Fix a case where Expr::isConstantInitializer would return true for an expression...
authorEli Friedman <eli.friedman@gmail.com>
Wed, 21 Dec 2011 00:43:02 +0000 (00:43 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 21 Dec 2011 00:43:02 +0000 (00:43 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147026 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Expr.cpp
test/Sema/static-init.c

index 40da32284dfb07247578cfc034dfad3f5ea3573a..9f87161290ec41e89ffee86184a564a5f1acd031 100644 (file)
@@ -2550,17 +2550,30 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
     if (getType()->isVectorType() && CE->getCastKind() == CK_BitCast)
       return CE->getSubExpr()->isConstantInitializer(Ctx, false);
 
-    // Handle casts with a destination that's a struct or union; this
-    // deals with both the gcc no-op struct cast extension and the
-    // cast-to-union extension.
-    if (getType()->isRecordType())
+    // Handle misc casts we want to ignore.
+    // FIXME: Is it really safe to ignore all these?
+    if (CE->getCastKind() == CK_NoOp ||
+        CE->getCastKind() == CK_LValueToRValue ||
+        CE->getCastKind() == CK_ToUnion ||
+        CE->getCastKind() == CK_ConstructorConversion)
       return CE->getSubExpr()->isConstantInitializer(Ctx, false);
 
-    // Integer->integer casts can be handled here, which is important for
-    // things like (int)(&&x-&&y).  Scary but true.
-    if (getType()->isIntegerType() &&
-        CE->getSubExpr()->getType()->isIntegerType())
-      return CE->getSubExpr()->isConstantInitializer(Ctx, false);
+    // Handle things like (int)(&&x-&&y). It's a bit nasty, but we support it.
+    if (CE->getCastKind() == CK_IntegralCast) {
+      const Expr *E = CE->getSubExpr()->IgnoreParenNoopCasts(Ctx);
+      while (const CastExpr *InnerCE = dyn_cast<CastExpr>(E)) {
+        if (InnerCE->getCastKind() != CK_IntegralCast)
+          break;
+        E = InnerCE->getSubExpr()->IgnoreParenNoopCasts(Ctx);
+      }
+
+      if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+        if (BO->getOpcode() == BO_Sub &&
+            isa<AddrLabelExpr>(BO->getLHS()->IgnoreParenNoopCasts(Ctx)) &&
+            isa<AddrLabelExpr>(BO->getRHS()->IgnoreParenNoopCasts(Ctx)))
+          return true;
+      }
+    }
 
     break;
   }
index b4de92713b88370de215de4063c6f97927288432..ec6d1e8fc0de8877f97b3dca53549c889a54fd1c 100644 (file)
@@ -19,5 +19,6 @@ struct foo {
 };
 
 union bar u[1];
-struct foo x = {(intptr_t) u}; // no-error
+struct foo x = {(intptr_t) u}; // expected-error {{initializer element is not a compile-time constant}}
 struct foo y = {(char) u}; // expected-error {{initializer element is not a compile-time constant}}
+intptr_t z = (intptr_t) u; // no-error