diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/Expr.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/Expr.cpp | 1336 |
1 files changed, 909 insertions, 427 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/Expr.cpp b/contrib/llvm/tools/clang/lib/AST/Expr.cpp index 5feef1c..391b26a 100644 --- a/contrib/llvm/tools/clang/lib/AST/Expr.cpp +++ b/contrib/llvm/tools/clang/lib/AST/Expr.cpp @@ -20,15 +20,16 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Lex/LiteralSupport.h" +#include "clang/Lex/Lexer.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> using namespace clang; -void Expr::ANCHOR() {} // key function for Expr class. - /// 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 @@ -90,6 +91,42 @@ bool Expr::isKnownToHaveBooleanValue() const { return false; } +// Amusing macro metaprogramming hack: check whether a class provides +// a more specific implementation of getExprLoc(). +namespace { + /// This implementation is used when a class provides a custom + /// implementation of getExprLoc. + template <class E, class T> + SourceLocation getExprLocImpl(const Expr *expr, + SourceLocation (T::*v)() const) { + return static_cast<const E*>(expr)->getExprLoc(); + } + + /// This implementation is used when a class doesn't provide + /// a custom implementation of getExprLoc. Overload resolution + /// should pick it over the implementation above because it's + /// more specialized according to function template partial ordering. + template <class E> + SourceLocation getExprLocImpl(const Expr *expr, + SourceLocation (Expr::*v)() const) { + return static_cast<const E*>(expr)->getSourceRange().getBegin(); + } +} + +SourceLocation Expr::getExprLoc() const { + switch (getStmtClass()) { + case Stmt::NoStmtClass: llvm_unreachable("statement without class"); +#define ABSTRACT_STMT(type) +#define STMT(type, base) \ + case Stmt::type##Class: llvm_unreachable(#type " is not an Expr"); break; +#define EXPR(type, base) \ + case Stmt::type##Class: return getExprLocImpl<type>(this, &type::getExprLoc); +#include "clang/AST/StmtNodes.inc" + } + llvm_unreachable("unknown statement kind"); + return SourceLocation(); +} + //===----------------------------------------------------------------------===// // Primary Expressions. //===----------------------------------------------------------------------===// @@ -105,6 +142,25 @@ void ExplicitTemplateArgumentList::initializeFrom( new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); } +void ExplicitTemplateArgumentList::initializeFrom( + const TemplateArgumentListInfo &Info, + bool &Dependent, + bool &ContainsUnexpandedParameterPack) { + LAngleLoc = Info.getLAngleLoc(); + RAngleLoc = Info.getRAngleLoc(); + NumTemplateArgs = Info.size(); + + TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); + for (unsigned i = 0; i != NumTemplateArgs; ++i) { + Dependent = Dependent || Info[i].getArgument().isDependent(); + ContainsUnexpandedParameterPack + = ContainsUnexpandedParameterPack || + Info[i].getArgument().containsUnexpandedParameterPack(); + + new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); + } +} + void ExplicitTemplateArgumentList::copyInto( TemplateArgumentListInfo &Info) const { Info.setLAngleLoc(LAngleLoc); @@ -123,11 +179,14 @@ std::size_t ExplicitTemplateArgumentList::sizeFor( return sizeFor(Info.size()); } -void DeclRefExpr::computeDependence() { +/// \brief Compute the type- and value-dependence of a declaration reference +/// based on the declaration being referenced. +static void computeDeclRefDependence(NamedDecl *D, QualType T, + bool &TypeDependent, + bool &ValueDependent) { TypeDependent = false; ValueDependent = false; - NamedDecl *D = getDecl(); // (TD) C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: @@ -136,63 +195,93 @@ void DeclRefExpr::computeDependence() { // // (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()) { + if (T->isDependentType()) { TypeDependent = true; ValueDependent = true; + return; } + // (TD) - a conversion-function-id that specifies a dependent type - else if (D->getDeclName().getNameKind() - == DeclarationName::CXXConversionFunctionName && + if (D->getDeclName().getNameKind() + == DeclarationName::CXXConversionFunctionName && D->getDeclName().getCXXNameType()->isDependentType()) { TypeDependent = true; ValueDependent = true; - } - // (TD) - a template-id that is dependent, - else if (hasExplicitTemplateArgs() && - TemplateSpecializationType::anyDependentTemplateArguments( - getTemplateArgs(), - getNumTemplateArgs())) { - TypeDependent = true; - ValueDependent = true; + return; } // (VD) - the name of a non-type template parameter, - else if (isa<NonTypeTemplateParmDecl>(D)) + if (isa<NonTypeTemplateParmDecl>(D)) { ValueDependent = true; + return; + } + // (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 (VarDecl *Var = dyn_cast<VarDecl>(D)) { if (Var->getType()->isIntegralOrEnumerationType() && Var->getType().getCVRQualifiers() == Qualifiers::Const) { if (const Expr *Init = Var->getAnyInitializer()) if (Init->isValueDependent()) ValueDependent = true; } + // (VD) - FIXME: Missing from the standard: // - a member function or a static data member of the current // instantiation else if (Var->isStaticDataMember() && Var->getDeclContext()->isDependentContext()) ValueDependent = true; - } + + return; + } + // (VD) - FIXME: Missing from the standard: // - a member function or a static data member of the current // instantiation - else if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) + if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) { ValueDependent = true; - // (TD) - a nested-name-specifier or a qualified-id that names a - // member of an unknown specialization. - // (handled by DependentScopeDeclRefExpr) + return; + } +} + +void DeclRefExpr::computeDependence() { + bool TypeDependent = false; + bool ValueDependent = false; + computeDeclRefDependence(getDecl(), getType(), TypeDependent, ValueDependent); + + // (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: + if (!TypeDependent && !ValueDependent && + hasExplicitTemplateArgs() && + TemplateSpecializationType::anyDependentTemplateArguments( + getTemplateArgs(), + getNumTemplateArgs())) { + TypeDependent = true; + ValueDependent = true; + } + + ExprBits.TypeDependent = TypeDependent; + ExprBits.ValueDependent = ValueDependent; + + // Is the declaration a parameter pack? + if (getDecl()->isParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; } DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, ValueDecl *D, SourceLocation NameLoc, const TemplateArgumentListInfo *TemplateArgs, - QualType T) - : Expr(DeclRefExprClass, T, false, false), + QualType T, ExprValueKind VK) + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), DecoratedD(D, (Qualifier? HasQualifierFlag : 0) | (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)), @@ -213,8 +302,8 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, ValueDecl *D, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, - QualType T) - : Expr(DeclRefExprClass, T, false, false), + QualType T, ExprValueKind VK) + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), DecoratedD(D, (Qualifier? HasQualifierFlag : 0) | (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)), @@ -237,10 +326,11 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, ValueDecl *D, SourceLocation NameLoc, QualType T, + ExprValueKind VK, const TemplateArgumentListInfo *TemplateArgs) { return Create(Context, Qualifier, QualifierRange, D, DeclarationNameInfo(D->getDeclName(), NameLoc), - T, TemplateArgs); + T, VK, TemplateArgs); } DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, @@ -249,6 +339,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, ValueDecl *D, const DeclarationNameInfo &NameInfo, QualType T, + ExprValueKind VK, const TemplateArgumentListInfo *TemplateArgs) { std::size_t Size = sizeof(DeclRefExpr); if (Qualifier != 0) @@ -257,21 +348,23 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, if (TemplateArgs) Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); - void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>()); + void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameInfo, - TemplateArgs, T); + TemplateArgs, T, VK); } -DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier, +DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, + bool HasQualifier, + bool HasExplicitTemplateArgs, unsigned NumTemplateArgs) { std::size_t Size = sizeof(DeclRefExpr); if (HasQualifier) Size += sizeof(NameQualifier); - if (NumTemplateArgs) + if (HasExplicitTemplateArgs) Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); - void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>()); + void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>()); return new (Mem) DeclRefExpr(EmptyShell()); } @@ -432,7 +525,7 @@ StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData, // any concatenated string tokens. void *Mem = C.Allocate(sizeof(StringLiteral)+ sizeof(SourceLocation)*(NumStrs-1), - llvm::alignof<StringLiteral>()); + llvm::alignOf<StringLiteral>()); StringLiteral *SL = new (Mem) StringLiteral(Ty); // OPTIMIZE: could allocate this appended to the StringLiteral. @@ -452,7 +545,7 @@ StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData, StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) { void *Mem = C.Allocate(sizeof(StringLiteral)+ sizeof(SourceLocation)*(NumStrs-1), - llvm::alignof<StringLiteral>()); + llvm::alignOf<StringLiteral>()); StringLiteral *SL = new (Mem) StringLiteral(QualType()); SL->StrData = 0; SL->ByteLength = 0; @@ -467,6 +560,72 @@ void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) { ByteLength = Str.size(); } +/// getLocationOfByte - Return a source location that points to the specified +/// byte of this string literal. +/// +/// Strings are amazingly complex. They can be formed from multiple tokens and +/// can have escape sequences in them in addition to the usual trigraph and +/// escaped newline business. This routine handles this complexity. +/// +SourceLocation StringLiteral:: +getLocationOfByte(unsigned ByteNo, const SourceManager &SM, + const LangOptions &Features, const TargetInfo &Target) const { + assert(!isWide() && "This doesn't work for wide strings yet"); + + // Loop over all of the tokens in this string until we find the one that + // contains the byte we're looking for. + unsigned TokNo = 0; + while (1) { + assert(TokNo < getNumConcatenated() && "Invalid byte number!"); + SourceLocation StrTokLoc = getStrTokenLoc(TokNo); + + // Get the spelling of the string so that we can get the data that makes up + // the string literal, not the identifier for the macro it is potentially + // expanded through. + SourceLocation StrTokSpellingLoc = SM.getSpellingLoc(StrTokLoc); + + // Re-lex the token to get its length and original spelling. + std::pair<FileID, unsigned> LocInfo =SM.getDecomposedLoc(StrTokSpellingLoc); + bool Invalid = false; + llvm::StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); + if (Invalid) + return StrTokSpellingLoc; + + const char *StrData = Buffer.data()+LocInfo.second; + + // Create a langops struct and enable trigraphs. This is sufficient for + // relexing tokens. + LangOptions LangOpts; + LangOpts.Trigraphs = true; + + // Create a lexer starting at the beginning of this token. + Lexer TheLexer(StrTokSpellingLoc, Features, Buffer.begin(), StrData, + Buffer.end()); + Token TheTok; + TheLexer.LexFromRawLexer(TheTok); + + // Use the StringLiteralParser to compute the length of the string in bytes. + StringLiteralParser SLP(&TheTok, 1, SM, Features, Target); + unsigned TokNumBytes = SLP.GetStringLength(); + + // If the byte is in this token, return the location of the byte. + if (ByteNo < TokNumBytes || + (ByteNo == TokNumBytes && TokNo == getNumConcatenated())) { + unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo); + + // Now that we know the offset of the token in the spelling, use the + // preprocessor to get the offset in the original source. + return Lexer::AdvanceToTokenCharacter(StrTokLoc, Offset, SM, Features); + } + + // Move to the next string token. + ++TokNo; + ByteNo -= TokNumBytes; + } +} + + + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "sizeof" or "[pre]++". const char *UnaryOperator::getOpcodeStr(Opcode Op) { @@ -522,43 +681,82 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) { // Postfix Operators. //===----------------------------------------------------------------------===// -CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, - unsigned numargs, QualType t, SourceLocation rparenloc) - : Expr(SC, t, - fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs), - fn->isValueDependent() || hasAnyValueDependentArguments(args,numargs)), +CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, + Expr **args, unsigned numargs, QualType t, ExprValueKind VK, + SourceLocation rparenloc) + : Expr(SC, t, VK, OK_Ordinary, + fn->isTypeDependent(), + fn->isValueDependent(), + fn->containsUnexpandedParameterPack()), NumArgs(numargs) { - SubExprs = new (C) Stmt*[numargs+1]; + SubExprs = new (C) Stmt*[numargs+PREARGS_START+NumPreArgs]; SubExprs[FN] = fn; - for (unsigned i = 0; i != numargs; ++i) - SubExprs[i+ARGS_START] = args[i]; + for (unsigned i = 0; i != numargs; ++i) { + if (args[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (args[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (args[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SubExprs[i+PREARGS_START+NumPreArgs] = args[i]; + } + CallExprBits.NumPreArgs = NumPreArgs; RParenLoc = rparenloc; } CallExpr::CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, - QualType t, SourceLocation rparenloc) - : Expr(CallExprClass, t, - fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs), - fn->isValueDependent() || hasAnyValueDependentArguments(args,numargs)), + QualType t, ExprValueKind VK, SourceLocation rparenloc) + : Expr(CallExprClass, t, VK, OK_Ordinary, + fn->isTypeDependent(), + fn->isValueDependent(), + fn->containsUnexpandedParameterPack()), NumArgs(numargs) { - SubExprs = new (C) Stmt*[numargs+1]; + SubExprs = new (C) Stmt*[numargs+PREARGS_START]; SubExprs[FN] = fn; - for (unsigned i = 0; i != numargs; ++i) - SubExprs[i+ARGS_START] = args[i]; + for (unsigned i = 0; i != numargs; ++i) { + if (args[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (args[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (args[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SubExprs[i+PREARGS_START] = args[i]; + } + CallExprBits.NumPreArgs = 0; RParenLoc = rparenloc; } CallExpr::CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty) : Expr(SC, Empty), SubExprs(0), NumArgs(0) { - SubExprs = new (C) Stmt*[1]; + // FIXME: Why do we allocate this? + SubExprs = new (C) Stmt*[PREARGS_START]; + CallExprBits.NumPreArgs = 0; +} + +CallExpr::CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, + EmptyShell Empty) + : Expr(SC, Empty), SubExprs(0), NumArgs(0) { + // FIXME: Why do we allocate this? + SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs]; + CallExprBits.NumPreArgs = NumPreArgs; } Decl *CallExpr::getCalleeDecl() { Expr *CEE = getCallee()->IgnoreParenCasts(); + // If we're calling a dereference, look at the pointer instead. + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CEE)) { + if (BO->isPtrMemOp()) + CEE = BO->getRHS()->IgnoreParenCasts(); + } else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(CEE)) { + if (UO->getOpcode() == UO_Deref) + CEE = UO->getSubExpr()->IgnoreParenCasts(); + } if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) return DRE->getDecl(); if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE)) @@ -585,12 +783,14 @@ void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) { } // Otherwise, we are growing the # arguments. New an bigger argument array. - Stmt **NewSubExprs = new (C) Stmt*[NumArgs+1]; + unsigned NumPreArgs = getNumPreArgs(); + Stmt **NewSubExprs = new (C) Stmt*[NumArgs+PREARGS_START+NumPreArgs]; // Copy over args. - for (unsigned i = 0; i != getNumArgs()+ARGS_START; ++i) + for (unsigned i = 0; i != getNumArgs()+PREARGS_START+NumPreArgs; ++i) NewSubExprs[i] = SubExprs[i]; // Null out new args. - for (unsigned i = getNumArgs()+ARGS_START; i != NumArgs+ARGS_START; ++i) + for (unsigned i = getNumArgs()+PREARGS_START+NumPreArgs; + i != NumArgs+PREARGS_START+NumPreArgs; ++i) NewSubExprs[i] = 0; if (SubExprs) C.Deallocate(SubExprs); @@ -600,7 +800,7 @@ void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) { /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If /// not, return 0. -unsigned CallExpr::isBuiltinCall(ASTContext &Context) const { +unsigned CallExpr::isBuiltinCall(const ASTContext &Context) const { // All simple function calls (e.g. func()) are implicitly cast to pointer to // function. As a result, we try and obtain the DeclRefExpr from the // ImplicitCastExpr. @@ -663,10 +863,10 @@ OffsetOfExpr::OffsetOfExpr(ASTContext &C, QualType type, OffsetOfNode* compsPtr, unsigned numComps, Expr** exprsPtr, unsigned numExprs, SourceLocation RParenLoc) - : Expr(OffsetOfExprClass, type, /*TypeDependent=*/false, - /*ValueDependent=*/tsi->getType()->isDependentType() || - hasAnyTypeDependentArguments(exprsPtr, numExprs) || - hasAnyValueDependentArguments(exprsPtr, numExprs)), + : Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, + /*ValueDependent=*/tsi->getType()->isDependentType(), + tsi->getType()->containsUnexpandedParameterPack()), OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi), NumComps(numComps), NumExprs(numExprs) { @@ -675,6 +875,11 @@ OffsetOfExpr::OffsetOfExpr(ASTContext &C, QualType type, } for(unsigned i = 0; i < numExprs; ++i) { + if (exprsPtr[i]->isTypeDependent() || exprsPtr[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (exprsPtr[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + setIndexExpr(i, exprsPtr[i]); } } @@ -694,7 +899,9 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, DeclAccessPair founddecl, DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs, - QualType ty) { + QualType ty, + ExprValueKind vk, + ExprObjectKind ok) { std::size_t Size = sizeof(MemberExpr); bool hasQualOrFound = (qual != 0 || @@ -706,8 +913,9 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, if (targs) Size += ExplicitTemplateArgumentList::sizeFor(*targs); - void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>()); - MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, ty); + void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>()); + MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, + ty, vk, ok); if (hasQualOrFound) { if (qual && qual->isDependent()) { @@ -732,12 +940,16 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, const char *CastExpr::getCastKindName() const { switch (getCastKind()) { - case CK_Unknown: - return "Unknown"; + case CK_Dependent: + return "Dependent"; case CK_BitCast: return "BitCast"; case CK_LValueBitCast: return "LValueBitCast"; + case CK_LValueToRValue: + return "LValueToRValue"; + case CK_GetObjCProperty: + return "GetObjCProperty"; case CK_NoOp: return "NoOp"; case CK_BaseToDerived: @@ -756,6 +968,8 @@ const char *CastExpr::getCastKindName() const { return "FunctionToPointerDecay"; case CK_NullToMemberPointer: return "NullToMemberPointer"; + case CK_NullToPointer: + return "NullToPointer"; case CK_BaseToDerivedMemberPointer: return "BaseToDerivedMemberPointer"; case CK_DerivedToBaseMemberPointer: @@ -768,18 +982,24 @@ const char *CastExpr::getCastKindName() const { return "IntegralToPointer"; case CK_PointerToIntegral: return "PointerToIntegral"; + case CK_PointerToBoolean: + return "PointerToBoolean"; case CK_ToVoid: return "ToVoid"; case CK_VectorSplat: return "VectorSplat"; case CK_IntegralCast: return "IntegralCast"; + case CK_IntegralToBoolean: + return "IntegralToBoolean"; case CK_IntegralToFloating: return "IntegralToFloating"; case CK_FloatingToIntegral: return "FloatingToIntegral"; case CK_FloatingCast: return "FloatingCast"; + case CK_FloatingToBoolean: + return "FloatingToBoolean"; case CK_MemberPointerToBoolean: return "MemberPointerToBoolean"; case CK_AnyPointerToObjCPointerCast: @@ -788,9 +1008,29 @@ const char *CastExpr::getCastKindName() const { return "AnyPointerToBlockPointerCast"; case CK_ObjCObjectLValueCast: return "ObjCObjectLValueCast"; + case CK_FloatingRealToComplex: + return "FloatingRealToComplex"; + case CK_FloatingComplexToReal: + return "FloatingComplexToReal"; + case CK_FloatingComplexToBoolean: + return "FloatingComplexToBoolean"; + case CK_FloatingComplexCast: + return "FloatingComplexCast"; + case CK_FloatingComplexToIntegralComplex: + return "FloatingComplexToIntegralComplex"; + case CK_IntegralRealToComplex: + return "IntegralRealToComplex"; + case CK_IntegralComplexToReal: + return "IntegralComplexToReal"; + case CK_IntegralComplexToBoolean: + return "IntegralComplexToBoolean"; + case CK_IntegralComplexCast: + return "IntegralComplexCast"; + case CK_IntegralComplexToFloatingComplex: + return "IntegralComplexToFloatingComplex"; } - assert(0 && "Unhandled cast kind!"); + llvm_unreachable("Unhandled cast kind!"); return 0; } @@ -859,7 +1099,7 @@ ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(ASTContext &C, CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T, - CastKind K, Expr *Op, + ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R) { @@ -867,7 +1107,7 @@ CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T, void *Buffer = C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CStyleCastExpr *E = - new (Buffer) CStyleCastExpr(T, K, Op, PathSize, WrittenTy, L, R); + new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -984,16 +1224,19 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) { InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc, Expr **initExprs, unsigned numInits, SourceLocation rbraceloc) - : Expr(InitListExprClass, QualType(), false, false), + : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, + false), InitExprs(C, numInits), LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0), UnionFieldInit(0), HadArrayRangeDesignator(false) { for (unsigned I = 0; I != numInits; ++I) { if (initExprs[I]->isTypeDependent()) - TypeDependent = true; + ExprBits.TypeDependent = true; if (initExprs[I]->isValueDependent()) - ValueDependent = true; + ExprBits.ValueDependent = true; + if (initExprs[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; } InitExprs.insert(C, InitExprs.end(), initExprs, initExprs+numInits); @@ -1020,6 +1263,35 @@ Expr *InitListExpr::updateInit(ASTContext &C, unsigned Init, Expr *expr) { return Result; } +SourceRange InitListExpr::getSourceRange() const { + if (SyntacticForm) + return SyntacticForm->getSourceRange(); + SourceLocation Beg = LBraceLoc, End = RBraceLoc; + if (Beg.isInvalid()) { + // Find the first non-null initializer. + for (InitExprsTy::const_iterator I = InitExprs.begin(), + E = InitExprs.end(); + I != E; ++I) { + if (Stmt *S = *I) { + Beg = S->getLocStart(); + break; + } + } + } + if (End.isInvalid()) { + // Find the first non-null initializer from the end. + for (InitExprsTy::const_reverse_iterator I = InitExprs.rbegin(), + E = InitExprs.rend(); + I != E; ++I) { + if (Stmt *S = *I) { + End = S->getSourceRange().getEnd(); + break; + } + } + } + return SourceRange(Beg, End); +} + /// getFunctionType - Return the underlying function type for this block. /// const FunctionType *BlockExpr::getFunctionType() const { @@ -1195,21 +1467,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, return false; } - case ObjCImplicitSetterGetterRefExprClass: { // Dot syntax for message send. -#if 0 - const ObjCImplicitSetterGetterRefExpr *Ref = - cast<ObjCImplicitSetterGetterRefExpr>(this); - // FIXME: We really want the location of the '.' here. - Loc = Ref->getLocation(); - R1 = SourceRange(Ref->getLocation(), Ref->getLocation()); - if (Ref->getBase()) - R2 = Ref->getBase()->getSourceRange(); -#else + case ObjCPropertyRefExprClass: Loc = getExprLoc(); R1 = getSourceRange(); -#endif return true; - } + 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. @@ -1217,9 +1479,13 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // 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 (!CS->body_empty()) { if (const Expr *E = dyn_cast<Expr>(CS->body_back())) return E->isUnusedResultAWarning(Loc, R1, R2, Ctx); + if (const LabelStmt *Label = dyn_cast<LabelStmt>(CS->body_back())) + if (const Expr *E = dyn_cast<Expr>(Label->getSubStmt())) + return E->isUnusedResultAWarning(Loc, R1, R2, Ctx); + } if (getType()->isVoidType()) return false; @@ -1268,8 +1534,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, case CXXBindTemporaryExprClass: return (cast<CXXBindTemporaryExpr>(this) ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); - case CXXExprWithTemporariesClass: - return (cast<CXXExprWithTemporaries>(this) + case ExprWithCleanupsClass: + return (cast<ExprWithCleanups>(this) ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); } } @@ -1311,12 +1577,254 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { return cast<ArraySubscriptExpr>(this)->getBase()->isOBJCGCCandidate(Ctx); } } + +bool Expr::isBoundMemberFunction(ASTContext &Ctx) const { + if (isTypeDependent()) + return false; + return ClassifyLValue(Ctx) == Expr::LV_MemberFunction; +} + +static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1, + Expr::CanThrowResult CT2) { + // CanThrowResult constants are ordered so that the maximum is the correct + // merge result. + return CT1 > CT2 ? CT1 : CT2; +} + +static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) { + Expr *E = const_cast<Expr*>(CE); + Expr::CanThrowResult R = Expr::CT_Cannot; + for (Expr::child_range I = E->children(); I && R != Expr::CT_Can; ++I) { + R = MergeCanThrow(R, cast<Expr>(*I)->CanThrow(C)); + } + return R; +} + +static Expr::CanThrowResult CanCalleeThrow(const Decl *D, + bool NullThrows = true) { + if (!D) + return NullThrows ? Expr::CT_Can : Expr::CT_Cannot; + + // See if we can get a function type from the decl somehow. + const ValueDecl *VD = dyn_cast<ValueDecl>(D); + if (!VD) // If we have no clue what we're calling, assume the worst. + return Expr::CT_Can; + + // As an extension, we assume that __attribute__((nothrow)) functions don't + // throw. + if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>()) + return Expr::CT_Cannot; + + QualType T = VD->getType(); + const FunctionProtoType *FT; + if ((FT = T->getAs<FunctionProtoType>())) { + } else if (const PointerType *PT = T->getAs<PointerType>()) + FT = PT->getPointeeType()->getAs<FunctionProtoType>(); + else if (const ReferenceType *RT = T->getAs<ReferenceType>()) + FT = RT->getPointeeType()->getAs<FunctionProtoType>(); + else if (const MemberPointerType *MT = T->getAs<MemberPointerType>()) + FT = MT->getPointeeType()->getAs<FunctionProtoType>(); + else if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) + FT = BT->getPointeeType()->getAs<FunctionProtoType>(); + + if (!FT) + return Expr::CT_Can; + + return FT->hasEmptyExceptionSpec() ? Expr::CT_Cannot : Expr::CT_Can; +} + +static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) { + if (DC->isTypeDependent()) + return Expr::CT_Dependent; + + if (!DC->getTypeAsWritten()->isReferenceType()) + return Expr::CT_Cannot; + + return DC->getCastKind() == clang::CK_Dynamic? Expr::CT_Can : Expr::CT_Cannot; +} + +static Expr::CanThrowResult CanTypeidThrow(ASTContext &C, + const CXXTypeidExpr *DC) { + if (DC->isTypeOperand()) + return Expr::CT_Cannot; + + Expr *Op = DC->getExprOperand(); + if (Op->isTypeDependent()) + return Expr::CT_Dependent; + + const RecordType *RT = Op->getType()->getAs<RecordType>(); + if (!RT) + return Expr::CT_Cannot; + + if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic()) + return Expr::CT_Cannot; + + if (Op->Classify(C).isPRValue()) + return Expr::CT_Cannot; + + return Expr::CT_Can; +} + +Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { + // C++ [expr.unary.noexcept]p3: + // [Can throw] if in a potentially-evaluated context the expression would + // contain: + switch (getStmtClass()) { + case CXXThrowExprClass: + // - a potentially evaluated throw-expression + return CT_Can; + + case CXXDynamicCastExprClass: { + // - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v), + // where T is a reference type, that requires a run-time check + CanThrowResult CT = CanDynamicCastThrow(cast<CXXDynamicCastExpr>(this)); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXTypeidExprClass: + // - a potentially evaluated typeid expression applied to a glvalue + // expression whose type is a polymorphic class type + return CanTypeidThrow(C, cast<CXXTypeidExpr>(this)); + + // - a potentially evaluated call to a function, member function, function + // pointer, or member function pointer that does not have a non-throwing + // exception-specification + case CallExprClass: + case CXXOperatorCallExprClass: + case CXXMemberCallExprClass: { + CanThrowResult CT = CanCalleeThrow(cast<CallExpr>(this)->getCalleeDecl()); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXConstructExprClass: + case CXXTemporaryObjectExprClass: { + CanThrowResult CT = CanCalleeThrow( + cast<CXXConstructExpr>(this)->getConstructor()); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXNewExprClass: { + CanThrowResult CT = MergeCanThrow( + CanCalleeThrow(cast<CXXNewExpr>(this)->getOperatorNew()), + CanCalleeThrow(cast<CXXNewExpr>(this)->getConstructor(), + /*NullThrows*/false)); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXDeleteExprClass: { + CanThrowResult CT = CanCalleeThrow( + cast<CXXDeleteExpr>(this)->getOperatorDelete()); + if (CT == CT_Can) + return CT; + const Expr *Arg = cast<CXXDeleteExpr>(this)->getArgument(); + // Unwrap exactly one implicit cast, which converts all pointers to void*. + if (const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg)) + Arg = Cast->getSubExpr(); + if (const PointerType *PT = Arg->getType()->getAs<PointerType>()) { + if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) { + CanThrowResult CT2 = CanCalleeThrow( + cast<CXXRecordDecl>(RT->getDecl())->getDestructor()); + if (CT2 == CT_Can) + return CT2; + CT = MergeCanThrow(CT, CT2); + } + } + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXBindTemporaryExprClass: { + // The bound temporary has to be destroyed again, which might throw. + CanThrowResult CT = CanCalleeThrow( + cast<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor()); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + // ObjC message sends are like function calls, but never have exception + // specs. + case ObjCMessageExprClass: + case ObjCPropertyRefExprClass: + return CT_Can; + + // Many other things have subexpressions, so we have to test those. + // Some are simple: + case ParenExprClass: + case MemberExprClass: + case CXXReinterpretCastExprClass: + case CXXConstCastExprClass: + case ConditionalOperatorClass: + case CompoundLiteralExprClass: + case ExtVectorElementExprClass: + case InitListExprClass: + case DesignatedInitExprClass: + case ParenListExprClass: + case VAArgExprClass: + case CXXDefaultArgExprClass: + case ExprWithCleanupsClass: + case ObjCIvarRefExprClass: + case ObjCIsaExprClass: + case ShuffleVectorExprClass: + return CanSubExprsThrow(C, this); + + // Some might be dependent for other reasons. + case UnaryOperatorClass: + case ArraySubscriptExprClass: + case ImplicitCastExprClass: + case CStyleCastExprClass: + case CXXStaticCastExprClass: + case CXXFunctionalCastExprClass: + case BinaryOperatorClass: + case CompoundAssignOperatorClass: { + CanThrowResult CT = isTypeDependent() ? CT_Dependent : CT_Cannot; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms. + case StmtExprClass: + return CT_Can; + + case ChooseExprClass: + if (isTypeDependent() || isValueDependent()) + return CT_Dependent; + return cast<ChooseExpr>(this)->getChosenSubExpr(C)->CanThrow(C); + + // Some expressions are always dependent. + case DependentScopeDeclRefExprClass: + case CXXUnresolvedConstructExprClass: + case CXXDependentScopeMemberExprClass: + return CT_Dependent; + + default: + // All other expressions don't have subexpressions, or else they are + // unevaluated. + return CT_Cannot; + } +} + Expr* Expr::IgnoreParens() { Expr* E = this; - while (ParenExpr* P = dyn_cast<ParenExpr>(E)) - E = P->getSubExpr(); - - return E; + while (true) { + if (ParenExpr* P = dyn_cast<ParenExpr>(E)) { + E = P->getSubExpr(); + continue; + } + if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + return E; + } } /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr @@ -1324,24 +1832,68 @@ Expr* Expr::IgnoreParens() { Expr *Expr::IgnoreParenCasts() { Expr *E = this; while (true) { - if (ParenExpr *P = dyn_cast<ParenExpr>(E)) + if (ParenExpr* P = dyn_cast<ParenExpr>(E)) { E = P->getSubExpr(); - else if (CastExpr *P = dyn_cast<CastExpr>(E)) + continue; + } + if (CastExpr *P = dyn_cast<CastExpr>(E)) { E = P->getSubExpr(); - else - return E; + continue; + } + if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + return E; } } +/// IgnoreParenLValueCasts - Ignore parentheses and lvalue-to-rvalue +/// casts. This is intended purely as a temporary workaround for code +/// that hasn't yet been rewritten to do the right thing about those +/// casts, and may disappear along with the last internal use. +Expr *Expr::IgnoreParenLValueCasts() { + Expr *E = this; + while (true) { + if (ParenExpr *P = dyn_cast<ParenExpr>(E)) { + E = P->getSubExpr(); + continue; + } else if (CastExpr *P = dyn_cast<CastExpr>(E)) { + if (P->getCastKind() == CK_LValueToRValue) { + E = P->getSubExpr(); + continue; + } + } else if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + break; + } + return E; +} + Expr *Expr::IgnoreParenImpCasts() { Expr *E = this; while (true) { - if (ParenExpr *P = dyn_cast<ParenExpr>(E)) + if (ParenExpr *P = dyn_cast<ParenExpr>(E)) { E = P->getSubExpr(); - else if (ImplicitCastExpr *P = dyn_cast<ImplicitCastExpr>(E)) + continue; + } + if (ImplicitCastExpr *P = dyn_cast<ImplicitCastExpr>(E)) { E = P->getSubExpr(); - else - return E; + continue; + } + if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + return E; } } @@ -1366,9 +1918,9 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { continue; } - if ((E->getType()->isPointerType() || + if ((E->getType()->isPointerType() || E->getType()->isIntegralType(Ctx)) && - (SE->getType()->isPointerType() || + (SE->getType()->isPointerType() || SE->getType()->isIntegralType(Ctx)) && Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) { E = SE; @@ -1376,6 +1928,13 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { } } + if (UnaryOperator* P = dyn_cast<UnaryOperator>(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + return E; } } @@ -1390,7 +1949,7 @@ bool Expr::isDefaultArgument() const { /// \brief Skip over any no-op casts and any temporary-binding /// expressions. -static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) { +static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) { while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { if (ICE->getCastKind() == CK_NoOp) E = ICE->getSubExpr(); @@ -1407,50 +1966,48 @@ static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) { else break; } - - return E; -} -const Expr *Expr::getTemporaryObject() const { - const Expr *E = skipTemporaryBindingsAndNoOpCasts(this); + return E->IgnoreParens(); +} - // 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() != CK_ConstructorConversion && - Cast->getCastKind() != CK_UserDefinedConversion) - return 0; +/// isTemporaryObject - Determines if this expression produces a +/// temporary of the given class type. +bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const { + if (!C.hasSameUnqualifiedType(getType(), C.getTypeDeclType(TempTy))) + return false; - // Strip off temporary bindings and no-op casts. - const Expr *Sub = skipTemporaryBindingsAndNoOpCasts(Cast->getSubExpr()); + const Expr *E = skipTemporaryBindingsNoOpCastsAndParens(this); - // If this is a constructor conversion, see if we have an object - // construction. - if (Cast->getCastKind() == CK_ConstructorConversion) - return dyn_cast<CXXConstructExpr>(Sub); + // Temporaries are by definition pr-values of class type. + if (!E->Classify(C).isPRValue()) { + // In this context, property reference is a message call and is pr-value. + if (!isa<ObjCPropertyRefExpr>(E)) + return false; + } - // 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() == CK_UserDefinedConversion) - if (const CallExpr *CE = dyn_cast<CallExpr>(Sub)) - if (CE->getCallReturnType()->isRecordType()) - return CE; + // Black-list a few cases which yield pr-values of class type that don't + // refer to temporaries of that type: - return 0; + // - implicit derived-to-base conversions + if (isa<ImplicitCastExpr>(E)) { + switch (cast<ImplicitCastExpr>(E)->getCastKind()) { + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + return false; + default: + break; + } } - // A call returning a class type returns a temporary. - if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { - if (CE->getCallReturnType()->isRecordType()) - return CE; + // - member expressions (all) + if (isa<MemberExpr>(E)) + return false; - return 0; - } + // - opaque values (all) + if (isa<OpaqueValueExpr>(E)) + return false; - // Explicit temporary object constructors create temporaries. - return dyn_cast<CXXTemporaryObjectExpr>(E); + return true; } /// hasAnyTypeDependentArguments - Determines if any of the expressions @@ -1533,6 +2090,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { case ParenExprClass: return cast<ParenExpr>(this)->getSubExpr() ->isConstantInitializer(Ctx, IsForRef); + case ChooseExprClass: + return cast<ChooseExpr>(this)->getChosenSubExpr(Ctx) + ->isConstantInitializer(Ctx, IsForRef); case UnaryOperatorClass: { const UnaryOperator* Exp = cast<UnaryOperator>(this); if (Exp->getOpcode() == UO_Extension) @@ -1572,11 +2132,14 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { return isEvaluatable(Ctx); } -/// 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*. -bool Expr::isNullPointerConstant(ASTContext &Ctx, - NullPointerConstantValueDependence NPC) const { +/// isNullPointerConstant - C99 6.3.2.3p3 - Return whether this is a null +/// pointer constant or not, as well as the specific kind of constant detected. +/// Null pointer constants can be integer constant expressions with the +/// value zero, casts of zero to void*, nullptr (C++0X), or __null +/// (a GNU extension). +Expr::NullPointerConstantKind +Expr::isNullPointerConstant(ASTContext &Ctx, + NullPointerConstantValueDependence NPC) const { if (isValueDependent()) { switch (NPC) { case NPC_NeverValueDependent: @@ -1584,10 +2147,13 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx, // If the unthinkable happens, fall through to the safest alternative. case NPC_ValueDependentIsNull: - return isTypeDependent() || getType()->isIntegralType(Ctx); + if (isTypeDependent() || getType()->isIntegralType(Ctx)) + return NPCK_ZeroInteger; + else + return NPCK_NotNull; case NPC_ValueDependentIsNotNull: - return false; + return NPCK_NotNull; } } @@ -1616,30 +2182,61 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx, return DefaultArg->getExpr()->isNullPointerConstant(Ctx, NPC); } else if (isa<GNUNullExpr>(this)) { // The GNU __null extension is always a null pointer constant. - return true; + return NPCK_GNUNull; } // C++0x nullptr_t is always a null pointer constant. if (getType()->isNullPtrType()) - return true; - + return NPCK_CXX0X_nullptr; + + if (const RecordType *UT = getType()->getAsUnionType()) + if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) + if (const CompoundLiteralExpr *CLE = dyn_cast<CompoundLiteralExpr>(this)){ + const Expr *InitExpr = CLE->getInitializer(); + if (const InitListExpr *ILE = dyn_cast<InitListExpr>(InitExpr)) + return ILE->getInit(0)->isNullPointerConstant(Ctx, NPC); + } // This expression must be an integer type. if (!getType()->isIntegerType() || (Ctx.getLangOptions().CPlusPlus && getType()->isEnumeralType())) - return false; + return NPCK_NotNull; // If we have an integer constant expression, we need to *evaluate* it and // test for the value 0. llvm::APSInt Result; - return isIntegerConstantExpr(Result, Ctx) && Result == 0; + bool IsNull = isIntegerConstantExpr(Result, Ctx) && Result == 0; + + return (IsNull ? NPCK_ZeroInteger : NPCK_NotNull); +} + +/// \brief If this expression is an l-value for an Objective C +/// property, find the underlying property reference expression. +const ObjCPropertyRefExpr *Expr::getObjCProperty() const { + const Expr *E = this; + while (true) { + assert((E->getValueKind() == VK_LValue && + E->getObjectKind() == OK_ObjCProperty) && + "expression is not a property reference"); + E = E->IgnoreParenCasts(); + if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + if (BO->getOpcode() == BO_Comma) { + E = BO->getRHS(); + continue; + } + } + + break; + } + + return cast<ObjCPropertyRefExpr>(E); } FieldDecl *Expr::getBitField() { Expr *E = this->IgnoreParens(); while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { - if (ICE->getValueKind() != VK_RValue && - ICE->getCastKind() == CK_NoOp) + if (ICE->getCastKind() == CK_LValueToRValue || + (ICE->getValueKind() != VK_RValue && ICE->getCastKind() == CK_NoOp)) E = ICE->getSubExpr()->IgnoreParens(); else break; @@ -1650,6 +2247,11 @@ FieldDecl *Expr::getBitField() { if (Field->isBitField()) return Field; + if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E)) + if (FieldDecl *Field = dyn_cast<FieldDecl>(DeclRef->getDecl())) + if (Field->isBitField()) + return Field; + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E)) if (BinOp->isAssignmentOp() && BinOp->getLHS()) return BinOp->getLHS()->getBitField(); @@ -1741,21 +2343,24 @@ void ExtVectorElementExpr::getEncodedElementAccess( } ObjCMessageExpr::ObjCMessageExpr(QualType T, + ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) - : Expr(ObjCMessageExprClass, T, /*TypeDependent=*/false, - /*ValueDependent=*/false), + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, + /*TypeDependent=*/false, /*ValueDependent=*/false, + /*ContainsUnexpandedParameterPack=*/false), NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass), HasMethod(Method != 0), SuperLoc(SuperLoc), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), - LBracLoc(LBracLoc), RBracLoc(RBracLoc) + SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { setReceiverPointer(SuperType.getAsOpaquePtr()); if (NumArgs) @@ -1763,88 +2368,115 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, } ObjCMessageExpr::ObjCMessageExpr(QualType T, + ExprValueKind VK, SourceLocation LBracLoc, TypeSourceInfo *Receiver, - Selector Sel, + Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) - : Expr(ObjCMessageExprClass, T, T->isDependentType(), - (T->isDependentType() || - hasAnyValueDependentArguments(Args, NumArgs))), + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(), + T->isDependentType(), T->containsUnexpandedParameterPack()), NumArgs(NumArgs), Kind(Class), HasMethod(Method != 0), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), - LBracLoc(LBracLoc), RBracLoc(RBracLoc) + SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { setReceiverPointer(Receiver); - if (NumArgs) - memcpy(getArgs(), Args, NumArgs * sizeof(Expr *)); + Expr **MyArgs = getArgs(); + for (unsigned I = 0; I != NumArgs; ++I) { + if (Args[I]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (Args[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Args[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + MyArgs[I] = Args[I]; + } } ObjCMessageExpr::ObjCMessageExpr(QualType T, + ExprValueKind VK, SourceLocation LBracLoc, Expr *Receiver, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) - : Expr(ObjCMessageExprClass, T, Receiver->isTypeDependent(), - (Receiver->isTypeDependent() || - hasAnyValueDependentArguments(Args, NumArgs))), + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(), + Receiver->isTypeDependent(), + Receiver->containsUnexpandedParameterPack()), NumArgs(NumArgs), Kind(Instance), HasMethod(Method != 0), SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method : Sel.getAsOpaquePtr())), - LBracLoc(LBracLoc), RBracLoc(RBracLoc) + SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { setReceiverPointer(Receiver); - if (NumArgs) - memcpy(getArgs(), Args, NumArgs * sizeof(Expr *)); + Expr **MyArgs = getArgs(); + for (unsigned I = 0; I != NumArgs; ++I) { + if (Args[I]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (Args[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Args[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + MyArgs[I] = Args[I]; + } } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, + ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) { unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + NumArgs * sizeof(Expr *); void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); - return new (Mem) ObjCMessageExpr(T, LBracLoc, SuperLoc, IsInstanceSuper, - SuperType, Sel, Method, Args, NumArgs, + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper, + SuperType, Sel, SelLoc, Method, Args,NumArgs, RBracLoc); } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, + ExprValueKind VK, SourceLocation LBracLoc, TypeSourceInfo *Receiver, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) { unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + NumArgs * sizeof(Expr *); void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); - return new (Mem) ObjCMessageExpr(T, LBracLoc, Receiver, Sel, Method, Args, - NumArgs, RBracLoc); + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLoc, + Method, Args, NumArgs, RBracLoc); } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, + ExprValueKind VK, SourceLocation LBracLoc, Expr *Receiver, - Selector Sel, + Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) { unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + NumArgs * sizeof(Expr *); void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); - return new (Mem) ObjCMessageExpr(T, LBracLoc, Receiver, Sel, Method, Args, - NumArgs, RBracLoc); + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLoc, + Method, Args, NumArgs, RBracLoc); } ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context, @@ -1854,7 +2486,23 @@ ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context, void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment); return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); } - + +SourceRange ObjCMessageExpr::getReceiverRange() const { + switch (getReceiverKind()) { + case Instance: + return getInstanceReceiver()->getSourceRange(); + + case Class: + return getClassReceiverTypeInfo()->getTypeLoc().getSourceRange(); + + case SuperInstance: + case SuperClass: + return getSuperLoc(); + } + + return SourceLocation(); +} + Selector ObjCMessageExpr::getSelector() const { if (HasMethod) return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod) @@ -1883,19 +2531,40 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { break; case SuperClass: - if (const ObjCObjectPointerType *Iface - = getSuperType()->getAs<ObjCObjectPointerType>()) - return Iface->getInterfaceDecl(); + if (const ObjCObjectType *Iface + = getSuperType()->getAs<ObjCObjectType>()) + return Iface->getInterface(); break; } return 0; } -bool ChooseExpr::isConditionTrue(ASTContext &C) const { +bool ChooseExpr::isConditionTrue(const ASTContext &C) const { return getCond()->EvaluateAsInt(C) != 0; } +ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr, + QualType Type, SourceLocation BLoc, + SourceLocation RP) + : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary, + Type->isDependentType(), Type->isDependentType(), + Type->containsUnexpandedParameterPack()), + BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr) +{ + SubExprs = new (C) Stmt*[nexpr]; + for (unsigned i = 0; i < nexpr; i++) { + if (args[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (args[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (args[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SubExprs[i] = args[i]; + } +} + void ShuffleVectorExpr::setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs) { if (SubExprs) C.Deallocate(SubExprs); @@ -1926,13 +2595,15 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumIndexExprs, Expr *Init) : Expr(DesignatedInitExprClass, Ty, - Init->isTypeDependent(), Init->isValueDependent()), + Init->getValueKind(), Init->getObjectKind(), + Init->isTypeDependent(), Init->isValueDependent(), + Init->containsUnexpandedParameterPack()), EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax), NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) { this->Designators = new (C) Designator[NumDesignators]; // Record the initializer itself. - child_iterator Child = child_begin(); + child_range Child = children(); *Child++ = Init; // Copy the designators and their subexpressions, computing @@ -1944,8 +2615,12 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty, if (this->Designators[I].isArrayDesignator()) { // Compute type- and value-dependence. Expr *Index = IndexExprs[IndexIdx]; - ValueDependent = ValueDependent || - Index->isTypeDependent() || Index->isValueDependent(); + if (Index->isTypeDependent() || Index->isValueDependent()) + ExprBits.ValueDependent = true; + + // Propagate unexpanded parameter packs. + if (Index->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; // Copy the index expressions into permanent storage. *Child++ = IndexExprs[IndexIdx++]; @@ -1953,9 +2628,14 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty, // Compute type- and value-dependence. Expr *Start = IndexExprs[IndexIdx]; Expr *End = IndexExprs[IndexIdx + 1]; - ValueDependent = ValueDependent || - Start->isTypeDependent() || Start->isValueDependent() || - End->isTypeDependent() || End->isValueDependent(); + if (Start->isTypeDependent() || Start->isValueDependent() || + End->isTypeDependent() || End->isValueDependent()) + ExprBits.ValueDependent = true; + + // Propagate unexpanded parameter packs. + if (Start->containsUnexpandedParameterPack() || + End->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; // Copy the start/end expressions into permanent storage. *Child++ = IndexExprs[IndexIdx++]; @@ -2066,14 +2746,30 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx, ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, unsigned nexprs, SourceLocation rparenloc) -: Expr(ParenListExprClass, QualType(), - hasAnyTypeDependentArguments(exprs, nexprs), - hasAnyValueDependentArguments(exprs, nexprs)), - NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) { + : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, + false, false, false), + NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) { Exprs = new (C) Stmt*[nexprs]; - for (unsigned i = 0; i != nexprs; ++i) + for (unsigned i = 0; i != nexprs; ++i) { + if (exprs[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (exprs[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (exprs[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + Exprs[i] = exprs[i]; + } +} + +const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { + if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(e)) + e = ewc->getSubExpr(); + e = cast<CXXConstructExpr>(e)->getArg(0); + while (const ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) + e = ice->getSubExpr(); + return cast<OpaqueValueExpr>(e); } //===----------------------------------------------------------------------===// @@ -2093,257 +2789,43 @@ const Expr* ConstExprIterator::operator->() const { return cast<Expr>(*I); } // Child Iterators for iterating over subexpressions/substatements //===----------------------------------------------------------------------===// -// DeclRefExpr -Stmt::child_iterator DeclRefExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator DeclRefExpr::child_end() { return child_iterator(); } - -// ObjCIvarRefExpr -Stmt::child_iterator ObjCIvarRefExpr::child_begin() { return &Base; } -Stmt::child_iterator ObjCIvarRefExpr::child_end() { return &Base+1; } - -// ObjCPropertyRefExpr -Stmt::child_iterator ObjCPropertyRefExpr::child_begin() { return &Base; } -Stmt::child_iterator ObjCPropertyRefExpr::child_end() { return &Base+1; } - -// ObjCImplicitSetterGetterRefExpr -Stmt::child_iterator ObjCImplicitSetterGetterRefExpr::child_begin() { - // If this is accessing a class member, skip that entry. - if (Base) return &Base; - return &Base+1; -} -Stmt::child_iterator ObjCImplicitSetterGetterRefExpr::child_end() { - return &Base+1; -} - -// ObjCSuperExpr -Stmt::child_iterator ObjCSuperExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator ObjCSuperExpr::child_end() { return child_iterator(); } - -// ObjCIsaExpr -Stmt::child_iterator ObjCIsaExpr::child_begin() { return &Base; } -Stmt::child_iterator ObjCIsaExpr::child_end() { return &Base+1; } - -// PredefinedExpr -Stmt::child_iterator PredefinedExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator PredefinedExpr::child_end() { return child_iterator(); } - -// IntegerLiteral -Stmt::child_iterator IntegerLiteral::child_begin() { return child_iterator(); } -Stmt::child_iterator IntegerLiteral::child_end() { return child_iterator(); } - -// CharacterLiteral -Stmt::child_iterator CharacterLiteral::child_begin() { return child_iterator();} -Stmt::child_iterator CharacterLiteral::child_end() { return child_iterator(); } - -// FloatingLiteral -Stmt::child_iterator FloatingLiteral::child_begin() { return child_iterator(); } -Stmt::child_iterator FloatingLiteral::child_end() { return child_iterator(); } - -// ImaginaryLiteral -Stmt::child_iterator ImaginaryLiteral::child_begin() { return &Val; } -Stmt::child_iterator ImaginaryLiteral::child_end() { return &Val+1; } - -// StringLiteral -Stmt::child_iterator StringLiteral::child_begin() { return child_iterator(); } -Stmt::child_iterator StringLiteral::child_end() { return child_iterator(); } - -// ParenExpr -Stmt::child_iterator ParenExpr::child_begin() { return &Val; } -Stmt::child_iterator ParenExpr::child_end() { return &Val+1; } - -// UnaryOperator -Stmt::child_iterator UnaryOperator::child_begin() { return &Val; } -Stmt::child_iterator UnaryOperator::child_end() { return &Val+1; } - -// OffsetOfExpr -Stmt::child_iterator OffsetOfExpr::child_begin() { - return reinterpret_cast<Stmt **> (reinterpret_cast<OffsetOfNode *> (this + 1) - + NumComps); -} -Stmt::child_iterator OffsetOfExpr::child_end() { - return child_iterator(&*child_begin() + NumExprs); -} - // SizeOfAlignOfExpr -Stmt::child_iterator SizeOfAlignOfExpr::child_begin() { +Stmt::child_range SizeOfAlignOfExpr::children() { // 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>( + if (const VariableArrayType* T = dyn_cast<VariableArrayType>( getArgumentType().getTypePtr())) - return child_iterator(T); - return child_iterator(); + return child_range(child_iterator(T), child_iterator()); + return child_range(); } - return child_iterator(&Argument.Ex); -} -Stmt::child_iterator SizeOfAlignOfExpr::child_end() { - if (isArgumentType()) - return child_iterator(); - return child_iterator(&Argument.Ex + 1); -} - -// ArraySubscriptExpr -Stmt::child_iterator ArraySubscriptExpr::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator ArraySubscriptExpr::child_end() { - return &SubExprs[0]+END_EXPR; -} - -// CallExpr -Stmt::child_iterator CallExpr::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator CallExpr::child_end() { - return &SubExprs[0]+NumArgs+ARGS_START; -} - -// MemberExpr -Stmt::child_iterator MemberExpr::child_begin() { return &Base; } -Stmt::child_iterator MemberExpr::child_end() { return &Base+1; } - -// ExtVectorElementExpr -Stmt::child_iterator ExtVectorElementExpr::child_begin() { return &Base; } -Stmt::child_iterator ExtVectorElementExpr::child_end() { return &Base+1; } - -// CompoundLiteralExpr -Stmt::child_iterator CompoundLiteralExpr::child_begin() { return &Init; } -Stmt::child_iterator CompoundLiteralExpr::child_end() { return &Init+1; } - -// CastExpr -Stmt::child_iterator CastExpr::child_begin() { return &Op; } -Stmt::child_iterator CastExpr::child_end() { return &Op+1; } - -// BinaryOperator -Stmt::child_iterator BinaryOperator::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator BinaryOperator::child_end() { - return &SubExprs[0]+END_EXPR; -} - -// ConditionalOperator -Stmt::child_iterator ConditionalOperator::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator ConditionalOperator::child_end() { - return &SubExprs[0]+END_EXPR; -} - -// AddrLabelExpr -Stmt::child_iterator AddrLabelExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator AddrLabelExpr::child_end() { return child_iterator(); } - -// StmtExpr -Stmt::child_iterator StmtExpr::child_begin() { return &SubStmt; } -Stmt::child_iterator StmtExpr::child_end() { return &SubStmt+1; } - -// TypesCompatibleExpr -Stmt::child_iterator TypesCompatibleExpr::child_begin() { - return child_iterator(); -} - -Stmt::child_iterator TypesCompatibleExpr::child_end() { - return child_iterator(); -} - -// ChooseExpr -Stmt::child_iterator ChooseExpr::child_begin() { return &SubExprs[0]; } -Stmt::child_iterator ChooseExpr::child_end() { return &SubExprs[0]+END_EXPR; } - -// GNUNullExpr -Stmt::child_iterator GNUNullExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator GNUNullExpr::child_end() { return child_iterator(); } - -// ShuffleVectorExpr -Stmt::child_iterator ShuffleVectorExpr::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator ShuffleVectorExpr::child_end() { - return &SubExprs[0]+NumExprs; -} - -// VAArgExpr -Stmt::child_iterator VAArgExpr::child_begin() { return &Val; } -Stmt::child_iterator VAArgExpr::child_end() { return &Val+1; } - -// InitListExpr -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; -} - -// DesignatedInitExpr -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); -} - -// ImplicitValueInitExpr -Stmt::child_iterator ImplicitValueInitExpr::child_begin() { - return child_iterator(); -} - -Stmt::child_iterator ImplicitValueInitExpr::child_end() { - return child_iterator(); -} - -// ParenListExpr -Stmt::child_iterator ParenListExpr::child_begin() { - return &Exprs[0]; -} -Stmt::child_iterator ParenListExpr::child_end() { - return &Exprs[0]+NumExprs; -} - -// ObjCStringLiteral -Stmt::child_iterator ObjCStringLiteral::child_begin() { - return &String; -} -Stmt::child_iterator ObjCStringLiteral::child_end() { - return &String+1; -} - -// ObjCEncodeExpr -Stmt::child_iterator ObjCEncodeExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator ObjCEncodeExpr::child_end() { return child_iterator(); } - -// ObjCSelectorExpr -Stmt::child_iterator ObjCSelectorExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator ObjCSelectorExpr::child_end() { - return child_iterator(); -} - -// ObjCProtocolExpr -Stmt::child_iterator ObjCProtocolExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator ObjCProtocolExpr::child_end() { - return child_iterator(); + return child_range(&Argument.Ex, &Argument.Ex + 1); } // ObjCMessageExpr -Stmt::child_iterator ObjCMessageExpr::child_begin() { +Stmt::child_range ObjCMessageExpr::children() { + Stmt **begin; if (getReceiverKind() == Instance) - return reinterpret_cast<Stmt **>(this + 1); - return getArgs(); -} -Stmt::child_iterator ObjCMessageExpr::child_end() { - return getArgs() + getNumArgs(); + begin = reinterpret_cast<Stmt **>(this + 1); + else + begin = reinterpret_cast<Stmt **>(getArgs()); + return child_range(begin, + reinterpret_cast<Stmt **>(getArgs() + getNumArgs())); } // Blocks -Stmt::child_iterator BlockExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator BlockExpr::child_end() { return child_iterator(); } +BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK, + SourceLocation l, bool ByRef, + bool constAdded) + : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary, false, false, + d->isParameterPack()), + D(d), Loc(l), IsByRef(ByRef), ConstQualAdded(constAdded) +{ + bool TypeDependent = false; + bool ValueDependent = false; + computeDeclRefDependence(D, getType(), TypeDependent, ValueDependent); + ExprBits.TypeDependent = TypeDependent; + ExprBits.ValueDependent = ValueDependent; +} -Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();} -Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); } |