summaryrefslogtreecommitdiff
path: root/lib/AST/Expr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r--lib/AST/Expr.cpp797
1 files changed, 537 insertions, 260 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 482e1062d88cb..0e4a29f916fa3 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -21,6 +22,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace clang;
@@ -28,34 +30,80 @@ using namespace clang;
// Primary Expressions.
//===----------------------------------------------------------------------===//
-PredefinedExpr* PredefinedExpr::Clone(ASTContext &C) const {
- return new (C) PredefinedExpr(Loc, getType(), Type);
-}
+// FIXME: Maybe this should use DeclPrinter with a special "print predefined
+// expr" policy instead.
+std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT,
+ const Decl *CurrentDecl) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurrentDecl)) {
+ if (IT != PrettyFunction)
+ return FD->getNameAsString();
-IntegerLiteral* IntegerLiteral::Clone(ASTContext &C) const {
- return new (C) IntegerLiteral(Value, getType(), Loc);
-}
+ llvm::SmallString<256> Name;
+ llvm::raw_svector_ostream Out(Name);
-CharacterLiteral* CharacterLiteral::Clone(ASTContext &C) const {
- return new (C) CharacterLiteral(Value, IsWide, getType(), Loc);
-}
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (MD->isVirtual())
+ Out << "virtual ";
+ }
-FloatingLiteral* FloatingLiteral::Clone(ASTContext &C) const {
- return new (C) FloatingLiteral(Value, IsExact, getType(), Loc);
-}
+ PrintingPolicy Policy(Context.getLangOptions());
+ Policy.SuppressTagKind = true;
-ImaginaryLiteral* ImaginaryLiteral::Clone(ASTContext &C) const {
- // FIXME: Use virtual Clone(), once it is available
- Expr *ClonedVal = 0;
- if (const IntegerLiteral *IntLit = dyn_cast<IntegerLiteral>(Val))
- ClonedVal = IntLit->Clone(C);
- else
- ClonedVal = cast<FloatingLiteral>(Val)->Clone(C);
- return new (C) ImaginaryLiteral(ClonedVal, getType());
-}
+ std::string Proto = FD->getQualifiedNameAsString(Policy);
+
+ const FunctionType *AFT = FD->getType()->getAs<FunctionType>();
+ 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 += ")";
+
+ AFT->getResultType().getAsStringInternal(Proto, Policy);
+
+ 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 << '[';
+ Out << MD->getClassInterface()->getNameAsString();
+ if (const ObjCCategoryImplDecl *CID =
+ dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext())) {
+ Out << '(';
+ Out << CID->getNameAsString();
+ Out << ')';
+ }
+ Out << ' ';
+ Out << MD->getSelector().getAsString();
+ Out << ']';
-GNUNullExpr* GNUNullExpr::Clone(ASTContext &C) const {
- return new (C) GNUNullExpr(getType(), TokenLoc);
+ 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 "";
}
/// getValueAsApproximateDouble - This returns the value as an inaccurate
@@ -72,7 +120,7 @@ double FloatingLiteral::getValueAsApproximateDouble() const {
StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData,
unsigned ByteLength, bool Wide,
QualType Ty,
- const SourceLocation *Loc,
+ const SourceLocation *Loc,
unsigned NumStrs) {
// Allocate enough space for the StringLiteral plus an array of locations for
// any concatenated string tokens.
@@ -80,7 +128,7 @@ StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData,
sizeof(SourceLocation)*(NumStrs-1),
llvm::alignof<StringLiteral>());
StringLiteral *SL = new (Mem) StringLiteral(Ty);
-
+
// OPTIMIZE: could allocate this appended to the StringLiteral.
char *AStrData = new (C, 1) char[ByteLength];
memcpy(AStrData, StrData, ByteLength);
@@ -106,25 +154,19 @@ StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) {
return SL;
}
-StringLiteral* StringLiteral::Clone(ASTContext &C) const {
- return Create(C, StrData, ByteLength, IsWide, getType(),
- TokLocs, NumConcatenated);
-}
-
-void StringLiteral::Destroy(ASTContext &C) {
+void StringLiteral::DoDestroy(ASTContext &C) {
C.Deallocate(const_cast<char*>(StrData));
- this->~StringLiteral();
- C.Deallocate(this);
+ Expr::DoDestroy(C);
}
-void StringLiteral::setStrData(ASTContext &C, const char *Str, unsigned Len) {
+void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) {
if (StrData)
C.Deallocate(const_cast<char*>(StrData));
- char *AStrData = new (C, 1) char[Len];
- memcpy(AStrData, Str, Len);
+ char *AStrData = new (C, 1) char[Str.size()];
+ memcpy(AStrData, Str.data(), Str.size());
StrData = AStrData;
- ByteLength = Len;
+ ByteLength = Str.size();
}
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
@@ -149,7 +191,7 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) {
}
}
-UnaryOperator::Opcode
+UnaryOperator::Opcode
UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) {
switch (OO) {
default: assert(false && "No unary operator for overloaded function");
@@ -185,11 +227,11 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args,
unsigned numargs, QualType t, SourceLocation rparenloc)
- : Expr(SC, t,
+ : Expr(SC, t,
fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs),
fn->isValueDependent() || hasAnyValueDependentArguments(args,numargs)),
NumArgs(numargs) {
-
+
SubExprs = new (C) Stmt*[numargs+1];
SubExprs[FN] = fn;
for (unsigned i = 0; i != numargs; ++i)
@@ -213,25 +255,33 @@ CallExpr::CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs,
RParenLoc = rparenloc;
}
-CallExpr::CallExpr(ASTContext &C, EmptyShell Empty)
- : Expr(CallExprClass, Empty), SubExprs(0), NumArgs(0) {
+CallExpr::CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty), SubExprs(0), NumArgs(0) {
SubExprs = new (C) Stmt*[1];
}
-void CallExpr::Destroy(ASTContext& C) {
+void CallExpr::DoDestroy(ASTContext& C) {
DestroyChildren(C);
if (SubExprs) C.Deallocate(SubExprs);
this->~CallExpr();
C.Deallocate(this);
}
+FunctionDecl *CallExpr::getDirectCallee() {
+ Expr *CEE = getCallee()->IgnoreParenCasts();
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE))
+ return dyn_cast<FunctionDecl>(DRE->getDecl());
+
+ return 0;
+}
+
/// 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.
void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) {
// No change, just return.
if (NumArgs == getNumArgs()) return;
-
+
// If shrinking # arguments, just delete the extras and forgot them.
if (NumArgs < getNumArgs()) {
for (unsigned i = NumArgs, e = getNumArgs(); i != e; ++i)
@@ -241,14 +291,14 @@ void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) {
}
// Otherwise, we are growing the # arguments. New an bigger argument array.
- Stmt **NewSubExprs = new Stmt*[NumArgs+1];
+ Stmt **NewSubExprs = new (C) Stmt*[NumArgs+1];
// 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;
-
+
if (SubExprs) C.Deallocate(SubExprs);
SubExprs = NewSubExprs;
this->NumArgs = NumArgs;
@@ -258,37 +308,130 @@ void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) {
/// not, return 0.
unsigned CallExpr::isBuiltinCall(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
+ // function. As a result, we try and obtain the DeclRefExpr from the
// ImplicitCastExpr.
const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(getCallee());
if (!ICE) // FIXME: deal with more complex calls (e.g. (func)(), (*func)()).
return 0;
-
+
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
if (!DRE)
return 0;
-
+
const FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
if (!FDecl)
return 0;
-
+
if (!FDecl->getIdentifier())
return 0;
- return FDecl->getBuiltinID(Context);
+ return FDecl->getBuiltinID();
}
QualType CallExpr::getCallReturnType() const {
QualType CalleeType = getCallee()->getType();
- if (const PointerType *FnTypePtr = CalleeType->getAsPointerType())
+ if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>())
CalleeType = FnTypePtr->getPointeeType();
- else if (const BlockPointerType *BPT = CalleeType->getAsBlockPointerType())
+ else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>())
CalleeType = BPT->getPointeeType();
-
- const FunctionType *FnType = CalleeType->getAsFunctionType();
+
+ const FunctionType *FnType = CalleeType->getAs<FunctionType>();
return FnType->getResultType();
}
+MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
+ SourceRange qualrange, NamedDecl *memberdecl,
+ SourceLocation l, bool has_explicit,
+ SourceLocation langle,
+ const TemplateArgument *targs, unsigned numtargs,
+ SourceLocation rangle, QualType ty)
+ : Expr(MemberExprClass, ty,
+ base->isTypeDependent() || (qual && qual->isDependent()),
+ base->isValueDependent() || (qual && qual->isDependent())),
+ Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
+ HasQualifier(qual != 0), HasExplicitTemplateArgumentList(has_explicit) {
+ // Initialize the qualifier, if any.
+ if (HasQualifier) {
+ NameQualifier *NQ = getMemberQualifier();
+ NQ->NNS = qual;
+ NQ->Range = qualrange;
+ }
+
+ // Initialize the explicit template argument list, if any.
+ if (HasExplicitTemplateArgumentList) {
+ ExplicitTemplateArgumentList *ETemplateArgs
+ = getExplicitTemplateArgumentList();
+ ETemplateArgs->LAngleLoc = langle;
+ ETemplateArgs->RAngleLoc = rangle;
+ ETemplateArgs->NumTemplateArgs = numtargs;
+
+ TemplateArgument *TemplateArgs = ETemplateArgs->getTemplateArgs();
+ for (unsigned I = 0; I < numtargs; ++I)
+ new (TemplateArgs + I) TemplateArgument(targs[I]);
+ }
+}
+
+MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
+ NestedNameSpecifier *qual,
+ SourceRange qualrange,
+ NamedDecl *memberdecl,
+ SourceLocation l,
+ bool has_explicit,
+ SourceLocation langle,
+ const TemplateArgument *targs,
+ unsigned numtargs,
+ SourceLocation rangle,
+ QualType ty) {
+ std::size_t Size = sizeof(MemberExpr);
+ if (qual != 0)
+ Size += sizeof(NameQualifier);
+
+ if (has_explicit)
+ Size += sizeof(ExplicitTemplateArgumentList) +
+ sizeof(TemplateArgument) * numtargs;
+
+ void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
+ return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
+ has_explicit, langle, targs, numtargs, rangle,
+ ty);
+}
+
+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";
+ case CastExpr::CK_DerivedToBase:
+ return "DerivedToBase";
+ 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";
+ case CastExpr::CK_UserDefinedConversion:
+ return "UserDefinedConversion";
+ case CastExpr::CK_ConstructorConversion:
+ return "ConstructorConversion";
+ case CastExpr::CK_IntegralToPointer:
+ return "IntegralToPointer";
+ case CastExpr::CK_PointerToIntegral:
+ return "PointerToIntegral";
+ }
+
+ assert(0 && "Unhandled cast kind!");
+ return 0;
+}
+
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
const char *BinaryOperator::getOpcodeStr(Opcode Op) {
@@ -330,7 +473,7 @@ const char *BinaryOperator::getOpcodeStr(Opcode Op) {
return "";
}
-BinaryOperator::Opcode
+BinaryOperator::Opcode
BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) {
switch (OO) {
default: assert(false && "Not an overloadable binary operator");
@@ -392,13 +535,13 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
return OverOps[Opc];
}
-InitListExpr::InitListExpr(SourceLocation lbraceloc,
+InitListExpr::InitListExpr(SourceLocation lbraceloc,
Expr **initExprs, unsigned numInits,
SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType(),
hasAnyTypeDependentArguments(initExprs, numInits),
hasAnyValueDependentArguments(initExprs, numInits)),
- LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
+ LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
UnionFieldInit(0), HadArrayRangeDesignator(false) {
InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits);
@@ -422,7 +565,7 @@ Expr *InitListExpr::updateInit(unsigned Init, Expr *expr) {
InitExprs.back() = expr;
return 0;
}
-
+
Expr *Result = cast_or_null<Expr>(InitExprs[Init]);
InitExprs[Init] = expr;
return Result;
@@ -431,18 +574,18 @@ Expr *InitListExpr::updateInit(unsigned Init, Expr *expr) {
/// getFunctionType - Return the underlying function type for this block.
///
const FunctionType *BlockExpr::getFunctionType() const {
- return getType()->getAsBlockPointerType()->
- getPointeeType()->getAsFunctionType();
+ return getType()->getAs<BlockPointerType>()->
+ getPointeeType()->getAs<FunctionType>();
}
-SourceLocation BlockExpr::getCaretLocation() const {
- return TheBlock->getCaretLocation();
+SourceLocation BlockExpr::getCaretLocation() const {
+ return TheBlock->getCaretLocation();
}
-const Stmt *BlockExpr::getBody() const {
+const Stmt *BlockExpr::getBody() const {
return TheBlock->getBody();
}
-Stmt *BlockExpr::getBody() {
- return TheBlock->getBody();
+Stmt *BlockExpr::getBody() {
+ return TheBlock->getBody();
}
@@ -460,7 +603,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// instantiating to void.
if (isTypeDependent())
return false;
-
+
switch (getStmtClass()) {
default:
Loc = getExprLoc();
@@ -471,7 +614,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
isUnusedResultAWarning(Loc, R1, R2);
case UnaryOperatorClass: {
const UnaryOperator *UO = cast<UnaryOperator>(this);
-
+
switch (UO->getOpcode()) {
default: break;
case UnaryOperator::PostInc:
@@ -503,7 +646,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
if (BO->getOpcode() == BinaryOperator::Comma)
return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) ||
BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2);
-
+
if (BO->isAssignmentOp())
return false;
Loc = BO->getOperatorLoc();
@@ -518,7 +661,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// The condition must be evaluated, but if either the LHS or RHS is a
// warning, warn about them.
const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
- if (Exp->getLHS() &&
+ if (Exp->getLHS() &&
Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2))
return true;
return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2);
@@ -533,7 +676,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
R1 = SourceRange(Loc, Loc);
R2 = cast<MemberExpr>(this)->getBase()->getSourceRange();
return true;
-
+
case ArraySubscriptExprClass:
// If the base pointer or element is to a volatile pointer/field, accessing
// it is a side effect.
@@ -549,26 +692,43 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case CXXMemberCallExprClass: {
// If this is a direct call, get the callee.
const CallExpr *CE = cast<CallExpr>(this);
- const Expr *CalleeExpr = CE->getCallee()->IgnoreParenCasts();
- if (const DeclRefExpr *CalleeDRE = dyn_cast<DeclRefExpr>(CalleeExpr)) {
+ if (const FunctionDecl *FD = CE->getDirectCallee()) {
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeDRE->getDecl()))
- 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;
- }
+ //
+ // 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;
+ }
}
return false;
}
case ObjCMessageExprClass:
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
+ 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.
@@ -579,17 +739,16 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
if (!CS->body_empty())
if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
return E->isUnusedResultAWarning(Loc, R1, R2);
-
+
Loc = cast<StmtExpr>(this)->getLParenLoc();
R1 = getSourceRange();
return true;
}
case CStyleCastExprClass:
- // If this is a cast to void, check the operand. Otherwise, the result of
- // the cast is unused.
+ // If this is an explicit cast to void, allow it. People do this when they
+ // think they know what they're doing :).
if (getType()->isVoidType())
- return cast<CastExpr>(this)->getSubExpr()
- ->isUnusedResultAWarning(Loc, R1, R2);
+ return false;
Loc = cast<CStyleCastExpr>(this)->getLParenLoc();
R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
@@ -602,7 +761,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
return true;
-
+
case ImplicitCastExprClass:
// Check the operand, since implicit casts are inserted by Sema
return cast<ImplicitCastExpr>(this)
@@ -617,6 +776,9 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// effects (e.g. a placement new with an uninitialized POD).
case CXXDeleteExprClass:
return false;
+ case CXXBindTemporaryExprClass:
+ return cast<CXXBindTemporaryExpr>(this)
+ ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
case CXXExprWithTemporariesClass:
return cast<CXXExprWithTemporaries>(this)
->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
@@ -628,14 +790,15 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) {
// C++ [temp.param]p6:
// A non-type non-reference template-parameter is not an lvalue.
- if (const NonTypeTemplateParmDecl *NTTParm
+ if (const NonTypeTemplateParmDecl *NTTParm
= dyn_cast<NonTypeTemplateParmDecl>(Decl))
return NTTParm->getType()->isReferenceType();
return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) ||
// C++ 3.10p2: An lvalue refers to an object or function.
(Ctx.getLangOptions().CPlusPlus &&
- (isa<FunctionDecl>(Decl) || isa<OverloadedFunctionDecl>(Decl)));
+ (isa<FunctionDecl>(Decl) || isa<OverloadedFunctionDecl>(Decl) ||
+ isa<FunctionTemplateDecl>(Decl)));
}
/// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or an
@@ -659,11 +822,11 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
// 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++.
- if (TR->isFunctionType())
+ if (TR->isFunctionType() || TR == Ctx.OverloadTy)
return LV_NotObjectType;
// Allow qualified void which is an incomplete type other than void (yuck).
- if (TR->isVoidType() && !Ctx.getCanonicalType(TR).getCVRQualifiers())
+ if (TR->isVoidType() && !Ctx.getCanonicalType(TR).hasQualifiers())
return LV_IncompleteVoidType;
return LV_Valid;
@@ -680,7 +843,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
if (cast<ArraySubscriptExpr>(this)->getBase()->getType()->isVectorType())
return cast<ArraySubscriptExpr>(this)->getBase()->isLvalue(Ctx);
return LV_Valid;
- case DeclRefExprClass:
+ case DeclRefExprClass:
case QualifiedDeclRefExprClass: { // C99 6.5.1p2
const NamedDecl *RefdDecl = cast<DeclRefExpr>(this)->getDecl();
if (DeclCanBeLvalue(RefdDecl, Ctx))
@@ -693,7 +856,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
return LV_Valid;
break;
}
- case MemberExprClass: {
+ case MemberExprClass: {
const MemberExpr *m = cast<MemberExpr>(this);
if (Ctx.getLangOptions().CPlusPlus) { // C++ [expr.ref]p4:
NamedDecl *Member = m->getMemberDecl();
@@ -727,7 +890,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
// Not an lvalue.
return LV_InvalidExpression;
- }
+ }
// C99 6.5.2.3p4
return m->isArrow() ? LV_Valid : m->getBase()->isLvalue(Ctx);
@@ -747,7 +910,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
return LV_Valid;
break;
case ImplicitCastExprClass:
- return cast<ImplicitCastExpr>(this)->isLvalueCast()? LV_Valid
+ return cast<ImplicitCastExpr>(this)->isLvalueCast()? LV_Valid
: LV_InvalidExpression;
case ParenExprClass: // C99 6.5.1p5
return cast<ParenExpr>(this)->getSubExpr()->isLvalue(Ctx);
@@ -760,16 +923,26 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
return BinOp->getRHS()->isLvalue(Ctx);
// C++ [expr.mptr.oper]p6
- if ((BinOp->getOpcode() == BinaryOperator::PtrMemD ||
- BinOp->getOpcode() == BinaryOperator::PtrMemI) &&
+ // 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 &&
!BinOp->getType()->isFunctionType())
return BinOp->getLHS()->isLvalue(Ctx);
+ // 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;
+ }
+
if (!BinOp->isAssignmentOp())
return LV_InvalidExpression;
if (Ctx.getLangOptions().CPlusPlus)
- // C++ [expr.ass]p1:
+ // C++ [expr.ass]p1:
// The result of an assignment operation [...] is an lvalue.
return LV_Valid;
@@ -778,7 +951,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
// An assignment expression [...] is not an lvalue.
return LV_InvalidExpression;
}
- case CallExprClass:
+ case CallExprClass:
case CXXOperatorCallExprClass:
case CXXMemberCallExprClass: {
// C++0x [expr.call]p10
@@ -803,7 +976,7 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
return LV_Valid;
case ObjCPropertyRefExprClass: // FIXME: check if read-only property.
return LV_Valid;
- case ObjCKVCRefExprClass: // FIXME: check if read-only property.
+ case ObjCImplicitSetterGetterRefExprClass: // FIXME: check if read-only property.
return LV_Valid;
case PredefinedExprClass:
return LV_Valid;
@@ -828,6 +1001,9 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
case CXXTypeidExprClass:
// C++ 5.2.8p1: The result of a typeid expression is an lvalue of ...
return LV_Valid;
+ case CXXBindTemporaryExprClass:
+ return cast<CXXBindTemporaryExpr>(this)->getSubExpr()->
+ isLvalueInternal(Ctx);
case ConditionalOperatorClass: {
// Complicated handling is only for C++.
if (!Ctx.getLangOptions().CPlusPlus)
@@ -862,15 +1038,15 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
/// 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
-/// if it is a structure or union, does not have any member (including,
+/// if it is a structure or union, does not have any member (including,
/// recursively, any member or element of all contained aggregates or unions)
/// with a const-qualified type.
-Expr::isModifiableLvalueResult
+Expr::isModifiableLvalueResult
Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
isLvalueResult lvalResult = isLvalue(Ctx);
-
+
switch (lvalResult) {
- case LV_Valid:
+ case LV_Valid:
// C++ 3.10p11: Functions cannot be modified, but pointers to
// functions can be modifiable.
if (Ctx.getLangOptions().CPlusPlus && TR->isFunctionType())
@@ -900,74 +1076,37 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
// void takeclosure(void (^C)(void));
// void func() { int x = 1; takeclosure(^{ x = 7; }); }
//
- if (isa<BlockDeclRefExpr>(this)) {
- const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(this);
+ if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(this)) {
if (!BDR->isByRef() && isa<VarDecl>(BDR->getDecl()))
return MLV_NotBlockQualified;
}
+ // Assigning to an 'implicit' property?
+ if (const ObjCImplicitSetterGetterRefExpr* Expr =
+ dyn_cast<ObjCImplicitSetterGetterRefExpr>(this)) {
+ if (Expr->getSetterMethod() == 0)
+ return MLV_NoSetterProperty;
+ }
+
QualType CT = Ctx.getCanonicalType(getType());
-
+
if (CT.isConstQualified())
return MLV_ConstQualified;
if (CT->isArrayType())
return MLV_ArrayType;
if (CT->isIncompleteType())
return MLV_IncompleteType;
-
- if (const RecordType *r = CT->getAsRecordType()) {
- if (r->hasConstFields())
+
+ if (const RecordType *r = CT->getAs<RecordType>()) {
+ if (r->hasConstFields())
return MLV_ConstQualified;
}
-
- // Assigning to an 'implicit' property?
- else if (isa<ObjCKVCRefExpr>(this)) {
- const ObjCKVCRefExpr* KVCExpr = cast<ObjCKVCRefExpr>(this);
- if (KVCExpr->getSetterMethod() == 0)
- return MLV_NoSetterProperty;
- }
- return MLV_Valid;
-}
-/// hasGlobalStorage - Return true if this expression has static storage
-/// duration. This means that the address of this expression is a link-time
-/// constant.
-bool Expr::hasGlobalStorage() const {
- switch (getStmtClass()) {
- default:
- return false;
- case BlockExprClass:
- return true;
- case ParenExprClass:
- return cast<ParenExpr>(this)->getSubExpr()->hasGlobalStorage();
- case ImplicitCastExprClass:
- return cast<ImplicitCastExpr>(this)->getSubExpr()->hasGlobalStorage();
- case CompoundLiteralExprClass:
- return cast<CompoundLiteralExpr>(this)->isFileScope();
- case DeclRefExprClass:
- case QualifiedDeclRefExprClass: {
- const Decl *D = cast<DeclRefExpr>(this)->getDecl();
- if (const VarDecl *VD = dyn_cast<VarDecl>(D))
- return VD->hasGlobalStorage();
- if (isa<FunctionDecl>(D))
- return true;
- return false;
- }
- case MemberExprClass: {
- const MemberExpr *M = cast<MemberExpr>(this);
- return !M->isArrow() && M->getBase()->hasGlobalStorage();
- }
- case ArraySubscriptExprClass:
- return cast<ArraySubscriptExpr>(this)->getBase()->hasGlobalStorage();
- case PredefinedExprClass:
- return true;
- case CXXDefaultArgExprClass:
- return cast<CXXDefaultArgExpr>(this)->getExpr()->hasGlobalStorage();
- }
+ return MLV_Valid;
}
/// isOBJCGCCandidate - Check if an expression is objc gc'able.
-///
+/// returns true, if it is; false otherwise.
bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
switch (getStmtClass()) {
default:
@@ -989,11 +1128,10 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
if (VD->hasGlobalStorage())
return true;
QualType T = VD->getType();
- // dereferencing to an object pointer is always a gc'able candidate
- if (T->isPointerType() &&
- Ctx.isObjCObjectPointerType(T->getAsPointerType()->getPointeeType()))
- return true;
-
+ // dereferencing to a pointer is always a gc'able candidate,
+ // unless it is __weak.
+ return T->isPointerType() &&
+ (Ctx.getObjCGCAttrKind(T) != Qualifiers::Weak);
}
return false;
}
@@ -1009,7 +1147,7 @@ Expr* Expr::IgnoreParens() {
Expr* E = this;
while (ParenExpr* P = dyn_cast<ParenExpr>(E))
E = P->getSubExpr();
-
+
return E;
}
@@ -1037,17 +1175,17 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
E = P->getSubExpr();
continue;
}
-
+
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();
-
+
if (Ctx.hasSameUnqualifiedType(E->getType(), SE->getType())) {
E = SE;
continue;
}
-
+
if ((E->getType()->isPointerType() || E->getType()->isIntegralType()) &&
(SE->getType()->isPointerType() || SE->getType()->isIntegralType()) &&
Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) {
@@ -1055,7 +1193,7 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) {
continue;
}
}
-
+
return E;
}
}
@@ -1094,6 +1232,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
switch (getStmtClass()) {
default: break;
case StringLiteralClass:
+ case ObjCStringLiteralClass:
case ObjCEncodeExprClass:
return true;
case CompoundLiteralExprClass: {
@@ -1110,22 +1249,31 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
const InitListExpr *Exp = cast<InitListExpr>(this);
unsigned numInits = Exp->getNumInits();
for (unsigned i = 0; i < numInits; i++) {
- if (!Exp->getInit(i)->isConstantInitializer(Ctx))
+ if (!Exp->getInit(i)->isConstantInitializer(Ctx))
return false;
}
return true;
}
case ImplicitValueInitExprClass:
return true;
- case ParenExprClass: {
+ case ParenExprClass:
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;
}
+ 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;
+ }
case ImplicitCastExprClass:
case CStyleCastExprClass:
// Handle casts with a destination that's a struct or union; this
@@ -1133,9 +1281,15 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
// cast-to-union extension.
if (getType()->isRecordType())
return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+
+ // 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);
+
break;
}
-
return isEvaluatable(Ctx);
}
@@ -1152,9 +1306,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
// 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
-// itself; the caller checks whether the expression is evaluatable, and
+// itself; the caller checks whether the expression is evaluatable, and
// in the rare cases where CheckICE actually cares about the evaluated
-// value, it calls into Evalute.
+// value, it calls into Evalute.
//
// Meanings of Val:
// 0: This expression is an ICE if it can be evaluated by Evaluate.
@@ -1190,8 +1344,65 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
}
switch (E->getStmtClass()) {
- default:
+#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::CXXConditionDeclExprClass: // FIXME: is this correct?
+ case Expr::CXXNewExprClass:
+ case Expr::CXXDeleteExprClass:
+ case Expr::CXXPseudoDestructorExprClass:
+ case Expr::UnresolvedFunctionNameExprClass:
+ case Expr::UnresolvedDeclRefExprClass:
+ case Expr::TemplateIdRefExprClass:
+ case Expr::CXXConstructExprClass:
+ case Expr::CXXBindTemporaryExprClass:
+ case Expr::CXXExprWithTemporariesClass:
+ case Expr::CXXTemporaryObjectExprClass:
+ case Expr::CXXUnresolvedConstructExprClass:
+ case Expr::CXXUnresolvedMemberExprClass:
+ 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:
+ case Expr::ExprClass:
return ICEDiag(2, E->getLocStart());
+
+ case Expr::GNUNullExprClass:
+ // GCC considers the GNU __null value to be an integral constant expression.
+ return NoDiag();
+
case Expr::ParenExprClass:
return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
case Expr::IntegerLiteralClass:
@@ -1201,7 +1412,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::TypesCompatibleExprClass:
case Expr::UnaryTypeTraitExprClass:
return NoDiag();
- case Expr::CallExprClass:
+ case Expr::CallExprClass:
case Expr::CXXOperatorCallExprClass: {
const CallExpr *CE = cast<CallExpr>(E);
if (CE->isBuiltinCall(Ctx))
@@ -1213,7 +1424,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
return NoDiag();
if (Ctx.getLangOptions().CPlusPlus &&
- E->getType().getCVRQualifiers() == QualType::Const) {
+ E->getType().getCVRQualifiers() == Qualifiers::Const) {
// 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.
@@ -1240,8 +1451,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::UnaryOperatorClass: {
const UnaryOperator *Exp = cast<UnaryOperator>(E);
switch (Exp->getOpcode()) {
- default:
+ case UnaryOperator::PostInc:
+ case UnaryOperator::PostDec:
+ case UnaryOperator::PreInc:
+ case UnaryOperator::PreDec:
+ case UnaryOperator::AddrOf:
+ case UnaryOperator::Deref:
return ICEDiag(2, E->getLocStart());
+
case UnaryOperator::Extension:
case UnaryOperator::LNot:
case UnaryOperator::Plus:
@@ -1269,8 +1486,21 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::BinaryOperatorClass: {
const BinaryOperator *Exp = cast<BinaryOperator>(E);
switch (Exp->getOpcode()) {
- default:
+ 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:
return ICEDiag(2, E->getLocStart());
+
case BinaryOperator::Mul:
case BinaryOperator::Div:
case BinaryOperator::Rem:
@@ -1340,9 +1570,15 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
}
}
}
+ case Expr::CastExprClass:
case Expr::ImplicitCastExprClass:
+ case Expr::ExplicitCastExprClass:
case Expr::CStyleCastExprClass:
- case Expr::CXXFunctionalCastExprClass: {
+ case Expr::CXXFunctionalCastExprClass:
+ case Expr::CXXNamedCastExprClass:
+ case Expr::CXXStaticCastExprClass:
+ case Expr::CXXReinterpretCastExprClass:
+ case Expr::CXXConstCastExprClass: {
const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
if (SubExpr->getType()->isIntegralType())
return CheckICE(SubExpr, Ctx);
@@ -1352,7 +1588,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
}
case Expr::ConditionalOperatorClass: {
const ConditionalOperator *Exp = cast<ConditionalOperator>(E);
- // If the condition (ignoring parens) is a __builtin_constant_p call,
+ // If the condition (ignoring parens) is a __builtin_constant_p call,
// then only the true side is actually considered in an integer constant
// expression, and it is fully evaluated. This is an important GNU
// extension. See GCC PR38377 for discussion.
@@ -1392,6 +1628,9 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
return CheckICE(cast<ChooseExpr>(E)->getChosenSubExpr(Ctx), Ctx);
}
}
+
+ // Silence a GCC warning
+ return ICEDiag(2, E->getLocStart());
}
bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx,
@@ -1413,31 +1652,45 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &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) const
-{
+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;
+ }
+ }
+
// Strip off a cast to void*, if it exists. Except in C++.
if (const ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(this)) {
if (!Ctx.getLangOptions().CPlusPlus) {
// Check that it is a cast to void*.
- if (const PointerType *PT = CE->getType()->getAsPointerType()) {
+ if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
QualType Pointee = PT->getPointeeType();
- if (Pointee.getCVRQualifiers() == 0 &&
+ if (!Pointee.hasQualifiers() &&
Pointee->isVoidType() && // to void*
CE->getSubExpr()->getType()->isIntegerType()) // from int.
- return CE->getSubExpr()->isNullPointerConstant(Ctx);
+ return CE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
}
}
} else if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(this)) {
// Ignore the ImplicitCastExpr type entirely.
- return ICE->getSubExpr()->isNullPointerConstant(Ctx);
+ return ICE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
} else if (const ParenExpr *PE = dyn_cast<ParenExpr>(this)) {
// Accept ((void*)0) as a null pointer constant, as many other
// implementations do.
- return PE->getSubExpr()->isNullPointerConstant(Ctx);
- } else if (const CXXDefaultArgExpr *DefaultArg
+ return PE->getSubExpr()->isNullPointerConstant(Ctx, NPC);
+ } else if (const CXXDefaultArgExpr *DefaultArg
= dyn_cast<CXXDefaultArgExpr>(this)) {
// See through default argument expressions
- return DefaultArg->getExpr()->isNullPointerConstant(Ctx);
+ return DefaultArg->getExpr()->isNullPointerConstant(Ctx, NPC);
} else if (isa<GNUNullExpr>(this)) {
// The GNU __null extension is always a null pointer constant.
return true;
@@ -1448,9 +1701,10 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const
return true;
// This expression must be an integer type.
- if (!getType()->isIntegerType())
+ if (!getType()->isIntegerType() ||
+ (Ctx.getLangOptions().CPlusPlus && getType()->isEnumeralType()))
return false;
-
+
// If we have an integer constant expression, we need to *evaluate* it and
// test for the value 0.
llvm::APSInt Result;
@@ -1458,7 +1712,7 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const
}
FieldDecl *Expr::getBitField() {
- Expr *E = this->IgnoreParenCasts();
+ Expr *E = this->IgnoreParens();
if (MemberExpr *MemRef = dyn_cast<MemberExpr>(E))
if (FieldDecl *Field = dyn_cast<FieldDecl>(MemRef->getMemberDecl()))
@@ -1479,7 +1733,7 @@ bool ExtVectorElementExpr::isArrow() const {
}
unsigned ExtVectorElementExpr::getNumElements() const {
- if (const VectorType *VT = getType()->getAsVectorType())
+ if (const VectorType *VT = getType()->getAs<VectorType>())
return VT->getNumElements();
return 1;
}
@@ -1490,20 +1744,20 @@ bool ExtVectorElementExpr::containsDuplicateElements() const {
unsigned length = Accessor->getLength();
// Halving swizzles do not contain duplicate elements.
- if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
+ if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
!strcmp(compStr, "even") || !strcmp(compStr, "odd"))
return false;
-
+
// Advance past s-char prefix on hex swizzles.
if (*compStr == 's' || *compStr == 'S') {
compStr++;
length--;
}
-
+
for (unsigned i = 0; i != length-1; i++) {
const char *s = compStr+i;
for (const char c = *s++; *s; s++)
- if (c == *s)
+ if (c == *s)
return true;
}
return false;
@@ -1515,15 +1769,15 @@ void ExtVectorElementExpr::getEncodedElementAccess(
const char *compStr = Accessor->getName();
if (*compStr == 's' || *compStr == 'S')
compStr++;
-
+
bool isHi = !strcmp(compStr, "hi");
bool isLo = !strcmp(compStr, "lo");
bool isEven = !strcmp(compStr, "even");
bool isOdd = !strcmp(compStr, "odd");
-
+
for (unsigned i = 0, e = getNumElements(); i != e; ++i) {
uint64_t Index;
-
+
if (isHi)
Index = e + i;
else if (isLo)
@@ -1544,7 +1798,7 @@ ObjCMessageExpr::ObjCMessageExpr(Expr *receiver, Selector selInfo,
QualType retType, ObjCMethodDecl *mproto,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned nargs)
- : Expr(ObjCMessageExprClass, retType), SelName(selInfo),
+ : Expr(ObjCMessageExprClass, retType), SelName(selInfo),
MethodProto(mproto) {
NumArgs = nargs;
SubExprs = new Stmt*[NumArgs+1];
@@ -1557,29 +1811,13 @@ ObjCMessageExpr::ObjCMessageExpr(Expr *receiver, Selector selInfo,
RBracloc = RBrac;
}
-ObjCStringLiteral* ObjCStringLiteral::Clone(ASTContext &C) const {
- // Clone the string literal.
- StringLiteral *NewString =
- String ? cast<StringLiteral>(String)->Clone(C) : 0;
-
- return new (C) ObjCStringLiteral(NewString, getType(), AtLoc);
-}
-
-ObjCSelectorExpr *ObjCSelectorExpr::Clone(ASTContext &C) const {
- return new (C) ObjCSelectorExpr(getType(), SelName, AtLoc, RParenLoc);
-}
-
-ObjCProtocolExpr *ObjCProtocolExpr::Clone(ASTContext &C) const {
- return new (C) ObjCProtocolExpr(getType(), TheProtocol, AtLoc, RParenLoc);
-}
-
-// constructor for class messages.
+// constructor for class messages.
// FIXME: clsName should be typed to ObjCInterfaceType
ObjCMessageExpr::ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
QualType retType, ObjCMethodDecl *mproto,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned nargs)
- : Expr(ObjCMessageExprClass, retType), SelName(selInfo),
+ : Expr(ObjCMessageExprClass, retType), SelName(selInfo),
MethodProto(mproto) {
NumArgs = nargs;
SubExprs = new Stmt*[NumArgs+1];
@@ -1592,12 +1830,12 @@ ObjCMessageExpr::ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
RBracloc = RBrac;
}
-// constructor for class messages.
+// constructor for class messages.
ObjCMessageExpr::ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
QualType retType, ObjCMethodDecl *mproto,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned nargs)
-: Expr(ObjCMessageExprClass, retType), SelName(selInfo),
+: Expr(ObjCMessageExprClass, retType), SelName(selInfo),
MethodProto(mproto) {
NumArgs = nargs;
SubExprs = new Stmt*[NumArgs+1];
@@ -1640,16 +1878,23 @@ bool ChooseExpr::isConditionTrue(ASTContext &C) const {
return getCond()->EvaluateAsInt(C) != 0;
}
-void ShuffleVectorExpr::setExprs(Expr ** Exprs, unsigned NumExprs) {
- if (NumExprs)
- delete [] SubExprs;
-
- SubExprs = new Stmt* [NumExprs];
+void ShuffleVectorExpr::setExprs(ASTContext &C, Expr ** Exprs,
+ unsigned NumExprs) {
+ if (SubExprs) C.Deallocate(SubExprs);
+
+ SubExprs = new (C) Stmt* [NumExprs];
this->NumExprs = NumExprs;
memcpy(SubExprs, Exprs, sizeof(Expr *) * NumExprs);
}
-void SizeOfAlignOfExpr::Destroy(ASTContext& C) {
+void ShuffleVectorExpr::DoDestroy(ASTContext& C) {
+ DestroyChildren(C);
+ if (SubExprs) C.Deallocate(SubExprs);
+ this->~ShuffleVectorExpr();
+ C.Deallocate(this);
+}
+
+void SizeOfAlignOfExpr::DoDestroy(ASTContext& C) {
// 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
@@ -1660,7 +1905,7 @@ void SizeOfAlignOfExpr::Destroy(ASTContext& C) {
C.Deallocate(this);
}
else
- Expr::Destroy(C);
+ Expr::DoDestroy(C);
}
//===----------------------------------------------------------------------===//
@@ -1675,17 +1920,17 @@ IdentifierInfo *DesignatedInitExpr::Designator::getFieldName() {
return getField()->getIdentifier();
}
-DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
+DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
const Designator *Designators,
- SourceLocation EqualOrColonLoc,
+ SourceLocation EqualOrColonLoc,
bool GNUSyntax,
- Expr **IndexExprs,
+ Expr **IndexExprs,
unsigned NumIndexExprs,
Expr *Init)
- : Expr(DesignatedInitExprClass, Ty,
+ : Expr(DesignatedInitExprClass, Ty,
Init->isTypeDependent(), Init->isValueDependent()),
- EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
- NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) {
+ EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax),
+ NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) {
this->Designators = new Designator[NumDesignators];
// Record the initializer itself.
@@ -1701,7 +1946,7 @@ DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
if (this->Designators[I].isArrayDesignator()) {
// Compute type- and value-dependence.
Expr *Index = IndexExprs[IndexIdx];
- ValueDependent = ValueDependent ||
+ ValueDependent = ValueDependent ||
Index->isTypeDependent() || Index->isValueDependent();
// Copy the index expressions into permanent storage.
@@ -1710,7 +1955,7 @@ DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
// Compute type- and value-dependence.
Expr *Start = IndexExprs[IndexIdx];
Expr *End = IndexExprs[IndexIdx + 1];
- ValueDependent = ValueDependent ||
+ ValueDependent = ValueDependent ||
Start->isTypeDependent() || Start->isValueDependent() ||
End->isTypeDependent() || End->isValueDependent();
@@ -1724,7 +1969,7 @@ DesignatedInitExpr::DesignatedInitExpr(QualType Ty, unsigned NumDesignators,
}
DesignatedInitExpr *
-DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
+DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
unsigned NumDesignators,
Expr **IndexExprs, unsigned NumIndexExprs,
SourceLocation ColonOrEqualLoc,
@@ -1736,14 +1981,14 @@ DesignatedInitExpr::Create(ASTContext &C, Designator *Designators,
IndexExprs, NumIndexExprs, Init);
}
-DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
+DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
unsigned NumIndexExprs) {
void *Mem = C.Allocate(sizeof(DesignatedInitExpr) +
sizeof(Stmt *) * (NumIndexExprs + 1), 8);
return new (Mem) DesignatedInitExpr(NumIndexExprs + 1);
}
-void DesignatedInitExpr::setDesignators(const Designator *Desigs,
+void DesignatedInitExpr::setDesignators(const Designator *Desigs,
unsigned NumDesigs) {
if (Designators)
delete [] Designators;
@@ -1778,7 +2023,7 @@ Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) {
}
Expr *DesignatedInitExpr::getArrayRangeStart(const Designator& D) {
- assert(D.Kind == Designator::ArrayRangeDesignator &&
+ assert(D.Kind == Designator::ArrayRangeDesignator &&
"Requires array range designator");
char* Ptr = static_cast<char*>(static_cast<void *>(this));
Ptr += sizeof(DesignatedInitExpr);
@@ -1787,7 +2032,7 @@ Expr *DesignatedInitExpr::getArrayRangeStart(const Designator& D) {
}
Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) {
- assert(D.Kind == Designator::ArrayRangeDesignator &&
+ assert(D.Kind == Designator::ArrayRangeDesignator &&
"Requires array range designator");
char* Ptr = static_cast<char*>(static_cast<void *>(this));
Ptr += sizeof(DesignatedInitExpr);
@@ -1797,8 +2042,8 @@ Expr *DesignatedInitExpr::getArrayRangeEnd(const Designator& D) {
/// \brief Replaces the designator at index @p Idx with the series
/// of designators in [First, Last).
-void DesignatedInitExpr::ExpandDesignator(unsigned Idx,
- const Designator *First,
+void DesignatedInitExpr::ExpandDesignator(unsigned Idx,
+ const Designator *First,
const Designator *Last) {
unsigned NumNewDesignators = Last - First;
if (NumNewDesignators == 0) {
@@ -1812,7 +2057,7 @@ void DesignatedInitExpr::ExpandDesignator(unsigned Idx,
return;
}
- Designator *NewDesignators
+ Designator *NewDesignators
= new Designator[NumDesignators - 1 + NumNewDesignators];
std::copy(Designators, Designators + Idx, NewDesignators);
std::copy(First, Last, NewDesignators + Idx);
@@ -1823,13 +2068,29 @@ void DesignatedInitExpr::ExpandDesignator(unsigned Idx,
NumDesignators = NumDesignators - 1 + NumNewDesignators;
}
-void DesignatedInitExpr::Destroy(ASTContext &C) {
+void DesignatedInitExpr::DoDestroy(ASTContext &C) {
delete [] Designators;
- Expr::Destroy(C);
+ Expr::DoDestroy(C);
}
-ImplicitValueInitExpr *ImplicitValueInitExpr::Clone(ASTContext &C) const {
- return new (C) ImplicitValueInitExpr(getType());
+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) {
+
+ 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);
}
//===----------------------------------------------------------------------===//
@@ -1861,14 +2122,22 @@ Stmt::child_iterator ObjCIvarRefExpr::child_end() { return &Base+1; }
Stmt::child_iterator ObjCPropertyRefExpr::child_begin() { return &Base; }
Stmt::child_iterator ObjCPropertyRefExpr::child_end() { return &Base+1; }
-// ObjCKVCRefExpr
-Stmt::child_iterator ObjCKVCRefExpr::child_begin() { return &Base; }
-Stmt::child_iterator ObjCKVCRefExpr::child_end() { return &Base+1; }
+// ObjCImplicitSetterGetterRefExpr
+Stmt::child_iterator ObjCImplicitSetterGetterRefExpr::child_begin() {
+ return &Base;
+}
+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(); }
@@ -1902,7 +2171,7 @@ Stmt::child_iterator UnaryOperator::child_begin() { return &Val; }
Stmt::child_iterator UnaryOperator::child_end() { return &Val+1; }
// SizeOfAlignOfExpr
-Stmt::child_iterator SizeOfAlignOfExpr::child_begin() {
+Stmt::child_iterator SizeOfAlignOfExpr::child_begin() {
// 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?
@@ -2024,16 +2293,24 @@ Stmt::child_iterator DesignatedInitExpr::child_end() {
}
// ImplicitValueInitExpr
-Stmt::child_iterator ImplicitValueInitExpr::child_begin() {
- return child_iterator();
+Stmt::child_iterator ImplicitValueInitExpr::child_begin() {
+ return child_iterator();
}
-Stmt::child_iterator ImplicitValueInitExpr::child_end() {
- 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() {
+Stmt::child_iterator ObjCStringLiteral::child_begin() {
return &String;
}
Stmt::child_iterator ObjCStringLiteral::child_end() {
@@ -2045,7 +2322,7 @@ 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() {
+Stmt::child_iterator ObjCSelectorExpr::child_begin() {
return child_iterator();
}
Stmt::child_iterator ObjCSelectorExpr::child_end() {
@@ -2061,7 +2338,7 @@ Stmt::child_iterator ObjCProtocolExpr::child_end() {
}
// ObjCMessageExpr
-Stmt::child_iterator ObjCMessageExpr::child_begin() {
+Stmt::child_iterator ObjCMessageExpr::child_begin() {
return getReceiver() ? &SubExprs[0] : &SubExprs[0] + ARGS_START;
}
Stmt::child_iterator ObjCMessageExpr::child_end() {