aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp529
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;
}