diff options
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 529 |
1 files changed, 2 insertions, 527 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 981d0f9bd5..0ad3839fde 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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; } |