summaryrefslogtreecommitdiffstats
path: root/lib/AST/Expr.cpp
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-07-13 17:21:42 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-07-13 17:21:42 +0000
commit1928da94b55683957759d5c5ff4593a118773394 (patch)
tree48b44512b5db8ced345df4a1a56b5065cf2a14d9 /lib/AST/Expr.cpp
parent53992adde3eda3ccf9da63bc7e45673f043de18f (diff)
downloadFreeBSD-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.cpp427
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;
OpenPOWER on IntegriCloud