[cfe-commits] r65502 - in /cfe/trunk/lib/Sema: Sema.h SemaDecl.cpp
Eli Friedman
eli.friedman at gmail.com
Wed Feb 25 20:47:59 PST 2009
Author: efriedma
Date: Wed Feb 25 22:47:58 2009
New Revision: 65502
URL: http://llvm.org/viewvc/llvm-project?rev=65502&view=rev
Log:
Zap the Sema constant initializer checking code that we aren't using
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.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=65502&r1=65501&r2=65502&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb 25 22:47:58 2009
@@ -1909,10 +1909,6 @@
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);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=65502&r1=65501&r2=65502&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 25 22:47:58 2009
@@ -2019,536 +2019,11 @@
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;
}
More information about the cfe-commits
mailing list