]> granicus.if.org Git - clang/commitdiff
Zap the Sema constant initializer checking code that we aren't using
authorEli Friedman <eli.friedman@gmail.com>
Thu, 26 Feb 2009 04:47:58 +0000 (04:47 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Thu, 26 Feb 2009 04:47:58 +0000 (04:47 +0000)
anymore.  If we want to reuse bits and pieces to add strict checking for
constant initializers, we can dig them out of SVN history; the existing
code won't be useful as-is.

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

lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp

index 1d36d46296bb28c5fe676b9060cf8ccab1113a15..1120f03f59deac75846bbbb6068b996052ff359b 100644 (file)
@@ -1909,10 +1909,6 @@ public:
                              bool DirectInit);
   bool CheckInitList(InitListExpr *&InitList, QualType &DeclType);
   bool CheckForConstantInitializer(Expr *e, QualType t);
-  bool CheckArithmeticConstantExpression(const Expr* e);
-  bool CheckAddressConstantExpression(const Expr* e);
-  bool CheckAddressConstantExpressionLValue(const Expr* e);
-  void InitializerElementNotConstant(const Expr *e);
   
   bool CheckValueInitialization(QualType Type, SourceLocation Loc);
 
index 981d0f9bd5a536d05e0299359820e81888a7be8a..0ad3839fde1e38bfd2011bb8b9a9a155817e8cd1 100644 (file)
@@ -2019,536 +2019,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   return NewFD;
 }
 
