diff options
author | Douglas Gregor <dgregor@apple.com> | 2008-10-28 00:22:11 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2008-10-28 00:22:11 +0000 |
commit | 6b75484ba6963a748fe08ea44f11b0de89d3d0c3 (patch) | |
tree | 710bfee679d9bb468a45071ab8d3048e6291b9ea /clang/lib/AST/Expr.cpp | |
parent | 100f87d6554b5b187a90ce294d6d3d0f6604aee1 (diff) | |
download | bcm5719-llvm-6b75484ba6963a748fe08ea44f11b0de89d3d0c3.tar.gz bcm5719-llvm-6b75484ba6963a748fe08ea44f11b0de89d3d0c3.zip |
Improve our handling of (C++) references within Clang. Specifically:
- Do not allow expressions to ever have reference type
- Extend Expr::isLvalue to handle more cases where having written a
reference into the source implies that the expression is an lvalue
(e.g., function calls, C++ casts).
- Make GRExprEngine::VisitCall treat the call arguments as lvalues when
they are being bound to a reference parameter.
llvm-svn: 58306
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 1380264e0e7..f330444f1d4 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -393,6 +393,20 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { break; case ParenExprClass: // C99 6.5.1p5 return cast<ParenExpr>(this)->getSubExpr()->isLvalue(Ctx); + case CallExprClass: { + // C++ [expr.call]p10: + // A function call is an lvalue if and only if the result type + // is a reference. + QualType CalleeType + = dyn_cast<CallExpr>(this)->getCallee()->IgnoreParens()->getType(); + if (const PointerType *FnTypePtr = CalleeType->getAsPointerType()) + if (const FunctionType *FnType + = FnTypePtr->getPointeeType()->getAsFunctionType()) + if (FnType->getResultType()->isReferenceType()) + return LV_Valid; + + break; + } case CompoundLiteralExprClass: // C99 6.5.2.5p5 return LV_Valid; case ExtVectorElementExprClass: @@ -407,10 +421,25 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { return (cast<PredefinedExpr>(this)->getIdentType() == PredefinedExpr::CXXThis ? LV_InvalidExpression : LV_Valid); + case VAArgExprClass: + return LV_Valid; case CXXDefaultArgExprClass: return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx); case CXXConditionDeclExprClass: return LV_Valid; + case ExplicitCCastExprClass: + 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 a 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()->isReferenceType()) + return LV_Valid; + break; default: break; } |