diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-07-13 17:21:42 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-07-13 17:21:42 +0000 |
commit | 1928da94b55683957759d5c5ff4593a118773394 (patch) | |
tree | 48b44512b5db8ced345df4a1a56b5065cf2a14d9 /lib/AST/Expr.cpp | |
parent | 53992adde3eda3ccf9da63bc7e45673f043de18f (diff) | |
download | FreeBSD-src-1928da94b55683957759d5c5ff4593a118773394.zip FreeBSD-src-1928da94b55683957759d5c5ff4593a118773394.tar.gz |
Update clang to r108243.
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r-- | lib/AST/Expr.cpp | 427 |
1 files changed, 42 insertions, 385 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index c38cec3..bd97b88 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -37,7 +37,7 @@ bool Expr::isKnownToHaveBooleanValue() const { // If this value has _Bool type, it is obvious 0/1. if (getType()->isBooleanType()) return true; // If this is a non-scalar-integer type, we don't care enough to try. - if (!getType()->isIntegralType()) return false; + if (!getType()->isIntegralOrEnumerationType()) return false; if (const ParenExpr *PE = dyn_cast<ParenExpr>(this)) return PE->getSubExpr()->isKnownToHaveBooleanValue(); @@ -52,7 +52,9 @@ bool Expr::isKnownToHaveBooleanValue() const { } } - if (const CastExpr *CE = dyn_cast<CastExpr>(this)) + // Only look through implicit casts. If the user writes + // '(int) (a && b)' treat it as an arbitrary int. + if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(this)) return CE->getSubExpr()->isKnownToHaveBooleanValue(); if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(this)) { @@ -111,10 +113,14 @@ void ExplicitTemplateArgumentList::copyInto( Info.addArgument(getTemplateArgs()[I]); } +std::size_t ExplicitTemplateArgumentList::sizeFor(unsigned NumTemplateArgs) { + return sizeof(ExplicitTemplateArgumentList) + + sizeof(TemplateArgumentLoc) * NumTemplateArgs; +} + std::size_t ExplicitTemplateArgumentList::sizeFor( const TemplateArgumentListInfo &Info) { - return sizeof(ExplicitTemplateArgumentList) + - sizeof(TemplateArgumentLoc) * Info.size(); + return sizeFor(Info.size()); } void DeclRefExpr::computeDependence() { @@ -158,7 +164,7 @@ void DeclRefExpr::computeDependence() { // (VD) - a constant with integral or enumeration type and is // initialized with an expression that is value-dependent. else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { - if (Var->getType()->isIntegralType() && + if (Var->getType()->isIntegralOrEnumerationType() && Var->getType().getCVRQualifiers() == Qualifiers::Const) { if (const Expr *Init = Var->getAnyInitializer()) if (Init->isValueDependent()) @@ -222,6 +228,19 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, TemplateArgs, T); } +DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier, + unsigned NumTemplateArgs) { + std::size_t Size = sizeof(DeclRefExpr); + if (HasQualifier) + Size += sizeof(NameQualifier); + + if (NumTemplateArgs) + Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); + + void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>()); + return new (Mem) DeclRefExpr(EmptyShell()); +} + SourceRange DeclRefExpr::getSourceRange() const { // FIXME: Does not handle multi-token names well, e.g., operator[]. SourceRange R(Loc); @@ -557,7 +576,10 @@ QualType CallExpr::getCallReturnType() const { CalleeType = FnTypePtr->getPointeeType(); else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>()) CalleeType = BPT->getPointeeType(); - + else if (const MemberPointerType *MPT + = CalleeType->getAs<MemberPointerType>()) + CalleeType = MPT->getPointeeType(); + const FunctionType *FnType = CalleeType->getAs<FunctionType>(); return FnType->getResultType(); } @@ -968,7 +990,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, switch (BO->getOpcode()) { default: break; - // Consider ',', '||', '&&' to have side effects if the LHS or RHS does. + // Consider the RHS of comma for side effects. LHS was checked by + // Sema::CheckCommaOperands. case BinaryOperator::Comma: // ((foo = <blah>), 0) is an idiom for hiding the result (and // lvalue-ness) of an assignment written in a macro. @@ -976,10 +999,14 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, dyn_cast<IntegerLiteral>(BO->getRHS()->IgnoreParens())) if (IE->getValue() == 0) return false; + return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx); + // Consider '||', '&&' to have side effects if the LHS or RHS does. case BinaryOperator::LAnd: case BinaryOperator::LOr: - return (BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) || - BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); + if (!BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) || + !BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx)) + return false; + break; } if (BO->isAssignmentOp()) return false; @@ -1140,378 +1167,6 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, } } -/// DeclCanBeLvalue - Determine whether the given declaration can be -/// an lvalue. This is a helper routine for isLvalue. -static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) { - // C++ [temp.param]p6: - // A non-type non-reference template-parameter is not an lvalue. - if (const NonTypeTemplateParmDecl *NTTParm - = dyn_cast<NonTypeTemplateParmDecl>(Decl)) - return NTTParm->getType()->isReferenceType(); - - return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) || - // C++ 3.10p2: An lvalue refers to an object or function. - (Ctx.getLangOptions().CPlusPlus && - (isa<FunctionDecl>(Decl) || isa<FunctionTemplateDecl>(Decl))); -} - -/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or an -/// incomplete type other than void. Nonarray expressions that can be lvalues: -/// - name, where name must be a variable -/// - e[i] -/// - (e), where e must be an lvalue -/// - e.name, where e must be an lvalue -/// - e->name -/// - *e, the type of e cannot be a function type -/// - string-constant -/// - (__real__ e) and (__imag__ e) where e is an lvalue [GNU extension] -/// - reference type [C++ [expr]] -/// -Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { - assert(!TR->isReferenceType() && "Expressions can't have reference type."); - - isLvalueResult Res = isLvalueInternal(Ctx); - if (Res != LV_Valid || Ctx.getLangOptions().CPlusPlus) - return Res; - - // first, check the type (C99 6.3.2.1). Expressions with function - // type in C are not lvalues, but they can be lvalues in C++. - if (TR->isFunctionType() || TR == Ctx.OverloadTy) - return LV_NotObjectType; - - // Allow qualified void which is an incomplete type other than void (yuck). - if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers()) - return LV_IncompleteVoidType; - - return LV_Valid; -} - -// Check whether the expression can be sanely treated like an l-value -Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const { - switch (getStmtClass()) { - case ObjCIsaExprClass: - case StringLiteralClass: // C99 6.5.1p4 - case ObjCEncodeExprClass: // @encode behaves like its string in every way. - return LV_Valid; - case ArraySubscriptExprClass: // C99 6.5.3p4 (e1[e2] == (*((e1)+(e2)))) - // For vectors, make sure base is an lvalue (i.e. not a function call). - if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType()) - return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx); - return LV_Valid; - case DeclRefExprClass: { // C99 6.5.1p2 - const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl(); - if (DeclCanBeLvalue(RefdDecl, Ctx)) - return LV_Valid; - break; - } - case BlockDeclRefExprClass: { - const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(this); - if (isa<VarDecl>(BDR->getDecl())) - return LV_Valid; - break; - } - case MemberExprClass: { - const MemberExpr *m = cast<MemberExpr>(this); - if (Ctx.getLangOptions().CPlusPlus) { // C++ [expr.ref]p4: - NamedDecl *Member = m->getMemberDecl(); - // C++ [expr.ref]p4: - // If E2 is declared to have type "reference to T", then E1.E2 - // is an lvalue. - if (ValueDecl *Value = dyn_cast<ValueDecl>(Member)) - if (Value->getType()->isReferenceType()) - return LV_Valid; - - // -- If E2 is a static data member [...] then E1.E2 is an lvalue. - if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord()) - return LV_Valid; - - // -- If E2 is a non-static data member [...]. If E1 is an - // lvalue, then E1.E2 is an lvalue. - if (isa<FieldDecl>(Member)) { - if (m->isArrow()) - return LV_Valid; - return m->getBase()->isLvalue(Ctx); - } - - // -- If it refers to a static member function [...], then - // E1.E2 is an lvalue. - // -- Otherwise, if E1.E2 refers to a non-static member - // function [...], then E1.E2 is not an lvalue. - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) - return Method->isStatic()? LV_Valid : LV_MemberFunction; - - // -- If E2 is a member enumerator [...], the expression E1.E2 - // is not an lvalue. - if (isa<EnumConstantDecl>(Member)) - return LV_InvalidExpression; - - // Not an lvalue. - return LV_InvalidExpression; - } - - // C99 6.5.2.3p4 - if (m->isArrow()) - return LV_Valid; - Expr *BaseExp = m->getBase(); - if (BaseExp->getStmtClass() == ObjCPropertyRefExprClass || - BaseExp->getStmtClass() == ObjCImplicitSetterGetterRefExprClass) - return LV_SubObjCPropertySetting; - return - BaseExp->isLvalue(Ctx); - } - case UnaryOperatorClass: - if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Deref) - return LV_Valid; // C99 6.5.3p4 - - if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Real || - cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Imag || - cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Extension) - return cast<UnaryOperator>(this)->getSubExpr()->isLvalue(Ctx); // GNU. - - if (Ctx.getLangOptions().CPlusPlus && // C++ [expr.pre.incr]p1 - (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::PreInc || - cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::PreDec)) - return LV_Valid; - break; - case ImplicitCastExprClass: - if (cast<ImplicitCastExpr>(this)->isLvalueCast()) - return LV_Valid; - - // If this is a conversion to a class temporary, make a note of - // that. - if (Ctx.getLangOptions().CPlusPlus && getType()->isRecordType()) - return LV_ClassTemporary; - - break; - case ParenExprClass: // C99 6.5.1p5 - return cast<ParenExpr>(this)->getSubExpr()->isLvalue(Ctx); - case BinaryOperatorClass: - case CompoundAssignOperatorClass: { - const BinaryOperator *BinOp = cast<BinaryOperator>(this); - - if (Ctx.getLangOptions().CPlusPlus && // C++ [expr.comma]p1 - BinOp->getOpcode() == BinaryOperator::Comma) - return BinOp->getRHS()->isLvalue(Ctx); - - // C++ [expr.mptr.oper]p6 - // The result of a .* expression is an lvalue only if its first operand is - // an lvalue and its second operand is a pointer to data member. - if (BinOp->getOpcode() == BinaryOperator::PtrMemD && - !BinOp->getType()->isFunctionType()) - return BinOp->getLHS()->isLvalue(Ctx); - - // The result of an ->* expression is an lvalue only if its second operand - // is a pointer to data member. - if (BinOp->getOpcode() == BinaryOperator::PtrMemI && - !BinOp->getType()->isFunctionType()) { - QualType Ty = BinOp->getRHS()->getType(); - if (Ty->isMemberPointerType() && !Ty->isMemberFunctionPointerType()) - return LV_Valid; - } - - if (!BinOp->isAssignmentOp()) - return LV_InvalidExpression; - - if (Ctx.getLangOptions().CPlusPlus) - // C++ [expr.ass]p1: - // The result of an assignment operation [...] is an lvalue. - return LV_Valid; - - - // C99 6.5.16: - // An assignment expression [...] is not an lvalue. - return LV_InvalidExpression; - } - case CallExprClass: - case CXXOperatorCallExprClass: - case CXXMemberCallExprClass: { - // C++0x [expr.call]p10 - // A function call is an lvalue if and only if the result type - // is an lvalue reference. - QualType ReturnType = cast<CallExpr>(this)->getCallReturnType(); - if (ReturnType->isLValueReferenceType()) - return LV_Valid; - - // If the function is returning a class temporary, make a note of - // that. - if (Ctx.getLangOptions().CPlusPlus && ReturnType->isRecordType()) - return LV_ClassTemporary; - - break; - } - case CompoundLiteralExprClass: // C99 6.5.2.5p5 - // FIXME: Is this what we want in C++? - return LV_Valid; - case ChooseExprClass: - // __builtin_choose_expr is an lvalue if the selected operand is. - return cast<ChooseExpr>(this)->getChosenSubExpr(Ctx)->isLvalue(Ctx); - case ExtVectorElementExprClass: - if (cast<ExtVectorElementExpr>(this)->containsDuplicateElements()) - return LV_DuplicateVectorComponents; - return LV_Valid; - case ObjCIvarRefExprClass: // ObjC instance variables are lvalues. - return LV_Valid; - case ObjCPropertyRefExprClass: // FIXME: check if read-only property. - return LV_Valid; - case ObjCImplicitSetterGetterRefExprClass: - // FIXME: check if read-only property. - return LV_Valid; - case PredefinedExprClass: - return LV_Valid; - case UnresolvedLookupExprClass: - case UnresolvedMemberExprClass: - return LV_Valid; - case CXXDefaultArgExprClass: - return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx); - case CStyleCastExprClass: - case CXXFunctionalCastExprClass: - case CXXStaticCastExprClass: - case CXXDynamicCastExprClass: - case CXXReinterpretCastExprClass: - case CXXConstCastExprClass: - // The result of an explicit cast is an lvalue if the type we are - // casting to is an lvalue reference type. See C++ [expr.cast]p1, - // C++ [expr.static.cast]p2, C++ [expr.dynamic.cast]p2, - // C++ [expr.reinterpret.cast]p1, C++ [expr.const.cast]p1. - if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()-> - isLValueReferenceType()) - return LV_Valid; - - // If this is a conversion to a class temporary, make a note of - // that. - if (Ctx.getLangOptions().CPlusPlus && - cast<ExplicitCastExpr>(this)->getTypeAsWritten()->isRecordType()) - return LV_ClassTemporary; - - break; - case CXXTypeidExprClass: - // C++ 5.2.8p1: The result of a typeid expression is an lvalue of ... - return LV_Valid; - case CXXBindTemporaryExprClass: - return cast<CXXBindTemporaryExpr>(this)->getSubExpr()-> - isLvalueInternal(Ctx); - case CXXBindReferenceExprClass: - // Something that's bound to a reference is always an lvalue. - return LV_Valid; - case ConditionalOperatorClass: { - // Complicated handling is only for C++. - if (!Ctx.getLangOptions().CPlusPlus) - return LV_InvalidExpression; - - // Sema should have taken care to ensure that a CXXTemporaryObjectExpr is - // everywhere there's an object converted to an rvalue. Also, any other - // casts should be wrapped by ImplicitCastExprs. There's just the special - // case involving throws to work out. - const ConditionalOperator *Cond = cast<ConditionalOperator>(this); - Expr *True = Cond->getTrueExpr(); - Expr *False = Cond->getFalseExpr(); - // C++0x 5.16p2 - // If either the second or the third operand has type (cv) void, [...] - // the result [...] is an rvalue. - if (True->getType()->isVoidType() || False->getType()->isVoidType()) - return LV_InvalidExpression; - - // Both sides must be lvalues for the result to be an lvalue. - if (True->isLvalue(Ctx) != LV_Valid || False->isLvalue(Ctx) != LV_Valid) - return LV_InvalidExpression; - - // That's it. - return LV_Valid; - } - - case Expr::CXXExprWithTemporariesClass: - return cast<CXXExprWithTemporaries>(this)->getSubExpr()->isLvalue(Ctx); - - case Expr::ObjCMessageExprClass: - if (const ObjCMethodDecl *Method - = cast<ObjCMessageExpr>(this)->getMethodDecl()) - if (Method->getResultType()->isLValueReferenceType()) - return LV_Valid; - break; - - case Expr::CXXConstructExprClass: - case Expr::CXXTemporaryObjectExprClass: - case Expr::CXXZeroInitValueExprClass: - return LV_ClassTemporary; - - default: - break; - } - return LV_InvalidExpression; -} - -/// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, -/// does not have an incomplete type, does not have a const-qualified type, and -/// if it is a structure or union, does not have any member (including, -/// recursively, any member or element of all contained aggregates or unions) -/// with a const-qualified type. -Expr::isModifiableLvalueResult -Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { - isLvalueResult lvalResult = isLvalue(Ctx); - - switch (lvalResult) { - case LV_Valid: - // C++ 3.10p11: Functions cannot be modified, but pointers to - // functions can be modifiable. - if (Ctx.getLangOptions().CPlusPlus && TR->isFunctionType()) - return MLV_NotObjectType; - break; - - case LV_NotObjectType: return MLV_NotObjectType; - case LV_IncompleteVoidType: return MLV_IncompleteVoidType; - case LV_DuplicateVectorComponents: return MLV_DuplicateVectorComponents; - case LV_InvalidExpression: - // If the top level is a C-style cast, and the subexpression is a valid - // lvalue, then this is probably a use of the old-school "cast as lvalue" - // GCC extension. We don't support it, but we want to produce good - // diagnostics when it happens so that the user knows why. - if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(IgnoreParens())) { - if (CE->getSubExpr()->isLvalue(Ctx) == LV_Valid) { - if (Loc) - *Loc = CE->getLParenLoc(); - return MLV_LValueCast; - } - } - return MLV_InvalidExpression; - case LV_MemberFunction: return MLV_MemberFunction; - case LV_SubObjCPropertySetting: return MLV_SubObjCPropertySetting; - case LV_ClassTemporary: - return MLV_ClassTemporary; - } - - // The following is illegal: - // void takeclosure(void (^C)(void)); - // void func() { int x = 1; takeclosure(^{ x = 7; }); } - // - if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(this)) { - if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl())) - return MLV_NotBlockQualified; - } - - // Assigning to an 'implicit' property? - if (const ObjCImplicitSetterGetterRefExpr* Expr = - dyn_cast<ObjCImplicitSetterGetterRefExpr>(this)) { - if (Expr->getSetterMethod() == 0) - return MLV_NoSetterProperty; - } - - QualType CT = Ctx.getCanonicalType(getType()); - - if (CT.isConstQualified()) - return MLV_ConstQualified; - if (CT->isArrayType()) - return MLV_ArrayType; - if (CT->isIncompleteType()) - return MLV_IncompleteType; - - if (const RecordType *r = CT->getAs<RecordType>()) { - if (r->hasConstFields()) - return MLV_ConstQualified; - } - - return MLV_Valid; -} - /// isOBJCGCCandidate - Check if an expression is objc gc'able. /// returns true, if it is; false otherwise. bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { @@ -1596,7 +1251,7 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { if (CastExpr *P = dyn_cast<CastExpr>(E)) { // We ignore integer <-> casts that are of the same width, ptr<->ptr and - // ptr<->int casts of the same width. We also ignore all identify casts. + // ptr<->int casts of the same width. We also ignore all identity casts. Expr *SE = P->getSubExpr(); if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) { @@ -1604,8 +1259,10 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { continue; } - if ((E->getType()->isPointerType() || E->getType()->isIntegralType()) && - (SE->getType()->isPointerType() || SE->getType()->isIntegralType()) && + if ((E->getType()->isPointerType() || + E->getType()->isIntegralType(Ctx)) && + (SE->getType()->isPointerType() || + SE->getType()->isIntegralType(Ctx)) && Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) { E = SE; continue; @@ -1795,7 +1452,7 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx, // If the unthinkable happens, fall through to the safest alternative. case NPC_ValueDependentIsNull: - return isTypeDependent() || getType()->isIntegralType(); + return isTypeDependent() || getType()->isIntegralType(Ctx); case NPC_ValueDependentIsNotNull: return false; |