-void Sema::InitializerElementNotConstant(const Expr *Init) {
-  Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
-    << Init->getSourceRange();
-}
-
-bool Sema::CheckAddressConstantExpressionLValue(const Expr* Init) {
-  switch (Init->getStmtClass()) {
-  default:
-    InitializerElementNotConstant(Init);
-    return true;
-  case Expr::ParenExprClass: {
-    const ParenExpr* PE = cast<ParenExpr>(Init);
-    return CheckAddressConstantExpressionLValue(PE->getSubExpr());
-  }
-  case Expr::CompoundLiteralExprClass:
-    return cast<CompoundLiteralExpr>(Init)->isFileScope();
-  case Expr::DeclRefExprClass: 
-  case Expr::QualifiedDeclRefExprClass: {
-    const Decl *D = cast<DeclRefExpr>(Init)->getDecl();
-    if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
-      if (VD->hasGlobalStorage())
-        return false;
-      InitializerElementNotConstant(Init);
-      return true;
-    }
-    if (isa<FunctionDecl>(D))
-      return false;
-    InitializerElementNotConstant(Init);
-    return true;
-  }
-  case Expr::MemberExprClass: {
-    const MemberExpr *M = cast<MemberExpr>(Init);
-    if (M->isArrow())
-      return CheckAddressConstantExpression(M->getBase());
-    return CheckAddressConstantExpressionLValue(M->getBase());
-  }
-  case Expr::ArraySubscriptExprClass: {
-    // FIXME: Should we pedwarn for "x[0+0]" (where x is a pointer)?
-    const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(Init);
-    return CheckAddressConstantExpression(ASE->getBase()) ||
-           CheckArithmeticConstantExpression(ASE->getIdx());
-  }
-  case Expr::StringLiteralClass:
-  case Expr::ObjCEncodeExprClass:
-  case Expr::PredefinedExprClass:
-    return false;
-  case Expr::UnaryOperatorClass: {
-    const UnaryOperator *Exp = cast<UnaryOperator>(Init);
-
-    // C99 6.6p9
-    if (Exp->getOpcode() == UnaryOperator::Deref)
-      return CheckAddressConstantExpression(Exp->getSubExpr());
-
-    InitializerElementNotConstant(Init);
-    return true;
-  }
-  }
-}
-
-bool Sema::CheckAddressConstantExpression(const Expr* Init) {
-  switch (Init->getStmtClass()) {
-  default:
-    InitializerElementNotConstant(Init);
-    return true;
-  case Expr::ParenExprClass:
-    return CheckAddressConstantExpression(cast<ParenExpr>(Init)->getSubExpr());
-  case Expr::StringLiteralClass:
-  case Expr::ObjCEncodeExprClass:
-  case Expr::ObjCStringLiteralClass:
-    return false;
-  case Expr::CallExprClass:
-  case Expr::CXXOperatorCallExprClass:
-    // __builtin___CFStringMakeConstantString is a valid constant l-value.
-    if (cast<CallExpr>(Init)->isBuiltinCall(Context) == 
-           Builtin::BI__builtin___CFStringMakeConstantString)
-      return false;
-      
-    InitializerElementNotConstant(Init);
-    return true;
-      
-  case Expr::UnaryOperatorClass: {
-    const UnaryOperator *Exp = cast<UnaryOperator>(Init);
-
-    // C99 6.6p9
-    if (Exp->getOpcode() == UnaryOperator::AddrOf)
-      return CheckAddressConstantExpressionLValue(Exp->getSubExpr());
-
-    if (Exp->getOpcode() == UnaryOperator::Extension)
-      return CheckAddressConstantExpression(Exp->getSubExpr());
-  
-    InitializerElementNotConstant(Init);
-    return true;
-  }
-  case Expr::BinaryOperatorClass: {
-    // FIXME: Should we pedwarn for expressions like "a + 1 + 2"?
-    const BinaryOperator *Exp = cast<BinaryOperator>(Init);
-
-    Expr *PExp = Exp->getLHS();
-    Expr *IExp = Exp->getRHS();
-    if (IExp->getType()->isPointerType())
-      std::swap(PExp, IExp);
-
-    // FIXME: Should we pedwarn if IExp isn't an integer constant expression?
-    return CheckAddressConstantExpression(PExp) ||
-           CheckArithmeticConstantExpression(IExp);
-  }
-  case Expr::ImplicitCastExprClass:
-  case Expr::CStyleCastExprClass: {
-    const Expr* SubExpr = cast<CastExpr>(Init)->getSubExpr();
-    if (Init->getStmtClass() == Expr::ImplicitCastExprClass) {
-      // Check for implicit promotion
-      if (SubExpr->getType()->isFunctionType() ||
-          SubExpr->getType()->isArrayType())
-        return CheckAddressConstantExpressionLValue(SubExpr);
-    }
-
-    // Check for pointer->pointer cast
-    if (SubExpr->getType()->isPointerType())
-      return CheckAddressConstantExpression(SubExpr);
-
-    if (SubExpr->getType()->isIntegralType()) {
-      // Check for the special-case of a pointer->int->pointer cast;
-      // this isn't standard, but some code requires it. See
-      // PR2720 for an example.
-      if (const CastExpr* SubCast = dyn_cast<CastExpr>(SubExpr)) {
-        if (SubCast->getSubExpr()->getType()->isPointerType()) {
-          unsigned IntWidth = Context.getIntWidth(SubCast->getType());
-          unsigned PointerWidth = Context.getTypeSize(Context.VoidPtrTy);
-          if (IntWidth >= PointerWidth) {
-            return CheckAddressConstantExpression(SubCast->getSubExpr());
-          }
-        }
-      }
-    }
-    if (SubExpr->getType()->isArithmeticType()) {
-      return CheckArithmeticConstantExpression(SubExpr);
-    }
-
-    InitializerElementNotConstant(Init);
-    return true;
-  }
-  case Expr::ConditionalOperatorClass: {
-    // FIXME: Should we pedwarn here?
-    const ConditionalOperator *Exp = cast<ConditionalOperator>(Init);
-    if (!Exp->getCond()->getType()->isArithmeticType()) {
-      InitializerElementNotConstant(Init);
-      return true;
-    }
-    if (CheckArithmeticConstantExpression(Exp->getCond()))
-      return true;
-    if (Exp->getLHS() &&
-        CheckAddressConstantExpression(Exp->getLHS()))
-      return true;
-    return CheckAddressConstantExpression(Exp->getRHS());
-  }
-  case Expr::AddrLabelExprClass:
-    return false;
-  }
-}
-
-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::CStyleCastExprClass: {
-    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:
-    InitializerElementNotConstant(Init);
-    return true;
-  case Expr::ParenExprClass: {
-    const ParenExpr* PE = cast<ParenExpr>(Init);
-    return CheckArithmeticConstantExpression(PE->getSubExpr());
-  }
-  case Expr::FloatingLiteralClass:
-  case Expr::IntegerLiteralClass:
-  case Expr::CharacterLiteralClass:
-  case Expr::ImaginaryLiteralClass:
-  case Expr::TypesCompatibleExprClass:
-  case Expr::CXXBoolLiteralExprClass:
-    return false;
-  case Expr::CallExprClass: 
-  case Expr::CXXOperatorCallExprClass: {
-    const CallExpr *CE = cast<CallExpr>(Init);
-
-    // Allow any constant foldable calls to builtins.
-    if (CE->isBuiltinCall(Context) && CE->isEvaluatable(Context))
-      return false;
-    
-    InitializerElementNotConstant(Init);
-    return true;
-  }
-  case Expr::DeclRefExprClass:
-  case Expr::QualifiedDeclRefExprClass: {
-    const Decl *D = cast<DeclRefExpr>(Init)->getDecl();
-    if (isa<EnumConstantDecl>(D))
-      return false;
-    InitializerElementNotConstant(Init);
-    return true;
-  }
-  case Expr::CompoundLiteralExprClass:
-    // Allow "(vector type){2,4}"; normal C constraints don't allow this,
-    // but vectors are allowed to be magic.
-    if (Init->getType()->isVectorType())
-      return false;
-    InitializerElementNotConstant(Init);
-    return true;
-  case Expr::UnaryOperatorClass: {
-    const UnaryOperator *Exp = cast<UnaryOperator>(Init);
-  
-    switch (Exp->getOpcode()) {
-    // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
-    // See C99 6.6p3.
-    default:
-      InitializerElementNotConstant(Init);
-      return true;
-    case UnaryOperator::OffsetOf:
-      if (Exp->getSubExpr()->getType()->isConstantSizeType())
-        return false;
-      InitializerElementNotConstant(Init);
-      return true;
-    case UnaryOperator::Extension:
-    case UnaryOperator::LNot:
-    case UnaryOperator::Plus:
-    case UnaryOperator::Minus:
-    case UnaryOperator::Not:
-      return CheckArithmeticConstantExpression(Exp->getSubExpr());
-    }
-  }
-  case Expr::SizeOfAlignOfExprClass: {
-    const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(Init);
-    // Special check for void types, which are allowed as an extension
-    if (Exp->getTypeOfArgument()->isVoidType())
-      return false;
-    // alignof always evaluates to a constant.
-    // FIXME: is sizeof(int[3.0]) a constant expression?
-    if (Exp->isSizeOf() && !Exp->getTypeOfArgument()->isConstantSizeType()) {
-      InitializerElementNotConstant(Init);
-      return true;
-    }
-    return false;
-  }
-  case Expr::BinaryOperatorClass: {
-    const BinaryOperator *Exp = cast<BinaryOperator>(Init);
-
-    if (Exp->getLHS()->getType()->isArithmeticType() &&
-        Exp->getRHS()->getType()->isArithmeticType()) {
-      return CheckArithmeticConstantExpression(Exp->getLHS()) ||
-             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());
-      }
-    }
-
-    InitializerElementNotConstant(Init);
-    return true;
-  }
-  case Expr::ImplicitCastExprClass:
-  case Expr::CStyleCastExprClass: {
-    const CastExpr *CE = cast<CastExpr>(Init);
-    const Expr *SubExpr = CE->getSubExpr();
-
-    if (SubExpr->getType()->isArithmeticType())
-      return CheckArithmeticConstantExpression(SubExpr);
-
-    if (SubExpr->getType()->isPointerType()) {
-      const Expr* Base = FindExpressionBaseAddress(SubExpr);
-      if (Base) {
-        // the cast is only valid if done to a wide enough type
-        if (Context.getTypeSize(CE->getType()) >=
-            Context.getTypeSize(SubExpr->getType()))
-          return false;
-      } else {
-        // If the pointer has a null base, this is an offsetof-like construct
-        return CheckAddressConstantExpression(SubExpr);
-      }
-    }
-
-    InitializerElementNotConstant(Init);
-    return true;
-  }
-  case Expr::ConditionalOperatorClass: {
-    const ConditionalOperator *Exp = cast<ConditionalOperator>(Init);
-    
-    // If GNU extensions are disabled, we require all operands to be arithmetic
-    // constant expressions.
-    if (getLangOptions().NoExtensions) {
-      return CheckArithmeticConstantExpression(Exp->getCond()) ||
-          (Exp->getLHS() && CheckArithmeticConstantExpression(Exp->getLHS())) ||
-             CheckArithmeticConstantExpression(Exp->getRHS());
-    }
-
-    // Otherwise, we have to emulate some of the behavior of fold here.
-    // Basically GCC treats things like "4 ? 1 : somefunc()" as a constant
-    // because it can constant fold things away.  To retain compatibility with
-    // GCC code, we see if we can fold the condition to a constant (which we
-    // should always be able to do in theory).  If so, we only require the
-    // specified arm of the conditional to be a constant.  This is a horrible
-    // hack, but is require by real world code that uses __builtin_constant_p.
-    Expr::EvalResult EvalResult;
-    if (!Exp->getCond()->Evaluate(EvalResult, Context) || 
-        EvalResult.HasSideEffects) {
-      // If Evaluate couldn't fold it, CheckArithmeticConstantExpression
-      // won't be able to either.  Use it to emit the diagnostic though.
-      bool Res = CheckArithmeticConstantExpression(Exp->getCond());
-      assert(Res && "Evaluate couldn't evaluate this constant?");
-      return Res;
-    }
-    
-    // Verify that the side following the condition is also a constant.
-    const Expr *TrueSide = Exp->getLHS(), *FalseSide = Exp->getRHS();
-    if (EvalResult.Val.getInt() == 0) 
-      std::swap(TrueSide, FalseSide);
-    
-    if (TrueSide && CheckArithmeticConstantExpression(TrueSide))
-      return true;
-      
-    // Okay, the evaluated side evaluates to a constant, so we accept this.
-    // Check to see if the other side is obviously not a constant.  If so, 
-    // emit a warning that this is a GNU extension.
-    if (FalseSide && !FalseSide->isEvaluatable(Context))
-      Diag(Init->getExprLoc(), 
-           diag::ext_typecheck_expression_not_constant_but_accepted)
-        << FalseSide->getSourceRange();
-    return false;
-  }
-  }
-}
-
 bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
   if (Init->isConstantInitializer(Context))
     return false;
