]> granicus.if.org Git - clang/commitdiff
Add code to make test/CodeGen/struct-init.c work correctly without the
authorEli Friedman <eli.friedman@gmail.com>
Mon, 9 Jun 2008 05:05:07 +0000 (05:05 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Mon, 9 Jun 2008 05:05:07 +0000 (05:05 +0000)
pointer cast hack currently in isIntegerConstantExpr
(in lib/AST/Expr.cpp).  Also removes an odd test that even gcc doesn't accept.

The reason the pointer cast hack is relevant here is that it makes Sema
end up misinterpreting the relevant expression as a null pointer constant.

The reason for this patch is that I plan to remove the pointer cast hack
sometime soon because it causes strange issues, especially in its
current form; see my recent email to cfe-dev
"[PATCH] add constant expression evaluation to the AST and fix PR2413".

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

lib/Sema/SemaDecl.cpp
test/CodeGen/struct-init.c

index ed34f9fe00dc90171ba5c6e46f00d89e840a9580..1b1e636a76109bb5a2a7d24297f22be4718d8a64 100644 (file)
@@ -935,6 +935,97 @@ bool Sema::CheckAddressConstantExpression(const Expr* Init) {
   }
 }
 
+static const Expr* FindExpressionBaseAddress(const Expr* E);
+
+static const Expr* FindExpressionBaseAddressLValue(const Expr* E) {
+  switch (E->getStmtClass()) {
+  default:
+    return E;
+  case Expr::ParenExprClass: {
+    const ParenExpr* PE = cast<ParenExpr>(E);
+    return FindExpressionBaseAddressLValue(PE->getSubExpr());
+  }
+  case Expr::MemberExprClass: {
+    const MemberExpr *M = cast<MemberExpr>(E);
+    if (M->isArrow())
+      return FindExpressionBaseAddress(M->getBase());
+    return FindExpressionBaseAddressLValue(M->getBase());
+  }
+  case Expr::ArraySubscriptExprClass: {
+    const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(E);
+    return FindExpressionBaseAddress(ASE->getBase());
+  }
+  case Expr::UnaryOperatorClass: {
+    const UnaryOperator *Exp = cast<UnaryOperator>(E);
+
+    if (Exp->getOpcode() == UnaryOperator::Deref)
+      return FindExpressionBaseAddress(Exp->getSubExpr());
+
+    return E;
+  }
+  }
+}
+
+static const Expr* FindExpressionBaseAddress(const Expr* E) {
+  switch (E->getStmtClass()) {
+  default:
+    return E;
+  case Expr::ParenExprClass: {
+    const ParenExpr* PE = cast<ParenExpr>(E);
+    return FindExpressionBaseAddress(PE->getSubExpr());
+  }
+  case Expr::UnaryOperatorClass: {
+    const UnaryOperator *Exp = cast<UnaryOperator>(E);
+
+    // C99 6.6p9
+    if (Exp->getOpcode() == UnaryOperator::AddrOf)
+      return FindExpressionBaseAddressLValue(Exp->getSubExpr());
+
+    if (Exp->getOpcode() == UnaryOperator::Extension)
+      return FindExpressionBaseAddress(Exp->getSubExpr());
+  
+    return E;
+  }
+  case Expr::BinaryOperatorClass: {
+    const BinaryOperator *Exp = cast<BinaryOperator>(E);
+
+    Expr *PExp = Exp->getLHS();
+    Expr *IExp = Exp->getRHS();
+    if (IExp->getType()->isPointerType())
+      std::swap(PExp, IExp);
+
+    return FindExpressionBaseAddress(PExp);
+  }
+  case Expr::ImplicitCastExprClass: {
+    const Expr* SubExpr = cast<ImplicitCastExpr>(E)->getSubExpr();
+
+    // Check for implicit promotion
+    if (SubExpr->getType()->isFunctionType() ||
+        SubExpr->getType()->isArrayType())
+      return FindExpressionBaseAddressLValue(SubExpr);
+
+    // Check for pointer->pointer cast
+    if (SubExpr->getType()->isPointerType())
+      return FindExpressionBaseAddress(SubExpr);
+
+    // We assume that we have an arithmetic expression here;
+    // if we don't, we'll figure it out later
+    return 0;
+  }
+  case Expr::CastExprClass: {
+    const Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
+
+    // Check for pointer->pointer cast
+    if (SubExpr->getType()->isPointerType())
+      return FindExpressionBaseAddress(SubExpr);
+
+    // We assume that we have an arithmetic expression here;
+    // if we don't, we'll figure it out later
+    return 0;
+  }
+  }
+}
+
 bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {
   switch (Init->getStmtClass()) {
   default:
@@ -1027,6 +1118,20 @@ bool Sema::CheckArithmeticConstantExpression(const Expr* Init) {
              CheckArithmeticConstantExpression(Exp->getRHS());
     }
 
+    if (Exp->getLHS()->getType()->isPointerType() &&
+        Exp->getRHS()->getType()->isPointerType()) {
+      const Expr* LHSBase = FindExpressionBaseAddress(Exp->getLHS());
+      const Expr* RHSBase = FindExpressionBaseAddress(Exp->getRHS());
+
+      // Only allow a null (constant integer) base; we could
+      // allow some additional cases if necessary, but this
+      // is sufficient to cover offsetof-like constructs.
+      if (!LHSBase && !RHSBase) {
+        return CheckAddressConstantExpression(Exp->getLHS()) ||
+               CheckAddressConstantExpression(Exp->getRHS());
+      }
+    }
+
     Diag(Init->getExprLoc(),
          diag::err_init_element_not_constant, Init->getSourceRange());
     return true;
index 5b815de3998899220385771ed78a54bd4d965229..02cbee06b0cdd636d55abf943499c5d0e86f7072 100644 (file)
@@ -9,5 +9,4 @@ char a;
 
 const zend_ini_entry ini_entries[] = {
        {  ((char*)&((zend_ini_entry*)0)->mh_arg1 - (char*)(void*)0)},
-       {  ((long long*)&a - (long long*)(void*)2)},
 };