aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprCXX.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2008-11-14 16:09:21 +0000
committerDouglas Gregor <dgregor@apple.com>2008-11-14 16:09:21 +0000
commitb4609806e9232593ece09ce08b630836e825865c (patch)
tree7b70b5d015a0fd6fbf2907a5a0a12596f2760823 /lib/AST/ExprCXX.cpp
parent0aab796da21bfc45381d3ce76c795710cb97acfc (diff)
Add a new expression node, CXXOperatorCallExpr, which expresses a
function call created in response to the use of operator syntax that resolves to an overloaded operator in C++, e.g., "str1 + str2" that resolves to std::operator+(str1, str2)". We now build a CXXOperatorCallExpr in C++ when we pick an overloaded operator. (But only for binary operators, where we actually implement overloading) I decided *not* to refactor the current CallExpr to make it abstract (with FunctionCallExpr and CXXOperatorCallExpr as derived classes). Doing so would allow us to make CXXOperatorCallExpr a little bit smaller, at the cost of making the argument and callee accessors virtual. We won't know if this is going to be a win until we can parse lots of C++ code to determine how much memory we'll save by making this change vs. the performance penalty due to the extra virtual calls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59306 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprCXX.cpp')
-rw-r--r--lib/AST/ExprCXX.cpp48
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index ff97e688b8..22f30f451e 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
using namespace clang;
@@ -75,6 +77,52 @@ Stmt::child_iterator CXXConditionDeclExpr::child_end() {
return child_iterator();
}
+OverloadedOperatorKind CXXOperatorCallExpr::getOperator() const {
+ // All simple function calls (e.g. func()) are implicitly cast to pointer to
+ // function. As a result, we try and obtain the DeclRefExpr from the
+ // ImplicitCastExpr.
+ const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee());
+ if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()).
+ return OO_None;
+
+ const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
+ if (!DRE)
+ return OO_None;
+
+ if (const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()))
+ return FDecl->getIdentifier()->getOverloadedOperatorID();
+ else if (const OverloadedFunctionDecl *Ovl
+ = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()))
+ return Ovl->getIdentifier()->getOverloadedOperatorID();
+ else
+ return OO_None;
+}
+
+SourceRange CXXOperatorCallExpr::getSourceRange() const {
+ OverloadedOperatorKind Kind = getOperator();
+ if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
+ if (getNumArgs() == 1)
+ // Prefix operator
+ return SourceRange(getOperatorLoc(),
+ getArg(0)->getSourceRange().getEnd());
+ else
+ // Postfix operator
+ return SourceRange(getArg(0)->getSourceRange().getEnd(),
+ getOperatorLoc());
+ } else if (Kind == OO_Call) {
+ return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc());
+ } else if (Kind == OO_Subscript) {
+ return SourceRange(getArg(0)->getSourceRange().getBegin(), getRParenLoc());
+ } else if (getNumArgs() == 1) {
+ return SourceRange(getOperatorLoc(), getArg(0)->getSourceRange().getEnd());
+ } else if (getNumArgs() == 2) {
+ return SourceRange(getArg(0)->getSourceRange().getBegin(),
+ getArg(1)->getSourceRange().getEnd());
+ } else {
+ return SourceRange();
+ }
+}
+
//===----------------------------------------------------------------------===//
// Named casts
//===----------------------------------------------------------------------===//