From 7cd7d1ad33fdf49eef83942e8855fe20d95aa1b9 Mon Sep 17 00:00:00 2001 From: John McCall Date: Mon, 15 Nov 2010 23:31:06 +0000 Subject: [PATCH] Add a new expression kind, OpaqueValueExpr, which is useful for certain internal type-checking procedures as well as for representing certain implicitly-generated operations. Uses to follow. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119289 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 29 ++++++++++++++++++++ include/clang/AST/RecursiveASTVisitor.h | 1 + include/clang/Basic/StmtNodes.td | 1 + include/clang/Serialization/ASTBitCodes.h | 4 ++- lib/AST/Expr.cpp | 6 +++++ lib/AST/ExprClassification.cpp | 32 ++++++++++++++++------- lib/AST/ExprConstant.cpp | 1 + lib/AST/StmtPrinter.cpp | 3 +++ lib/AST/StmtProfile.cpp | 4 +++ lib/Checker/GRExprEngine.cpp | 1 + lib/CodeGen/Mangle.cpp | 3 +++ lib/Sema/TreeTransform.h | 8 ++++++ lib/Serialization/ASTReaderStmt.cpp | 11 ++++++++ lib/Serialization/ASTWriterStmt.cpp | 8 ++++++ tools/libclang/CXCursor.cpp | 1 + 15 files changed, 102 insertions(+), 11 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 98056c45eb..fb603165d6 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -3509,6 +3509,35 @@ public: virtual child_iterator child_end(); }; +/// 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; +public: + OpaqueValueExpr(QualType T, ExprValueKind VK) + : Expr(OpaqueValueExprClass, T, T->isDependentType(), + T->isDependentType()) { + setValueKind(VK); + } + + explicit OpaqueValueExpr(EmptyShell Empty) + : Expr(OpaqueValueExprClass, Empty) { } + + using Expr::getValueKind; + + virtual SourceRange getSourceRange() const; + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + + 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 527d46f430..f343881685 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1791,6 +1791,7 @@ DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { }) DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { }) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { }) +DEF_TRAVERSE_STMT(OpaqueValueExpr, { }) // These operators (all of them) do not need any action except // iterating over the children. diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 53beb98eea..c9ec0ef148 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -127,6 +127,7 @@ def ObjCIsaExpr : DStmt; def ShuffleVectorExpr : DStmt; def BlockExpr : DStmt; def BlockDeclRefExpr : DStmt; +def OpaqueValueExpr : DStmt; // Microsoft Extensions. def CXXUuidofExpr : DStmt; diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 38b87ed47c..646d09006a 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -922,7 +922,9 @@ namespace clang { EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr - EXPR_CXX_NOEXCEPT // CXXNoexceptExpr + EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr + + EXPR_OPAQUE_VALUE // OpaqueValueExpr }; /// \brief The kinds of designators that can occur in a diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index d6c6bf67ac..6ae334ed25 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2709,3 +2709,9 @@ Stmt::child_iterator BlockExpr::child_end() { return child_iterator(); } Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();} Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); } + +// OpaqueValueExpr +SourceRange OpaqueValueExpr::getSourceRange() const { return SourceRange(); } +Stmt::child_iterator OpaqueValueExpr::child_begin() { return child_iterator(); } +Stmt::child_iterator OpaqueValueExpr::child_end() { return child_iterator(); } + diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 0ab1402fa8..1daa475b9e 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -33,6 +33,22 @@ static Cl::Kinds ClassifyConditional(ASTContext &Ctx, static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, Cl::Kinds Kind, SourceLocation &Loc); +static Cl::Kinds ClassifyExprValueKind(const LangOptions &Lang, + const Expr *E, + ExprValueKind Kind) { + switch (Kind) { + case VK_RValue: + return Lang.CPlusPlus && E->getType()->isRecordType() ? + Cl::CL_ClassTemporary : Cl::CL_PRValue; + case VK_LValue: + return Cl::CL_LValue; + case VK_XValue: + return Cl::CL_XValue; + } + llvm_unreachable("Invalid value category of implicit cast."); + return Cl::CL_PRValue; +} + Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { assert(!TR->isReferenceType() && "Expressions can't have reference type."); @@ -171,19 +187,15 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return Cl::CL_PRValue; } + case Expr::OpaqueValueExprClass: + return ClassifyExprValueKind(Lang, E, + cast(E)->getValueKind()); + // Implicit casts are lvalues if they're lvalue casts. Other than that, we // only specifically record class temporaries. case Expr::ImplicitCastExprClass: - switch (cast(E)->getValueKind()) { - case VK_RValue: - return Lang.CPlusPlus && E->getType()->isRecordType() ? - Cl::CL_ClassTemporary : Cl::CL_PRValue; - case VK_LValue: - return Cl::CL_LValue; - case VK_XValue: - return Cl::CL_XValue; - } - llvm_unreachable("Invalid value category of implicit cast."); + return ClassifyExprValueKind(Lang, E, + cast(E)->getValueKind()); // C++ [expr.prim.general]p4: The presence of parentheses does not affect // whether the expression is an lvalue. diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 8a6d4ba7c4..d0b4c31937 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -2541,6 +2541,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::BlockExprClass: case Expr::BlockDeclRefExprClass: case Expr::NoStmtClass: + case Expr::OpaqueValueExprClass: return ICEDiag(2, E->getLocStart()); case Expr::GNUNullExprClass: diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 270c9e1d1d..d4791bcd0e 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1335,6 +1335,9 @@ void StmtPrinter::VisitBlockExpr(BlockExpr *Node) { void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) { OS << Node->getDecl(); } + +void StmtPrinter::VisitOpaqueValueExpr(OpaqueValueExpr *Node) {} + //===----------------------------------------------------------------------===// // Stmt method implementations //===----------------------------------------------------------------------===// diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 3f17a2b471..d67f5fad6b 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -834,6 +834,10 @@ void StmtProfiler::VisitCXXNoexceptExpr(CXXNoexceptExpr *S) { VisitExpr(S); } +void StmtProfiler::VisitOpaqueValueExpr(OpaqueValueExpr *E) { + VisitExpr(E); +} + void StmtProfiler::VisitObjCStringLiteral(ObjCStringLiteral *S) { VisitExpr(S); } diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index ecf21035cf..d5c9ffa0af 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -744,6 +744,7 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred, case Stmt::NoStmtClass: case Stmt::NullStmtClass: case Stmt::SwitchCaseClass: + case Stmt::OpaqueValueExprClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); break; diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 1b7cfa1c8c..83d43ebb8f 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -1681,6 +1681,9 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { break; } + case Expr::OpaqueValueExprClass: + llvm_unreachable("cannot mangle opaque value; mangling wrong thing?"); + case Expr::CXXDefaultArgExprClass: mangleExpression(cast(E)->getExpr(), Arity); break; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 12192c9ea2..bae703daa3 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -4442,6 +4442,14 @@ TreeTransform::TransformOffsetOfExpr(OffsetOfExpr *E) { E->getRParenLoc()); } +template +ExprResult +TreeTransform::TransformOpaqueValueExpr(OpaqueValueExpr *E) { + assert(getDerived().AlreadyTransformed(E->getType()) && + "opaque value expression requires transformation"); + return SemaRef.Owned(E); +} + template ExprResult TreeTransform::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 41386dcafa..26077c5fb7 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -178,6 +178,8 @@ namespace clang { void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); void VisitCXXNoexceptExpr(CXXNoexceptExpr *E); + + void VisitOpaqueValueExpr(OpaqueValueExpr *E); }; } @@ -1280,6 +1282,11 @@ void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { E->Operand = Reader.ReadSubExpr(); } +void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { + VisitExpr(E); + E->setValueKind(static_cast(Record[Idx++])); +} + Stmt *ASTReader::ReadStmt(PerFileData &F) { switch (ReadingKind) { case Read_Decl: @@ -1795,6 +1802,10 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) { case EXPR_CXX_NOEXCEPT: S = new (Context) CXXNoexceptExpr(Empty); break; + + case EXPR_OPAQUE_VALUE: + S = new (Context) OpaqueValueExpr(Empty); + break; } // We hit a STMT_STOP, so we're done with this expression. diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index fc8e9e0e59..efbfd94401 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -152,6 +152,8 @@ namespace clang { void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E); void VisitCXXNoexceptExpr(CXXNoexceptExpr *E); + + void VisitOpaqueValueExpr(OpaqueValueExpr *E); }; } @@ -1293,6 +1295,12 @@ void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { Code = serialization::EXPR_CXX_NOEXCEPT; } +void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { + VisitExpr(E); + Record.push_back(E->getValueKind()); + Code = serialization::EXPR_OPAQUE_VALUE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 9dd94f972e..f5941e7327 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -160,6 +160,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, ASTUnit *TU) { case Stmt::ObjCIsaExprClass: case Stmt::ShuffleVectorExprClass: case Stmt::BlockExprClass: + case Stmt::OpaqueValueExprClass: K = CXCursor_UnexposedExpr; break; -- 2.40.0