diff options
author | John McCall <rjmccall@apple.com> | 2011-02-17 10:25:35 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-02-17 10:25:35 +0000 |
commit | 56ca35d396d8692c384c785f9aeebcf22563fe1e (patch) | |
tree | cd52281e952ff00244a59c5d47e34459c22fd7c0 | |
parent | 05c699e97aea64ee8cea1faaca900a39f977350c (diff) |
Change the representation of GNU ?: expressions to use a different expression
class and to bind the shared value using OpaqueValueExpr. This fixes an
unnoticed problem with deserialization of these expressions where the
deserialized form would lose the vital pointer-equality trait; or rather,
it fixes it because this patch also does the right thing for deserializing
OVEs.
Change OVEs to not be a "temporary object" in the sense that copy elision is
permitted.
This new representation is not totally unawkward to work with, but I think
that's really part and parcel with the semantics we're modelling here. In
particular, it's much easier to fix things like the copy elision bug and to
make the CFG look right.
I've tried to update the analyzer to deal with this in at least some
obvious cases, and I think we get a much better CFG out, but the printing
of OpaqueValueExprs probably needs some work.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125744 91177308-0d34-0410-b5e6-96231b3b80d8
40 files changed, 986 insertions, 429 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index b5724a6475..36644784c9 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -43,6 +43,7 @@ namespace clang { class ObjCPropertyRefExpr; class TemplateArgumentLoc; class TemplateArgumentListInfo; + class OpaqueValueExpr; /// \brief A simple array of base specifiers. typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; @@ -319,6 +320,11 @@ public: return static_cast<ExprObjectKind>(ExprBits.ObjectKind); } + bool isOrdinaryOrBitFieldObject() const { + ExprObjectKind OK = getObjectKind(); + return (OK == OK_Ordinary || OK == OK_BitField); + } + /// setValueKind - Set the value kind produced by this expression. void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; } @@ -538,6 +544,63 @@ public: // Primary Expressions. //===----------------------------------------------------------------------===// +/// OpaqueValueExpr - An expression referring to an opaque object of a +/// fixed type and value class. These don't correspond to concrete +/// syntax; instead they're used to express operations (usually copy +/// operations) on values whose source is generally obvious from +/// context. +class OpaqueValueExpr : public Expr { + friend class ASTStmtReader; + Expr *SourceExpr; + SourceLocation Loc; + +public: + OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, + ExprObjectKind OK = OK_Ordinary) + : Expr(OpaqueValueExprClass, T, VK, OK, + T->isDependentType(), T->isDependentType(), false), + SourceExpr(0), Loc(Loc) { + } + + /// Given an expression which invokes a copy constructor --- i.e. a + /// CXXConstructExpr, possibly wrapped in an ExprWithCleanups --- + /// find the OpaqueValueExpr that's the source of the construction. + static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr); + + explicit OpaqueValueExpr(EmptyShell Empty) + : Expr(OpaqueValueExprClass, Empty) { } + + /// \brief Retrieve the location of this expression. + SourceLocation getLocation() const { return Loc; } + + SourceRange getSourceRange() const { + if (SourceExpr) return SourceExpr->getSourceRange(); + return Loc; + } + SourceLocation getExprLoc() const { + if (SourceExpr) return SourceExpr->getExprLoc(); + return Loc; + } + + child_range children() { return child_range(); } + + /// The source expression of an opaque value expression is the + /// expression which originally generated the value. This is + /// provided as a convenience for analyses that don't wish to + /// precisely model the execution behavior of the program. + /// + /// The source expression is typically set when building the + /// expression which binds the opaque value expression in the first + /// place. + Expr *getSourceExpr() const { return SourceExpr; } + void setSourceExpr(Expr *e) { SourceExpr = e; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OpaqueValueExprClass; + } + static bool classof(const OpaqueValueExpr *) { return true; } +}; + /// \brief Represents the qualifier that may precede a C++ name, e.g., the /// "std::" in "std::sort". struct NameQualifier { @@ -2552,77 +2615,95 @@ public: } }; -/// ConditionalOperator - The ?: operator. Note that LHS may be null when the -/// GNU "missing LHS" extension is in use. -/// -class ConditionalOperator : public Expr { +/// AbstractConditionalOperator - An abstract base class for +/// ConditionalOperator and BinaryConditionalOperator. +class AbstractConditionalOperator : public Expr { + SourceLocation QuestionLoc, ColonLoc; + friend class ASTStmtReader; + +protected: + AbstractConditionalOperator(StmtClass SC, QualType T, + ExprValueKind VK, ExprObjectKind OK, + bool TD, bool VD, + bool ContainsUnexpandedParameterPack, + SourceLocation qloc, + SourceLocation cloc) + : Expr(SC, T, VK, OK, TD, VD, ContainsUnexpandedParameterPack), + QuestionLoc(qloc), ColonLoc(cloc) {} + + AbstractConditionalOperator(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty) { } + +public: + // getCond - Return the expression representing the condition for + // the ?: operator. + Expr *getCond() const; + + // getTrueExpr - Return the subexpression representing the value of + // the expression if the condition evaluates to true. + Expr *getTrueExpr() const; + + // getFalseExpr - Return the subexpression representing the value of + // the expression if the condition evaluates to false. This is + // the same as getRHS. + Expr *getFalseExpr() const; + + SourceLocation getQuestionLoc() const { return QuestionLoc; } + SourceLocation getColonLoc() const { return ColonLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConditionalOperatorClass || + T->getStmtClass() == BinaryConditionalOperatorClass; + } + static bool classof(const AbstractConditionalOperator *) { return true; } +}; + +/// ConditionalOperator - The ?: ternary operator. The GNU "missing +/// middle" extension is a BinaryConditionalOperator. +class ConditionalOperator : public AbstractConditionalOperator { enum { COND, LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. - Stmt* Save; - SourceLocation QuestionLoc, ColonLoc; + + friend class ASTStmtReader; public: ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, - SourceLocation CLoc, Expr *rhs, Expr *save, + SourceLocation CLoc, Expr *rhs, QualType t, ExprValueKind VK, ExprObjectKind OK) - : Expr(ConditionalOperatorClass, t, VK, OK, + : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK, // FIXME: the type of the conditional operator doesn't // depend on the type of the conditional, but the standard // seems to imply that it could. File a bug! - ((lhs && lhs->isTypeDependent()) || (rhs && rhs->isTypeDependent())), - (cond->isValueDependent() || - (lhs && lhs->isValueDependent()) || - (rhs && rhs->isValueDependent())), + (lhs->isTypeDependent() || rhs->isTypeDependent()), + (cond->isValueDependent() || lhs->isValueDependent() || + rhs->isValueDependent()), (cond->containsUnexpandedParameterPack() || - (lhs && lhs->containsUnexpandedParameterPack()) || - (rhs && rhs->containsUnexpandedParameterPack()))), - QuestionLoc(QLoc), - ColonLoc(CLoc) { + lhs->containsUnexpandedParameterPack() || + rhs->containsUnexpandedParameterPack()), + QLoc, CLoc) { SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - Save = save; } /// \brief Build an empty conditional operator. explicit ConditionalOperator(EmptyShell Empty) - : Expr(ConditionalOperatorClass, Empty) { } + : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { } // getCond - Return the expression representing the condition for - // the ?: operator. + // the ?: operator. Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } - void setCond(Expr *E) { SubExprs[COND] = E; } - // getTrueExpr - Return the subexpression representing the value of the ?: - // expression if the condition evaluates to true. - Expr *getTrueExpr() const { - return cast<Expr>(SubExprs[LHS]); - } + // getTrueExpr - Return the subexpression representing the value of + // the expression if the condition evaluates to true. + Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); } - // getFalseExpr - Return the subexpression representing the value of the ?: - // expression if the condition evaluates to false. This is the same as getRHS. + // getFalseExpr - Return the subexpression representing the value of + // the expression if the condition evaluates to false. This is + // the same as getRHS. Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } - // getSaveExpr - In most cases this value will be null. Except a GCC extension - // allows the left subexpression to be omitted, and instead of that condition - // be returned. e.g: x ?: y is shorthand for x ? x : y, except that the - // expression "x" is only evaluated once. Under this senario, this function - // returns the original, non-converted condition expression for the ?:operator - Expr *getSaveExpr() const { return Save? cast<Expr>(Save) : (Expr*)0; } - - Expr *getLHS() const { return Save ? 0 : cast<Expr>(SubExprs[LHS]); } - void setLHS(Expr *E) { SubExprs[LHS] = E; } - + Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } - void setRHS(Expr *E) { SubExprs[RHS] = E; } - - Expr *getSAVE() const { return Save? cast<Expr>(Save) : (Expr*)0; } - void setSAVE(Expr *E) { Save = E; } - - SourceLocation getQuestionLoc() const { return QuestionLoc; } - void setQuestionLoc(SourceLocation L) { QuestionLoc = L; } - - SourceLocation getColonLoc() const { return ColonLoc; } - void setColonLoc(SourceLocation L) { ColonLoc = L; } SourceRange getSourceRange() const { return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd()); @@ -2638,6 +2719,105 @@ public: } }; +/// BinaryConditionalOperator - The GNU extension to the conditional +/// operator which allows the middle operand to be omitted. +/// +/// This is a different expression kind on the assumption that almost +/// every client ends up needing to know that these are different. +class BinaryConditionalOperator : public AbstractConditionalOperator { + enum { COMMON, COND, LHS, RHS, NUM_SUBEXPRS }; + + /// - the common condition/left-hand-side expression, which will be + /// evaluated as the opaque value + /// - the condition, expressed in terms of the opaque value + /// - the left-hand-side, expressed in terms of the opaque value + /// - the right-hand-side + Stmt *SubExprs[NUM_SUBEXPRS]; + OpaqueValueExpr *OpaqueValue; + + friend class ASTStmtReader; +public: + BinaryConditionalOperator(Expr *common, OpaqueValueExpr *opaqueValue, + Expr *cond, Expr *lhs, Expr *rhs, + SourceLocation qloc, SourceLocation cloc, + QualType t, ExprValueKind VK, ExprObjectKind OK) + : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK, + (common->isTypeDependent() || rhs->isTypeDependent()), + (common->isValueDependent() || rhs->isValueDependent()), + (common->containsUnexpandedParameterPack() || + rhs->containsUnexpandedParameterPack()), + qloc, cloc), + OpaqueValue(opaqueValue) { + SubExprs[COMMON] = common; + SubExprs[COND] = cond; + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + + OpaqueValue->setSourceExpr(common); + } + + /// \brief Build an empty conditional operator. + explicit BinaryConditionalOperator(EmptyShell Empty) + : AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { } + + /// \brief getCommon - Return the common expression, written to the + /// left of the condition. The opaque value will be bound to the + /// result of this expression. + Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); } + + /// \brief getOpaqueValue - Return the opaque value placeholder. + OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; } + + /// \brief getCond - Return the condition expression; this is defined + /// in terms of the opaque value. + Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } + + /// \brief getTrueExpr - Return the subexpression which will be + /// evaluated if the condition evaluates to true; this is defined + /// in terms of the opaque value. + Expr *getTrueExpr() const { + return cast<Expr>(SubExprs[LHS]); + } + + /// \brief getFalseExpr - Return the subexpression which will be + /// evaluated if the condnition evaluates to false; this is + /// defined in terms of the opaque value. + Expr *getFalseExpr() const { + return cast<Expr>(SubExprs[RHS]); + } + + SourceRange getSourceRange() const { + return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == BinaryConditionalOperatorClass; + } + static bool classof(const BinaryConditionalOperator *) { return true; } + + // Iterators + child_range children() { + return child_range(SubExprs, SubExprs + NUM_SUBEXPRS); + } +}; + +inline Expr *AbstractConditionalOperator::getCond() const { + if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this)) + return co->getCond(); + return cast<BinaryConditionalOperator>(this)->getCond(); +} + +inline Expr *AbstractConditionalOperator::getTrueExpr() const { + if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this)) + return co->getTrueExpr(); + return cast<BinaryConditionalOperator>(this)->getTrueExpr(); +} + +inline Expr *AbstractConditionalOperator::getFalseExpr() const { + if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this)) + return co->getFalseExpr(); + return cast<BinaryConditionalOperator>(this)->getFalseExpr(); +} + /// AddrLabelExpr - The GNU address of label extension, representing &&label. class AddrLabelExpr : public Expr { SourceLocation AmpAmpLoc, LabelLoc; @@ -3619,43 +3799,6 @@ public: child_range children() { return child_range(); } }; -/// OpaqueValueExpr - An expression referring to an opaque object of a -/// fixed type and value class. These don't correspond to concrete -/// syntax; instead they're used to express operations (usually copy -/// operations) on values whose source is generally obvious from -/// context. -class OpaqueValueExpr : public Expr { - friend class ASTStmtReader; - SourceLocation Loc; - -public: - OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, - ExprObjectKind OK = OK_Ordinary) - : Expr(OpaqueValueExprClass, T, VK, OK, - T->isDependentType(), T->isDependentType(), false), - Loc(Loc) { - } - - /// Given an expression which invokes a copy constructor --- i.e. a - /// CXXConstructExpr, possibly wrapped in an ExprWithCleanups --- - /// find the OpaqueValueExpr that's the source of the construction. - static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr); - - explicit OpaqueValueExpr(EmptyShell Empty) - : Expr(OpaqueValueExprClass, Empty) { } - - /// \brief Retrieve the location of this expression. - SourceLocation getLocation() const { return Loc; } - - SourceRange getSourceRange() const { return Loc; } - child_range children() { return child_range(); } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == OpaqueValueExprClass; - } - static bool classof(const OpaqueValueExpr *) { return true; } -}; - } // end namespace clang #endif diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 667b840889..ade0b2a799 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1852,6 +1852,7 @@ DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { }) // These operators (all of them) do not need any action except // iterating over the children. +DEF_TRAVERSE_STMT(BinaryConditionalOperator, { }) DEF_TRAVERSE_STMT(ConditionalOperator, { }) DEF_TRAVERSE_STMT(UnaryOperator, { }) DEF_TRAVERSE_STMT(BinaryOperator, { }) diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h index 2d59119f25..d197e69bab 100644 --- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -80,6 +80,7 @@ public: DISPATCH_CASE(StmtExpr) DISPATCH_CASE(ConditionalOperator) + DISPATCH_CASE(BinaryConditionalOperator) DISPATCH_CASE(ObjCForCollectionStmt) case Stmt::BinaryOperatorClass: { @@ -102,6 +103,7 @@ public: DEFAULT_BLOCKSTMT_VISIT(StmtExpr) DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator) + DEFAULT_BLOCKSTMT_VISIT(BinaryConditionalOperator) RetTy BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) { return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 54e9c6723c..be0d8ff091 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -61,7 +61,9 @@ def MemberExpr : DStmt<Expr>; def CastExpr : DStmt<Expr, 1>; def BinaryOperator : DStmt<Expr>; def CompoundAssignOperator : DStmt<BinaryOperator>; -def ConditionalOperator : DStmt<Expr>; +def AbstractConditionalOperator : DStmt<Expr, 1>; +def ConditionalOperator : DStmt<AbstractConditionalOperator>; +def BinaryConditionalOperator : DStmt<AbstractConditionalOperator>; def ImplicitCastExpr : DStmt<CastExpr>; def ExplicitCastExpr : DStmt<CastExpr, 1>; def CStyleCastExpr : DStmt<ExplicitCastExpr>; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 23bcb94976..98328479c4 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4762,10 +4762,10 @@ public: void ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType& LHSTy); QualType CheckConditionalOperands( // C99 6.5.15 - Expr *&cond, Expr *&lhs, Expr *&rhs, Expr *&save, + Expr *&cond, Expr *&lhs, Expr *&rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); QualType CXXCheckConditionalOperands( // C++ 5.16 - Expr *&cond, Expr *&lhs, Expr *&rhs, Expr *&save, + Expr *&cond, Expr *&lhs, Expr *&rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, bool *NonStandardCompositeType = 0); diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index d1998c29a3..5b77dff7f2 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -959,6 +959,7 @@ namespace clang { EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr EXPR_OPAQUE_VALUE, // OpaqueValueExpr + EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr EXPR_PACK_EXPANSION, // PackExpansionExpr diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 002f6be410..9799b8d852 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -58,6 +58,7 @@ class CXXCtorInitializer; class GotoStmt; class MacroDefinition; class NamedDecl; +class OpaqueValueExpr; class Preprocessor; class Sema; class SwitchCase; @@ -645,6 +646,9 @@ private: /// switch statement can refer to them. std::map<unsigned, SwitchCase *> SwitchCaseStmts; + /// \brief Mapping from opaque value IDs to OpaqueValueExprs. + std::map<unsigned, OpaqueValueExpr*> OpaqueValueExprs; + /// \brief The number of stat() calls that hit/missed the stat /// cache. unsigned NumStatHits, NumStatMisses; diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index d5f622a340..beb493625e 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -46,6 +46,7 @@ class FPOptions; class HeaderSearch; class MacroDefinition; class MemorizeStatCalls; +class OpaqueValueExpr; class OpenCLOptions; class ASTReader; class PreprocessedEntity; @@ -260,6 +261,9 @@ private: /// \brief Mapping from SwitchCase statements to IDs. std::map<SwitchCase *, unsigned> SwitchCaseIDs; + /// \brief Mapping from OpaqueValueExpr expressions to IDs. + llvm::DenseMap<OpaqueValueExpr *, unsigned> OpaqueValues; + /// \brief The number of statements written to the AST file. unsigned NumStatements; @@ -549,6 +553,9 @@ public: void ClearSwitchCaseIDs(); + /// \brief Retrieve the ID for the given opaque value expression. + unsigned getOpaqueValueID(OpaqueValueExpr *e); + unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; } bool hasChain() const { return Chain; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 209e5d3260..7e46d4fe45 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2003,6 +2003,10 @@ bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const { if (isa<MemberExpr>(E)) return false; + // - opaque values (all) + if (isa<OpaqueValueExpr>(E)) + return false; + return true; } diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 593f7830b4..890898a985 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -29,7 +29,8 @@ static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T); static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E); static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E); static Cl::Kinds ClassifyConditional(ASTContext &Ctx, - const ConditionalOperator *E); + const Expr *trueExpr, + const Expr *falseExpr); static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, Cl::Kinds Kind, SourceLocation &Loc); @@ -274,10 +275,18 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { if (!Lang.CPlusPlus) return Cl::CL_PRValue; return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten()); - case Expr::ConditionalOperatorClass: + case Expr::BinaryConditionalOperatorClass: { + if (!Lang.CPlusPlus) return Cl::CL_PRValue; + const BinaryConditionalOperator *co = cast<BinaryConditionalOperator>(E); + return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr()); + } + + case Expr::ConditionalOperatorClass: { // Once again, only C++ is interesting. if (!Lang.CPlusPlus) return Cl::CL_PRValue; - return ClassifyConditional(Ctx, cast<ConditionalOperator>(E)); + const ConditionalOperator *co = cast<ConditionalOperator>(E); + return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr()); + } // ObjC message sends are effectively function calls, if the target function // is known. @@ -447,13 +456,11 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { return Cl::CL_PRValue; } -static Cl::Kinds ClassifyConditional(ASTContext &Ctx, - const ConditionalOperator *E) { +static Cl::Kinds ClassifyConditional(ASTContext &Ctx, const Expr *True, + const Expr *False) { assert(Ctx.getLangOptions().CPlusPlus && "This is only relevant for C++."); - Expr *True = E->getTrueExpr(); - Expr *False = E->getFalseExpr(); // C++ [expr.cond]p2 // If either the second or the third operand has type (cv) void, [...] // the result [...] is a prvalue. diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 0c3f647536..656bb99df9 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -48,6 +48,14 @@ struct EvalInfo { /// EvalResult - Contains information about the evaluation. Expr::EvalResult &EvalResult; + llvm::DenseMap<const OpaqueValueExpr*, APValue> OpaqueValues; + const APValue *getOpaqueValue(const OpaqueValueExpr *e) { + llvm::DenseMap<const OpaqueValueExpr*, APValue>::iterator + i = OpaqueValues.find(e); + if (i == OpaqueValues.end()) return 0; + return &i->second; + } + EvalInfo(const ASTContext &ctx, Expr::EvalResult& evalresult) : Ctx(ctx), EvalResult(evalresult) {} }; @@ -73,12 +81,24 @@ namespace { APSInt &getComplexIntReal() { return IntReal; } APSInt &getComplexIntImag() { return IntImag; } - void moveInto(APValue &v) { + void moveInt |