2007-08-25 04:21:10 +08:00
|
|
|
//===--- ExprCXX.cpp - (C++) Expression AST Node Implementation -----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-08-25 04:21:10 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the subclesses of Expr class declared in ExprCXX.h
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-11-15 00:09:21 +08:00
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
2007-08-25 04:21:10 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
|
|
|
using namespace clang;
|
|
|
|
|
2008-09-10 10:14:49 +08:00
|
|
|
void CXXConditionDeclExpr::Destroy(ASTContext& C) {
|
2009-02-05 23:12:41 +08:00
|
|
|
// FIXME: Cannot destroy the decl here, because it is linked into the
|
|
|
|
// DeclContext's chain.
|
|
|
|
//getVarDecl()->Destroy(C);
|
2009-02-07 09:47:29 +08:00
|
|
|
this->~CXXConditionDeclExpr();
|
|
|
|
C.Deallocate(this);
|
2008-09-10 10:14:49 +08:00
|
|
|
}
|
2008-09-10 07:47:53 +08:00
|
|
|
|
2007-08-25 04:21:10 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Child Iterators for iterating over subexpressions/substatements
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-11-11 19:37:55 +08:00
|
|
|
// CXXTypeidExpr - has child iterators if the operand is an expression
|
|
|
|
Stmt::child_iterator CXXTypeidExpr::child_begin() {
|
2008-12-04 07:17:54 +08:00
|
|
|
return isTypeOperand() ? child_iterator() : &Operand.Ex;
|
2008-11-11 19:37:55 +08:00
|
|
|
}
|
|
|
|
Stmt::child_iterator CXXTypeidExpr::child_end() {
|
2008-12-04 07:17:54 +08:00
|
|
|
return isTypeOperand() ? child_iterator() : &Operand.Ex+1;
|
2008-11-11 19:37:55 +08:00
|
|
|
}
|
2007-08-25 04:21:10 +08:00
|
|
|
|
|
|
|
// CXXBoolLiteralExpr
|
2007-10-19 07:28:49 +08:00
|
|
|
Stmt::child_iterator CXXBoolLiteralExpr::child_begin() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
|
|
|
Stmt::child_iterator CXXBoolLiteralExpr::child_end() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
2008-02-26 08:51:44 +08:00
|
|
|
|
2008-11-04 22:32:21 +08:00
|
|
|
// CXXThisExpr
|
|
|
|
Stmt::child_iterator CXXThisExpr::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator CXXThisExpr::child_end() { return child_iterator(); }
|
|
|
|
|
2008-02-26 08:51:44 +08:00
|
|
|
// CXXThrowExpr
|
2008-06-17 11:11:08 +08:00
|
|
|
Stmt::child_iterator CXXThrowExpr::child_begin() { return &Op; }
|
2008-02-26 08:51:44 +08:00
|
|
|
Stmt::child_iterator CXXThrowExpr::child_end() {
|
|
|
|
// If Op is 0, we are processing throw; which has no children.
|
2008-06-17 11:11:08 +08:00
|
|
|
return Op ? &Op+1 : &Op;
|
2008-02-26 08:51:44 +08:00
|
|
|
}
|
2008-04-08 12:40:51 +08:00
|
|
|
|
|
|
|
// CXXDefaultArgExpr
|
|
|
|
Stmt::child_iterator CXXDefaultArgExpr::child_begin() {
|
2008-04-10 10:22:51 +08:00
|
|
|
return child_iterator();
|
2008-04-08 12:40:51 +08:00
|
|
|
}
|
|
|
|
Stmt::child_iterator CXXDefaultArgExpr::child_end() {
|
2008-04-10 10:22:51 +08:00
|
|
|
return child_iterator();
|
2008-04-08 12:40:51 +08:00
|
|
|
}
|
2008-08-22 23:38:55 +08:00
|
|
|
|
2009-01-17 02:33:17 +08:00
|
|
|
// CXXTemporaryObjectExpr
|
|
|
|
Stmt::child_iterator CXXTemporaryObjectExpr::child_begin() {
|
|
|
|
return child_iterator(Args);
|
|
|
|
}
|
|
|
|
Stmt::child_iterator CXXTemporaryObjectExpr::child_end() {
|
|
|
|
return child_iterator(Args + NumArgs);
|
|
|
|
}
|
|
|
|
|
2008-08-22 23:38:55 +08:00
|
|
|
// CXXZeroInitValueExpr
|
|
|
|
Stmt::child_iterator CXXZeroInitValueExpr::child_begin() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
|
|
|
Stmt::child_iterator CXXZeroInitValueExpr::child_end() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
2008-09-10 07:47:53 +08:00
|
|
|
|
|
|
|
// CXXConditionDeclExpr
|
|
|
|
Stmt::child_iterator CXXConditionDeclExpr::child_begin() {
|
|
|
|
return getVarDecl();
|
|
|
|
}
|
|
|
|
Stmt::child_iterator CXXConditionDeclExpr::child_end() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
2008-10-28 03:41:14 +08:00
|
|
|
|
2008-11-22 03:14:01 +08:00
|
|
|
// CXXNewExpr
|
|
|
|
CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew,
|
|
|
|
Expr **placementArgs, unsigned numPlaceArgs,
|
2008-12-02 22:43:59 +08:00
|
|
|
bool parenTypeId, Expr *arraySize,
|
2008-11-22 03:14:01 +08:00
|
|
|
CXXConstructorDecl *constructor, bool initializer,
|
|
|
|
Expr **constructorArgs, unsigned numConsArgs,
|
|
|
|
FunctionDecl *operatorDelete, QualType ty,
|
|
|
|
SourceLocation startLoc, SourceLocation endLoc)
|
|
|
|
: Expr(CXXNewExprClass, ty), GlobalNew(globalNew), ParenTypeId(parenTypeId),
|
2008-12-02 22:43:59 +08:00
|
|
|
Initializer(initializer), Array(arraySize), NumPlacementArgs(numPlaceArgs),
|
2008-11-22 03:14:01 +08:00
|
|
|
NumConstructorArgs(numConsArgs), OperatorNew(operatorNew),
|
2008-12-02 22:43:59 +08:00
|
|
|
OperatorDelete(operatorDelete), Constructor(constructor),
|
2008-11-22 03:14:01 +08:00
|
|
|
StartLoc(startLoc), EndLoc(endLoc)
|
|
|
|
{
|
2008-12-02 22:43:59 +08:00
|
|
|
unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs;
|
2008-11-22 03:14:01 +08:00
|
|
|
SubExprs = new Stmt*[TotalSize];
|
|
|
|
unsigned i = 0;
|
2008-12-02 22:43:59 +08:00
|
|
|
if (Array)
|
|
|
|
SubExprs[i++] = arraySize;
|
|
|
|
for (unsigned j = 0; j < NumPlacementArgs; ++j)
|
2008-11-22 03:14:01 +08:00
|
|
|
SubExprs[i++] = placementArgs[j];
|
2008-12-02 22:43:59 +08:00
|
|
|
for (unsigned j = 0; j < NumConstructorArgs; ++j)
|
2008-11-22 03:14:01 +08:00
|
|
|
SubExprs[i++] = constructorArgs[j];
|
|
|
|
assert(i == TotalSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; }
|
|
|
|
Stmt::child_iterator CXXNewExpr::child_end() {
|
2008-12-02 22:43:59 +08:00
|
|
|
return &SubExprs[0] + Array + getNumPlacementArgs() + getNumConstructorArgs();
|
2008-11-22 03:14:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// CXXDeleteExpr
|
|
|
|
Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; }
|
|
|
|
Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; }
|
|
|
|
|
2009-02-04 23:01:18 +08:00
|
|
|
// UnresolvedFunctionNameExpr
|
|
|
|
Stmt::child_iterator UnresolvedFunctionNameExpr::child_begin() {
|
2008-12-06 08:22:45 +08:00
|
|
|
return child_iterator();
|
|
|
|
}
|
2009-02-04 23:01:18 +08:00
|
|
|
Stmt::child_iterator UnresolvedFunctionNameExpr::child_end() {
|
2008-12-06 08:22:45 +08:00
|
|
|
return child_iterator();
|
|
|
|
}
|
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
// UnaryTypeTraitExpr
|
|
|
|
Stmt::child_iterator UnaryTypeTraitExpr::child_begin() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
|
|
|
Stmt::child_iterator UnaryTypeTraitExpr::child_end() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool UnaryTypeTraitExpr::Evaluate() const {
|
|
|
|
switch(UTT) {
|
|
|
|
default: assert(false && "Unknown type trait or not implemented");
|
|
|
|
case UTT_IsPOD: return QueriedType->isPODType();
|
|
|
|
case UTT_IsClass: // Fallthrough
|
|
|
|
case UTT_IsUnion:
|
|
|
|
if (const RecordType *Record = QueriedType->getAsRecordType()) {
|
|
|
|
bool Union = Record->getDecl()->isUnion();
|
|
|
|
return UTT == UTT_IsUnion ? Union : !Union;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
case UTT_IsEnum: return QueriedType->isEnumeralType();
|
|
|
|
case UTT_IsPolymorphic:
|
|
|
|
if (const RecordType *Record = QueriedType->getAsRecordType()) {
|
|
|
|
// Type traits are only parsed in C++, so we've got CXXRecords.
|
|
|
|
return cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-15 00:09:21 +08:00
|
|
|
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()))
|
Extend DeclarationName to support C++ overloaded operators, e.g.,
operator+, directly, using the same mechanism as all other special
names.
Removed the "special" identifiers for the overloaded operators from
the identifier table and IdentifierInfo data structure. IdentifierInfo
is back to representing only real identifiers.
Added a new Action, ActOnOperatorFunctionIdExpr, that builds an
expression from an parsed operator-function-id (e.g., "operator
+"). ActOnIdentifierExpr used to do this job, but
operator-function-ids are no longer represented by IdentifierInfo's.
Extended Declarator to store overloaded operator names.
Sema::GetNameForDeclarator now knows how to turn the operator
name into a DeclarationName for the overloaded operator.
Except for (perhaps) consolidating the functionality of
ActOnIdentifier, ActOnOperatorFunctionIdExpr, and
ActOnConversionFunctionExpr into a common routine that builds an
appropriate DeclRefExpr by looking up a DeclarationName, all of the
work on normalizing declaration names should be complete with this
commit.
llvm-svn: 59526
2008-11-18 22:39:36 +08:00
|
|
|
return FDecl->getDeclName().getCXXOverloadedOperator();
|
2008-11-15 00:09:21 +08:00
|
|
|
else if (const OverloadedFunctionDecl *Ovl
|
|
|
|
= dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()))
|
Extend DeclarationName to support C++ overloaded operators, e.g.,
operator+, directly, using the same mechanism as all other special
names.
Removed the "special" identifiers for the overloaded operators from
the identifier table and IdentifierInfo data structure. IdentifierInfo
is back to representing only real identifiers.
Added a new Action, ActOnOperatorFunctionIdExpr, that builds an
expression from an parsed operator-function-id (e.g., "operator
+"). ActOnIdentifierExpr used to do this job, but
operator-function-ids are no longer represented by IdentifierInfo's.
Extended Declarator to store overloaded operator names.
Sema::GetNameForDeclarator now knows how to turn the operator
name into a DeclarationName for the overloaded operator.
Except for (perhaps) consolidating the functionality of
ActOnIdentifier, ActOnOperatorFunctionIdExpr, and
ActOnConversionFunctionExpr into a common routine that builds an
appropriate DeclRefExpr by looking up a DeclarationName, all of the
work on normalizing declaration names should be complete with this
commit.
llvm-svn: 59526
2008-11-18 22:39:36 +08:00
|
|
|
return Ovl->getDeclName().getCXXOverloadedOperator();
|
2008-11-15 00:09:21 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-22 13:46:06 +08:00
|
|
|
Expr *CXXMemberCallExpr::getImplicitObjectArgument() {
|
|
|
|
if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(getCallee()->IgnoreParens()))
|
|
|
|
return MemExpr->getBase();
|
|
|
|
|
|
|
|
// FIXME: Will eventually need to cope with member pointers.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-10-28 03:41:14 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Named casts
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// getCastName - Get the name of the C++ cast being used, e.g.,
|
|
|
|
/// "static_cast", "dynamic_cast", "reinterpret_cast", or
|
|
|
|
/// "const_cast". The returned pointer must not be freed.
|
|
|
|
const char *CXXNamedCastExpr::getCastName() const {
|
|
|
|
switch (getStmtClass()) {
|
|
|
|
case CXXStaticCastExprClass: return "static_cast";
|
|
|
|
case CXXDynamicCastExprClass: return "dynamic_cast";
|
|
|
|
case CXXReinterpretCastExprClass: return "reinterpret_cast";
|
|
|
|
case CXXConstCastExprClass: return "const_cast";
|
|
|
|
default: return "<invalid cast>";
|
|
|
|
}
|
|
|
|
}
|
2009-01-17 02:33:17 +08:00
|
|
|
|
|
|
|
CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(CXXConstructorDecl *Cons,
|
|
|
|
QualType writtenTy,
|
|
|
|
SourceLocation tyBeginLoc,
|
|
|
|
Expr **Args,
|
|
|
|
unsigned NumArgs,
|
|
|
|
SourceLocation rParenLoc)
|
|
|
|
: Expr(CXXTemporaryObjectExprClass, writtenTy),
|
|
|
|
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc),
|
|
|
|
Constructor(Cons), Args(0), NumArgs(NumArgs) {
|
|
|
|
if (NumArgs > 0) {
|
|
|
|
this->Args = new Stmt*[NumArgs];
|
|
|
|
for (unsigned i = 0; i < NumArgs; ++i)
|
|
|
|
this->Args[i] = Args[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CXXTemporaryObjectExpr::~CXXTemporaryObjectExpr() {
|
|
|
|
delete [] Args;
|
|
|
|
}
|