diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/DeclBase.cpp | 6 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 82 | ||||
-rw-r--r-- | lib/AST/ExprClassification.cpp | 5 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 1 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 1 | ||||
-rw-r--r-- | lib/AST/StmtDumper.cpp | 10 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 4 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 9 |
8 files changed, 117 insertions, 1 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index a4daea2287..4c31bbd3d7 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -640,7 +640,11 @@ void Decl::CheckAccessDeclContext() const { } DeclContext *Decl::getNonClosureContext() { - DeclContext *DC = getDeclContext(); + return getDeclContext()->getNonClosureAncestor(); +} + +DeclContext *DeclContext::getNonClosureAncestor() { + DeclContext *DC = this; // This is basically "while (DC->isClosure()) DC = DC->getParent();" // except that it's significantly more efficient to cast to a known diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 3239973688..6eb6116b01 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1694,6 +1694,19 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, R1 = getSourceRange(); return true; + case PseudoObjectExprClass: { + const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(this); + + // Only complain about things that have the form of a getter. + if (isa<UnaryOperator>(PO->getSyntacticForm()) || + isa<BinaryOperator>(PO->getSyntacticForm())) + return false; + + Loc = getExprLoc(); + R1 = getSourceRange(); + 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. @@ -2598,6 +2611,9 @@ Expr::isNullPointerConstant(ASTContext &Ctx, } else if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(this)) { return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC); + } else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) { + if (const Expr *Source = OVE->getSourceExpr()) + return Source->isNullPointerConstant(Ctx, NPC); } // C++0x nullptr_t is always a null pointer constant. @@ -3306,6 +3322,72 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { return cast<OpaqueValueExpr>(e); } +PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &Context, EmptyShell sh, + unsigned numSemanticExprs) { + void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) + + (1 + numSemanticExprs) * sizeof(Expr*), + llvm::alignOf<PseudoObjectExpr>()); + return new(buffer) PseudoObjectExpr(sh, numSemanticExprs); +} + +PseudoObjectExpr::PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs) + : Expr(PseudoObjectExprClass, shell) { + PseudoObjectExprBits.NumSubExprs = numSemanticExprs + 1; +} + +PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &C, Expr *syntax, + ArrayRef<Expr*> semantics, + unsigned resultIndex) { + assert(syntax && "no syntactic expression!"); + assert(semantics.size() && "no semantic expressions!"); + + QualType type; + ExprValueKind VK; + if (resultIndex == NoResult) { + type = C.VoidTy; + VK = VK_RValue; + } else { + assert(resultIndex < semantics.size()); + type = semantics[resultIndex]->getType(); + VK = semantics[resultIndex]->getValueKind(); + assert(semantics[resultIndex]->getObjectKind() == OK_Ordinary); + } + + void *buffer = C.Allocate(sizeof(PseudoObjectExpr) + + (1 + semantics.size()) * sizeof(Expr*), + llvm::alignOf<PseudoObjectExpr>()); + return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics, + resultIndex); +} + +PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK, + Expr *syntax, ArrayRef<Expr*> semantics, + unsigned resultIndex) + : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary, + /*filled in at end of ctor*/ false, false, false, false) { + PseudoObjectExprBits.NumSubExprs = semantics.size() + 1; + PseudoObjectExprBits.ResultIndex = resultIndex + 1; + + for (unsigned i = 0, e = semantics.size() + 1; i != e; ++i) { + Expr *E = (i == 0 ? syntax : semantics[i-1]); + getSubExprsBuffer()[i] = E; + + if (E->isTypeDependent()) + ExprBits.TypeDependent = true; + if (E->isValueDependent()) + ExprBits.ValueDependent = true; + if (E->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (E->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + if (isa<OpaqueValueExpr>(E)) + assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != 0 && + "opaque-value semantic expressions for pseudo-object " + "operations must have sources"); + } +} + //===----------------------------------------------------------------------===// // ExprIterator. //===----------------------------------------------------------------------===// diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 594ae69ec4..1251b96fba 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -232,6 +232,11 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return ClassifyExprValueKind(Lang, E, cast<OpaqueValueExpr>(E)->getValueKind()); + // Pseudo-object expressions can produce l-values with reference magic. + case Expr::PseudoObjectExprClass: + return ClassifyExprValueKind(Lang, E, + cast<PseudoObjectExpr>(E)->getValueKind()); + // Implicit casts are lvalues if they're lvalue casts. Other than that, we // only specifically record class temporaries. case Expr::ImplicitCastExprClass: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 3011b7f25f..9c9e473f7b 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -3450,6 +3450,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::AsTypeExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::MaterializeTemporaryExprClass: + case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: return ICEDiag(2, E->getLocStart()); diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 889cf513bb..b2e1d20ca0 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2257,6 +2257,7 @@ recurse: case Expr::CXXNoexceptExprClass: case Expr::CUDAKernelCallExprClass: case Expr::AsTypeExprClass: + case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: { // As bad as this diagnostic is, it's better than crashing. diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index 54e62fe35b..2248343199 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -148,6 +148,7 @@ namespace { void VisitCompoundAssignOperator(CompoundAssignOperator *Node); void VisitAddrLabelExpr(AddrLabelExpr *Node); void VisitBlockExpr(BlockExpr *Node); + void VisitOpaqueValueExpr(OpaqueValueExpr *Node); // C++ void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node); @@ -524,6 +525,15 @@ void StmtDumper::VisitBlockExpr(BlockExpr *Node) { DumpSubTree(block->getBody()); } +void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { + DumpExpr(Node); + + if (Expr *Source = Node->getSourceExpr()) { + OS << '\n'; + DumpSubTree(Source); + } +} + // GNU extensions. void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) { diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 5b1654c924..04617bf9ac 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1027,6 +1027,10 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { OS << ")"; } +void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) { + PrintExpr(Node->getSyntacticForm()); +} + void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { const char *Name = 0; switch (Node->getOp()) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index db97e59804..5a6b771b9a 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -475,6 +475,15 @@ void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { } } +void StmtProfiler::VisitPseudoObjectExpr(const PseudoObjectExpr *S) { + VisitExpr(S); + for (PseudoObjectExpr::const_semantics_iterator + i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) + // Normally, we would not profile the source expressions of OVEs. + if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(*i)) + Visit(OVE->getSourceExpr()); +} + void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) { VisitExpr(S); ID.AddInteger(S->getOp()); |