2007-07-11 21:01:13 +04:00
|
|
|
//===--- Expr.cpp - Expression AST Node Implementation --------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 22:59:25 +03:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-07-11 21:01:13 +04:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the Expr class and subclasses.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-08-11 09:35:13 +04:00
|
|
|
#include "clang/AST/Expr.h"
|
2009-09-01 01:41:48 +04:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2008-10-06 10:40:35 +04:00
|
|
|
#include "clang/AST/APValue.h"
|
2007-07-16 03:32:58 +04:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2008-10-06 10:40:35 +04:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2008-10-22 03:43:52 +04:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2009-02-04 22:02:06 +03:00
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2009-07-18 23:43:29 +04:00
|
|
|
#include "clang/AST/RecordLayout.h"
|
2007-07-11 21:01:13 +04:00
|
|
|
#include "clang/AST/StmtVisitor.h"
|
2009-06-14 05:54:56 +04:00
|
|
|
#include "clang/Basic/Builtins.h"
|
2007-11-27 21:22:04 +03:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2009-11-01 23:32:48 +03:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-09-08 22:24:21 +04:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-04-15 10:41:24 +04:00
|
|
|
#include <algorithm>
|
2007-07-11 21:01:13 +04:00
|
|
|
using namespace clang;
|
|
|
|
|
2010-04-17 03:34:13 +04:00
|
|
|
/// isKnownToHaveBooleanValue - Return true if this is an integer expression
|
|
|
|
/// that is known to return 0 or 1. This happens for _Bool/bool expressions
|
|
|
|
/// but also int expressions which are produced by things like comparisons in
|
|
|
|
/// C.
|
|
|
|
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 (const ParenExpr *PE = dyn_cast<ParenExpr>(this))
|
|
|
|
return PE->getSubExpr()->isKnownToHaveBooleanValue();
|
|
|
|
|
|
|
|
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(this)) {
|
|
|
|
switch (UO->getOpcode()) {
|
|
|
|
case UnaryOperator::Plus:
|
|
|
|
case UnaryOperator::Extension:
|
|
|
|
return UO->getSubExpr()->isKnownToHaveBooleanValue();
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const CastExpr *CE = dyn_cast<CastExpr>(this))
|
|
|
|
return CE->getSubExpr()->isKnownToHaveBooleanValue();
|
|
|
|
|
|
|
|
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(this)) {
|
|
|
|
switch (BO->getOpcode()) {
|
|
|
|
default: return false;
|
|
|
|
case BinaryOperator::LT: // Relational operators.
|
|
|
|
case BinaryOperator::GT:
|
|
|
|
case BinaryOperator::LE:
|
|
|
|
case BinaryOperator::GE:
|
|
|
|
case BinaryOperator::EQ: // Equality operators.
|
|
|
|
case BinaryOperator::NE:
|
|
|
|
case BinaryOperator::LAnd: // AND operator.
|
|
|
|
case BinaryOperator::LOr: // Logical OR operator.
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case BinaryOperator::And: // Bitwise AND operator.
|
|
|
|
case BinaryOperator::Xor: // Bitwise XOR operator.
|
|
|
|
case BinaryOperator::Or: // Bitwise OR operator.
|
|
|
|
// Handle things like (x==2)|(y==12).
|
|
|
|
return BO->getLHS()->isKnownToHaveBooleanValue() &&
|
|
|
|
BO->getRHS()->isKnownToHaveBooleanValue();
|
|
|
|
|
|
|
|
case BinaryOperator::Comma:
|
|
|
|
case BinaryOperator::Assign:
|
|
|
|
return BO->getRHS()->isKnownToHaveBooleanValue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(this))
|
|
|
|
return CO->getTrueExpr()->isKnownToHaveBooleanValue() &&
|
|
|
|
CO->getFalseExpr()->isKnownToHaveBooleanValue();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Primary Expressions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-11-23 04:53:49 +03:00
|
|
|
void ExplicitTemplateArgumentList::initializeFrom(
|
|
|
|
const TemplateArgumentListInfo &Info) {
|
|
|
|
LAngleLoc = Info.getLAngleLoc();
|
|
|
|
RAngleLoc = Info.getRAngleLoc();
|
|
|
|
NumTemplateArgs = Info.size();
|
|
|
|
|
|
|
|
TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
|
|
|
|
for (unsigned i = 0; i != NumTemplateArgs; ++i)
|
|
|
|
new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExplicitTemplateArgumentList::copyInto(
|
|
|
|
TemplateArgumentListInfo &Info) const {
|
|
|
|
Info.setLAngleLoc(LAngleLoc);
|
|
|
|
Info.setRAngleLoc(RAngleLoc);
|
|
|
|
for (unsigned I = 0; I != NumTemplateArgs; ++I)
|
|
|
|
Info.addArgument(getTemplateArgs()[I]);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t ExplicitTemplateArgumentList::sizeFor(
|
|
|
|
const TemplateArgumentListInfo &Info) {
|
|
|
|
return sizeof(ExplicitTemplateArgumentList) +
|
|
|
|
sizeof(TemplateArgumentLoc) * Info.size();
|
|
|
|
}
|
|
|
|
|
2009-11-23 14:41:28 +03:00
|
|
|
void DeclRefExpr::computeDependence() {
|
|
|
|
TypeDependent = false;
|
|
|
|
ValueDependent = false;
|
|
|
|
|
|
|
|
NamedDecl *D = getDecl();
|
|
|
|
|
|
|
|
// (TD) C++ [temp.dep.expr]p3:
|
|
|
|
// An id-expression is type-dependent if it contains:
|
|
|
|
//
|
|
|
|
// and
|
|
|
|
//
|
|
|
|
// (VD) C++ [temp.dep.constexpr]p2:
|
|
|
|
// An identifier is value-dependent if it is:
|
|
|
|
|
|
|
|
// (TD) - an identifier that was declared with dependent type
|
|
|
|
// (VD) - a name declared with a dependent type,
|
|
|
|
if (getType()->isDependentType()) {
|
|
|
|
TypeDependent = true;
|
|
|
|
ValueDependent = true;
|
|
|
|
}
|
|
|
|
// (TD) - a conversion-function-id that specifies a dependent type
|
|
|
|
else if (D->getDeclName().getNameKind()
|
|
|
|
== DeclarationName::CXXConversionFunctionName &&
|
|
|
|
D->getDeclName().getCXXNameType()->isDependentType()) {
|
|
|
|
TypeDependent = true;
|
|
|
|
ValueDependent = true;
|
|
|
|
}
|
|
|
|
// (TD) - a template-id that is dependent,
|
|
|
|
else if (hasExplicitTemplateArgumentList() &&
|
|
|
|
TemplateSpecializationType::anyDependentTemplateArguments(
|
|
|
|
getTemplateArgs(),
|
|
|
|
getNumTemplateArgs())) {
|
|
|
|
TypeDependent = true;
|
|
|
|
ValueDependent = true;
|
|
|
|
}
|
|
|
|
// (VD) - the name of a non-type template parameter,
|
|
|
|
else if (isa<NonTypeTemplateParmDecl>(D))
|
|
|
|
ValueDependent = true;
|
|
|
|
// (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() &&
|
2010-01-15 19:21:02 +03:00
|
|
|
Var->getType().getCVRQualifiers() == Qualifiers::Const) {
|
2010-02-01 23:16:42 +03:00
|
|
|
if (const Expr *Init = Var->getAnyInitializer())
|
2010-01-15 19:21:02 +03:00
|
|
|
if (Init->isValueDependent())
|
|
|
|
ValueDependent = true;
|
|
|
|
}
|
2009-11-23 14:41:28 +03:00
|
|
|
}
|
|
|
|
// (TD) - a nested-name-specifier or a qualified-id that names a
|
|
|
|
// member of an unknown specialization.
|
|
|
|
// (handled by DependentScopeDeclRefExpr)
|
|
|
|
}
|
|
|
|
|
2009-10-23 22:54:35 +04:00
|
|
|
DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
|
|
|
|
SourceRange QualifierRange,
|
2009-12-08 12:08:17 +03:00
|
|
|
ValueDecl *D, SourceLocation NameLoc,
|
2009-11-23 04:53:49 +03:00
|
|
|
const TemplateArgumentListInfo *TemplateArgs,
|
2009-11-23 14:41:28 +03:00
|
|
|
QualType T)
|
|
|
|
: Expr(DeclRefExprClass, T, false, false),
|
2009-10-23 22:54:35 +04:00
|
|
|
DecoratedD(D,
|
|
|
|
(Qualifier? HasQualifierFlag : 0) |
|
2009-11-23 04:53:49 +03:00
|
|
|
(TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)),
|
2009-10-23 22:54:35 +04:00
|
|
|
Loc(NameLoc) {
|
|
|
|
if (Qualifier) {
|
|
|
|
NameQualifier *NQ = getNameQualifier();
|
|
|
|
NQ->NNS = Qualifier;
|
|
|
|
NQ->Range = QualifierRange;
|
|
|
|
}
|
|
|
|
|
2009-11-23 04:53:49 +03:00
|
|
|
if (TemplateArgs)
|
|
|
|
getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs);
|
2009-10-23 22:54:35 +04:00
|
|
|
|
2009-11-23 14:41:28 +03:00
|
|
|
computeDependence();
|
2009-10-23 22:54:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
|
|
|
|
NestedNameSpecifier *Qualifier,
|
|
|
|
SourceRange QualifierRange,
|
2009-12-08 12:08:17 +03:00
|
|
|
ValueDecl *D,
|
2009-10-23 22:54:35 +04:00
|
|
|
SourceLocation NameLoc,
|
2009-11-23 14:41:28 +03:00
|
|
|
QualType T,
|
|
|
|
const TemplateArgumentListInfo *TemplateArgs) {
|
2009-10-23 22:54:35 +04:00
|
|
|
std::size_t Size = sizeof(DeclRefExpr);
|
|
|
|
if (Qualifier != 0)
|
|
|
|
Size += sizeof(NameQualifier);
|
|
|
|
|
2009-11-23 04:53:49 +03:00
|
|
|
if (TemplateArgs)
|
|
|
|
Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
|
2009-10-23 22:54:35 +04:00
|
|
|
|
|
|
|
void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>());
|
|
|
|
return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc,
|
2009-11-23 14:41:28 +03:00
|
|
|
TemplateArgs, T);
|
2009-10-23 22:54:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
SourceRange DeclRefExpr::getSourceRange() const {
|
|
|
|
// FIXME: Does not handle multi-token names well, e.g., operator[].
|
|
|
|
SourceRange R(Loc);
|
|
|
|
|
|
|
|
if (hasQualifier())
|
|
|
|
R.setBegin(getQualifierRange().getBegin());
|
|
|
|
if (hasExplicitTemplateArgumentList())
|
|
|
|
R.setEnd(getRAngleLoc());
|
|
|
|
return R;
|
|
|
|
}
|
|
|
|
|
2009-09-08 22:24:21 +04:00
|
|
|
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
|
|
|
|
// expr" policy instead.
|
2010-02-11 21:20:28 +03:00
|
|
|
std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
|
|
|
|
ASTContext &Context = CurrentDecl->getASTContext();
|
|
|
|
|
2009-09-08 22:24:21 +04:00
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
|
2010-02-11 21:20:28 +03:00
|
|
|
if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual)
|
2009-09-08 22:24:21 +04:00
|
|
|
return FD->getNameAsString();
|
|
|
|
|
|
|
|
llvm::SmallString<256> Name;
|
|
|
|
llvm::raw_svector_ostream Out(Name);
|
|
|
|
|
|
|
|
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
2010-02-11 21:20:28 +03:00
|
|
|
if (MD->isVirtual() && IT != PrettyFunctionNoVirtual)
|
2009-09-08 22:24:21 +04:00
|
|
|
Out << "virtual ";
|
2009-12-27 04:38:20 +03:00
|
|
|
if (MD->isStatic())
|
|
|
|
Out << "static ";
|
2009-09-08 22:24:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
PrintingPolicy Policy(Context.getLangOptions());
|
|
|
|
|
|
|
|
std::string Proto = FD->getQualifiedNameAsString(Policy);
|
|
|
|
|
2009-09-22 03:43:11 +04:00
|
|
|
const FunctionType *AFT = FD->getType()->getAs<FunctionType>();
|
2009-09-08 22:24:21 +04:00
|
|
|
const FunctionProtoType *FT = 0;
|
|
|
|
if (FD->hasWrittenPrototype())
|
|
|
|
FT = dyn_cast<FunctionProtoType>(AFT);
|
|
|
|
|
|
|
|
Proto += "(";
|
|
|
|
if (FT) {
|
|
|
|
llvm::raw_string_ostream POut(Proto);
|
|
|
|
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
|
|
|
|
if (i) POut << ", ";
|
|
|
|
std::string Param;
|
|
|
|
FD->getParamDecl(i)->getType().getAsStringInternal(Param, Policy);
|
|
|
|
POut << Param;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FT->isVariadic()) {
|
|
|
|
if (FD->getNumParams()) POut << ", ";
|
|
|
|
POut << "...";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Proto += ")";
|
|
|
|
|
2009-12-27 04:38:20 +03:00
|
|
|
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
|
|
|
|
Qualifiers ThisQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
|
|
|
|
if (ThisQuals.hasConst())
|
|
|
|
Proto += " const";
|
|
|
|
if (ThisQuals.hasVolatile())
|
|
|
|
Proto += " volatile";
|
|
|
|
}
|
|
|
|
|
2009-12-07 02:55:13 +03:00
|
|
|
if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))
|
|
|
|
AFT->getResultType().getAsStringInternal(Proto, Policy);
|
2009-09-08 22:24:21 +04:00
|
|
|
|
|
|
|
Out << Proto;
|
|
|
|
|
|
|
|
Out.flush();
|
|
|
|
return Name.str().str();
|
|
|
|
}
|
|
|
|
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurrentDecl)) {
|
|
|
|
llvm::SmallString<256> Name;
|
|
|
|
llvm::raw_svector_ostream Out(Name);
|
|
|
|
Out << (MD->isInstanceMethod() ? '-' : '+');
|
|
|
|
Out << '[';
|
2010-03-19 00:23:08 +03:00
|
|
|
|
|
|
|
// For incorrect code, there might not be an ObjCInterfaceDecl. Do
|
|
|
|
// a null check to avoid a crash.
|
|
|
|
if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
|
|
|
|
Out << ID->getNameAsString();
|
|
|
|
|
2009-09-08 22:24:21 +04:00
|
|
|
if (const ObjCCategoryImplDecl *CID =
|
|
|
|
dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext())) {
|
|
|
|
Out << '(';
|
|
|
|
Out << CID->getNameAsString();
|
|
|
|
Out << ')';
|
|
|
|
}
|
|
|
|
Out << ' ';
|
|
|
|
Out << MD->getSelector().getAsString();
|
|
|
|
Out << ']';
|
|
|
|
|
|
|
|
Out.flush();
|
|
|
|
return Name.str().str();
|
|
|
|
}
|
|
|
|
if (isa<TranslationUnitDecl>(CurrentDecl) && IT == PrettyFunction) {
|
|
|
|
// __PRETTY_FUNCTION__ -> "top level", the others produce an empty string.
|
|
|
|
return "top level";
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2008-06-08 02:13:43 +04:00
|
|
|
/// getValueAsApproximateDouble - This returns the value as an inaccurate
|
|
|
|
/// double. Note that this may cause loss of precision, but is useful for
|
|
|
|
/// debugging dumps, etc.
|
|
|
|
double FloatingLiteral::getValueAsApproximateDouble() const {
|
|
|
|
llvm::APFloat V = getValue();
|
2008-10-10 03:02:32 +04:00
|
|
|
bool ignored;
|
|
|
|
V.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven,
|
|
|
|
&ignored);
|
2008-06-08 02:13:43 +04:00
|
|
|
return V.convertToDouble();
|
|
|
|
}
|
|
|
|
|
2009-02-18 09:40:38 +03:00
|
|
|
StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData,
|
|
|
|
unsigned ByteLength, bool Wide,
|
|
|
|
QualType Ty,
|
2009-09-09 19:08:12 +04:00
|
|
|
const SourceLocation *Loc,
|
2009-03-15 21:34:13 +03:00
|
|
|
unsigned NumStrs) {
|
2009-02-18 09:40:38 +03:00
|
|
|
// Allocate enough space for the StringLiteral plus an array of locations for
|
|
|
|
// any concatenated string tokens.
|
|
|
|
void *Mem = C.Allocate(sizeof(StringLiteral)+
|
|
|
|
sizeof(SourceLocation)*(NumStrs-1),
|
|
|
|
llvm::alignof<StringLiteral>());
|
|
|
|
StringLiteral *SL = new (Mem) StringLiteral(Ty);
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
// OPTIMIZE: could allocate this appended to the StringLiteral.
|
2009-02-18 09:40:38 +03:00
|
|
|
char *AStrData = new (C, 1) char[ByteLength];
|
|
|
|
memcpy(AStrData, StrData, ByteLength);
|
|
|
|
SL->StrData = AStrData;
|
|
|
|
SL->ByteLength = ByteLength;
|
|
|
|
SL->IsWide = Wide;
|
|
|
|
SL->TokLocs[0] = Loc[0];
|
|
|
|
SL->NumConcatenated = NumStrs;
|
2007-07-11 21:01:13 +04:00
|
|
|
|
2009-02-18 08:49:11 +03:00
|
|
|
if (NumStrs != 1)
|
2009-02-18 09:40:38 +03:00
|
|
|
memcpy(&SL->TokLocs[1], Loc+1, sizeof(SourceLocation)*(NumStrs-1));
|
|
|
|
return SL;
|
2009-02-18 08:49:11 +03:00
|
|
|
}
|
|
|
|
|
2009-04-15 20:35:07 +04:00
|
|
|
StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) {
|
|
|
|
void *Mem = C.Allocate(sizeof(StringLiteral)+
|
|
|
|
sizeof(SourceLocation)*(NumStrs-1),
|
|
|
|
llvm::alignof<StringLiteral>());
|
|
|
|
StringLiteral *SL = new (Mem) StringLiteral(QualType());
|
|
|
|
SL->StrData = 0;
|
|
|
|
SL->ByteLength = 0;
|
|
|
|
SL->NumConcatenated = NumStrs;
|
|
|
|
return SL;
|
|
|
|
}
|
|
|
|
|
2009-08-07 10:08:38 +04:00
|
|
|
void StringLiteral::DoDestroy(ASTContext &C) {
|
2009-02-07 04:47:29 +03:00
|
|
|
C.Deallocate(const_cast<char*>(StrData));
|
2009-08-07 10:08:38 +04:00
|
|
|
Expr::DoDestroy(C);
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
|
|
|
|
2009-09-22 07:27:33 +04:00
|
|
|
void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) {
|
2009-04-15 20:35:07 +04:00
|
|
|
if (StrData)
|
|
|
|
C.Deallocate(const_cast<char*>(StrData));
|
|
|
|
|
2009-09-22 07:27:33 +04:00
|
|
|
char *AStrData = new (C, 1) char[Str.size()];
|
|
|
|
memcpy(AStrData, Str.data(), Str.size());
|
2009-04-15 20:35:07 +04:00
|
|
|
StrData = AStrData;
|
2009-09-22 07:27:33 +04:00
|
|
|
ByteLength = Str.size();
|
2009-04-15 20:35:07 +04:00
|
|
|
}
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
|
|
|
|
/// corresponds to, e.g. "sizeof" or "[pre]++".
|
|
|
|
const char *UnaryOperator::getOpcodeStr(Opcode Op) {
|
|
|
|
switch (Op) {
|
|
|
|
default: assert(0 && "Unknown unary operator");
|
|
|
|
case PostInc: return "++";
|
|
|
|
case PostDec: return "--";
|
|
|
|
case PreInc: return "++";
|
|
|
|
case PreDec: return "--";
|
|
|
|
case AddrOf: return "&";
|
|
|
|
case Deref: return "*";
|
|
|
|
case Plus: return "+";
|
|
|
|
case Minus: return "-";
|
|
|
|
case Not: return "~";
|
|
|
|
case LNot: return "!";
|
|
|
|
case Real: return "__real";
|
|
|
|
case Imag: return "__imag";
|
|
|
|
case Extension: return "__extension__";
|
2007-08-30 21:45:32 +04:00
|
|
|
case OffsetOf: return "__builtin_offsetof";
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
UnaryOperator::Opcode
|
2009-03-14 02:49:33 +03:00
|
|
|
UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) {
|
|
|
|
switch (OO) {
|
|
|
|
default: assert(false && "No unary operator for overloaded function");
|
2009-03-22 03:10:22 +03:00
|
|
|
case OO_PlusPlus: return Postfix ? PostInc : PreInc;
|
|
|
|
case OO_MinusMinus: return Postfix ? PostDec : PreDec;
|
|
|
|
case OO_Amp: return AddrOf;
|
|
|
|
case OO_Star: return Deref;
|
|
|
|
case OO_Plus: return Plus;
|
|
|
|
case OO_Minus: return Minus;
|
|
|
|
case OO_Tilde: return Not;
|
|
|
|
case OO_Exclaim: return LNot;
|
2009-03-14 02:49:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
|
|
|
|
switch (Opc) {
|
|
|
|
case PostInc: case PreInc: return OO_PlusPlus;
|
|
|
|
case PostDec: case PreDec: return OO_MinusMinus;
|
|
|
|
case AddrOf: return OO_Amp;
|
|
|
|
case Deref: return OO_Star;
|
|
|
|
case Plus: return OO_Plus;
|
|
|
|
case Minus: return OO_Minus;
|
|
|
|
case Not: return OO_Tilde;
|
|
|
|
case LNot: return OO_Exclaim;
|
|
|
|
default: return OO_None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Postfix Operators.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-09 23:51:47 +03:00
|
|
|
CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args,
|
2009-02-07 04:47:29 +03:00
|
|
|
unsigned numargs, QualType t, SourceLocation rparenloc)
|
2009-09-09 19:08:12 +04:00
|
|
|
: Expr(SC, t,
|
2008-12-06 02:32:09 +03:00
|
|
|
fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs),
|
2009-02-17 01:33:34 +03:00
|
|
|
fn->isValueDependent() || hasAnyValueDependentArguments(args,numargs)),
|
2008-12-06 02:32:09 +03:00
|
|
|
NumArgs(numargs) {
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-02-09 23:51:47 +03:00
|
|
|
SubExprs = new (C) Stmt*[numargs+1];
|
2008-11-14 19:09:21 +03:00
|
|
|
SubExprs[FN] = fn;
|
|
|
|
for (unsigned i = 0; i != numargs; ++i)
|
|
|
|
SubExprs[i+ARGS_START] = args[i];
|
2009-02-09 23:51:47 +03:00
|
|
|
|
2008-11-14 19:09:21 +03:00
|
|
|
RParenLoc = rparenloc;
|
|
|
|
}
|
2008-01-17 20:46:27 +03:00
|
|
|
|
2009-02-09 23:51:47 +03:00
|
|
|
CallExpr::CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs,
|
|
|
|
QualType t, SourceLocation rparenloc)
|
2008-12-06 02:32:09 +03:00
|
|
|
: Expr(CallExprClass, t,
|
|
|
|
fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs),
|
2009-02-17 01:33:34 +03:00
|
|
|
fn->isValueDependent() || hasAnyValueDependentArguments(args,numargs)),
|
2008-12-06 02:32:09 +03:00
|
|
|
NumArgs(numargs) {
|
2009-02-09 23:51:47 +03:00
|
|
|
|
|
|
|
SubExprs = new (C) Stmt*[numargs+1];
|
2007-08-24 22:13:47 +04:00
|
|
|
SubExprs[FN] = fn;
|
2007-07-11 21:01:13 +04:00
|
|
|
for (unsigned i = 0; i != numargs; ++i)
|
2007-08-24 22:13:47 +04:00
|
|
|
SubExprs[i+ARGS_START] = args[i];
|
2009-02-09 23:51:47 +03:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
RParenLoc = rparenloc;
|
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
CallExpr::CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty)
|
|
|
|
: Expr(SC, Empty), SubExprs(0), NumArgs(0) {
|
2009-04-15 21:43:59 +04:00
|
|
|
SubExprs = new (C) Stmt*[1];
|
|
|
|
}
|
|
|
|
|
2009-08-07 10:08:38 +04:00
|
|
|
void CallExpr::DoDestroy(ASTContext& C) {
|
2009-02-09 23:51:47 +03:00
|
|
|
DestroyChildren(C);
|
|
|
|
if (SubExprs) C.Deallocate(SubExprs);
|
|
|
|
this->~CallExpr();
|
|
|
|
C.Deallocate(this);
|
|
|
|
}
|
|
|
|
|
2009-12-21 02:11:08 +03:00
|
|
|
Decl *CallExpr::getCalleeDecl() {
|
2009-07-17 11:29:51 +04:00
|
|
|
Expr *CEE = getCallee()->IgnoreParenCasts();
|
2009-07-17 19:46:27 +04:00
|
|
|
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE))
|
2009-12-21 02:11:08 +03:00
|
|
|
return DRE->getDecl();
|
2009-12-24 03:28:18 +03:00
|
|
|
if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE))
|
|
|
|
return ME->getMemberDecl();
|
2009-07-17 11:29:51 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-12-21 02:11:08 +03:00
|
|
|
FunctionDecl *CallExpr::getDirectCallee() {
|
2009-12-21 04:10:56 +03:00
|
|
|
return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
|
2009-12-21 02:11:08 +03:00
|
|
|
}
|
|
|
|
|
2007-12-28 08:25:02 +03:00
|
|
|
/// setNumArgs - This changes the number of arguments present in this call.
|
|
|
|
/// Any orphaned expressions are deleted by this, and any new operands are set
|
|
|
|
/// to null.
|
2009-02-07 04:47:29 +03:00
|
|
|
void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) {
|
2007-12-28 08:25:02 +03:00
|
|
|
// No change, just return.
|
|
|
|
if (NumArgs == getNumArgs()) return;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2007-12-28 08:25:02 +03:00
|
|
|
// If shrinking # arguments, just delete the extras and forgot them.
|
|
|
|
if (NumArgs < getNumArgs()) {
|
|
|
|
for (unsigned i = NumArgs, e = getNumArgs(); i != e; ++i)
|
2009-02-07 04:47:29 +03:00
|
|
|
getArg(i)->Destroy(C);
|
2007-12-28 08:25:02 +03:00
|
|
|
this->NumArgs = NumArgs;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we are growing the # arguments. New an bigger argument array.
|
2009-07-28 10:29:46 +04:00
|
|
|
Stmt **NewSubExprs = new (C) Stmt*[NumArgs+1];
|
2007-12-28 08:25:02 +03:00
|
|
|
// Copy over args.
|
|
|
|
for (unsigned i = 0; i != getNumArgs()+ARGS_START; ++i)
|
|
|
|
NewSubExprs[i] = SubExprs[i];
|
|
|
|
// Null out new args.
|
|
|
|
for (unsigned i = getNumArgs()+ARGS_START; i != NumArgs+ARGS_START; ++i)
|
|
|
|
NewSubExprs[i] = 0;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-04-18 01:46:47 +04:00
|
|
|
if (SubExprs) C.Deallocate(SubExprs);
|
2007-12-28 08:25:02 +03:00
|
|
|
SubExprs = NewSubExprs;
|
|
|
|
this->NumArgs = NumArgs;
|
|
|
|
}
|
|
|
|
|
2008-10-06 09:00:53 +04:00
|
|
|
/// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
|
|
|
|
/// not, return 0.
|
2009-02-14 21:57:46 +03:00
|
|
|
unsigned CallExpr::isBuiltinCall(ASTContext &Context) const {
|
2008-01-31 04:07:12 +03:00
|
|
|
// All simple function calls (e.g. func()) are implicitly cast to pointer to
|
2009-09-09 19:08:12 +04:00
|
|
|
// function. As a result, we try and obtain the DeclRefExpr from the
|
2008-01-31 04:07:12 +03:00
|
|
|
// ImplicitCastExpr.
|
|
|
|
const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee());
|
|
|
|
if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()).
|
2008-10-06 09:00:53 +04:00
|
|
|
return 0;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2008-01-31 04:07:12 +03:00
|
|
|
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
|
|
|
|
if (!DRE)
|
2008-10-06 09:00:53 +04:00
|
|
|
return 0;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2008-01-31 05:13:57 +03:00
|
|
|
const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
|
|
|
|
if (!FDecl)
|
2008-10-06 09:00:53 +04:00
|
|
|
return 0;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2008-11-21 18:30:19 +03:00
|
|
|
if (!FDecl->getIdentifier())
|
|
|
|
return 0;
|
|
|
|
|
2009-09-12 04:22:50 +04:00
|
|
|
return FDecl->getBuiltinID();
|
2008-10-06 09:00:53 +04:00
|
|
|
}
|
2008-01-31 05:13:57 +03:00
|
|
|
|
2009-05-26 08:57:27 +04:00
|
|
|
QualType CallExpr::getCallReturnType() const {
|
|
|
|
QualType CalleeType = getCallee()->getType();
|
2009-07-30 01:53:49 +04:00
|
|
|
if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>())
|
2009-05-26 08:57:27 +04:00
|
|
|
CalleeType = FnTypePtr->getPointeeType();
|
2009-07-30 01:53:49 +04:00
|
|
|
else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>())
|
2009-05-26 08:57:27 +04:00
|
|
|
CalleeType = BPT->getPointeeType();
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-09-22 03:43:11 +04:00
|
|
|
const FunctionType *FnType = CalleeType->getAs<FunctionType>();
|
2009-05-26 08:57:27 +04:00
|
|
|
return FnType->getResultType();
|
|
|
|
}
|
2008-10-06 09:00:53 +04:00
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
|
|
|
|
NestedNameSpecifier *qual,
|
2009-09-01 03:41:50 +04:00
|
|
|
SourceRange qualrange,
|
2009-12-04 09:40:45 +03:00
|
|
|
ValueDecl *memberdecl,
|
2010-04-07 01:38:20 +04:00
|
|
|
DeclAccessPair founddecl,
|
2009-09-09 19:08:12 +04:00
|
|
|
SourceLocation l,
|
2009-11-23 04:53:49 +03:00
|
|
|
const TemplateArgumentListInfo *targs,
|
2009-09-01 04:37:14 +04:00
|
|
|
QualType ty) {
|
2009-09-01 03:41:50 +04:00
|
|
|
std::size_t Size = sizeof(MemberExpr);
|
2010-03-31 01:47:33 +04:00
|
|
|
|
2010-04-07 01:38:20 +04:00
|
|
|
bool hasQualOrFound = (qual != 0 ||
|
|
|
|
founddecl.getDecl() != memberdecl ||
|
|
|
|
founddecl.getAccess() != memberdecl->getAccess());
|
2010-03-31 01:47:33 +04:00
|
|
|
if (hasQualOrFound)
|
|
|
|
Size += sizeof(MemberNameQualifier);
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-11-23 04:53:49 +03:00
|
|
|
if (targs)
|
|
|
|
Size += ExplicitTemplateArgumentList::sizeFor(*targs);
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-09-01 03:41:50 +04:00
|
|
|
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
|
2010-03-31 01:47:33 +04:00
|
|
|
MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, l, ty);
|
|
|
|
|
|
|
|
if (hasQualOrFound) {
|
|
|
|
if (qual && qual->isDependent()) {
|
|
|
|
E->setValueDependent(true);
|
|
|
|
E->setTypeDependent(true);
|
|
|
|
}
|
|
|
|
E->HasQualifierOrFoundDecl = true;
|
|
|
|
|
|
|
|
MemberNameQualifier *NQ = E->getMemberQualifier();
|
|
|
|
NQ->NNS = qual;
|
|
|
|
NQ->Range = qualrange;
|
|
|
|
NQ->FoundDecl = founddecl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (targs) {
|
|
|
|
E->HasExplicitTemplateArgumentList = true;
|
|
|
|
E->getExplicitTemplateArgumentList()->initializeFrom(*targs);
|
|
|
|
}
|
|
|
|
|
|
|
|
return E;
|
2009-09-01 03:41:50 +04:00
|
|
|
}
|
|
|
|
|
2009-09-03 04:59:21 +04:00
|
|
|
const char *CastExpr::getCastKindName() const {
|
|
|
|
switch (getCastKind()) {
|
|
|
|
case CastExpr::CK_Unknown:
|
|
|
|
return "Unknown";
|
|
|
|
case CastExpr::CK_BitCast:
|
|
|
|
return "BitCast";
|
|
|
|
case CastExpr::CK_NoOp:
|
|
|
|
return "NoOp";
|
2009-11-12 19:43:42 +03:00
|
|
|
case CastExpr::CK_BaseToDerived:
|
|
|
|
return "BaseToDerived";
|
2009-09-03 04:59:21 +04:00
|
|
|
case CastExpr::CK_DerivedToBase:
|
|
|
|
return "DerivedToBase";
|
2010-03-31 03:58:03 +04:00
|
|
|
case CastExpr::CK_UncheckedDerivedToBase:
|
|
|
|
return "UncheckedDerivedToBase";
|
2009-09-03 04:59:21 +04:00
|
|
|
case CastExpr::CK_Dynamic:
|
|
|
|
return "Dynamic";
|
|
|
|
case CastExpr::CK_ToUnion:
|
|
|
|
return "ToUnion";
|
|
|
|
case CastExpr::CK_ArrayToPointerDecay:
|
|
|
|
return "ArrayToPointerDecay";
|
|
|
|
case CastExpr::CK_FunctionToPointerDecay:
|
|
|
|
return "FunctionToPointerDecay";
|
|
|
|
case CastExpr::CK_NullToMemberPointer:
|
|
|
|
return "NullToMemberPointer";
|
|
|
|
case CastExpr::CK_BaseToDerivedMemberPointer:
|
|
|
|
return "BaseToDerivedMemberPointer";
|
2009-10-30 03:46:35 +03:00
|
|
|
case CastExpr::CK_DerivedToBaseMemberPointer:
|
|
|
|
return "DerivedToBaseMemberPointer";
|
2009-09-03 04:59:21 +04:00
|
|
|
case CastExpr::CK_UserDefinedConversion:
|
|
|
|
return "UserDefinedConversion";
|
|
|
|
case CastExpr::CK_ConstructorConversion:
|
|
|
|
return "ConstructorConversion";
|
2009-09-15 08:48:33 +04:00
|
|
|
case CastExpr::CK_IntegralToPointer:
|
|
|
|
return "IntegralToPointer";
|
|
|
|
case CastExpr::CK_PointerToIntegral:
|
|
|
|
return "PointerToIntegral";
|
2009-10-16 06:35:04 +04:00
|
|
|
case CastExpr::CK_ToVoid:
|
|
|
|
return "ToVoid";
|
2009-10-16 09:23:41 +04:00
|
|
|
case CastExpr::CK_VectorSplat:
|
|
|
|
return "VectorSplat";
|
2009-10-18 22:12:03 +04:00
|
|
|
case CastExpr::CK_IntegralCast:
|
|
|
|
return "IntegralCast";
|
|
|
|
case CastExpr::CK_IntegralToFloating:
|
|
|
|
return "IntegralToFloating";
|
|
|
|
case CastExpr::CK_FloatingToIntegral:
|
|
|
|
return "FloatingToIntegral";
|
2009-10-18 23:02:15 +04:00
|
|
|
case CastExpr::CK_FloatingCast:
|
|
|
|
return "FloatingCast";
|
2009-11-23 23:04:44 +03:00
|
|
|
case CastExpr::CK_MemberPointerToBoolean:
|
|
|
|
return "MemberPointerToBoolean";
|
2009-12-09 02:46:15 +03:00
|
|
|
case CastExpr::CK_AnyPointerToObjCPointerCast:
|
|
|
|
return "AnyPointerToObjCPointerCast";
|
2009-12-12 01:40:48 +03:00
|
|
|
case CastExpr::CK_AnyPointerToBlockPointerCast:
|
|
|
|
return "AnyPointerToBlockPointerCast";
|
2009-09-03 04:59:21 +04:00
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-09-03 04:59:21 +04:00
|
|
|
assert(0 && "Unhandled cast kind!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-12-14 22:27:10 +03:00
|
|
|
Expr *CastExpr::getSubExprAsWritten() {
|
|
|
|
Expr *SubExpr = 0;
|
|
|
|
CastExpr *E = this;
|
|
|
|
do {
|
|
|
|
SubExpr = E->getSubExpr();
|
|
|
|
|
|
|
|
// Skip any temporary bindings; they're implicit.
|
|
|
|
if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
|
|
|
|
SubExpr = Binder->getSubExpr();
|
|
|
|
|
|
|
|
// Conversions by constructor and conversion functions have a
|
|
|
|
// subexpression describing the call; strip it off.
|
|
|
|
if (E->getCastKind() == CastExpr::CK_ConstructorConversion)
|
|
|
|
SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0);
|
|
|
|
else if (E->getCastKind() == CastExpr::CK_UserDefinedConversion)
|
|
|
|
SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
|
|
|
|
|
|
|
|
// If the subexpression we're left with is an implicit cast, look
|
|
|
|
// through that, too.
|
|
|
|
} while ((E = dyn_cast<ImplicitCastExpr>(SubExpr)));
|
|
|
|
|
|
|
|
return SubExpr;
|
|
|
|
}
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
|
|
|
|
/// corresponds to, e.g. "<<=".
|
|
|
|
const char *BinaryOperator::getOpcodeStr(Opcode Op) {
|
|
|
|
switch (Op) {
|
2009-03-13 01:51:37 +03:00
|
|
|
case PtrMemD: return ".*";
|
|
|
|
case PtrMemI: return "->*";
|
2007-07-11 21:01:13 +04:00
|
|
|
case Mul: return "*";
|
|
|
|
case Div: return "/";
|
|
|
|
case Rem: return "%";
|
|
|
|
case Add: return "+";
|
|
|
|
case Sub: return "-";
|
|
|
|
case Shl: return "<<";
|
|
|
|
case Shr: return ">>";
|
|
|
|
case LT: return "<";
|
|
|
|
case GT: return ">";
|
|
|
|
case LE: return "<=";
|
|
|
|
case GE: return ">=";
|
|
|
|
case EQ: return "==";
|
|
|
|
case NE: return "!=";
|
|
|
|
case And: return "&";
|
|
|
|
case Xor: return "^";
|
|
|
|
case Or: return "|";
|
|
|
|
case LAnd: return "&&";
|
|
|
|
case LOr: return "||";
|
|
|
|
case Assign: return "=";
|
|
|
|
case MulAssign: return "*=";
|
|
|
|
case DivAssign: return "/=";
|
|
|
|
case RemAssign: return "%=";
|
|
|
|
case AddAssign: return "+=";
|
|
|
|
case SubAssign: return "-=";
|
|
|
|
case ShlAssign: return "<<=";
|
|
|
|
case ShrAssign: return ">>=";
|
|
|
|
case AndAssign: return "&=";
|
|
|
|
case XorAssign: return "^=";
|
|
|
|
case OrAssign: return "|=";
|
|
|
|
case Comma: return ",";
|
|
|
|
}
|
2009-03-13 01:51:37 +03:00
|
|
|
|
|
|
|
return "";
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
BinaryOperator::Opcode
|
2009-03-13 21:40:31 +03:00
|
|
|
BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) {
|
|
|
|
switch (OO) {
|
2009-03-22 03:10:22 +03:00
|
|
|
default: assert(false && "Not an overloadable binary operator");
|
2009-03-13 21:40:31 +03:00
|
|
|
case OO_Plus: return Add;
|
|
|
|
case OO_Minus: return Sub;
|
|
|
|
case OO_Star: return Mul;
|
|
|
|
case OO_Slash: return Div;
|
|
|
|
case OO_Percent: return Rem;
|
|
|
|
case OO_Caret: return Xor;
|
|
|
|
case OO_Amp: return And;
|
|
|
|
case OO_Pipe: return Or;
|
|
|
|
case OO_Equal: return Assign;
|
|
|
|
case OO_Less: return LT;
|
|
|
|
case OO_Greater: return GT;
|
|
|
|
case OO_PlusEqual: return AddAssign;
|
|
|
|
case OO_MinusEqual: return SubAssign;
|
|
|
|
case OO_StarEqual: return MulAssign;
|
|
|
|
case OO_SlashEqual: return DivAssign;
|
|
|
|
case OO_PercentEqual: return RemAssign;
|
|
|
|
case OO_CaretEqual: return XorAssign;
|
|
|
|
case OO_AmpEqual: return AndAssign;
|
|
|
|
case OO_PipeEqual: return OrAssign;
|
|
|
|
case OO_LessLess: return Shl;
|
|
|
|
case OO_GreaterGreater: return Shr;
|
|
|
|
case OO_LessLessEqual: return ShlAssign;
|
|
|
|
case OO_GreaterGreaterEqual: return ShrAssign;
|
|
|
|
case OO_EqualEqual: return EQ;
|
|
|
|
case OO_ExclaimEqual: return NE;
|
|
|
|
case OO_LessEqual: return LE;
|
|
|
|
case OO_GreaterEqual: return GE;
|
|
|
|
case OO_AmpAmp: return LAnd;
|
|
|
|
case OO_PipePipe: return LOr;
|
|
|
|
case OO_Comma: return Comma;
|
|
|
|
case OO_ArrowStar: return PtrMemI;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
|
|
|
|
static const OverloadedOperatorKind OverOps[] = {
|
|
|
|
/* .* Cannot be overloaded */OO_None, OO_ArrowStar,
|
|
|
|
OO_Star, OO_Slash, OO_Percent,
|
|
|
|
OO_Plus, OO_Minus,
|
|
|
|
OO_LessLess, OO_GreaterGreater,
|
|
|
|
OO_Less, OO_Greater, OO_LessEqual, OO_GreaterEqual,
|
|
|
|
OO_EqualEqual, OO_ExclaimEqual,
|
|
|
|
OO_Amp,
|
|
|
|
OO_Caret,
|
|
|
|
OO_Pipe,
|
|
|
|
OO_AmpAmp,
|
|
|
|
OO_PipePipe,
|
|
|
|
OO_Equal, OO_StarEqual,
|
|
|
|
OO_SlashEqual, OO_PercentEqual,
|
|
|
|
OO_PlusEqual, OO_MinusEqual,
|
|
|
|
OO_LessLessEqual, OO_GreaterGreaterEqual,
|
|
|
|
OO_AmpEqual, OO_CaretEqual,
|
|
|
|
OO_PipeEqual,
|
|
|
|
OO_Comma
|
|
|
|
};
|
|
|
|
return OverOps[Opc];
|
|
|
|
}
|
|
|
|
|
2010-04-14 03:39:13 +04:00
|
|
|
InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc,
|
2008-10-27 02:43:26 +03:00
|
|
|
Expr **initExprs, unsigned numInits,
|
2009-01-29 00:54:33 +03:00
|
|
|
SourceLocation rbraceloc)
|
2009-11-20 02:25:22 +03:00
|
|
|
: Expr(InitListExprClass, QualType(), false, false),
|
2010-04-14 03:39:13 +04:00
|
|
|
InitExprs(C, numInits),
|
2009-09-09 19:08:12 +04:00
|
|
|
LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
|
2010-02-19 04:50:18 +03:00
|
|
|
UnionFieldInit(0), HadArrayRangeDesignator(false)
|
|
|
|
{
|
|
|
|
for (unsigned I = 0; I != numInits; ++I) {
|
|
|
|
if (initExprs[I]->isTypeDependent())
|
2009-11-20 02:25:22 +03:00
|
|
|
TypeDependent = true;
|
2010-02-19 04:50:18 +03:00
|
|
|
if (initExprs[I]->isValueDependent())
|
2009-11-20 02:25:22 +03:00
|
|
|
ValueDependent = true;
|
|
|
|
}
|
2010-02-19 04:50:18 +03:00
|
|
|
|
2010-04-14 03:39:13 +04:00
|
|
|
InitExprs.insert(C, InitExprs.end(), initExprs, initExprs+numInits);
|
2007-08-31 08:56:16 +04:00
|
|
|
}
|
2007-07-11 21:01:13 +04:00
|
|
|
|
2010-04-14 03:39:13 +04:00
|
|
|
void InitListExpr::reserveInits(ASTContext &C, unsigned NumInits) {
|
2010-02-19 04:50:18 +03:00
|
|
|
if (NumInits > InitExprs.size())
|
2010-04-14 03:39:13 +04:00
|
|
|
InitExprs.reserve(C, NumInits);
|
2009-03-21 02:58:33 +03:00
|
|
|
}
|
|
|
|
|
2010-04-14 03:39:13 +04:00
|
|
|
void InitListExpr::resizeInits(ASTContext &C, unsigned NumInits) {
|
2010-02-19 04:50:18 +03:00
|
|
|
for (unsigned Idx = NumInits, LastIdx = InitExprs.size();
|
|
|
|
Idx < LastIdx; ++Idx)
|
2010-04-14 03:39:13 +04:00
|
|
|
InitExprs[Idx]->Destroy(C);
|
|
|
|
InitExprs.resize(C, NumInits, 0);
|
2009-01-29 00:54:33 +03:00
|
|
|
}
|
|
|
|
|
2010-04-14 03:39:13 +04:00
|
|
|
Expr *InitListExpr::updateInit(ASTContext &C, unsigned Init, Expr *expr) {
|
2010-02-19 04:50:18 +03:00
|
|
|
if (Init >= InitExprs.size()) {
|
2010-04-14 03:39:13 +04:00
|
|
|
InitExprs.insert(C, InitExprs.end(), Init - InitExprs.size() + 1, 0);
|
2010-02-19 04:50:18 +03:00
|
|
|
InitExprs.back() = expr;
|
|
|
|
return 0;
|
2009-01-29 00:54:33 +03:00
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-01-29 00:54:33 +03:00
|
|
|
Expr *Result = cast_or_null<Expr>(InitExprs[Init]);
|
|
|
|
InitExprs[Init] = expr;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2008-09-04 19:31:07 +04:00
|
|
|
/// getFunctionType - Return the underlying function type for this block.
|
2008-09-03 22:15:37 +04:00
|
|
|
///
|
|
|
|
const FunctionType *BlockExpr::getFunctionType() const {
|
2009-07-30 01:53:49 +04:00
|
|
|
return getType()->getAs<BlockPointerType>()->
|
2009-09-22 03:43:11 +04:00
|
|
|
getPointeeType()->getAs<FunctionType>();
|
2008-09-03 22:15:37 +04:00
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
SourceLocation BlockExpr::getCaretLocation() const {
|
|
|
|
return TheBlock->getCaretLocation();
|
2008-10-08 21:01:13 +04:00
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
const Stmt *BlockExpr::getBody() const {
|
2009-04-18 04:02:19 +04:00
|
|
|
return TheBlock->getBody();
|
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
Stmt *BlockExpr::getBody() {
|
|
|
|
return TheBlock->getBody();
|
2009-04-18 04:02:19 +04:00
|
|
|
}
|
2008-10-08 21:01:13 +04:00
|
|
|
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Generic Expression Routines
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-14 10:37:35 +03:00
|
|
|
/// isUnusedResultAWarning - Return true if this immediate expression should
|
|
|
|
/// be warned about if the result is unused. If so, fill in Loc and Ranges
|
|
|
|
/// with location to warn on and the source range[s] to report with the
|
|
|
|
/// warning.
|
|
|
|
bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
|
2009-11-04 02:25:48 +03:00
|
|
|
SourceRange &R2, ASTContext &Ctx) const {
|
2009-05-16 03:10:19 +04:00
|
|
|
// Don't warn if the expr is type dependent. The type could end up
|
|
|
|
// instantiating to void.
|
|
|
|
if (isTypeDependent())
|
|
|
|
return false;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
switch (getStmtClass()) {
|
|
|
|
default:
|
2010-03-12 10:11:26 +03:00
|
|
|
if (getType()->isVoidType())
|
|
|
|
return false;
|
2009-02-14 10:37:35 +03:00
|
|
|
Loc = getExprLoc();
|
|
|
|
R1 = getSourceRange();
|
|
|
|
return true;
|
2007-07-11 21:01:13 +04:00
|
|
|
case ParenExprClass:
|
2009-02-14 10:37:35 +03:00
|
|
|
return cast<ParenExpr>(this)->getSubExpr()->
|
2009-11-04 02:25:48 +03:00
|
|
|
isUnusedResultAWarning(Loc, R1, R2, Ctx);
|
2007-07-11 21:01:13 +04:00
|
|
|
case UnaryOperatorClass: {
|
|
|
|
const UnaryOperator *UO = cast<UnaryOperator>(this);
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
switch (UO->getOpcode()) {
|
2009-02-14 10:37:35 +03:00
|
|
|
default: break;
|
2007-07-11 21:01:13 +04:00
|
|
|
case UnaryOperator::PostInc:
|
|
|
|
case UnaryOperator::PostDec:
|
|
|
|
case UnaryOperator::PreInc:
|
2009-02-14 10:37:35 +03:00
|
|
|
case UnaryOperator::PreDec: // ++/--
|
|
|
|
return false; // Not a warning.
|
2007-07-11 21:01:13 +04:00
|
|
|
case UnaryOperator::Deref:
|
|
|
|
// Dereferencing a volatile pointer is a side-effect.
|
2009-11-04 02:25:48 +03:00
|
|
|
if (Ctx.getCanonicalType(getType()).isVolatileQualified())
|
2009-02-14 10:37:35 +03:00
|
|
|
return false;
|
|
|
|
break;
|
2007-07-11 21:01:13 +04:00
|
|
|
case UnaryOperator::Real:
|
|
|
|
case UnaryOperator::Imag:
|
|
|
|
// accessing a piece of a volatile complex is a side-effect.
|
2009-11-04 02:25:48 +03:00
|
|
|
if (Ctx.getCanonicalType(UO->getSubExpr()->getType())
|
|
|
|
.isVolatileQualified())
|
2009-02-14 10:37:35 +03:00
|
|
|
return false;
|
|
|
|
break;
|
2007-07-11 21:01:13 +04:00
|
|
|
case UnaryOperator::Extension:
|
2009-11-04 02:25:48 +03:00
|
|
|
return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2009-02-14 10:37:35 +03:00
|
|
|
Loc = UO->getOperatorLoc();
|
|
|
|
R1 = UO->getSubExpr()->getSourceRange();
|
|
|
|
return true;
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2007-12-01 09:07:34 +03:00
|
|
|
case BinaryOperatorClass: {
|
2009-02-14 10:37:35 +03:00
|
|
|
const BinaryOperator *BO = cast<BinaryOperator>(this);
|
2010-04-07 22:49:21 +04:00
|
|
|
switch (BO->getOpcode()) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
// Consider ',', '||', '&&' to have side effects if the LHS or RHS does.
|
|
|
|
case BinaryOperator::Comma:
|
|
|
|
// ((foo = <blah>), 0) is an idiom for hiding the result (and
|
|
|
|
// lvalue-ness) of an assignment written in a macro.
|
|
|
|
if (IntegerLiteral *IE =
|
|
|
|
dyn_cast<IntegerLiteral>(BO->getRHS()->IgnoreParens()))
|
|
|
|
if (IE->getValue() == 0)
|
|
|
|
return false;
|
|
|
|
case BinaryOperator::LAnd:
|
|
|
|
case BinaryOperator::LOr:
|
|
|
|
return (BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
|
|
|
|
BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
2010-02-16 07:10:53 +03:00
|
|
|
}
|
2009-02-14 10:37:35 +03:00
|
|
|
if (BO->isAssignmentOp())
|
|
|
|
return false;
|
|
|
|
Loc = BO->getOperatorLoc();
|
|
|
|
R1 = BO->getLHS()->getSourceRange();
|
|
|
|
R2 = BO->getRHS()->getSourceRange();
|
|
|
|
return true;
|
2007-12-01 09:07:34 +03:00
|
|
|
}
|
2007-08-25 06:00:02 +04:00
|
|
|
case CompoundAssignOperatorClass:
|
2009-02-14 10:37:35 +03:00
|
|
|
return false;
|
2007-07-11 21:01:13 +04:00
|
|
|
|
2007-12-01 22:58:28 +03:00
|
|
|
case ConditionalOperatorClass: {
|
2009-02-14 10:37:35 +03:00
|
|
|
// The condition must be evaluated, but if either the LHS or RHS is a
|
|
|
|
// warning, warn about them.
|
2007-12-01 22:58:28 +03:00
|
|
|
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
|
2009-09-09 19:08:12 +04:00
|
|
|
if (Exp->getLHS() &&
|
2009-11-04 02:25:48 +03:00
|
|
|
Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx))
|
2009-02-14 10:37:35 +03:00
|
|
|
return true;
|
2009-11-04 02:25:48 +03:00
|
|
|
return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
|
2007-12-01 22:58:28 +03:00
|
|
|
}
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
case MemberExprClass:
|
2009-02-14 10:37:35 +03:00
|
|
|
// If the base pointer or element is to a volatile pointer/field, accessing
|
|
|
|
// it is a side effect.
|
2009-11-04 02:25:48 +03:00
|
|
|
if (Ctx.getCanonicalType(getType()).isVolatileQualified())
|
2009-02-14 10:37:35 +03:00
|
|
|
return false;
|
|
|
|
Loc = cast<MemberExpr>(this)->getMemberLoc();
|
|
|
|
R1 = SourceRange(Loc, Loc);
|
|
|
|
R2 = cast<MemberExpr>(this)->getBase()->getSourceRange();
|
|
|
|
return true;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
case ArraySubscriptExprClass:
|
|
|
|
// If the base pointer or element is to a volatile pointer/field, accessing
|
2009-02-14 10:37:35 +03:00
|
|
|
// it is a side effect.
|
2009-11-04 02:25:48 +03:00
|
|
|
if (Ctx.getCanonicalType(getType()).isVolatileQualified())
|
2009-02-14 10:37:35 +03:00
|
|
|
return false;
|
|
|
|
Loc = cast<ArraySubscriptExpr>(this)->getRBracketLoc();
|
|
|
|
R1 = cast<ArraySubscriptExpr>(this)->getLHS()->getSourceRange();
|
|
|
|
R2 = cast<ArraySubscriptExpr>(this)->getRHS()->getSourceRange();
|
|
|
|
return true;
|
2008-05-27 19:24:04 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
case CallExprClass:
|
2009-04-29 20:35:53 +04:00
|
|
|
case CXXOperatorCallExprClass:
|
|
|
|
case CXXMemberCallExprClass: {
|
2009-02-14 10:37:35 +03:00
|
|
|
// If this is a direct call, get the callee.
|
|
|
|
const CallExpr *CE = cast<CallExpr>(this);
|
2009-12-21 02:11:08 +03:00
|
|
|
if (const Decl *FD = CE->getCalleeDecl()) {
|
2009-02-14 10:37:35 +03:00
|
|
|
// If the callee has attribute pure, const, or warn_unused_result, warn
|
|
|
|
// about it. void foo() { strlen("bar"); } should warn.
|
2009-10-13 08:53:48 +04:00
|
|
|
//
|
|
|
|
// Note: If new cases are added here, DiagnoseUnusedExprResult should be
|
|
|
|
// updated to match for QoI.
|
|
|
|
if (FD->getAttr<WarnUnusedResultAttr>() ||
|
|
|
|
FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) {
|
|
|
|
Loc = CE->getCallee()->getLocStart();
|
|
|
|
R1 = CE->getCallee()->getSourceRange();
|
|
|
|
|
|
|
|
if (unsigned NumArgs = CE->getNumArgs())
|
|
|
|
R2 = SourceRange(CE->getArg(0)->getLocStart(),
|
|
|
|
CE->getArg(NumArgs-1)->getLocEnd());
|
|
|
|
return true;
|
|
|
|
}
|
2009-02-14 10:37:35 +03:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2009-11-17 20:11:23 +03:00
|
|
|
|
|
|
|
case CXXTemporaryObjectExprClass:
|
|
|
|
case CXXConstructExprClass:
|
|
|
|
return false;
|
|
|
|
|
2010-03-30 22:22:15 +04:00
|
|
|
case ObjCMessageExprClass: {
|
|
|
|
const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this);
|
|
|
|
const ObjCMethodDecl *MD = ME->getMethodDecl();
|
|
|
|
if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
|
|
|
|
Loc = getExprLoc();
|
|
|
|
return true;
|
|
|
|
}
|
2009-02-14 10:37:35 +03:00
|
|
|
return false;
|
2010-03-30 22:22:15 +04:00
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-08-20 21:02:02 +04:00
|
|
|
case ObjCImplicitSetterGetterRefExprClass: { // Dot syntax for message send.
|
2009-08-16 20:45:18 +04:00
|
|
|
#if 0
|
2009-09-09 19:08:12 +04:00
|
|
|
const ObjCImplicitSetterGetterRefExpr *Ref =
|
2009-08-20 21:02:02 +04:00
|
|
|
cast<ObjCImplicitSetterGetterRefExpr>(this);
|
2009-08-16 20:45:18 +04:00
|
|
|
// FIXME: We really want the location of the '.' here.
|
2009-08-19 00:50:23 +04:00
|
|
|
Loc = Ref->getLocation();
|
|
|
|
R1 = SourceRange(Ref->getLocation(), Ref->getLocation());
|
|
|
|
if (Ref->getBase())
|
|
|
|
R2 = Ref->getBase()->getSourceRange();
|
2009-08-16 20:51:50 +04:00
|
|
|
#else
|
|
|
|
Loc = getExprLoc();
|
|
|
|
R1 = getSourceRange();
|
2009-08-16 20:45:18 +04:00
|
|
|
#endif
|
|
|
|
return true;
|
|
|
|
}
|
2008-07-26 23:51:01 +04:00
|
|
|
case StmtExprClass: {
|
|
|
|
// Statement exprs don't logically have side effects themselves, but are
|
|
|
|
// sometimes used in macros in ways that give them a type that is unused.
|
|
|
|
// For example ({ blah; foo(); }) will end up with a type if foo has a type.
|
|
|
|
// however, if the result of the stmt expr is dead, we don't want to emit a
|
|
|
|
// warning.
|
|
|
|
const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
|
|
|
|
if (!CS->body_empty())
|
|
|
|
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
|
2009-11-04 02:25:48 +03:00
|
|
|
return E->isUnusedResultAWarning(Loc, R1, R2, Ctx);
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2010-03-12 10:11:26 +03:00
|
|
|
if (getType()->isVoidType())
|
|
|
|
return false;
|
2009-02-14 10:37:35 +03:00
|
|
|
Loc = cast<StmtExpr>(this)->getLParenLoc();
|
|
|
|
R1 = getSourceRange();
|
|
|
|
return true;
|
2008-07-26 23:51:01 +04:00
|
|
|
}
|
2008-10-28 18:36:24 +03:00
|
|
|
case CStyleCastExprClass:
|
2009-07-28 22:25:28 +04:00
|
|
|
// If this is an explicit cast to void, allow it. People do this when they
|
|
|
|
// think they know what they're doing :).
|
2009-02-14 10:37:35 +03:00
|
|
|
if (getType()->isVoidType())
|
2009-07-28 22:25:28 +04:00
|
|
|
return false;
|
2009-02-14 10:37:35 +03:00
|
|
|
Loc = cast<CStyleCastExpr>(this)->getLParenLoc();
|
|
|
|
R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
|
|
|
|
return true;
|
2009-11-17 20:11:23 +03:00
|
|
|
case CXXFunctionalCastExprClass: {
|
2010-03-12 10:11:26 +03:00
|
|
|
if (getType()->isVoidType())
|
|
|
|
return false;
|
2009-11-17 20:11:23 +03:00
|
|
|
const CastExpr *CE = cast<CastExpr>(this);
|
|
|
|
|
|
|
|
// If this is a cast to void or a constructor conversion, check the operand.
|
|
|
|
// Otherwise, the result of the cast is unused.
|
|
|
|
if (CE->getCastKind() == CastExpr::CK_ToVoid ||
|
|
|
|
CE->getCastKind() == CastExpr::CK_ConstructorConversion)
|
2009-11-04 02:25:48 +03:00
|
|
|
return (cast<CastExpr>(this)->getSubExpr()
|
|
|
|
->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
2009-02-14 10:37:35 +03:00
|
|
|
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
|
|
|
|
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
|
|
|
|
return true;
|
2009-11-17 20:11:23 +03:00
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2008-05-20 01:24:43 +04:00
|
|
|
case ImplicitCastExprClass:
|
|
|
|
// Check the operand, since implicit casts are inserted by Sema
|
2009-11-04 02:25:48 +03:00
|
|
|
return (cast<ImplicitCastExpr>(this)
|
|
|
|
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
2008-05-20 01:24:43 +04:00
|
|
|
|
2008-04-08 08:40:51 +04:00
|
|
|
case CXXDefaultArgExprClass:
|
2009-11-04 02:25:48 +03:00
|
|
|
return (cast<CXXDefaultArgExpr>(this)
|
|
|
|
->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
2008-11-21 22:14:01 +03:00
|
|
|
|
|
|
|
case CXXNewExprClass:
|
|
|
|
// FIXME: In theory, there might be new expressions that don't have side
|
|
|
|
// effects (e.g. a placement new with an uninitialized POD).
|
|
|
|
case CXXDeleteExprClass:
|
2009-02-14 10:37:35 +03:00
|
|
|
return false;
|
2009-08-16 08:11:06 +04:00
|
|
|
case CXXBindTemporaryExprClass:
|
2009-11-04 02:25:48 +03:00
|
|
|
return (cast<CXXBindTemporaryExpr>(this)
|
|
|
|
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
2009-05-18 01:11:30 +04:00
|
|
|
case CXXExprWithTemporariesClass:
|
2009-11-04 02:25:48 +03:00
|
|
|
return (cast<CXXExprWithTemporaries>(this)
|
|
|
|
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx));
|
2008-11-21 22:14:01 +03:00
|
|
|
}
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
|
|
|
|
2008-10-22 19:04:37 +04:00
|
|
|
/// 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) {
|
2008-12-05 21:15:24 +03:00
|
|
|
// C++ [temp.param]p6:
|
|
|
|
// A non-type non-reference template-parameter is not an lvalue.
|
2009-09-09 19:08:12 +04:00
|
|
|
if (const NonTypeTemplateParmDecl *NTTParm
|
2008-12-05 21:15:24 +03:00
|
|
|
= dyn_cast<NonTypeTemplateParmDecl>(Decl))
|
|
|
|
return NTTParm->getType()->isReferenceType();
|
|
|
|
|
2008-12-11 19:49:14 +03:00
|
|
|
return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) ||
|
2008-10-22 19:04:37 +04:00
|
|
|
// C++ 3.10p2: An lvalue refers to an object or function.
|
|
|
|
(Ctx.getLangOptions().CPlusPlus &&
|
2009-12-02 11:47:38 +03:00
|
|
|
(isa<FunctionDecl>(Decl) || isa<FunctionTemplateDecl>(Decl)));
|
2008-10-22 19:04:37 +04:00
|
|
|
}
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
/// 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
|
2007-10-31 01:53:42 +03:00
|
|
|
/// - (__real__ e) and (__imag__ e) where e is an lvalue [GNU extension]
|
2007-07-17 07:52:31 +04:00
|
|
|
/// - reference type [C++ [expr]]
|
2007-07-11 21:01:13 +04:00
|
|
|
///
|
2008-07-27 01:30:36 +04:00
|
|
|
Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
|
2009-05-04 02:36:05 +04:00
|
|
|
assert(!TR->isReferenceType() && "Expressions can't have reference type.");
|
|
|
|
|
|
|
|
isLvalueResult Res = isLvalueInternal(Ctx);
|
|
|
|
if (Res != LV_Valid || Ctx.getLangOptions().CPlusPlus)
|
|
|
|
return Res;
|
|
|
|
|
2008-10-22 03:43:52 +04:00
|
|
|
// 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++.
|
2009-07-09 00:55:45 +04:00
|
|
|
if (TR->isFunctionType() || TR == Ctx.OverloadTy)
|
2007-07-11 21:01:13 +04:00
|
|
|
return LV_NotObjectType;
|
|
|
|
|
2008-02-10 04:39:04 +03:00
|
|
|
// Allow qualified void which is an incomplete type other than void (yuck).
|
2009-09-24 23:53:00 +04:00
|
|
|
if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
|
2008-02-10 04:39:04 +03:00
|
|
|
return LV_IncompleteVoidType;
|
|
|
|
|
2009-05-04 02:36:05 +04:00
|
|
|
return LV_Valid;
|
|
|
|
}
|
2007-07-17 07:52:31 +04:00
|
|
|
|
2009-05-04 02:36:05 +04:00
|
|
|
// Check whether the expression can be sanely treated like an l-value
|
|
|
|
Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
|
2007-07-11 21:01:13 +04:00
|
|
|
switch (getStmtClass()) {
|
2009-12-10 02:35:29 +03:00
|
|
|
case ObjCIsaExprClass:
|
2009-02-25 01:18:39 +03:00
|
|
|
case StringLiteralClass: // C99 6.5.1p4
|
|
|
|
case ObjCEncodeExprClass: // @encode behaves like its string in every way.
|
2007-12-01 01:47:59 +03:00
|
|
|
return LV_Valid;
|
2007-07-11 21:01:13 +04:00
|
|
|
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())
|
2008-07-27 01:30:36 +04:00
|
|
|
return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx);
|
2007-07-11 21:01:13 +04:00
|
|
|
return LV_Valid;
|
2009-10-23 22:54:35 +04:00
|
|
|
case DeclRefExprClass: { // C99 6.5.1p2
|
2008-10-22 19:04:37 +04:00
|
|
|
const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl();
|
|
|
|
if (DeclCanBeLvalue(RefdDecl, Ctx))
|
2007-07-11 21:01:13 +04:00
|
|
|
return LV_Valid;
|
|
|
|
break;
|
2008-06-17 22:05:57 +04:00
|
|
|
}
|
2008-09-06 02:11:13 +04:00
|
|
|
case BlockDeclRefExprClass: {
|
|
|
|
const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(this);
|
2008-09-26 18:41:28 +04:00
|
|
|
if (isa<VarDecl>(BDR->getDecl()))
|
2008-09-06 02:11:13 +04:00
|
|
|
return LV_Valid;
|
|
|
|
break;
|
|
|
|
}
|
2009-09-01 03:41:50 +04:00
|
|
|
case MemberExprClass: {
|
2007-07-11 21:01:13 +04:00
|
|
|
const MemberExpr *m = cast<MemberExpr>(this);
|
2008-12-21 02:49:58 +03:00
|
|
|
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.
|
2009-03-11 23:22:50 +03:00
|
|
|
if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord())
|
2008-12-21 02:49:58 +03:00
|
|
|
return LV_Valid;
|
|
|
|
|
|
|
|
// -- If E2 is a non-static data member [...]. If E1 is an
|
|
|
|
// lvalue, then E1.E2 is an lvalue.
|
2009-12-16 02:59:41 +03:00
|
|
|
if (isa<FieldDecl>(Member)) {
|
|
|
|
if (m->isArrow())
|
|
|
|
return LV_Valid;
|
2010-02-13 00:02:28 +03:00
|
|
|
return m->getBase()->isLvalue(Ctx);
|
2009-12-16 02:59:41 +03:00
|
|
|
}
|
2008-12-21 02:49:58 +03:00
|
|
|
|
|
|
|
// -- 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;
|
2009-09-09 19:08:12 +04:00
|
|
|
}
|
2009-12-16 02:59:41 +03:00
|
|
|
|
2008-12-21 02:49:58 +03:00
|
|
|
// C99 6.5.2.3p4
|
2009-12-16 02:59:41 +03:00
|
|
|
if (m->isArrow())
|
|
|
|
return LV_Valid;
|
|
|
|
Expr *BaseExp = m->getBase();
|
2010-03-18 21:50:41 +03:00
|
|
|
if (BaseExp->getStmtClass() == ObjCPropertyRefExprClass ||
|
|
|
|
BaseExp->getStmtClass() == ObjCImplicitSetterGetterRefExprClass)
|
2010-02-11 04:11:34 +03:00
|
|
|
return LV_SubObjCPropertySetting;
|
|
|
|
return
|
2010-03-18 21:50:41 +03:00
|
|
|
BaseExp->isLvalue(Ctx);
|
2007-07-12 19:26:50 +04:00
|
|
|
}
|
2007-10-31 01:53:42 +03:00
|
|
|
case UnaryOperatorClass:
|
2007-07-11 21:01:13 +04:00
|
|
|
if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Deref)
|
2007-10-31 01:53:42 +03:00
|
|
|
return LV_Valid; // C99 6.5.3p4
|
|
|
|
|
|
|
|
if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Real ||
|
2008-07-25 22:07:19 +04:00
|
|
|
cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Imag ||
|
|
|
|
cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Extension)
|
2008-07-27 01:30:36 +04:00
|
|
|
return cast<UnaryOperator>(this)->getSubExpr()->isLvalue(Ctx); // GNU.
|
2008-11-19 18:42:04 +03:00
|
|
|
|
|
|
|
if (Ctx.getLangOptions().CPlusPlus && // C++ [expr.pre.incr]p1
|
|
|
|
(cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::PreInc ||
|
|
|
|
cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::PreDec))
|
|
|
|
return LV_Valid;
|
2007-07-11 21:01:13 +04:00
|
|
|
break;
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59148 91177308-0d34-0410-b5e6-96231b3b80d8
2008-11-12 20:17:38 +03:00
|
|
|
case ImplicitCastExprClass:
|
2010-02-17 00:39:57 +03:00
|
|
|
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;
|
2007-07-11 21:01:13 +04:00
|
|
|
case ParenExprClass: // C99 6.5.1p5
|
2008-07-27 01:30:36 +04:00
|
|
|
return cast<ParenExpr>(this)->getSubExpr()->isLvalue(Ctx);
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59148 91177308-0d34-0410-b5e6-96231b3b80d8
2008-11-12 20:17:38 +03:00
|
|
|
case BinaryOperatorClass:
|
|
|
|
case CompoundAssignOperatorClass: {
|
|
|
|
const BinaryOperator *BinOp = cast<BinaryOperator>(this);
|
2008-11-19 20:17:41 +03:00
|
|
|
|
|
|
|
if (Ctx.getLangOptions().CPlusPlus && // C++ [expr.comma]p1
|
|
|
|
BinOp->getOpcode() == BinaryOperator::Comma)
|
|
|
|
return BinOp->getRHS()->isLvalue(Ctx);
|
|
|
|
|
2009-02-07 03:15:38 +03:00
|
|
|
// C++ [expr.mptr.oper]p6
|
2009-10-08 22:00:39 +04:00
|
|
|
// 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 &&
|
2009-02-07 03:15:38 +03:00
|
|
|
!BinOp->getType()->isFunctionType())
|
|
|
|
return BinOp->getLHS()->isLvalue(Ctx);
|
|
|
|
|
2009-10-08 22:00:39 +04:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2008-11-13 23:12:29 +03:00
|
|
|
if (!BinOp->isAssignmentOp())
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59148 91177308-0d34-0410-b5e6-96231b3b80d8
2008-11-12 20:17:38 +03:00
|
|
|
return LV_InvalidExpression;
|
|
|
|
|
2008-11-13 23:12:29 +03:00
|
|
|
if (Ctx.getLangOptions().CPlusPlus)
|
2009-09-09 19:08:12 +04:00
|
|
|
// C++ [expr.ass]p1:
|
2008-11-13 23:12:29 +03:00
|
|
|
// 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;
|
Implement support for operator overloading using candidate operator
functions for built-in operators, e.g., the builtin
bool operator==(int const*, int const*)
can be used for the expression "x1 == x2" given:
struct X {
operator int const*();
} x1, x2;
The scheme for handling these built-in operators is relatively simple:
for each candidate required by the standard, create a special kind of
candidate function for the built-in. If overload resolution picks the
built-in operator, we perform the appropriate conversions on the
arguments and then let the normal built-in operator take care of it.
There may be some optimization opportunity left: if we can reduce the
number of built-in operator overloads we generate, overload resolution
for these cases will go faster. However, one must be careful when
doing this: GCC generates too few operator overloads in our little
test program, and fails to compile it because none of the overloads it
generates match.
Note that we only support operator overload for non-member binary
operators at the moment. The other operators will follow.
As part of this change, ImplicitCastExpr can now be an lvalue.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59148 91177308-0d34-0410-b5e6-96231b3b80d8
2008-11-12 20:17:38 +03:00
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
case CallExprClass:
|
2008-12-22 08:46:06 +03:00
|
|
|
case CXXOperatorCallExprClass:
|
|
|
|
case CXXMemberCallExprClass: {
|
2009-03-17 02:22:08 +03:00
|
|
|
// C++0x [expr.call]p10
|
2008-10-28 03:22:11 +03:00
|
|
|
// A function call is an lvalue if and only if the result type
|
2009-03-17 02:22:08 +03:00
|
|
|
// is an lvalue reference.
|
2009-05-26 08:57:27 +04:00
|
|
|
QualType ReturnType = cast<CallExpr>(this)->getCallReturnType();
|
|
|
|
if (ReturnType->isLValueReferenceType())
|
|
|
|
return LV_Valid;
|
2009-03-17 02:22:08 +03:00
|
|
|
|
2010-02-17 00:39:57 +03:00
|
|
|
// If the function is returning a class temporary, make a note of
|
|
|
|
// that.
|
|
|
|
if (Ctx.getLangOptions().CPlusPlus && ReturnType->isRecordType())
|
|
|
|
return LV_ClassTemporary;
|
|
|
|
|
2008-10-28 03:22:11 +03:00
|
|
|
break;
|
|
|
|
}
|
2007-12-05 07:00:10 +03:00
|
|
|
case CompoundLiteralExprClass: // C99 6.5.2.5p5
|
2010-02-17 00:39:57 +03:00
|
|
|
// FIXME: Is this what we want in C++?
|
2007-12-05 07:00:10 +03:00
|
|
|
return LV_Valid;
|
2008-12-12 08:35:08 +03:00
|
|
|
case ChooseExprClass:
|
|
|
|
// __builtin_choose_expr is an lvalue if the selected operand is.
|
2009-03-04 08:52:32 +03:00
|
|
|
return cast<ChooseExpr>(this)->getChosenSubExpr(Ctx)->isLvalue(Ctx);
|
2008-04-19 03:10:10 +04:00
|
|
|
case ExtVectorElementExprClass:
|
|
|
|
if (cast<ExtVectorElementExpr>(this)->containsDuplicateElements())
|
2007-07-30 07:29:09 +04:00
|
|
|
return LV_DuplicateVectorComponents;
|
|
|
|
return LV_Valid;
|
2007-11-12 17:34:27 +03:00
|
|
|
case ObjCIvarRefExprClass: // ObjC instance variables are lvalues.
|
|
|
|
return LV_Valid;
|
2008-05-31 03:23:16 +04:00
|
|
|
case ObjCPropertyRefExprClass: // FIXME: check if read-only property.
|
|
|
|
return LV_Valid;
|
2009-08-20 21:02:02 +04:00
|
|
|
case ObjCImplicitSetterGetterRefExprClass: // FIXME: check if read-only property.
|
2008-12-12 08:35:08 +03:00
|
|
|
return LV_Valid;
|
2008-08-10 05:53:14 +04:00
|
|
|
case PredefinedExprClass:
|
2008-11-04 17:32:21 +03:00
|
|
|
return LV_Valid;
|
2009-11-21 11:51:07 +03:00
|
|
|
case UnresolvedLookupExprClass:
|
|
|
|
return LV_Valid;
|
2008-04-08 08:40:51 +04:00
|
|
|
case CXXDefaultArgExprClass:
|
2008-07-27 01:30:36 +04:00
|
|
|
return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx);
|
2008-10-28 18:36:24 +03:00
|
|
|
case CStyleCastExprClass:
|
2008-10-28 03:22:11 +03:00
|
|
|
case CXXFunctionalCastExprClass:
|
|
|
|
case CXXStaticCastExprClass:
|
|
|
|
case CXXDynamicCastExprClass:
|
|
|
|
case CXXReinterpretCastExprClass:
|
|
|
|
case CXXConstCastExprClass:
|
|
|
|
// The result of an explicit cast is an lvalue if the type we are
|
2009-03-17 02:22:08 +03:00
|
|
|
// casting to is an lvalue reference type. See C++ [expr.cast]p1,
|
2008-10-28 03:22:11 +03:00
|
|
|
// C++ [expr.static.cast]p2, C++ [expr.dynamic.cast]p2,
|
|
|
|
// C++ [expr.reinterpret.cast]p1, C++ [expr.const.cast]p1.
|
2009-03-17 02:22:08 +03:00
|
|
|
if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()->
|
|
|
|
isLValueReferenceType())
|
2008-10-28 03:22:11 +03:00
|
|
|
return LV_Valid;
|
2010-02-17 00:39:57 +03:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2008-10-28 03:22:11 +03:00
|
|
|
break;
|
2008-11-11 14:37:55 +03:00
|
|
|
case CXXTypeidExprClass:
|
|
|
|
// C++ 5.2.8p1: The result of a typeid expression is an lvalue of ...
|
|
|
|
return LV_Valid;
|
2009-08-16 07:42:12 +04:00
|
|
|
case CXXBindTemporaryExprClass:
|
|
|
|
return cast<CXXBindTemporaryExpr>(this)->getSubExpr()->
|
|
|
|
isLvalueInternal(Ctx);
|
2010-01-29 05:39:32 +03:00
|
|
|
case CXXBindReferenceExprClass:
|
|
|
|
// Something that's bound to a reference is always an lvalue.
|
|
|
|
return LV_Valid;
|
2009-04-17 20:30:52 +04:00
|
|
|
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);
|
2009-05-20 00:13:50 +04:00
|
|
|
Expr *True = Cond->getTrueExpr();
|
|
|
|
Expr *False = Cond->getFalseExpr();
|
2009-04-17 20:30:52 +04:00
|
|
|
// C++0x 5.16p2
|
|
|
|
// If either the second or the third operand has type (cv) void, [...]
|
|
|
|
// the result [...] is an rvalue.
|
2009-05-20 00:13:50 +04:00
|
|
|
if (True->getType()->isVoidType() || False->getType()->isVoidType())
|
2009-04-17 20:30:52 +04:00
|
|
|
return LV_InvalidExpression;
|
|
|
|
|
|
|
|
// Both sides must be lvalues for the result to be an lvalue.
|
2009-05-20 00:13:50 +04:00
|
|
|
if (True->isLvalue(Ctx) != LV_Valid || False->isLvalue(Ctx) != LV_Valid)
|
2009-04-17 20:30:52 +04:00
|
|
|
return LV_InvalidExpression;
|
|
|
|
|
|
|
|
// That's it.
|
|
|
|
return LV_Valid;
|
|
|
|
}
|
|
|
|
|
2009-12-19 10:07:47 +03:00
|
|
|
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;
|
|
|
|
|
2010-02-17 00:39:57 +03:00
|
|
|
case Expr::CXXConstructExprClass:
|
|
|
|
case Expr::CXXTemporaryObjectExprClass:
|
|
|
|
case Expr::CXXZeroInitValueExprClass:
|
|
|
|
return LV_ClassTemporary;
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
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
|
2009-09-09 19:08:12 +04:00
|
|
|
/// if it is a structure or union, does not have any member (including,
|
2007-07-11 21:01:13 +04:00
|
|
|
/// recursively, any member or element of all contained aggregates or unions)
|
|
|
|
/// with a const-qualified type.
|
2009-09-09 19:08:12 +04:00
|
|
|
Expr::isModifiableLvalueResult
|
2009-04-15 04:08:05 +04:00
|
|
|
Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
|
2008-07-27 01:30:36 +04:00
|
|
|
isLvalueResult lvalResult = isLvalue(Ctx);
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
switch (lvalResult) {
|
2009-09-09 19:08:12 +04:00
|
|
|
case LV_Valid:
|
2008-10-22 04:03:08 +04:00
|
|
|
// C++ 3.10p11: Functions cannot be modified, but pointers to
|
|
|
|
// functions can be modifiable.
|
|
|
|
if (Ctx.getLangOptions().CPlusPlus && TR->isFunctionType())
|
|
|
|
return MLV_NotObjectType;
|
|
|
|
break;
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
case LV_NotObjectType: return MLV_NotObjectType;
|
|
|
|
case LV_IncompleteVoidType: return MLV_IncompleteVoidType;
|
2007-07-30 07:29:09 +04:00
|
|
|
case LV_DuplicateVectorComponents: return MLV_DuplicateVectorComponents;
|
2008-11-17 22:51:54 +03:00
|
|
|
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.
|
2009-04-15 04:08:05 +04:00
|
|
|
if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(IgnoreParens())) {
|
|
|
|
if (CE->getSubExpr()->isLvalue(Ctx) == LV_Valid) {
|
|
|
|
if (Loc)
|
|
|
|
*Loc = CE->getLParenLoc();
|
2008-11-17 22:51:54 +03:00
|
|
|
return MLV_LValueCast;
|
2009-04-15 04:08:05 +04:00
|
|
|
}
|
|
|
|
}
|
2008-11-17 22:51:54 +03:00
|
|
|
return MLV_InvalidExpression;
|
2008-12-21 02:49:58 +03:00
|
|
|
case LV_MemberFunction: return MLV_MemberFunction;
|
2010-02-11 04:11:34 +03:00
|
|
|
case LV_SubObjCPropertySetting: return MLV_SubObjCPropertySetting;
|
2010-02-17 00:39:57 +03:00
|
|
|
case LV_ClassTemporary:
|
|
|
|
return MLV_ClassTemporary;
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2009-03-23 02:26:56 +03:00
|
|
|
|
|
|
|
// The following is illegal:
|
|
|
|
// void takeclosure(void (^C)(void));
|
|
|
|
// void func() { int x = 1; takeclosure(^{ x = 7; }); }
|
|
|
|
//
|
2009-09-14 20:40:48 +04:00
|
|
|
if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(this)) {
|
2009-03-23 02:26:56 +03:00
|
|
|
if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl()))
|
|
|
|
return MLV_NotBlockQualified;
|
|
|
|
}
|
2009-09-17 10:31:17 +04:00
|
|
|
|
2009-09-14 20:40:48 +04:00
|
|
|
// Assigning to an 'implicit' property?
|
2009-09-17 10:31:17 +04:00
|
|
|
if (const ObjCImplicitSetterGetterRefExpr* Expr =
|
2009-09-14 20:40:48 +04:00
|
|
|
dyn_cast<ObjCImplicitSetterGetterRefExpr>(this)) {
|
|
|
|
if (Expr->getSetterMethod() == 0)
|
|
|
|
return MLV_NoSetterProperty;
|
|
|
|
}
|
2009-09-17 10:31:17 +04:00
|
|
|
|
2008-08-04 11:31:14 +04:00
|
|
|
QualType CT = Ctx.getCanonicalType(getType());
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2008-08-04 11:31:14 +04:00
|
|
|
if (CT.isConstQualified())
|
2007-07-11 21:01:13 +04:00
|
|
|
return MLV_ConstQualified;
|
2008-08-04 11:31:14 +04:00
|
|
|
if (CT->isArrayType())
|
2007-07-11 21:01:13 +04:00
|
|
|
return MLV_ArrayType;
|
2008-08-04 11:31:14 +04:00
|
|
|
if (CT->isIncompleteType())
|
2007-07-11 21:01:13 +04:00
|
|
|
return MLV_IncompleteType;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-07-30 01:53:49 +04:00
|
|
|
if (const RecordType *r = CT->getAs<RecordType>()) {
|
2009-09-09 19:08:12 +04:00
|
|
|
if (r->hasConstFields())
|
2007-07-11 21:01:13 +04:00
|
|
|
return MLV_ConstQualified;
|
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
|
|
|
|
return MLV_Valid;
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
|
|
|
|
2009-02-22 21:40:18 +03:00
|
|
|
/// isOBJCGCCandidate - Check if an expression is objc gc'able.
|
2009-09-09 03:38:54 +04:00
|
|
|
/// returns true, if it is; false otherwise.
|
2009-06-02 01:29:32 +04:00
|
|
|
bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
|
2009-02-22 21:40:18 +03:00
|
|
|
switch (getStmtClass()) {
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case ObjCIvarRefExprClass:
|
|
|
|
return true;
|
2009-02-23 21:59:50 +03:00
|
|
|
case Expr::UnaryOperatorClass:
|
2009-06-02 01:29:32 +04:00
|
|
|
return cast<UnaryOperator>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
2009-02-22 21:40:18 +03:00
|
|
|
case ParenExprClass:
|
2009-06-02 01:29:32 +04:00
|
|
|
return cast<ParenExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
2009-02-22 21:40:18 +03:00
|
|
|
case ImplicitCastExprClass:
|
2009-06-02 01:29:32 +04:00
|
|
|
return cast<ImplicitCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
2009-05-06 03:28:21 +04:00
|
|
|
case CStyleCastExprClass:
|
2009-06-02 01:29:32 +04:00
|
|
|
return cast<CStyleCastExpr>(this)->getSubExpr()->isOBJCGCCandidate(Ctx);
|
2009-10-23 22:54:35 +04:00
|
|
|
case DeclRefExprClass: {
|
2009-02-22 21:40:18 +03:00
|
|
|
const Decl *D = cast<DeclRefExpr>(this)->getDecl();
|
2009-06-02 01:29:32 +04:00
|
|
|
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
|
|
|
if (VD->hasGlobalStorage())
|
|
|
|
return true;
|
|
|
|
QualType T = VD->getType();
|
2009-09-16 22:09:18 +04:00
|
|
|
// dereferencing to a pointer is always a gc'able candidate,
|
|
|
|
// unless it is __weak.
|
2009-09-17 10:31:17 +04:00
|
|
|
return T->isPointerType() &&
|
2009-09-24 23:53:00 +04:00
|
|
|
(Ctx.getObjCGCAttrKind(T) != Qualifiers::Weak);
|
2009-06-02 01:29:32 +04:00
|
|
|
}
|
2009-02-22 21:40:18 +03:00
|
|
|
return false;
|
|
|
|
}
|
2009-09-01 03:41:50 +04:00
|
|
|
case MemberExprClass: {
|
2009-02-22 21:40:18 +03:00
|
|
|
const MemberExpr *M = cast<MemberExpr>(this);
|
2009-06-02 01:29:32 +04:00
|
|
|
return M->getBase()->isOBJCGCCandidate(Ctx);
|
2009-02-22 21:40:18 +03:00
|
|
|
}
|
|
|
|
case ArraySubscriptExprClass:
|
2009-06-02 01:29:32 +04:00
|
|
|
return cast<ArraySubscriptExpr>(this)->getBase()->isOBJCGCCandidate(Ctx);
|
2009-02-22 21:40:18 +03:00
|
|
|
}
|
|
|
|
}
|
2008-01-17 19:57:34 +03:00
|
|
|
Expr* Expr::IgnoreParens() {
|
|
|
|
Expr* E = this;
|
|
|
|
while (ParenExpr* P = dyn_cast<ParenExpr>(E))
|
|
|
|
E = P->getSubExpr();
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2008-01-17 19:57:34 +03:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2008-02-13 04:02:39 +03:00
|
|
|
/// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr
|
|
|
|
/// or CastExprs or ImplicitCastExprs, returning their operand.
|
|
|
|
Expr *Expr::IgnoreParenCasts() {
|
|
|
|
Expr *E = this;
|
|
|
|
while (true) {
|
|
|
|
if (ParenExpr *P = dyn_cast<ParenExpr>(E))
|
|
|
|
E = P->getSubExpr();
|
|
|
|
else if (CastExpr *P = dyn_cast<CastExpr>(E))
|
|
|
|
E = P->getSubExpr();
|
|
|
|
else
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-13 20:28:01 +03:00
|
|
|
/// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the
|
|
|
|
/// value (including ptr->int casts of the same size). Strip off any
|
|
|
|
/// ParenExpr or CastExprs, returning their operand.
|
|
|
|
Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
|
|
|
|
Expr *E = this;
|
|
|
|
while (true) {
|
|
|
|
if (ParenExpr *P = dyn_cast<ParenExpr>(E)) {
|
|
|
|
E = P->getSubExpr();
|
|
|
|
continue;
|
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-03-13 20:28:01 +03:00
|
|
|
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.
|
|
|
|
Expr *SE = P->getSubExpr();
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-03-13 20:28:01 +03:00
|
|
|
if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) {
|
|
|
|
E = SE;
|
|
|
|
continue;
|
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-03-13 20:28:01 +03:00
|
|
|
if ((E->getType()->isPointerType() || E->getType()->isIntegralType()) &&
|
|
|
|
(SE->getType()->isPointerType() || SE->getType()->isIntegralType()) &&
|
|
|
|
Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) {
|
|
|
|
E = SE;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-03-13 20:28:01 +03:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-14 22:27:10 +03:00
|
|
|
bool Expr::isDefaultArgument() const {
|
|
|
|
const Expr *E = this;
|
|
|
|
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
|
|
|
|
E = ICE->getSubExprAsWritten();
|
|
|
|
|
|
|
|
return isa<CXXDefaultArgExpr>(E);
|
|
|
|
}
|
2009-03-13 20:28:01 +03:00
|
|
|
|
Rework our handling of copy construction of temporaries, which was a
poor (and wrong) approximation of the actual rules governing when to
build a copy and when it can be elided.
The correct implementation is actually simpler than the
approximation. When we only enumerate constructors as part of
initialization (e.g., for direct initialization or when we're copying
from a class type or one of its derived classes), we don't create a
copy. When we enumerate all conversion functions, we do create a
copy. Before, we created some extra copies and missed some
others. The new test copy-initialization.cpp shows a case where we
missed creating a (required, non-elidable) copy as part of a
user-defined conversion, which resulted in a miscompile. This commit
also fixes PR6757, where the missing copy made us reject well-formed
code in the ternary operator.
This commit also cleans up our handling of copy elision in the case
where we create an extra copy of a temporary object, which became
necessary now that we produce the right copies. The code that seeks to
find the temporary object being copied has moved into
Expr::getTemporaryObject(); it used to have two different
not-quite-the-same implementations, one in Sema and one in CodeGen.
Note that we still do not attempt to perform the named return value
optimization, so we miss copy elisions for return values and throw
expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100196 91177308-0d34-0410-b5e6-96231b3b80d8
2010-04-02 22:24:57 +04:00
|
|
|
/// \brief Skip over any no-op casts and any temporary-binding
|
|
|
|
/// expressions.
|
|
|
|
static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) {
|
|
|
|
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
|
|
|
|
if (ICE->getCastKind() == CastExpr::CK_NoOp)
|
|
|
|
E = ICE->getSubExpr();
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (const CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
|
|
|
|
E = BE->getSubExpr();
|
|
|
|
|
|
|
|
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
|
|
|
|
if (ICE->getCastKind() == CastExpr::CK_NoOp)
|
|
|
|
E = ICE->getSubExpr();
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Expr *Expr::getTemporaryObject() const {
|
|
|
|
const Expr *E = skipTemporaryBindingsAndNoOpCasts(this);
|
|
|
|
|
|
|
|
// A cast can produce a temporary object. The object's construction
|
|
|
|
// is represented as a CXXConstructExpr.
|
|
|
|
if (const CastExpr *Cast = dyn_cast<CastExpr>(E)) {
|
|
|
|
// Only user-defined and constructor conversions can produce
|
|
|
|
// temporary objects.
|
|
|
|
if (Cast->getCastKind() != CastExpr::CK_ConstructorConversion &&
|
|
|
|
Cast->getCastKind() != CastExpr::CK_UserDefinedConversion)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Strip off temporary bindings and no-op casts.
|
|
|
|
const Expr *Sub = skipTemporaryBindingsAndNoOpCasts(Cast->getSubExpr());
|
|
|
|
|
|
|
|
// If this is a constructor conversion, see if we have an object
|
|
|
|
// construction.
|
|
|
|
if (Cast->getCastKind() == CastExpr::CK_ConstructorConversion)
|
|
|
|
return dyn_cast<CXXConstructExpr>(Sub);
|
|
|
|
|
|
|
|
// If this is a user-defined conversion, see if we have a call to
|
|
|
|
// a function that itself returns a temporary object.
|
|
|
|
if (Cast->getCastKind() == CastExpr::CK_UserDefinedConversion)
|
|
|
|
if (const CallExpr *CE = dyn_cast<CallExpr>(Sub))
|
|
|
|
if (CE->getCallReturnType()->isRecordType())
|
|
|
|
return CE;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A call returning a class type returns a temporary.
|
|
|
|
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
|
|
|
|
if (CE->getCallReturnType()->isRecordType())
|
|
|
|
return CE;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Explicit temporary object constructors create temporaries.
|
|
|
|
return dyn_cast<CXXTemporaryObjectExpr>(E);
|
|
|
|
}
|
|
|
|
|
2008-12-06 02:32:09 +03:00
|
|
|
/// hasAnyTypeDependentArguments - Determines if any of the expressions
|
|
|
|
/// in Exprs is type-dependent.
|
|
|
|
bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) {
|
|
|
|
for (unsigned I = 0; I < NumExprs; ++I)
|
|
|
|
if (Exprs[I]->isTypeDependent())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// hasAnyValueDependentArguments - Determines if any of the expressions
|
|
|
|
/// in Exprs is value-dependent.
|
|
|
|
bool Expr::hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs) {
|
|
|
|
for (unsigned I = 0; I < NumExprs; ++I)
|
|
|
|
if (Exprs[I]->isValueDependent())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-01-25 05:32:41 +03:00
|
|
|
bool Expr::isConstantInitializer(ASTContext &Ctx) const {
|
2009-01-25 06:12:18 +03:00
|
|
|
// This function is attempting whether an expression is an initializer
|
|
|
|
// which can be evaluated at compile-time. isEvaluatable handles most
|
|
|
|
// of the cases, but it can't deal with some initializer-specific
|
|
|
|
// expressions, and it can't deal with aggregates; we deal with those here,
|
|
|
|
// and fall back to isEvaluatable for the other cases.
|
|
|
|
|
2009-02-20 05:36:22 +03:00
|
|
|
// FIXME: This function assumes the variable being assigned to
|
|
|
|
// isn't a reference type!
|
|
|
|
|
2008-11-24 08:23:59 +03:00
|
|
|
switch (getStmtClass()) {
|
2009-01-25 06:12:18 +03:00
|
|
|
default: break;
|
2008-11-24 08:23:59 +03:00
|
|
|
case StringLiteralClass:
|
2009-07-11 03:34:53 +04:00
|
|
|
case ObjCStringLiteralClass:
|
2009-02-25 01:18:39 +03:00
|
|
|
case ObjCEncodeExprClass:
|
2008-11-24 08:23:59 +03:00
|
|
|
return true;
|
2009-01-18 06:20:47 +03:00
|
|
|
case CompoundLiteralExprClass: {
|
2009-02-20 05:36:22 +03:00
|
|
|
// This handles gcc's extension that allows global initializers like
|
|
|
|
// "struct x {int x;} x = (struct x) {};".
|
|
|
|
// FIXME: This accepts other cases it shouldn't!
|
2009-01-18 06:20:47 +03:00
|
|
|
const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
|
2009-01-25 05:32:41 +03:00
|
|
|
return Exp->isConstantInitializer(Ctx);
|
2009-01-18 06:20:47 +03:00
|
|
|
}
|
2008-11-24 08:23:59 +03:00
|
|
|
case InitListExprClass: {
|
2009-02-20 05:36:22 +03:00
|
|
|
// FIXME: This doesn't deal with fields with reference types correctly.
|
|
|
|
// FIXME: This incorrectly allows pointers cast to integers to be assigned
|
|
|
|
// to bitfields.
|
2008-11-24 08:23:59 +03:00
|
|
|
const InitListExpr *Exp = cast<InitListExpr>(this);
|
|
|
|
unsigned numInits = Exp->getNumInits();
|
|
|
|
for (unsigned i = 0; i < numInits; i++) {
|
2009-09-09 19:08:12 +04:00
|
|
|
if (!Exp->getInit(i)->isConstantInitializer(Ctx))
|
2008-11-24 08:23:59 +03:00
|
|
|
return false;
|
|
|
|
}
|
2009-01-25 06:12:18 +03:00
|
|
|
return true;
|
2008-11-24 08:23:59 +03:00
|
|
|
}
|
2009-01-29 20:44:32 +03:00
|
|
|
case ImplicitValueInitExprClass:
|
|
|
|
return true;
|
2009-10-13 11:14:16 +04:00
|
|
|
case ParenExprClass:
|
2009-01-25 06:12:18 +03:00
|
|
|
return cast<ParenExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
|
|
|
|
case UnaryOperatorClass: {
|
|
|
|
const UnaryOperator* Exp = cast<UnaryOperator>(this);
|
|
|
|
if (Exp->getOpcode() == UnaryOperator::Extension)
|
|
|
|
return Exp->getSubExpr()->isConstantInitializer(Ctx);
|
|
|
|
break;
|
|
|
|
}
|
2009-10-13 11:14:16 +04:00
|
|
|
case BinaryOperatorClass: {
|
|
|
|
// Special case &&foo - &&bar. It would be nice to generalize this somehow
|
|
|
|
// but this handles the common case.
|
|
|
|
const BinaryOperator *Exp = cast<BinaryOperator>(this);
|
|
|
|
if (Exp->getOpcode() == BinaryOperator::Sub &&
|
|
|
|
isa<AddrLabelExpr>(Exp->getLHS()->IgnoreParenNoopCasts(Ctx)) &&
|
|
|
|
isa<AddrLabelExpr>(Exp->getRHS()->IgnoreParenNoopCasts(Ctx)))
|
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
}
|
2009-04-21 09:19:11 +04:00
|
|
|
case ImplicitCastExprClass:
|
2009-01-25 06:12:18 +03:00
|
|
|
case CStyleCastExprClass:
|
|
|
|
// Handle casts with a destination that's a struct or union; this
|
|
|
|
// deals with both the gcc no-op struct cast extension and the
|
|
|
|
// cast-to-union extension.
|
|
|
|
if (getType()->isRecordType())
|
|
|
|
return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
|
2009-10-14 02:12:09 +04:00
|
|
|
|
|
|
|
// Integer->integer casts can be handled here, which is important for
|
|
|
|
// things like (int)(&&x-&&y). Scary but true.
|
|
|
|
if (getType()->isIntegerType() &&
|
|
|
|
cast<CastExpr>(this)->getSubExpr()->getType()->isIntegerType())
|
|
|
|
return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
|
|
|
|
|
2009-01-25 06:12:18 +03:00
|
|
|
break;
|
2008-11-24 08:23:59 +03:00
|
|
|
}
|
2009-01-25 06:12:18 +03:00
|
|
|
return isEvaluatable(Ctx);
|
2007-09-03 00:30:18 +04:00
|
|
|
}
|
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
/// isIntegerConstantExpr - this recursive routine will test if an expression is
|
2009-02-26 12:29:13 +03:00
|
|
|
/// an integer constant expression.
|
2007-07-11 21:01:13 +04:00
|
|
|
|
|
|
|
/// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero,
|
|
|
|
/// comma, etc
|
|
|
|
///
|
2007-07-18 09:21:20 +04:00
|
|
|
/// FIXME: Handle offsetof. Two things to do: Handle GCC's __builtin_offsetof
|
|
|
|
/// to support gcc 4.0+ and handle the idiom GCC recognizes with a null pointer
|
|
|
|
/// cast+dereference.
|
2009-02-18 03:47:45 +03:00
|
|
|
|
2009-02-26 12:29:13 +03:00
|
|
|
// CheckICE - This function does the fundamental ICE checking: the returned
|
|
|
|
// ICEDiag contains a Val of 0, 1, or 2, and a possibly null SourceLocation.
|
|
|
|
// Note that to reduce code duplication, this helper does no evaluation
|
2009-09-09 19:08:12 +04:00
|
|
|
// itself; the caller checks whether the expression is evaluatable, and
|
2009-02-26 12:29:13 +03:00
|
|
|
// in the rare cases where CheckICE actually cares about the evaluated
|
2009-09-09 19:08:12 +04:00
|
|
|
// value, it calls into Evalute.
|
2009-02-26 12:29:13 +03:00
|
|
|
//
|
|
|
|
// Meanings of Val:
|
|
|
|
// 0: This expression is an ICE if it can be evaluated by Evaluate.
|
|
|
|
// 1: This expression is not an ICE, but if it isn't evaluated, it's
|
|
|
|
// a legal subexpression for an ICE. This return value is used to handle
|
|
|
|
// the comma operator in C99 mode.
|
|
|
|
// 2: This expression is not an ICE, and is not a legal subexpression for one.
|
|
|
|
|
|
|
|
struct ICEDiag {
|
|
|
|
unsigned Val;
|
|
|
|
SourceLocation Loc;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ICEDiag(unsigned v, SourceLocation l) : Val(v), Loc(l) {}
|
|
|
|
ICEDiag() : Val(0) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
ICEDiag NoDiag() { return ICEDiag(); }
|
|
|
|
|
2009-02-27 07:07:58 +03:00
|
|
|
static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) {
|
|
|
|
Expr::EvalResult EVResult;
|
|
|
|
if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects ||
|
|
|
|
!EVResult.Val.isInt()) {
|
|
|
|
return ICEDiag(2, E->getLocStart());
|
|
|
|
}
|
|
|
|
return NoDiag();
|
|
|
|
}
|
|
|
|
|
2009-02-26 12:29:13 +03:00
|
|
|
static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
|
2009-03-14 03:33:21 +03:00
|
|
|
assert(!E->isValueDependent() && "Should not see value dependent exprs!");
|
2009-02-26 12:29:13 +03:00
|
|
|
if (!E->getType()->isIntegralType()) {
|
|
|
|
return ICEDiag(2, E->getLocStart());
|
2008-11-13 09:09:17 +03:00
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
|
|
|
|
switch (E->getStmtClass()) {
|
2009-09-11 03:31:45 +04:00
|
|
|
#define STMT(Node, Base) case Expr::Node##Class:
|
|
|
|
#define EXPR(Node, Base)
|
|
|
|
#include "clang/AST/StmtNodes.def"
|
|
|
|
case Expr::PredefinedExprClass:
|
|
|
|
case Expr::FloatingLiteralClass:
|
|
|
|
case Expr::ImaginaryLiteralClass:
|
|
|
|
case Expr::StringLiteralClass:
|
|
|
|
case Expr::ArraySubscriptExprClass:
|
|
|
|
case Expr::MemberExprClass:
|
|
|
|
case Expr::CompoundAssignOperatorClass:
|
|
|
|
case Expr::CompoundLiteralExprClass:
|
|
|
|
case Expr::ExtVectorElementExprClass:
|
|
|
|
case Expr::InitListExprClass:
|
|
|
|
case Expr::DesignatedInitExprClass:
|
|
|
|
case Expr::ImplicitValueInitExprClass:
|
|
|
|
case Expr::ParenListExprClass:
|
|
|
|
case Expr::VAArgExprClass:
|
|
|
|
case Expr::AddrLabelExprClass:
|
|
|
|
case Expr::StmtExprClass:
|
|
|
|
case Expr::CXXMemberCallExprClass:
|
|
|
|
case Expr::CXXDynamicCastExprClass:
|
|
|
|
case Expr::CXXTypeidExprClass:
|
|
|
|
case Expr::CXXNullPtrLiteralExprClass:
|
|
|
|
case Expr::CXXThisExprClass:
|
|
|
|
case Expr::CXXThrowExprClass:
|
|
|
|
case Expr::CXXNewExprClass:
|
|
|
|
case Expr::CXXDeleteExprClass:
|
|
|
|
case Expr::CXXPseudoDestructorExprClass:
|
2009-11-21 11:51:07 +03:00
|
|
|
case Expr::UnresolvedLookupExprClass:
|
2009-11-20 01:55:06 +03:00
|
|
|
case Expr::DependentScopeDeclRefExprClass:
|
2009-09-11 03:31:45 +04:00
|
|
|
case Expr::CXXConstructExprClass:
|
|
|
|
case Expr::CXXBindTemporaryExprClass:
|
2010-01-29 05:39:32 +03:00
|
|
|
case Expr::CXXBindReferenceExprClass:
|
2009-09-11 03:31:45 +04:00
|
|
|
case Expr::CXXExprWithTemporariesClass:
|
|
|
|
case Expr::CXXTemporaryObjectExprClass:
|
|
|
|
case Expr::CXXUnresolvedConstructExprClass:
|
2009-11-20 01:55:06 +03:00
|
|
|
case Expr::CXXDependentScopeMemberExprClass:
|
2009-12-01 01:42:35 +03:00
|
|
|
case Expr::UnresolvedMemberExprClass:
|
2009-09-11 03:31:45 +04:00
|
|
|
case Expr::ObjCStringLiteralClass:
|
|
|
|
case Expr::ObjCEncodeExprClass:
|
|
|
|
case Expr::ObjCMessageExprClass:
|
|
|
|
case Expr::ObjCSelectorExprClass:
|
|
|
|
case Expr::ObjCProtocolExprClass:
|
|
|
|
case Expr::ObjCIvarRefExprClass:
|
|
|
|
case Expr::ObjCPropertyRefExprClass:
|
|
|
|
case Expr::ObjCImplicitSetterGetterRefExprClass:
|
|
|
|
case Expr::ObjCSuperExprClass:
|
|
|
|
case Expr::ObjCIsaExprClass:
|
|
|
|
case Expr::ShuffleVectorExprClass:
|
|
|
|
case Expr::BlockExprClass:
|
|
|
|
case Expr::BlockDeclRefExprClass:
|
|
|
|
case Expr::NoStmtClass:
|
2009-02-26 12:29:13 +03:00
|
|
|
return ICEDiag(2, E->getLocStart());
|
2009-09-17 10:31:17 +04:00
|
|
|
|
2009-09-11 04:18:58 +04:00
|
|
|
case Expr::GNUNullExprClass:
|
|
|
|
// GCC considers the GNU __null value to be an integral constant expression.
|
|
|
|
return NoDiag();
|
2009-09-17 10:31:17 +04:00
|
|
|
|
2009-02-26 12:29:13 +03:00
|
|
|
case Expr::ParenExprClass:
|
|
|
|
return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
|
|
|
|
case Expr::IntegerLiteralClass:
|
|
|
|
case Expr::CharacterLiteralClass:
|
|
|
|
case Expr::CXXBoolLiteralExprClass:
|
|
|
|
case Expr::CXXZeroInitValueExprClass:
|
|
|
|
case Expr::TypesCompatibleExprClass:
|
|
|
|
case Expr::UnaryTypeTraitExprClass:
|
|
|
|
return NoDiag();
|
2009-09-09 19:08:12 +04:00
|
|
|
case Expr::CallExprClass:
|
2009-02-26 12:29:13 +03:00
|
|
|
case Expr::CXXOperatorCallExprClass: {
|
|
|
|
const CallExpr *CE = cast<CallExpr>(E);
|
2009-02-27 07:07:58 +03:00
|
|
|
if (CE->isBuiltinCall(Ctx))
|
|
|
|
return CheckEvalInICE(E, Ctx);
|
2009-02-26 12:29:13 +03:00
|
|
|
return ICEDiag(2, E->getLocStart());
|
2007-08-09 02:15:55 +04:00
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
case Expr::DeclRefExprClass:
|
|
|
|
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
|
|
|
|
return NoDiag();
|
2009-02-07 16:06:23 +03:00
|
|
|
if (Ctx.getLangOptions().CPlusPlus &&
|
2009-09-24 23:53:00 +04:00
|
|
|
E->getType().getCVRQualifiers() == Qualifiers::Const) {
|
2010-02-24 12:03:18 +03:00
|
|
|
const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
|
|
|
|
|
|
|
|
// Parameter variables are never constants. Without this check,
|
|
|
|
// getAnyInitializer() can find a default argument, which leads
|
|
|
|
// to chaos.
|
|
|
|
if (isa<ParmVarDecl>(D))
|
|
|
|
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
|
|
|
|
2009-02-07 16:06:23 +03:00
|
|
|
// C++ 7.1.5.1p2
|
|
|
|
// A variable of non-volatile const-qualified integral or enumeration
|
|
|
|
// type initialized by an ICE can be used in ICEs.
|
2010-02-24 12:03:18 +03:00
|
|
|
if (const VarDecl *Dcl = dyn_cast<VarDecl>(D)) {
|
2009-11-01 23:32:48 +03:00
|
|
|
Qualifiers Quals = Ctx.getCanonicalType(Dcl->getType()).getQualifiers();
|
|
|
|
if (Quals.hasVolatile() || !Quals.hasConst())
|
|
|
|
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
|
|
|
|
2010-02-01 23:16:42 +03:00
|
|
|
// Look for a declaration of this variable that has an initializer.
|
|
|
|
const VarDecl *ID = 0;
|
|
|
|
const Expr *Init = Dcl->getAnyInitializer(ID);
|
2009-11-01 23:32:48 +03:00
|
|
|
if (Init) {
|
2010-02-01 23:16:42 +03:00
|
|
|
if (ID->isInitKnownICE()) {
|
2009-11-01 23:32:48 +03:00
|
|
|
// We have already checked whether this subexpression is an
|
|
|
|
// integral constant expression.
|
2010-02-01 23:16:42 +03:00
|
|
|
if (ID->isInitICE())
|
2009-11-01 23:32:48 +03:00
|
|
|
return NoDiag();
|
|
|
|
else
|
|
|
|
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
|
|
|
}
|
2009-05-26 22:54:04 +04:00
|
|
|
|
2010-02-06 04:07:37 +03:00
|
|
|
// It's an ICE whether or not the definition we found is
|
|
|
|
// out-of-line. See DR 721 and the discussion in Clang PR
|
|
|
|
// 6206 for details.
|
2009-12-03 23:31:57 +03:00
|
|
|
|
|
|
|
if (Dcl->isCheckingICE()) {
|
|
|
|
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
|
|
|
|
}
|
|
|
|
|
|
|
|
Dcl->setCheckingICE();
|
2009-05-26 22:54:04 +04:00
|
|
|
ICEDiag Result = CheckICE(Init, Ctx);
|
|
|
|
// Cache the result of the ICE test.
|
2009-12-03 23:31:57 +03:00
|
|
|
Dcl->setInitKnownICE(Result.Val == 0);
|
2009-05-26 22:54:04 +04:00
|
|
|
return Result;
|
|
|
|
}
|
2009-02-07 16:06:23 +03:00
|
|
|
}
|
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
return ICEDiag(2, E->getLocStart());
|
|
|
|
case Expr::UnaryOperatorClass: {
|
|
|
|
const UnaryOperator *Exp = cast<UnaryOperator>(E);
|
2007-07-11 21:01:13 +04:00
|
|
|
switch (Exp->getOpcode()) {
|
2009-09-11 03:31:45 +04:00
|
|
|
case UnaryOperator::PostInc:
|
|
|
|
case UnaryOperator::PostDec:
|
|
|
|
case UnaryOperator::PreInc:
|
|
|
|
case UnaryOperator::PreDec:
|
|
|
|
case UnaryOperator::AddrOf:
|
|
|
|
case UnaryOperator::Deref:
|
2009-02-26 12:29:13 +03:00
|
|
|
return ICEDiag(2, E->getLocStart());
|
2009-09-17 10:31:17 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
case UnaryOperator::Extension:
|
2009-02-26 12:29:13 +03:00
|
|
|
case UnaryOperator::LNot:
|
2007-07-11 21:01:13 +04:00
|
|
|
case UnaryOperator::Plus:
|
|
|
|
case UnaryOperator::Minus:
|
|
|
|
case UnaryOperator::Not:
|
2009-02-27 07:07:58 +03:00
|
|
|
case UnaryOperator::Real:
|
|
|
|
case UnaryOperator::Imag:
|
2009-02-26 12:29:13 +03:00
|
|
|
return CheckICE(Exp->getSubExpr(), Ctx);
|
2008-01-29 18:56:48 +03:00
|
|
|
case UnaryOperator::OffsetOf:
|
2009-02-27 07:07:58 +03:00
|
|
|
// Note that per C99, offsetof must be an ICE. And AFAIK, using
|
|
|
|
// Evaluate matches the proposed gcc behavior for cases like
|
|
|
|
// "offsetof(struct s{int x[4];}, x[!.0])". This doesn't affect
|
|
|
|
// compliance: we should warn earlier for offsetof expressions with
|
|
|
|
// array subscripts that aren't ICEs, and if the array subscripts
|
|
|
|
// are ICEs, the value of the offsetof must be an integer constant.
|
|
|
|
return CheckEvalInICE(E, Ctx);
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
case Expr::SizeOfAlignOfExprClass: {
|
|
|
|
const SizeOfAlignOfExpr *Exp = cast<SizeOfAlignOfExpr>(E);
|
|
|
|
if (Exp->isSizeOf() && Exp->getTypeOfArgument()->isVariableArrayType())
|
|
|
|
return ICEDiag(2, E->getLocStart());
|
|
|
|
return NoDiag();
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
case Expr::BinaryOperatorClass: {
|
|
|
|
const BinaryOperator *Exp = cast<BinaryOperator>(E);
|
2007-07-11 21:01:13 +04:00
|
|
|
switch (Exp->getOpcode()) {
|
2009-09-11 03:31:45 +04:00
|
|
|
case BinaryOperator::PtrMemD:
|
|
|
|
case BinaryOperator::PtrMemI:
|
|
|
|
case BinaryOperator::Assign:
|
|
|
|
case BinaryOperator::MulAssign:
|
|
|
|
case BinaryOperator::DivAssign:
|
|
|
|
case BinaryOperator::RemAssign:
|
|
|
|
case BinaryOperator::AddAssign:
|
|
|
|
case BinaryOperator::SubAssign:
|
|
|
|
case BinaryOperator::ShlAssign:
|
|
|
|
case BinaryOperator::ShrAssign:
|
|
|
|
case BinaryOperator::AndAssign:
|
|
|
|
case BinaryOperator::XorAssign:
|
|
|
|
case BinaryOperator::OrAssign:
|
2009-02-26 12:29:13 +03:00
|
|
|
return ICEDiag(2, E->getLocStart());
|
2009-09-17 10:31:17 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
case BinaryOperator::Mul:
|
|
|
|
case BinaryOperator::Div:
|
|
|
|
case BinaryOperator::Rem:
|
2009-02-26 12:29:13 +03:00
|
|
|
case BinaryOperator::Add:
|
|
|
|
case BinaryOperator::Sub:
|
2007-07-11 21:01:13 +04:00
|
|
|
case BinaryOperator::Shl:
|
|
|
|
case BinaryOperator::Shr:
|
2009-02-26 12:29:13 +03:00
|
|
|
case BinaryOperator::LT:
|
|
|
|
case BinaryOperator::GT:
|
|
|
|
case BinaryOperator::LE:
|
|
|
|
case BinaryOperator::GE:
|
|
|
|
case BinaryOperator::EQ:
|
|
|
|
case BinaryOperator::NE:
|
|
|
|
case BinaryOperator::And:
|
|
|
|
case BinaryOperator::Xor:
|
|
|
|
case BinaryOperator::Or:
|
|
|
|
case BinaryOperator::Comma: {
|
|
|
|
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
|
|
|
|
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
|
2009-02-27 07:07:58 +03:00
|
|
|
if (Exp->getOpcode() == BinaryOperator::Div ||
|
|
|
|
Exp->getOpcode() == BinaryOperator::Rem) {
|
|
|
|
// Evaluate gives an error for undefined Div/Rem, so make sure
|
|
|
|
// we don't evaluate one.
|
|
|
|
if (LHSResult.Val != 2 && RHSResult.Val != 2) {
|
|
|
|
llvm::APSInt REval = Exp->getRHS()->EvaluateAsInt(Ctx);
|
|
|
|
if (REval == 0)
|
|
|
|
return ICEDiag(1, E->getLocStart());
|
|
|
|
if (REval.isSigned() && REval.isAllOnesValue()) {
|
|
|
|
llvm::APSInt LEval = Exp->getLHS()->EvaluateAsInt(Ctx);
|
|
|
|
if (LEval.isMinSignedValue())
|
|
|
|
return ICEDiag(1, E->getLocStart());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Exp->getOpcode() == BinaryOperator::Comma) {
|
|
|
|
if (Ctx.getLangOptions().C99) {
|
|
|
|
// C99 6.6p3 introduces a strange edge case: comma can be in an ICE
|
|
|
|
// if it isn't evaluated.
|
|
|
|
if (LHSResult.Val == 0 && RHSResult.Val == 0)
|
|
|
|
return ICEDiag(1, E->getLocStart());
|
|
|
|
} else {
|
|
|
|
// In both C89 and C++, commas in ICEs are illegal.
|
|
|
|
return ICEDiag(2, E->getLocStart());
|
|
|
|
}
|
2008-11-13 05:13:11 +03:00
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
if (LHSResult.Val >= RHSResult.Val)
|
|
|
|
return LHSResult;
|
|
|
|
return RHSResult;
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
case BinaryOperator::LAnd:
|
|
|
|
case BinaryOperator::LOr: {
|
|
|
|
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
|
|
|
|
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
|
|
|
|
if (LHSResult.Val == 0 && RHSResult.Val == 1) {
|
|
|
|
// Rare case where the RHS has a comma "side-effect"; we need
|
|
|
|
// to actually check the condition to see whether the side
|
|
|
|
// with the comma is evaluated.
|
|
|
|
if ((Exp->getOpcode() == BinaryOperator::LAnd) !=
|
2009-02-27 07:07:58 +03:00
|
|
|
(Exp->getLHS()->EvaluateAsInt(Ctx) == 0))
|
2009-02-26 12:29:13 +03:00
|
|
|
return RHSResult;
|
|
|
|
return NoDiag();
|
2009-02-18 03:32:53 +03:00
|
|
|
}
|
2009-02-27 07:07:58 +03:00
|
|
|
|
2009-02-26 12:29:13 +03:00
|
|
|
if (LHSResult.Val >= RHSResult.Val)
|
|
|
|
return LHSResult;
|
|
|
|
return RHSResult;
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2007-09-22 23:04:13 +04:00
|
|
|
}
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
case Expr::ImplicitCastExprClass:
|
|
|
|
case Expr::CStyleCastExprClass:
|
2009-09-10 21:44:23 +04:00
|
|
|
case Expr::CXXFunctionalCastExprClass:
|
2009-09-11 03:31:45 +04:00
|
|
|
case Expr::CXXNamedCastExprClass:
|
2009-09-10 21:44:23 +04:00
|
|
|
case Expr::CXXStaticCastExprClass:
|
|
|
|
case Expr::CXXReinterpretCastExprClass:
|
|
|
|
case Expr::CXXConstCastExprClass: {
|
2009-02-26 12:29:13 +03:00
|
|
|
const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
|
|
|
|
if (SubExpr->getType()->isIntegralType())
|
|
|
|
return CheckICE(SubExpr, Ctx);
|
|
|
|
if (isa<FloatingLiteral>(SubExpr->IgnoreParens()))
|
|
|
|
return NoDiag();
|
|
|
|
return ICEDiag(2, E->getLocStart());
|
|
|
|
}
|
|
|
|
case Expr::ConditionalOperatorClass: {
|
|
|
|
const ConditionalOperator *Exp = cast<ConditionalOperator>(E);
|
2009-09-09 19:08:12 +04:00
|
|
|
// If the condition (ignoring parens) is a __builtin_constant_p call,
|
2008-12-12 09:55:44 +03:00
|
|
|
// then only the true side is actually considered in an integer constant
|
2008-12-12 21:00:51 +03:00
|
|
|
// expression, and it is fully evaluated. This is an important GNU
|
|
|
|
// extension. See GCC PR38377 for discussion.
|
2009-02-26 12:29:13 +03:00
|
|
|
if (const CallExpr *CallCE = dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts()))
|
2009-02-14 21:57:46 +03:00
|
|
|
if (CallCE->isBuiltinCall(Ctx) == Builtin::BI__builtin_constant_p) {
|
2009-02-26 12:29:13 +03:00
|
|
|
Expr::EvalResult EVResult;
|
|
|
|
if (!E->Evaluate(EVResult, Ctx) || EVResult.HasSideEffects ||
|
|
|
|
!EVResult.Val.isInt()) {
|
2009-02-27 07:07:58 +03:00
|
|
|
return ICEDiag(2, E->getLocStart());
|
2009-02-26 12:29:13 +03:00
|
|
|
}
|
|
|
|
return NoDiag();
|
2008-12-12 21:00:51 +03:00
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx);
|
|
|
|
ICEDiag TrueResult = CheckICE(Exp->getTrueExpr(), Ctx);
|
|
|
|
ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx);
|
|
|
|
if (CondResult.Val == 2)
|
|
|
|
return CondResult;
|
|
|
|
if (TrueResult.Val == 2)
|
|
|
|
return TrueResult;
|
|
|
|
if (FalseResult.Val == 2)
|
|
|
|
return FalseResult;
|
|
|
|
if (CondResult.Val == 1)
|
|
|
|
return CondResult;
|
|
|
|
if (TrueResult.Val == 0 && FalseResult.Val == 0)
|
|
|
|
return NoDiag();
|
|
|
|
// Rare case where the diagnostics depend on which side is evaluated
|
|
|
|
// Note that if we get here, CondResult is 0, and at least one of
|
|
|
|
// TrueResult and FalseResult is non-zero.
|
2009-02-27 07:07:58 +03:00
|
|
|
if (Exp->getCond()->EvaluateAsInt(Ctx) == 0) {
|
2009-02-26 12:29:13 +03:00
|
|
|
return FalseResult;
|
|
|
|
}
|
|
|
|
return TrueResult;
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2009-02-26 12:29:13 +03:00
|
|
|
case Expr::CXXDefaultArgExprClass:
|
|
|
|
return CheckICE(cast<CXXDefaultArgExpr>(E)->getExpr(), Ctx);
|
2009-02-27 07:07:58 +03:00
|
|
|
case Expr::ChooseExprClass: {
|
2009-03-04 08:52:32 +03:00
|
|
|
return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(Ctx), Ctx);
|
2009-02-27 07:07:58 +03:00
|
|
|
}
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2009-09-17 10:31:17 +04:00
|
|
|
|
2009-09-11 03:31:45 +04:00
|
|
|
// Silence a GCC warning
|
|
|
|
return ICEDiag(2, E->getLocStart());
|
2009-02-26 12:29:13 +03:00
|
|
|
}
|
2007-07-11 21:01:13 +04:00
|
|
|
|
2009-02-26 12:29:13 +03:00
|
|
|
bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
|
|
|
|
SourceLocation *Loc, bool isEvaluated) const {
|
|
|
|
ICEDiag d = CheckICE(this, Ctx);
|
|
|
|
if (d.Val != 0) {
|
|
|
|
if (Loc) *Loc = d.Loc;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
EvalResult EvalResult;
|
2009-02-27 07:07:58 +03:00
|
|
|
if (!Evaluate(EvalResult, Ctx))
|
2009-12-12 08:05:38 +03:00
|
|
|
llvm_unreachable("ICE cannot be evaluated!");
|
2009-02-27 07:07:58 +03:00
|
|
|
assert(!EvalResult.HasSideEffects && "ICE with side effects!");
|
|
|
|
assert(EvalResult.Val.isInt() && "ICE that isn't integer!");
|
2009-02-26 12:29:13 +03:00
|
|
|
Result = EvalResult.Val.getInt();
|
2007-07-11 21:01:13 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// isNullPointerConstant - C99 6.3.2.3p3 - Return true if this is either an
|
|
|
|
/// integer constant expression with the value zero, or if this is one that is
|
|
|
|
/// cast to void*.
|
2009-09-25 08:25:58 +04:00
|
|
|
bool Expr::isNullPointerConstant(ASTContext &Ctx,
|
|
|
|
NullPointerConstantValueDependence NPC) const {
|
|
|
|
if (isValueDependent()) {
|
|
|
|
switch (NPC) {
|
|
|
|
case NPC_NeverValueDependent:
|
|
|
|
assert(false && "Unexpected value dependent expression!");
|
|
|
|
// If the unthinkable happens, fall through to the safest alternative.
|
|
|
|
|
|
|
|
case NPC_ValueDependentIsNull:
|
|
|
|
return isTypeDependent() || getType()->isIntegralType();
|
|
|
|
|
|
|
|
case NPC_ValueDependentIsNotNull:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2009-09-18 12:46:16 +04:00
|
|
|
|
2008-10-31 17:43:28 +03:00
|
|
|
// Strip off a cast to void*, if it exists. Except in C++.
|
2008-08-19 03:01:59 +04:00
|
|
|
if (const ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(this)) {
|
2008-11-04 14:45:54 +03:00
|
|
|
if (!Ctx.getLangOptions().CPlusPlus) {
|
2008-10-31 17:43:28 +03:00
|
|
|
// Check that it is a cast to void*.
|
2009-07-30 01:53:49 +04:00
|
|
|
if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
|
2008-10-31 17:43:28 +03:00
|
|
|
QualType Pointee = PT->getPointeeType();
|
2009-09-24 23:53:00 +04:00
|
|
|
if (!Pointee.hasQualifiers() &&
|
2008-10-31 17:43:28 +03:00
|
|
|
Pointee->isVoidType() && // to void*
|
|
|
|
CE->getSubExpr()->getType()->isIntegerType()) // from int.
|
2009-09-25 08:25:58 +04:00
|
|
|
return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
|
2008-10-31 17:43:28 +03:00
|
|
|
}
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2008-01-14 19:10:57 +03:00
|
|
|
} else if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(this)) {
|
|
|
|
// Ignore the ImplicitCastExpr type entirely.
|
2009-09-25 08:25:58 +04:00
|
|
|
return ICE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
|
2008-01-14 19:10:57 +03:00
|
|
|
} else if (const ParenExpr *PE = dyn_cast<ParenExpr>(this)) {
|
|
|
|
// Accept ((void*)0) as a null pointer constant, as many other
|
|
|
|
// implementations do.
|
2009-09-25 08:25:58 +04:00
|
|
|
return PE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
|
2009-09-09 19:08:12 +04:00
|
|
|
} else if (const CXXDefaultArgExpr *DefaultArg
|
2008-04-10 06:22:51 +04:00
|
|
|
= dyn_cast<CXXDefaultArgExpr>(this)) {
|
2008-04-08 08:40:51 +04:00
|
|
|
// See through default argument expressions
|
2009-09-25 08:25:58 +04:00
|
|
|
return DefaultArg->getExpr()->isNullPointerConstant(Ctx, NPC);
|
2008-11-29 07:51:27 +03:00
|
|
|
} else if (isa<GNUNullExpr>(this)) {
|
|
|
|
// The GNU __null extension is always a null pointer constant.
|
|
|
|
return true;
|
2008-01-14 05:53:34 +03:00
|
|
|
}
|
2008-11-29 07:51:27 +03:00
|
|
|
|
2009-05-10 22:38:11 +04:00
|
|
|
// C++0x nullptr_t is always a null pointer constant.
|
|
|
|
if (getType()->isNullPtrType())
|
|
|
|
return true;
|
|
|
|
|
2008-01-14 19:10:57 +03:00
|
|
|
// This expression must be an integer type.
|
2009-10-06 04:09:31 +04:00
|
|
|
if (!getType()->isIntegerType() ||
|
|
|
|
(Ctx.getLangOptions().CPlusPlus && getType()->isEnumeralType()))
|
2008-01-14 19:10:57 +03:00
|
|
|
return false;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2007-07-11 21:01:13 +04:00
|
|
|
// If we have an integer constant expression, we need to *evaluate* it and
|
|
|
|
// test for the value 0.
|
2009-04-26 02:37:12 +04:00
|
|
|
llvm::APSInt Result;
|
|
|
|
return isIntegerConstantExpr(Result, Ctx) && Result == 0;
|
2007-07-11 21:01:13 +04:00
|
|
|
}
|
2007-07-29 03:10:27 +04:00
|
|
|
|
2009-05-02 06:18:30 +04:00
|
|
|
FieldDecl *Expr::getBitField() {
|
2009-07-06 19:38:40 +04:00
|
|
|
Expr *E = this->IgnoreParens();
|
2009-05-02 06:18:30 +04:00
|
|
|
|
2010-01-29 22:14:02 +03:00
|
|
|
while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
|
|
|
|
if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
|
|
|
|
E = ICE->getSubExpr()->IgnoreParens();
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-10-29 03:13:59 +03:00
|
|
|
if (MemberExpr *MemRef = dyn_cast<MemberExpr>(E))
|
2008-12-21 02:49:58 +03:00
|
|
|
if (FieldDecl *Field = dyn_cast<FieldDecl>(MemRef->getMemberDecl()))
|
2009-05-02 06:18:30 +04:00
|
|
|
if (Field->isBitField())
|
|
|
|
return Field;
|
|
|
|
|
|
|
|
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E))
|
|
|
|
if (BinOp->isAssignmentOp() && BinOp->getLHS())
|
|
|
|
return BinOp->getLHS()->getBitField();
|
|
|
|
|
|
|
|
return 0;
|
2008-10-29 03:13:59 +03:00
|
|
|
}
|
|
|
|
|
2010-01-31 20:18:49 +03:00
|
|
|
bool Expr::refersToVectorElement() const {
|
|
|
|
const Expr *E = this->IgnoreParens();
|
|
|
|
|
|
|
|
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
|
|
|
|
if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
|
|
|
|
E = ICE->getSubExpr()->IgnoreParens();
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E))
|
|
|
|
return ASE->getBase()->getType()->isVectorType();
|
|
|
|
|
|
|
|
if (isa<ExtVectorElementExpr>(E))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-02-17 01:14:05 +03:00
|
|
|
/// isArrow - Return true if the base expression is a pointer to vector,
|
|
|
|
/// return false if the base expression is a vector.
|
|
|
|
bool ExtVectorElementExpr::isArrow() const {
|
|
|
|
return getBase()->getType()->isPointerType();
|
|
|
|
}
|
|
|
|
|
2008-04-19 03:10:10 +04:00
|
|
|
unsigned ExtVectorElementExpr::getNumElements() const {
|
2009-09-22 03:43:11 +04:00
|
|
|
if (const VectorType *VT = getType()->getAs<VectorType>())
|
2008-05-09 10:41:27 +04:00
|
|
|
return VT->getNumElements();
|
|
|
|
return 1;
|
2007-08-03 20:00:20 +04:00
|
|
|
}
|
|
|
|
|
2008-05-09 10:41:27 +04:00
|
|
|
/// containsDuplicateElements - Return true if any element access is repeated.
|
2008-04-19 03:10:10 +04:00
|
|
|
bool ExtVectorElementExpr::containsDuplicateElements() const {
|
2009-10-18 06:09:09 +04:00
|
|
|
// FIXME: Refactor this code to an accessor on the AST node which returns the
|
|
|
|
// "type" of component access, and share with code below and in Sema.
|
2009-10-19 01:17:35 +04:00
|
|
|
llvm::StringRef Comp = Accessor->getName();
|
2009-01-18 05:01:21 +03:00
|
|
|
|
|
|
|
// Halving swizzles do not contain duplicate elements.
|
2009-10-18 03:53:04 +04:00
|
|
|
if (Comp == "hi" || Comp == "lo" || Comp == "even" || Comp == "odd")
|
2009-01-18 05:01:21 +03:00
|
|
|
return false;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-01-18 05:01:21 +03:00
|
|
|
// Advance past s-char prefix on hex swizzles.
|
2009-10-18 03:53:04 +04:00
|
|
|
if (Comp[0] == 's' || Comp[0] == 'S')
|
|
|
|
Comp = Comp.substr(1);
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-10-18 03:53:04 +04:00
|
|
|
for (unsigned i = 0, e = Comp.size(); i != e; ++i)
|
|
|
|
if (Comp.substr(i + 1).find(Comp[i]) != llvm::StringRef::npos)
|
2007-07-30 07:29:09 +04:00
|
|
|
return true;
|
2009-10-18 03:53:04 +04:00
|
|
|
|
2007-07-30 07:29:09 +04:00
|
|
|
return false;
|
|
|
|
}
|
2007-08-03 03:36:59 +04:00
|
|
|
|
2008-05-09 10:41:27 +04:00
|
|
|
/// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.
|
2008-05-14 01:03:02 +04:00
|
|
|
void ExtVectorElementExpr::getEncodedElementAccess(
|
|
|
|
llvm::SmallVectorImpl<unsigned> &Elts) const {
|
2009-10-18 06:09:31 +04:00
|
|
|
llvm::StringRef Comp = Accessor->getName();
|
|
|
|
if (Comp[0] == 's' || Comp[0] == 'S')
|
|
|
|
Comp = Comp.substr(1);
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-10-18 06:09:31 +04:00
|
|
|
bool isHi = Comp == "hi";
|
|
|
|
bool isLo = Comp == "lo";
|
|
|
|
bool isEven = Comp == "even";
|
|
|
|
bool isOdd = Comp == "odd";
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2008-05-09 10:41:27 +04:00
|
|
|
for (unsigned i = 0, e = getNumElements(); i != e; ++i) {
|
|
|
|
uint64_t Index;
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2008-05-09 10:41:27 +04:00
|
|
|
if (isHi)
|
|
|
|
Index = e + i;
|
|
|
|
else if (isLo)
|
|
|
|
Index = i;
|
|
|
|
else if (isEven)
|
|
|
|
Index = 2 * i;
|
|
|
|
else if (isOdd)
|
|
|
|
Index = 2 * i + 1;
|
|
|
|
else
|
2009-10-18 06:09:31 +04:00
|
|
|
Index = ExtVectorType::getAccessorIdx(Comp[i]);
|
2007-08-03 03:36:59 +04:00
|
|
|
|
2008-05-14 01:03:02 +04:00
|
|
|
Elts.push_back(Index);
|
2007-08-03 03:36:59 +04:00
|
|
|
}
|
2008-05-09 10:41:27 +04:00
|
|
|
}
|
|
|
|
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42395 91177308-0d34-0410-b5e6-96231b3b80d8
2007-09-27 18:38:14 +04:00
|
|
|
// constructor for instance messages.
|
2010-02-12 01:41:21 +03:00
|
|
|
ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, Expr *receiver,
|
|
|
|
Selector selInfo,
|
|
|
|
QualType retType, ObjCMethodDecl *mproto,
|
|
|
|
SourceLocation LBrac, SourceLocation RBrac,
|
|
|
|
Expr **ArgExprs, unsigned nargs)
|
2009-12-30 03:13:48 +03:00
|
|
|
: Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo),
|
2008-05-01 21:26:20 +04:00
|
|
|
MethodProto(mproto) {
|
2007-11-15 16:05:42 +03:00
|
|
|
NumArgs = nargs;
|
2010-02-12 01:41:21 +03:00
|
|
|
SubExprs = new (C) Stmt*[NumArgs+1];
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42395 91177308-0d34-0410-b5e6-96231b3b80d8
2007-09-27 18:38:14 +04:00
|
|
|
SubExprs[RECEIVER] = receiver;
|
2007-11-15 16:05:42 +03:00
|
|
|
if (NumArgs) {
|
|
|
|
for (unsigned i = 0; i != NumArgs; ++i)
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42395 91177308-0d34-0410-b5e6-96231b3b80d8
2007-09-27 18:38:14 +04:00
|
|
|
SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]);
|
|
|
|
}
|
2007-09-19 03:55:05 +04:00
|
|
|
LBracloc = LBrac;
|
|
|
|
RBracloc = RBrac;
|
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
// constructor for class messages.
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42395 91177308-0d34-0410-b5e6-96231b3b80d8
2007-09-27 18:38:14 +04:00
|
|
|
// FIXME: clsName should be typed to ObjCInterfaceType
|
2010-02-12 01:41:21 +03:00
|
|
|
ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName,
|
2010-03-08 19:40:19 +03:00
|
|
|
SourceLocation clsNameLoc, Selector selInfo,
|
|
|
|
QualType retType, ObjCMethodDecl *mproto,
|
2010-02-12 01:41:21 +03:00
|
|
|
SourceLocation LBrac, SourceLocation RBrac,
|
|
|
|
Expr **ArgExprs, unsigned nargs)
|
2010-03-08 19:40:19 +03:00
|
|
|
: Expr(ObjCMessageExprClass, retType, false, false), ClassNameLoc(clsNameLoc),
|
|
|
|
SelName(selInfo), MethodProto(mproto) {
|
2007-11-15 16:05:42 +03:00
|
|
|
NumArgs = nargs;
|
2010-02-12 01:41:21 +03:00
|
|
|
SubExprs = new (C) Stmt*[NumArgs+1];
|
2008-06-24 19:50:53 +04:00
|
|
|
SubExprs[RECEIVER] = (Expr*) ((uintptr_t) clsName | IsClsMethDeclUnknown);
|
2007-11-15 16:05:42 +03:00
|
|
|
if (NumArgs) {
|
|
|
|
for (unsigned i = 0; i != NumArgs; ++i)
|
Add SelectorInfo (similar in spirit to IdentifierInfo). The key difference is SelectorInfo is not string-oriented, it is a unique aggregate of IdentifierInfo's (using a folding set). SelectorInfo also has a richer API that simplifies the parser/action interface. 3 noteworthy benefits:
#1: It is cleaner. I never "liked" storing keyword selectors (i.e. foo:bar:baz) in the IdentifierTable.
#2: It is more space efficient. Since Cocoa keyword selectors can be quite long, this technique is space saving. For Cocoa.h, pulling the keyword selectors out saves ~180k. The cost of the SelectorInfo data is ~100k. Saves ~80k, or 43%.
#3: It results in many API simplifications. Here are some highlights:
- Removed 3 actions (ActOnKeywordMessage, ActOnUnaryMessage, & one flavor of ObjcBuildMethodDeclaration that was specific to unary messages).
- Removed 3 funky structs from DeclSpec.h (ObjcKeywordMessage, ObjcKeywordDecl, and ObjcKeywordInfo).
- Removed 2 ivars and 2 constructors from ObjCMessageExpr (fyi, this space savings has not been measured).
I am happy with the way it turned out (though it took a bit more hacking than I expected). Given the central role of selectors in ObjC, making sure this is "right" will pay dividends later.
Thanks to Chris for talking this through with me and suggesting this approach.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42395 91177308-0d34-0410-b5e6-96231b3b80d8
2007-09-27 18:38:14 +04:00
|
|
|
SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]);
|
|
|
|
}
|
2007-09-19 03:55:05 +04:00
|
|
|
LBracloc = LBrac;
|
|
|
|
RBracloc = RBrac;
|
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
// constructor for class messages.
|
2010-02-12 01:41:21 +03:00
|
|
|
ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls,
|
2010-03-08 19:40:19 +03:00
|
|
|
SourceLocation clsNameLoc, Selector selInfo,
|
|
|
|
QualType retType,
|
2010-02-12 01:41:21 +03:00
|
|
|
ObjCMethodDecl *mproto, SourceLocation LBrac,
|
|
|
|
SourceLocation RBrac, Expr **ArgExprs,
|
|
|
|
unsigned nargs)
|
2010-03-08 19:40:19 +03:00
|
|
|
: Expr(ObjCMessageExprClass, retType, false, false), ClassNameLoc(clsNameLoc),
|
|
|
|
SelName(selInfo), MethodProto(mproto)
|
|
|
|
{
|
2008-06-24 19:50:53 +04:00
|
|
|
NumArgs = nargs;
|
2010-02-12 01:41:21 +03:00
|
|
|
SubExprs = new (C) Stmt*[NumArgs+1];
|
2008-06-24 19:50:53 +04:00
|
|
|
SubExprs[RECEIVER] = (Expr*) ((uintptr_t) cls | IsClsMethDeclKnown);
|
|
|
|
if (NumArgs) {
|
|
|
|
for (unsigned i = 0; i != NumArgs; ++i)
|
|
|
|
SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]);
|
|
|
|
}
|
|
|
|
LBracloc = LBrac;
|
|
|
|
RBracloc = RBrac;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjCMessageExpr::ClassInfo ObjCMessageExpr::getClassInfo() const {
|
|
|
|
uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
|
|
|
|
switch (x & Flags) {
|
|
|
|
default:
|
|
|
|
assert(false && "Invalid ObjCMessageExpr.");
|
|
|
|
case IsInstMeth:
|
2010-03-08 19:40:19 +03:00
|
|
|
return ClassInfo(0, 0, SourceLocation());
|
2008-06-24 19:50:53 +04:00
|
|
|
case IsClsMethDeclUnknown:
|
2010-03-08 19:40:19 +03:00
|
|
|
return ClassInfo(0, (IdentifierInfo*) (x & ~Flags), ClassNameLoc);
|
2008-06-24 19:50:53 +04:00
|
|
|
case IsClsMethDeclKnown: {
|
|
|
|
ObjCInterfaceDecl* D = (ObjCInterfaceDecl*) (x & ~Flags);
|
2010-03-08 19:40:19 +03:00
|
|
|
return ClassInfo(D, D->getIdentifier(), ClassNameLoc);
|
2008-06-24 19:50:53 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-26 04:44:05 +04:00
|
|
|
void ObjCMessageExpr::setClassInfo(const ObjCMessageExpr::ClassInfo &CI) {
|
2010-03-08 19:40:19 +03:00
|
|
|
if (CI.Decl == 0 && CI.Name == 0) {
|
2009-04-26 04:44:05 +04:00
|
|
|
SubExprs[RECEIVER] = (Expr*)((uintptr_t)0 | IsInstMeth);
|
2010-03-08 19:40:19 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CI.Decl == 0)
|
|
|
|
SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Name | IsClsMethDeclUnknown);
|
2009-04-26 04:44:05 +04:00
|
|
|
else
|
2010-03-08 19:40:19 +03:00
|
|
|
SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Decl | IsClsMethDeclKnown);
|
|
|
|
ClassNameLoc = CI.Loc;
|
2009-04-26 04:44:05 +04:00
|
|
|
}
|
|
|
|
|
2010-02-12 01:41:21 +03:00
|
|
|
void ObjCMessageExpr::DoDestroy(ASTContext &C) {
|
|
|
|
DestroyChildren(C);
|
|
|
|
if (SubExprs)
|
|
|
|
C.Deallocate(SubExprs);
|
|
|
|
this->~ObjCMessageExpr();
|
|
|
|
C.Deallocate((void*) this);
|
|
|
|
}
|
2009-04-26 04:44:05 +04:00
|
|
|
|
2007-10-25 04:29:32 +04:00
|
|
|
bool ChooseExpr::isConditionTrue(ASTContext &C) const {
|
2009-04-26 23:19:15 +04:00
|
|
|
return getCond()->EvaluateAsInt(C) != 0;
|
2007-10-25 04:29:32 +04:00
|
|
|
}
|
|
|
|
|
2009-08-12 06:28:50 +04:00
|
|
|
void ShuffleVectorExpr::setExprs(ASTContext &C, Expr ** Exprs,
|
|
|
|
unsigned NumExprs) {
|
|
|
|
if (SubExprs) C.Deallocate(SubExprs);
|
|
|
|
|
|
|
|
SubExprs = new (C) Stmt* [NumExprs];
|
2009-04-16 04:01:45 +04:00
|
|
|
this->NumExprs = NumExprs;
|
|
|
|
memcpy(SubExprs, Exprs, sizeof(Expr *) * NumExprs);
|
2009-09-09 19:08:12 +04:00
|
|
|
}
|
2009-08-12 06:28:50 +04:00
|
|
|
|
|
|
|
void ShuffleVectorExpr::DoDestroy(ASTContext& C) {
|
|
|
|
DestroyChildren(C);
|
|
|
|
if (SubExprs) C.Deallocate(SubExprs);
|
|
|
|
this->~ShuffleVectorExpr();
|
|
|
|
C.Deallocate(this);
|
2009-04-16 04:01:45 +04:00
|
|
|
}
|
|
|
|
|
2009-08-07 10:08:38 +04:00
|
|
|
void SizeOfAlignOfExpr::DoDestroy(ASTContext& C) {
|
2008-11-11 20:56:53 +03:00
|
|
|
// Override default behavior of traversing children. If this has a type
|
|
|
|
// operand and the type is a variable-length array, the child iteration
|
|
|
|
// will iterate over the size expression. However, this expression belongs
|
|
|
|
// to the type, not to this, so we don't want to delete it.
|
|
|
|
// We still want to delete this expression.
|
2009-02-07 04:47:29 +03:00
|
|
|
if (isArgumentType()) {
|
|
|
|
this->~SizeOfAlignOfExpr();
|
|
|
|
C.Deallocate(this);
|
|
|
|
}
|
2008-11-11 20:56:53 +03:00
|
|
|
else
|
2009-08-07 10:08:38 +04:00
|
|
|
Expr::DoDestroy(C);
|
2008-08-28 22:02:04 +04:00
|
|
|
}
|
|
|
|
|
2009-01-22 03:58:24 +03:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DesignatedInitExpr
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() {
|
|
|
|
assert(Kind == FieldDesignator && "Only valid on a field designator");
|
|
|
|
if (Field.NameOrField & 0x01)
|
|
|
|
return reinterpret_cast<IdentifierInfo *>(Field.NameOrField&~0x01);
|
|
|
|
else
|
|
|
|
return getField()->getIdentifier();
|
|
|
|
}
|
|
|
|
|
2010-01-07 02:17:19 +03:00
|
|
|
DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty,
|
|
|
|
unsigned NumDesignators,
|
2009-04-15 10:41:24 +04:00
|
|
|
const Designator *Designators,
|
2009-09-09 19:08:12 +04:00
|
|
|
SourceLocation EqualOrColonLoc,
|
2009-04-15 10:41:24 +04:00
|
|
|
bool GNUSyntax,
|
2009-09-09 19:08:12 +04:00
|
|
|
Expr **IndexExprs,
|
2009-05-22 03:17:49 +04:00
|
|
|
unsigned NumIndexExprs,
|
|
|
|
Expr *Init)
|
2009-09-09 19:08:12 +04:00
|
|
|
: Expr(DesignatedInitExprClass, Ty,
|
2009-05-22 03:17:49 +04:00
|
|
|
Init->isTypeDependent(), Init->isValueDependent()),
|
2009-09-09 19:08:12 +04:00
|
|
|
EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
|
|
|
|
NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) {
|
2010-01-07 02:17:19 +03:00
|
|
|
this->Designators = new (C) Designator[NumDesignators];
|
2009-05-22 03:17:49 +04:00
|
|
|
|
|
|
|
// Record the initializer itself.
|
|
|
|
child_iterator Child = child_begin();
|
|
|
|
*Child++ = Init;
|
|
|
|
|
|
|
|
// Copy the designators and their subexpressions, computing
|
|
|
|
// value-dependence along the way.
|
|
|
|
unsigned IndexIdx = 0;
|
|
|
|
for (unsigned I = 0; I != NumDesignators; ++I) {
|
2009-04-15 10:41:24 +04:00
|
|
|
this->Designators[I] = Designators[I];
|
2009-05-22 03:17:49 +04:00
|
|
|
|
|
|
|
if (this->Designators[I].isArrayDesignator()) {
|
|
|
|
// Compute type- and value-dependence.
|
|
|
|
Expr *Index = IndexExprs[IndexIdx];
|
2009-09-09 19:08:12 +04:00
|
|
|
ValueDependent = ValueDependent ||
|
2009-05-22 03:17:49 +04:00
|
|
|
Index->isTypeDependent() || Index->isValueDependent();
|
|
|
|
|
|
|
|
// Copy the index expressions into permanent storage.
|
|
|
|
*Child++ = IndexExprs[IndexIdx++];
|
|
|
|
} else if (this->Designators[I].isArrayRangeDesignator()) {
|
|
|
|
// Compute type- and value-dependence.
|
|
|
|
Expr *Start = IndexExprs[IndexIdx];
|
|
|
|
Expr *End = IndexExprs[IndexIdx + 1];
|
2009-09-09 19:08:12 +04:00
|
|
|
ValueDependent = ValueDependent ||
|
2009-05-22 03:17:49 +04:00
|
|
|
Start->isTypeDependent() || Start->isValueDependent() ||
|
|
|
|
End->isTypeDependent() || End->isValueDependent();
|
|
|
|
|
|
|
|
// Copy the start/end expressions into permanent storage.
|
|
|
|
*Child++ = IndexExprs[IndexIdx++];
|
|
|
|
*Child++ = IndexExprs[IndexIdx++];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(IndexIdx == NumIndexExprs && "Wrong number of index expressions");
|
2009-04-15 10:41:24 +04:00
|
|
|
}
|
|
|
|
|
2009-01-22 03:58:24 +03:00
|
|
|
DesignatedInitExpr *
|
2009-09-09 19:08:12 +04:00
|
|
|
DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
|
2009-01-22 03:58:24 +03:00
|
|
|
unsigned NumDesignators,
|
|
|
|
Expr **IndexExprs, unsigned NumIndexExprs,
|
|
|
|
SourceLocation ColonOrEqualLoc,
|
|
|
|
bool UsesColonSyntax, Expr *Init) {
|
2009-01-28 02:20:32 +03:00
|
|
|
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
|
|
|
|
sizeof(Stmt *) * (NumIndexExprs + 1), 8);
|
2010-01-07 02:17:19 +03:00
|
|
|
return new (Mem) DesignatedInitExpr(C, C.VoidTy, NumDesignators, Designators,
|
2009-05-22 03:17:49 +04:00
|
|
|
ColonOrEqualLoc, UsesColonSyntax,
|
|
|
|
IndexExprs, NumIndexExprs, Init);
|
2009-01-22 03:58:24 +03:00
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
|
2009-04-16 04:55:48 +04:00
|
|
|
unsigned NumIndexExprs) {
|
|
|
|
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
|
|
|
|
sizeof(Stmt *) * (NumIndexExprs + 1), 8);
|
|
|
|
return new (Mem) DesignatedInitExpr(NumIndexExprs + 1);
|
|
|
|
}
|
|
|
|
|
2010-01-07 02:17:19 +03:00
|
|
|
void DesignatedInitExpr::setDesignators(ASTContext &C,
|
|
|
|
const Designator *Desigs,
|
2009-04-16 04:55:48 +04:00
|
|
|
unsigned NumDesigs) {
|
2010-01-07 02:17:19 +03:00
|
|
|
DestroyDesignators(C);
|
2009-04-16 04:55:48 +04:00
|
|
|
|
2010-01-07 02:17:19 +03:00
|
|
|
Designators = new (C) Designator[NumDesigs];
|
2009-04-16 04:55:48 +04:00
|
|
|
NumDesignators = NumDesigs;
|
|
|
|
for (unsigned I = 0; I != NumDesigs; ++I)
|
|
|
|
Designators[I] = Desigs[I];
|
|
|
|
}
|
|
|
|
|
2009-01-22 03:58:24 +03:00
|
|
|
SourceRange DesignatedInitExpr::getSourceRange() const {
|
|
|
|
SourceLocation StartLoc;
|
2009-02-17 01:33:34 +03:00
|
|
|
Designator &First =
|
|
|
|
*const_cast<DesignatedInitExpr*>(this)->designators_begin();
|
2009-01-22 03:58:24 +03:00
|
|
|
if (First.isFieldDesignator()) {
|
2009-03-28 03:41:23 +03:00
|
|
|
if (GNUSyntax)
|
2009-01-22 03:58:24 +03:00
|
|
|
StartLoc = SourceLocation::getFromRawEncoding(First.Field.FieldLoc);
|
|
|
|
else
|
|
|
|
StartLoc = SourceLocation::getFromRawEncoding(First.Field.DotLoc);
|
|
|
|
} else
|
2009-02-17 01:33:34 +03:00
|
|
|
StartLoc =
|
|
|
|
SourceLocation::getFromRawEncoding(First.ArrayOrRange.LBracketLoc);
|
2009-01-22 03:58:24 +03:00
|
|
|
return SourceRange(StartLoc, getInit()->getSourceRange().getEnd());
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) {
|
|
|
|
assert(D.Kind == Designator::ArrayDesignator && "Requires array designator");
|
|
|
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
|
|
|
Ptr += sizeof(DesignatedInitExpr);
|
|
|
|
Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
|
|
|
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *DesignatedInitExpr::getArrayRangeStart(const Designator& D) {
|
2009-09-09 19:08:12 +04:00
|
|
|
assert(D.Kind == Designator::ArrayRangeDesignator &&
|
2009-01-22 03:58:24 +03:00
|
|
|
"Requires array range designator");
|
|
|
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
|
|
|
Ptr += sizeof(DesignatedInitExpr);
|
|
|
|
Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
|
|
|
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) {
|
2009-09-09 19:08:12 +04:00
|
|
|
assert(D.Kind == Designator::ArrayRangeDesignator &&
|
2009-01-22 03:58:24 +03:00
|
|
|
"Requires array range designator");
|
|
|
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
|
|
|
Ptr += sizeof(DesignatedInitExpr);
|
|
|
|
Stmt **SubExprs = reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
|
|
|
return cast<Expr>(*(SubExprs + D.ArrayOrRange.Index + 2));
|
|
|
|
}
|
|
|
|
|
2009-04-15 10:41:24 +04:00
|
|
|
/// \brief Replaces the designator at index @p Idx with the series
|
|
|
|
/// of designators in [First, Last).
|
2010-01-07 02:17:19 +03:00
|
|
|
void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
|
2009-09-09 19:08:12 +04:00
|
|
|
const Designator *First,
|
2009-04-15 10:41:24 +04:00
|
|
|
const Designator *Last) {
|
|
|
|
unsigned NumNewDesignators = Last - First;
|
|
|
|
if (NumNewDesignators == 0) {
|
|
|
|
std::copy_backward(Designators + Idx + 1,
|
|
|
|
Designators + NumDesignators,
|
|
|
|
Designators + Idx);
|
|
|
|
--NumNewDesignators;
|
|
|
|
return;
|
|
|
|
} else if (NumNewDesignators == 1) {
|
|
|
|
Designators[Idx] = *First;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
Designator *NewDesignators
|
2010-01-07 02:17:19 +03:00
|
|
|
= new (C) Designator[NumDesignators - 1 + NumNewDesignators];
|
2009-04-15 10:41:24 +04:00
|
|
|
std::copy(Designators, Designators + Idx, NewDesignators);
|
|
|
|
std::copy(First, Last, NewDesignators + Idx);
|
|
|
|
std::copy(Designators + Idx + 1, Designators + NumDesignators,
|
|
|
|
NewDesignators + Idx + NumNewDesignators);
|
2010-01-07 02:17:19 +03:00
|
|
|
DestroyDesignators(C);
|
2009-04-15 10:41:24 +04:00
|
|
|
Designators = NewDesignators;
|
|
|
|
NumDesignators = NumDesignators - 1 + NumNewDesignators;
|
|
|
|
}
|
|
|
|
|
2009-08-07 10:08:38 +04:00
|
|
|
void DesignatedInitExpr::DoDestroy(ASTContext &C) {
|
2010-01-07 02:17:19 +03:00
|
|
|
DestroyDesignators(C);
|
2009-08-07 10:08:38 +04:00
|
|
|
Expr::DoDestroy(C);
|
2009-04-15 10:41:24 +04:00
|
|
|
}
|
|
|
|
|
2010-01-07 02:17:19 +03:00
|
|
|
void DesignatedInitExpr::DestroyDesignators(ASTContext &C) {
|
|
|
|
for (unsigned I = 0; I != NumDesignators; ++I)
|
|
|
|
Designators[I].~Designator();
|
|
|
|
C.Deallocate(Designators);
|
|
|
|
Designators = 0;
|
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
|
2009-08-11 03:49:36 +04:00
|
|
|
Expr **exprs, unsigned nexprs,
|
|
|
|
SourceLocation rparenloc)
|
|
|
|
: Expr(ParenListExprClass, QualType(),
|
|
|
|
hasAnyTypeDependentArguments(exprs, nexprs),
|
2009-09-09 19:08:12 +04:00
|
|
|
hasAnyValueDependentArguments(exprs, nexprs)),
|
2009-08-11 03:49:36 +04:00
|
|
|
NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) {
|
2009-09-09 19:08:12 +04:00
|
|
|
|
2009-08-11 03:49:36 +04:00
|
|
|
Exprs = new (C) Stmt*[nexprs];
|
|
|
|
for (unsigned i = 0; i != nexprs; ++i)
|
|
|
|
Exprs[i] = exprs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParenListExpr::DoDestroy(ASTContext& C) {
|
|
|
|
DestroyChildren(C);
|
|
|
|
if (Exprs) C.Deallocate(Exprs);
|
|
|
|
this->~ParenListExpr();
|
|
|
|
C.Deallocate(this);
|
|
|
|
}
|
|
|
|
|
2008-10-27 21:40:21 +03:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ExprIterator.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
Expr* ExprIterator::operator[](size_t idx) { return cast<Expr>(I[idx]); }
|
|
|
|
Expr* ExprIterator::operator*() const { return cast<Expr>(*I); }
|
|
|
|
Expr* ExprIterator::operator->() const { return cast<Expr>(*I); }
|
|
|
|
const Expr* ConstExprIterator::operator[](size_t idx) const {
|
|
|
|
return cast<Expr>(I[idx]);
|
|
|
|
}
|
|
|
|
const Expr* ConstExprIterator::operator*() const { return cast<Expr>(*I); }
|
|
|
|
const Expr* ConstExprIterator::operator->() const { return cast<Expr>(*I); }
|
|
|
|
|
2007-08-24 22:13:47 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Child Iterators for iterating over subexpressions/substatements
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// DeclRefExpr
|
2007-10-19 03:28:49 +04:00
|
|
|
Stmt::child_iterator DeclRefExpr::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator DeclRefExpr::child_end() { return child_iterator(); }
|
2007-08-24 22:13:47 +04:00
|
|
|
|
2007-11-12 17:29:37 +03:00
|
|
|
// ObjCIvarRefExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator ObjCIvarRefExpr::child_begin() { return &Base; }
|
|
|
|
Stmt::child_iterator ObjCIvarRefExpr::child_end() { return &Base+1; }
|
2007-11-12 17:29:37 +03:00
|
|
|
|
2008-06-03 03:03:37 +04:00
|
|
|
// ObjCPropertyRefExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator ObjCPropertyRefExpr::child_begin() { return &Base; }
|
|
|
|
Stmt::child_iterator ObjCPropertyRefExpr::child_end() { return &Base+1; }
|
2008-05-30 04:40:33 +04:00
|
|
|
|
2009-08-20 21:02:02 +04:00
|
|
|
// ObjCImplicitSetterGetterRefExpr
|
2009-09-09 19:08:12 +04:00
|
|
|
Stmt::child_iterator ObjCImplicitSetterGetterRefExpr::child_begin() {
|
|
|
|
return &Base;
|
2009-08-19 00:50:23 +04:00
|
|
|
}
|
2009-09-09 19:08:12 +04:00
|
|
|
Stmt::child_iterator ObjCImplicitSetterGetterRefExpr::child_end() {
|
|
|
|
return &Base+1;
|
2009-08-19 00:50:23 +04:00
|
|
|
}
|
2008-11-22 21:39:36 +03:00
|
|
|
|
2008-11-04 17:56:14 +03:00
|
|
|
// ObjCSuperExpr
|
|
|
|
Stmt::child_iterator ObjCSuperExpr::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator ObjCSuperExpr::child_end() { return child_iterator(); }
|
|
|
|
|
2009-07-24 21:54:45 +04:00
|
|
|
// ObjCIsaExpr
|
|
|
|
Stmt::child_iterator ObjCIsaExpr::child_begin() { return &Base; }
|
|
|
|
Stmt::child_iterator ObjCIsaExpr::child_end() { return &Base+1; }
|
|
|
|
|
2008-08-10 05:53:14 +04:00
|
|
|
// PredefinedExpr
|
|
|
|
Stmt::child_iterator PredefinedExpr::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator PredefinedExpr::child_end() { return child_iterator(); }
|
2007-08-24 22:13:47 +04:00
|
|
|
|
|
|
|
// IntegerLiteral
|
2007-10-19 03:28:49 +04:00
|
|
|
Stmt::child_iterator IntegerLiteral::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator IntegerLiteral::child_end() { return child_iterator(); }
|
2007-08-24 22:13:47 +04:00
|
|
|
|
|
|
|
// CharacterLiteral
|
2009-02-17 01:33:34 +03:00
|
|
|
Stmt::child_iterator CharacterLiteral::child_begin() { return child_iterator();}
|
2007-10-19 03:28:49 +04:00
|
|
|
Stmt::child_iterator CharacterLiteral::child_end() { return child_iterator(); }
|
2007-08-24 22:13:47 +04:00
|
|
|
|
|
|
|
// FloatingLiteral
|
2007-10-19 03:28:49 +04:00
|
|
|
Stmt::child_iterator FloatingLiteral::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator FloatingLiteral::child_end() { return child_iterator(); }
|
2007-08-24 22:13:47 +04:00
|
|
|
|
2007-08-26 07:42:43 +04:00
|
|
|
// ImaginaryLiteral
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator ImaginaryLiteral::child_begin() { return &Val; }
|
|
|
|
Stmt::child_iterator ImaginaryLiteral::child_end() { return &Val+1; }
|
2007-08-26 07:42:43 +04:00
|
|
|
|
2007-08-24 22:13:47 +04:00
|
|
|
// StringLiteral
|
2007-10-19 03:28:49 +04:00
|
|
|
Stmt::child_iterator StringLiteral::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator StringLiteral::child_end() { return child_iterator(); }
|
2007-08-24 22:13:47 +04:00
|
|
|
|
|
|
|
// ParenExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator ParenExpr::child_begin() { return &Val; }
|
|
|
|
Stmt::child_iterator ParenExpr::child_end() { return &Val+1; }
|
2007-08-24 22:13:47 +04:00
|
|
|
|
|
|
|
// UnaryOperator
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator UnaryOperator::child_begin() { return &Val; }
|
|
|
|
Stmt::child_iterator UnaryOperator::child_end() { return &Val+1; }
|
2007-08-24 22:13:47 +04:00
|
|
|
|
2008-11-11 20:56:53 +03:00
|
|
|
// SizeOfAlignOfExpr
|
2009-09-09 19:08:12 +04:00
|
|
|
Stmt::child_iterator SizeOfAlignOfExpr::child_begin() {
|
2008-11-11 20:56:53 +03:00
|
|
|
// If this is of a type and the type is a VLA type (and not a typedef), the
|
|
|
|
// size expression of the VLA needs to be treated as an executable expression.
|
|
|
|
// Why isn't this weirdness documented better in StmtIterator?
|
|
|
|
if (isArgumentType()) {
|
|
|
|
if (VariableArrayType* T = dyn_cast<VariableArrayType>(
|
|
|
|
getArgumentType().getTypePtr()))
|
|
|
|
return child_iterator(T);
|
|
|
|
return child_iterator();
|
|
|
|
}
|
2008-12-04 02:17:54 +03:00
|
|
|
return child_iterator(&Argument.Ex);
|
2007-10-19 03:28:49 +04:00
|
|
|
}
|
2008-11-11 20:56:53 +03:00
|
|
|
Stmt::child_iterator SizeOfAlignOfExpr::child_end() {
|
|
|
|
if (isArgumentType())
|
|
|
|
return child_iterator();
|
2008-12-04 02:17:54 +03:00
|
|
|
return child_iterator(&Argument.Ex + 1);
|
2007-10-19 03:28:49 +04:00
|
|
|
}
|
2007-08-24 22:13:47 +04:00
|
|
|
|
|
|
|
// ArraySubscriptExpr
|
2007-08-25 00:06:47 +04:00
|
|
|
Stmt::child_iterator ArraySubscriptExpr::child_begin() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0];
|
2007-08-24 22:13:47 +04:00
|
|
|
}
|
2007-08-25 00:06:47 +04:00
|
|
|
Stmt::child_iterator ArraySubscriptExpr::child_end() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0]+END_EXPR;
|
2007-08-24 22:13:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// CallExpr
|
2007-08-25 00:06:47 +04:00
|
|
|
Stmt::child_iterator CallExpr::child_begin() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0];
|
2007-08-24 22:13:47 +04:00
|
|
|
}
|
2007-08-25 00:06:47 +04:00
|
|
|
Stmt::child_iterator CallExpr::child_end() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0]+NumArgs+ARGS_START;
|
2007-08-24 22:13:47 +04:00
|
|
|
}
|
2007-08-25 00:06:47 +04:00
|
|
|
|
|
|
|
// MemberExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator MemberExpr::child_begin() { return &Base; }
|
|
|
|
Stmt::child_iterator MemberExpr::child_end() { return &Base+1; }
|
2007-08-25 00:06:47 +04:00
|
|
|
|
2008-04-19 03:10:10 +04:00
|
|
|
// ExtVectorElementExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator ExtVectorElementExpr::child_begin() { return &Base; }
|
|
|
|
Stmt::child_iterator ExtVectorElementExpr::child_end() { return &Base+1; }
|
2007-08-25 00:06:47 +04:00
|
|
|
|
|
|
|
// CompoundLiteralExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator CompoundLiteralExpr::child_begin() { return &Init; }
|
|
|
|
Stmt::child_iterator CompoundLiteralExpr::child_end() { return &Init+1; }
|
2007-08-25 00:06:47 +04:00
|
|
|
|
|
|
|
// CastExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator CastExpr::child_begin() { return &Op; }
|
|
|
|
Stmt::child_iterator CastExpr::child_end() { return &Op+1; }
|
2007-08-25 00:06:47 +04:00
|
|
|
|
|
|
|
// BinaryOperator
|
|
|
|
Stmt::child_iterator BinaryOperator::child_begin() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0];
|
2007-08-25 00:06:47 +04:00
|
|
|
}
|
|
|
|
Stmt::child_iterator BinaryOperator::child_end() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0]+END_EXPR;
|
2007-08-25 00:06:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// ConditionalOperator
|
|
|
|
Stmt::child_iterator ConditionalOperator::child_begin() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0];
|
2007-08-25 00:06:47 +04:00
|
|
|
}
|
|
|
|
Stmt::child_iterator ConditionalOperator::child_end() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0]+END_EXPR;
|
2007-08-25 00:06:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// AddrLabelExpr
|
2007-10-19 03:28:49 +04:00
|
|
|
Stmt::child_iterator AddrLabelExpr::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator AddrLabelExpr::child_end() { return child_iterator(); }
|
2007-08-25 00:06:47 +04:00
|
|
|
|
|
|
|
// StmtExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator StmtExpr::child_begin() { return &SubStmt; }
|
|
|
|
Stmt::child_iterator StmtExpr::child_end() { return &SubStmt+1; }
|
2007-08-25 00:06:47 +04:00
|
|
|
|
|
|
|
// TypesCompatibleExpr
|
2007-10-19 03:28:49 +04:00
|
|
|
Stmt::child_iterator TypesCompatibleExpr::child_begin() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
|
|
|
|
|
|
|
Stmt::child_iterator TypesCompatibleExpr::child_end() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
2007-08-25 00:06:47 +04:00
|
|
|
|
|
|
|
// ChooseExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator ChooseExpr::child_begin() { return &SubExprs[0]; }
|
|
|
|
Stmt::child_iterator ChooseExpr::child_end() { return &SubExprs[0]+END_EXPR; }
|
2008-11-29 07:51:27 +03:00
|
|
|
|
|
|
|
// GNUNullExpr
|
|
|
|
Stmt::child_iterator GNUNullExpr::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator GNUNullExpr::child_end() { return child_iterator(); }
|
2007-08-25 00:06:47 +04:00
|
|
|
|
2008-05-14 23:38:39 +04:00
|
|
|
// ShuffleVectorExpr
|
|
|
|
Stmt::child_iterator ShuffleVectorExpr::child_begin() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0];
|
2008-05-14 23:38:39 +04:00
|
|
|
}
|
|
|
|
Stmt::child_iterator ShuffleVectorExpr::child_end() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0]+NumExprs;
|
2008-05-14 23:38:39 +04:00
|
|
|
}
|
|
|
|
|
2007-10-16 00:28:48 +04:00
|
|
|
// VAArgExpr
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
Stmt::child_iterator VAArgExpr::child_begin() { return &Val; }
|
|
|
|
Stmt::child_iterator VAArgExpr::child_end() { return &Val+1; }
|
2007-10-16 00:28:48 +04:00
|
|
|
|
2007-08-31 08:56:16 +04:00
|
|
|
// InitListExpr
|
2010-02-19 04:50:18 +03:00
|
|
|
Stmt::child_iterator InitListExpr::child_begin() {
|
|
|
|
return InitExprs.size() ? &InitExprs[0] : 0;
|
|
|
|
}
|
|
|
|
Stmt::child_iterator InitListExpr::child_end() {
|
|
|
|
return InitExprs.size() ? &InitExprs[0] + InitExprs.size() : 0;
|
|
|
|
}
|
2007-08-31 08:56:16 +04:00
|
|
|
|
2009-01-29 20:44:32 +03:00
|
|
|
// DesignatedInitExpr
|
2009-01-22 03:58:24 +03:00
|
|
|
Stmt::child_iterator DesignatedInitExpr::child_begin() {
|
|
|
|
char* Ptr = static_cast<char*>(static_cast<void *>(this));
|
|
|
|
Ptr += sizeof(DesignatedInitExpr);
|
|
|
|
return reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
|
|
|
|
}
|
|
|
|
Stmt::child_iterator DesignatedInitExpr::child_end() {
|
|
|
|
return child_iterator(&*child_begin() + NumSubExprs);
|
|
|
|
}
|
|
|
|
|
2009-01-29 20:44:32 +03:00
|
|
|
// ImplicitValueInitExpr
|
2009-09-09 19:08:12 +04:00
|
|
|
Stmt::child_iterator ImplicitValueInitExpr::child_begin() {
|
|
|
|
return child_iterator();
|
2009-01-29 20:44:32 +03:00
|
|
|
}
|
|
|
|
|
2009-09-09 19:08:12 +04:00
|
|
|
Stmt::child_iterator ImplicitValueInitExpr::child_end() {
|
|
|
|
return child_iterator();
|
2009-01-29 20:44:32 +03:00
|
|
|
}
|
|
|
|
|
2009-08-11 03:49:36 +04:00
|
|
|
// ParenListExpr
|
|
|
|
Stmt::child_iterator ParenListExpr::child_begin() {
|
|
|
|
return &Exprs[0];
|
|
|
|
}
|
|
|
|
Stmt::child_iterator ParenListExpr::child_end() {
|
|
|
|
return &Exprs[0]+NumExprs;
|
|
|
|
}
|
|
|
|
|
2007-08-25 00:06:47 +04:00
|
|
|
// ObjCStringLiteral
|
2009-09-09 19:08:12 +04:00
|
|
|
Stmt::child_iterator ObjCStringLiteral::child_begin() {
|
2009-02-18 09:53:08 +03:00
|
|
|
return &String;
|
2007-10-19 03:28:49 +04:00
|
|
|
}
|
|
|
|
Stmt::child_iterator ObjCStringLiteral::child_end() {
|
2009-02-18 09:53:08 +03:00
|
|
|
return &String+1;
|
2007-10-19 03:28:49 +04:00
|
|
|
}
|
2007-08-25 00:06:47 +04:00
|
|
|
|
|
|
|
// ObjCEncodeExpr
|
2007-10-19 03:28:49 +04:00
|
|
|
Stmt::child_iterator ObjCEncodeExpr::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator ObjCEncodeExpr::child_end() { return child_iterator(); }
|
2007-08-25 00:06:47 +04:00
|
|
|
|
2007-10-17 00:40:23 +04:00
|
|
|
// ObjCSelectorExpr
|
2009-09-09 19:08:12 +04:00
|
|
|
Stmt::child_iterator ObjCSelectorExpr::child_begin() {
|
2007-10-19 03:28:49 +04:00
|
|
|
return child_iterator();
|
|
|
|
}
|
|
|
|
Stmt::child_iterator ObjCSelectorExpr::child_end() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
2007-10-17 00:40:23 +04:00
|
|
|
|
2007-10-17 20:58:11 +04:00
|
|
|
// ObjCProtocolExpr
|
2007-10-19 03:28:49 +04:00
|
|
|
Stmt::child_iterator ObjCProtocolExpr::child_begin() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
|
|
|
Stmt::child_iterator ObjCProtocolExpr::child_end() {
|
|
|
|
return child_iterator();
|
|
|
|
}
|
2007-10-17 20:58:11 +04:00
|
|
|
|
2007-09-19 03:55:05 +04:00
|
|
|
// ObjCMessageExpr
|
2009-09-09 19:08:12 +04:00
|
|
|
Stmt::child_iterator ObjCMessageExpr::child_begin() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return getReceiver() ? &SubExprs[0] : &SubExprs[0] + ARGS_START;
|
2007-09-19 03:55:05 +04:00
|
|
|
}
|
|
|
|
Stmt::child_iterator ObjCMessageExpr::child_end() {
|
This patch is motivated by numerous strict-aliasing warnings when compiling
clang as a Release build.
The big change is that all AST nodes (subclasses of Stmt) whose children are
Expr* store their children as Stmt* or arrays of Stmt*. This is to remove
strict-aliasing warnings when using StmtIterator. None of the interfaces of any
of the classes have changed (except those with arg_iterators, see below), as the
accessor methods introduce the needed casts (via cast<>). While this extra
casting may seem cumbersome, it actually adds some important sanity checks
throughout the codebase, as clients using StmtIterator can potentially overwrite
children that are expected to be Expr* with Stmt* (that aren't Expr*). The casts
provide extra sanity checks that are operational in debug builds to catch
invariant violations such as these.
For classes that have arg_iterators (e.g., CallExpr), the definition of
arg_iterator has been replaced. Instead of it being Expr**, it is an actual
class (called ExprIterator) that wraps a Stmt**, and provides the necessary
operators for iteration. The nice thing about this class is that it also uses
cast<> to type-checking, which introduces extra sanity checks throughout the
codebase that are useful for debugging.
A few of the CodeGen functions that use arg_iterator (especially from
OverloadExpr) have been modified to take begin and end iterators instead of a
base Expr** and the number of arguments. This matches more with the abstraction
of iteration. This still needs to be cleaned up a little bit, as clients expect
that ExprIterator is a RandomAccessIterator (which we may or may not wish to
allow for efficiency of representation).
This is a fairly large patch. It passes the tests (except CodeGen/bitfield.c,
which was already broken) on both a Debug and Release build, but it should
obviously be reviewed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52378 91177308-0d34-0410-b5e6-96231b3b80d8
2008-06-17 06:43:46 +04:00
|
|
|
return &SubExprs[0]+ARGS_START+getNumArgs();
|
2007-09-19 03:55:05 +04:00
|
|
|
}
|
|
|
|
|
2008-09-03 22:15:37 +04:00
|
|
|
// Blocks
|
2008-10-08 21:01:13 +04:00
|
|
|
Stmt::child_iterator BlockExpr::child_begin() { return child_iterator(); }
|
|
|
|
Stmt::child_iterator BlockExpr::child_end() { return child_iterator(); }
|
2008-09-03 22:15:37 +04:00
|
|
|
|
2008-09-27 03:24:14 +04:00
|
|
|
Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();}
|
|
|
|
Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); }
|