-  InitializerElementNotConstant(Init);
-  return true;
-
-  if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init))
-    Init = DIE->getInit();
-
-  Init = Init->IgnoreParens();
-
-  if (Init->isEvaluatable(Context))
-    return false;
-
-  // Look through CXXDefaultArgExprs; they have no meaning in this context.
-  if (CXXDefaultArgExpr* DAE = dyn_cast<CXXDefaultArgExpr>(Init))
-    return CheckForConstantInitializer(DAE->getExpr(), DclT);
-
-  if (CompoundLiteralExpr *e = dyn_cast<CompoundLiteralExpr>(Init))
-    return CheckForConstantInitializer(e->getInitializer(), DclT);
-
-  if (isa<ImplicitValueInitExpr>(Init)) {
-    // FIXME: In C++, check for non-POD types.
-    return false;
-  }
-
-  if (InitListExpr *Exp = dyn_cast<InitListExpr>(Init)) {
-    unsigned numInits = Exp->getNumInits();
-    for (unsigned i = 0; i < numInits; i++) {
-      // FIXME: Need to get the type of the declaration for C++,
-      // because it could be a reference?
-
-      if (CheckForConstantInitializer(Exp->getInit(i),
-                                      Exp->getInit(i)->getType()))
-        return true;
-    }
-    return false;
-  }
-
-  // FIXME: We can probably remove some of this code below, now that 
-  // Expr::Evaluate is doing the heavy lifting for scalars.
-  
-  if (Init->isNullPointerConstant(Context))
-    return false;
-  if (Init->getType()->isArithmeticType()) {
-    QualType InitTy = Context.getCanonicalType(Init->getType())
-                             .getUnqualifiedType();
-    if (InitTy == Context.BoolTy) {
-      // Special handling for pointers implicitly cast to bool;
-      // (e.g. "_Bool rr = &rr;"). This is only legal at the top level.
-      if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Init)) {
-        Expr* SubE = ICE->getSubExpr();
-        if (SubE->getType()->isPointerType() ||
-            SubE->getType()->isArrayType() ||
-            SubE->getType()->isFunctionType()) {
-          return CheckAddressConstantExpression(Init);
-        }
-      }
-    } else if (InitTy->isIntegralType()) {
-      Expr* SubE = 0;
-      if (CastExpr* CE = dyn_cast<CastExpr>(Init))
-        SubE = CE->getSubExpr();
-      // Special check for pointer cast to int; we allow as an extension
-      // an address constant cast to an integer if the integer
-      // is of an appropriate width (this sort of code is apparently used
-      // in some places).
-      // FIXME: Add pedwarn?
-      // FIXME: Don't allow bitfields here!  Need the FieldDecl for that.
-      if (SubE && (SubE->getType()->isPointerType() ||
-                   SubE->getType()->isArrayType() ||
-                   SubE->getType()->isFunctionType())) {
-        unsigned IntWidth = Context.getTypeSize(Init->getType());
-        unsigned PointerWidth = Context.getTypeSize(Context.VoidPtrTy);
-        if (IntWidth >= PointerWidth)
-          return CheckAddressConstantExpression(Init);
-      }
-    }
-
-    return CheckArithmeticConstantExpression(Init);
-  }
-
-  if (Init->getType()->isPointerType())
-    return CheckAddressConstantExpression(Init);
-
-  // An array type at the top level that isn't an init-list must
-  // be a string literal
-  if (Init->getType()->isArrayType())
-    return false;
-
-  if (Init->getType()->isFunctionType())
-    return false;
-
-  // Allow block exprs at top level.
-  if (Init->getType()->isBlockPointerType())
-    return false;
-
-  // GCC cast to union extension
-  // note: the validity of the cast expr is checked by CheckCastTypes()
-  if (CastExpr *C = dyn_cast<CastExpr>(Init)) {
-    QualType T = C->getType();
-    return T->isUnionType() && CheckForConstantInitializer(C->getSubExpr(), T);
-  }
-
-  InitializerElementNotConstant(Init);
+  Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
+    << Init->getSourceRange();
   return true;
 }