diff options
author | dim <dim@FreeBSD.org> | 2015-12-30 11:49:41 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-12-30 11:49:41 +0000 |
commit | 3176e97f130184ece0e1a21352c8124cc83ff24a (patch) | |
tree | 0a5b74c0b9ca73aded34df95c91fcaf3815230d8 /include/clang/AST/ExprCXX.h | |
parent | 1e9b8d38881c3213d1e67b0c47ab9b2c00721a5c (diff) | |
download | FreeBSD-src-3176e97f130184ece0e1a21352c8124cc83ff24a.zip FreeBSD-src-3176e97f130184ece0e1a21352c8124cc83ff24a.tar.gz |
Vendor import of clang trunk r256633:
https://llvm.org/svn/llvm-project/cfe/trunk@256633
Diffstat (limited to 'include/clang/AST/ExprCXX.h')
-rw-r--r-- | include/clang/AST/ExprCXX.h | 689 |
1 files changed, 494 insertions, 195 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 1dbf574..707aeed 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -235,7 +235,9 @@ public: /// /// This expression node represents a C++ static cast, e.g., /// \c static_cast<int>(1.0). -class CXXStaticCastExpr : public CXXNamedCastExpr { +class CXXStaticCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> { CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, @@ -259,6 +261,9 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXStaticCastExprClass; } + + friend TrailingObjects; + friend class CastExpr; }; /// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]). @@ -266,7 +271,9 @@ public: /// This expression node represents a dynamic cast, e.g., /// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time /// check to determine how to perform the type conversion. -class CXXDynamicCastExpr : public CXXNamedCastExpr { +class CXXDynamicCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> { CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, @@ -293,6 +300,9 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDynamicCastExprClass; } + + friend TrailingObjects; + friend class CastExpr; }; /// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]). @@ -303,7 +313,10 @@ public: /// A reinterpret_cast provides a differently-typed view of a value but /// (in Clang, as in most C++ implementations) performs no actual work at /// run time. -class CXXReinterpretCastExpr : public CXXNamedCastExpr { +class CXXReinterpretCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXReinterpretCastExpr, + CXXBaseSpecifier *> { CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, @@ -328,6 +341,9 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXReinterpretCastExprClass; } + + friend TrailingObjects; + friend class CastExpr; }; /// \brief A C++ \c const_cast expression (C++ [expr.const.cast]). @@ -337,7 +353,9 @@ public: /// /// A const_cast can remove type qualifiers but does not change the underlying /// value. -class CXXConstCastExpr : public CXXNamedCastExpr { +class CXXConstCastExpr final + : public CXXNamedCastExpr, + private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> { CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) @@ -358,6 +376,9 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstCastExprClass; } + + friend TrailingObjects; + friend class CastExpr; }; /// \brief A call to a literal operator (C++11 [over.literal]) @@ -457,7 +478,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief The null pointer literal (C++11 [lex.nullptr]) @@ -484,7 +507,9 @@ public: return T->getStmtClass() == CXXNullPtrLiteralExprClass; } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Implicit construction of a std::initializer_list<T> object from an @@ -607,7 +632,8 @@ public: // Iterators child_range children() { - if (isTypeOperand()) return child_range(); + if (isTypeOperand()) + return child_range(child_iterator(), child_iterator()); Stmt **begin = reinterpret_cast<Stmt**>(&Operand); return child_range(begin, begin + 1); } @@ -672,6 +698,69 @@ public: friend class ASTStmtReader; }; +/// MS property subscript expression. +/// MSVC supports 'property' attribute and allows to apply it to the +/// declaration of an empty array in a class or structure definition. +/// For example: +/// \code +/// __declspec(property(get=GetX, put=PutX)) int x[]; +/// \endcode +/// The above statement indicates that x[] can be used with one or more array +/// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and +/// p->x[a][b] = i will be turned into p->PutX(a, b, i). +/// This is a syntactic pseudo-object expression. +class MSPropertySubscriptExpr : public Expr { + friend class ASTStmtReader; + enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 }; + Stmt *SubExprs[NUM_SUBEXPRS]; + SourceLocation RBracketLoc; + + void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; } + void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; } + +public: + MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK, + ExprObjectKind OK, SourceLocation RBracketLoc) + : Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(), + Idx->isValueDependent(), Idx->isInstantiationDependent(), + Idx->containsUnexpandedParameterPack()), + RBracketLoc(RBracketLoc) { + SubExprs[BASE_EXPR] = Base; + SubExprs[IDX_EXPR] = Idx; + } + + /// \brief Create an empty array subscript expression. + explicit MSPropertySubscriptExpr(EmptyShell Shell) + : Expr(MSPropertySubscriptExprClass, Shell) {} + + Expr *getBase() { return cast<Expr>(SubExprs[BASE_EXPR]); } + const Expr *getBase() const { return cast<Expr>(SubExprs[BASE_EXPR]); } + + Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); } + const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); } + + SourceLocation getLocStart() const LLVM_READONLY { + return getBase()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } + + SourceLocation getRBracketLoc() const { return RBracketLoc; } + void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } + + SourceLocation getExprLoc() const LLVM_READONLY { + return getBase()->getExprLoc(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MSPropertySubscriptExprClass; + } + + // Iterators + child_range children() { + return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS); + } +}; + /// A Microsoft C++ @c __uuidof expression, which gets /// the _GUID that corresponds to the supplied type or expression. /// @@ -749,7 +838,8 @@ public: // Iterators child_range children() { - if (isTypeOperand()) return child_range(); + if (isTypeOperand()) + return child_range(child_iterator(), child_iterator()); Stmt **begin = reinterpret_cast<Stmt**>(&Operand); return child_range(begin, begin + 1); } @@ -797,7 +887,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief A C++ throw-expression (C++ [except.throw]). @@ -935,7 +1027,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTStmtReader; friend class ASTStmtWriter; @@ -991,7 +1085,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTReader; friend class ASTStmtReader; @@ -1238,7 +1334,9 @@ public: /// \code /// x = int(0.5); /// \endcode -class CXXFunctionalCastExpr : public ExplicitCastExpr { +class CXXFunctionalCastExpr final + : public ExplicitCastExpr, + private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> { SourceLocation LParenLoc; SourceLocation RParenLoc; @@ -1275,6 +1373,9 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == CXXFunctionalCastExprClass; } + + friend TrailingObjects; + friend class CastExpr; }; /// @brief Represents a C++ functional cast expression that builds a @@ -1401,25 +1502,39 @@ class LambdaExpr : public Expr { ExplicitResultType(false), HasArrayIndexVars(true) { getStoredStmts()[NumCaptures] = nullptr; } - - Stmt **getStoredStmts() const { - return reinterpret_cast<Stmt **>(const_cast<LambdaExpr *>(this) + 1); + + Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); } + + Stmt *const *getStoredStmts() const { + return reinterpret_cast<Stmt *const *>(this + 1); } - + /// \brief Retrieve the mapping from captures to the first array index /// variable. - unsigned *getArrayIndexStarts() const { + unsigned *getArrayIndexStarts() { return reinterpret_cast<unsigned *>(getStoredStmts() + NumCaptures + 1); } + const unsigned *getArrayIndexStarts() const { + return reinterpret_cast<const unsigned *>(getStoredStmts() + NumCaptures + + 1); + } + /// \brief Retrieve the complete set of array-index variables. - VarDecl **getArrayIndexVars() const { + VarDecl **getArrayIndexVars() { unsigned ArrayIndexSize = llvm::RoundUpToAlignment( sizeof(unsigned) * (NumCaptures + 1), llvm::alignOf<VarDecl *>()); return reinterpret_cast<VarDecl **>( reinterpret_cast<char *>(getArrayIndexStarts()) + ArrayIndexSize); } + VarDecl *const *getArrayIndexVars() const { + unsigned ArrayIndexSize = llvm::RoundUpToAlignment( + sizeof(unsigned) * (NumCaptures + 1), llvm::alignOf<VarDecl *>()); + return reinterpret_cast<VarDecl *const *>( + reinterpret_cast<const char *>(getArrayIndexStarts()) + ArrayIndexSize); + } + public: /// \brief Construct a new lambda expression. static LambdaExpr *Create(const ASTContext &C, @@ -1501,31 +1616,52 @@ public: /// arguments. typedef Expr **capture_init_iterator; + /// \brief Const iterator that walks over the capture initialization + /// arguments. + typedef Expr *const *const_capture_init_iterator; + + /// \brief Retrieve the initialization expressions for this lambda's captures. + llvm::iterator_range<capture_init_iterator> capture_inits() { + return llvm::make_range(capture_init_begin(), capture_init_end()); + } + /// \brief Retrieve the initialization expressions for this lambda's captures. - llvm::iterator_range<capture_init_iterator> capture_inits() const { - return llvm::iterator_range<capture_init_iterator>(capture_init_begin(), - capture_init_end()); + llvm::iterator_range<const_capture_init_iterator> capture_inits() const { + return llvm::make_range(capture_init_begin(), capture_init_end()); } /// \brief Retrieve the first initialization argument for this /// lambda expression (which initializes the first capture field). - capture_init_iterator capture_init_begin() const { + capture_init_iterator capture_init_begin() { return reinterpret_cast<Expr **>(getStoredStmts()); } + /// \brief Retrieve the first initialization argument for this + /// lambda expression (which initializes the first capture field). + const_capture_init_iterator capture_init_begin() const { + return reinterpret_cast<Expr *const *>(getStoredStmts()); + } + /// \brief Retrieve the iterator pointing one past the last /// initialization argument for this lambda expression. - capture_init_iterator capture_init_end() const { - return capture_init_begin() + NumCaptures; + capture_init_iterator capture_init_end() { + return capture_init_begin() + NumCaptures; } - /// \brief Retrieve the set of index variables used in the capture + /// \brief Retrieve the iterator pointing one past the last + /// initialization argument for this lambda expression. + const_capture_init_iterator capture_init_end() const { + return capture_init_begin() + NumCaptures; + } + + /// \brief Retrieve the set of index variables used in the capture /// initializer of an array captured by copy. /// - /// \param Iter The iterator that points at the capture initializer for + /// \param Iter The iterator that points at the capture initializer for /// which we are extracting the corresponding index variables. - ArrayRef<VarDecl *> getCaptureInitIndexVars(capture_init_iterator Iter) const; - + ArrayRef<VarDecl *> + getCaptureInitIndexVars(const_capture_init_iterator Iter) const; + /// \brief Retrieve the source range covering the lambda introducer, /// which contains the explicit capture list surrounded by square /// brackets ([...]). @@ -1615,7 +1751,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Represents a new-expression for memory allocation and constructor @@ -1770,6 +1908,14 @@ public: typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; + llvm::iterator_range<arg_iterator> placement_arguments() { + return llvm::make_range(placement_arg_begin(), placement_arg_end()); + } + + llvm::iterator_range<const_arg_iterator> placement_arguments() const { + return llvm::make_range(placement_arg_begin(), placement_arg_end()); + } + arg_iterator placement_arg_begin() { return SubExprs + Array + hasInitializer(); } @@ -2164,8 +2310,10 @@ public: } // Iterators - child_range children() { return child_range(); } - + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + friend class ASTStmtReader; friend class ASTStmtWriter; @@ -2237,7 +2385,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTStmtReader; }; @@ -2294,7 +2444,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } friend class ASTStmtReader; }; @@ -2322,13 +2474,18 @@ protected: bool HasTemplateKWAndArgsInfo; /// \brief Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo(); // defined far below. + ASTTemplateKWAndArgsInfo * + getTrailingASTTemplateKWAndArgsInfo(); // defined far below. /// \brief Return the optional template keyword and arguments info. - const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { - return const_cast<OverloadExpr*>(this)->getTemplateKWAndArgsInfo(); + const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const { + return const_cast<OverloadExpr *>(this) + ->getTrailingASTTemplateKWAndArgsInfo(); } + /// Return the optional template arguments. + TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below + OverloadExpr(StmtClass K, const ASTContext &C, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, @@ -2391,7 +2548,7 @@ public: return UnresolvedSetIterator(Results + NumResults); } llvm::iterator_range<decls_iterator> decls() const { - return llvm::iterator_range<decls_iterator>(decls_begin(), decls_end()); + return llvm::make_range(decls_begin(), decls_end()); } /// \brief Gets the number of declarations in the unresolved set. @@ -2419,21 +2576,21 @@ public: /// this name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc; } /// \brief Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->LAngleLoc; + return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc; } /// \brief Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->RAngleLoc; + return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc; } /// \brief Determines whether the name was preceded by the template keyword. @@ -2442,39 +2599,23 @@ public: /// \brief Determines whether this expression had explicit template arguments. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - // Note that, inconsistently with the explicit-template-argument AST - // nodes, users are *forbidden* from calling these methods on objects - // without explicit template arguments. - - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *getTemplateKWAndArgsInfo(); - } - - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs(); - } - TemplateArgumentLoc const *getTemplateArgs() const { - return getExplicitTemplateArgs().getTemplateArgs(); + if (!hasExplicitTemplateArgs()) + return nullptr; + return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc(); } unsigned getNumTemplateArgs() const { - return getExplicitTemplateArgs().NumTemplateArgs; + if (!hasExplicitTemplateArgs()) + return 0; + + return getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs; } /// \brief Copies the template arguments into the given structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - getExplicitTemplateArgs().copyInto(List); - } - - /// \brief Retrieves the optional explicit template arguments. - /// - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return nullptr; - return &getExplicitTemplateArgs(); + if (hasExplicitTemplateArgs()) + getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List); } static bool classof(const Stmt *T) { @@ -2497,7 +2638,10 @@ public: /// /// These never include UnresolvedUsingValueDecls, which are always class /// members and therefore appear only in UnresolvedMemberLookupExprs. -class UnresolvedLookupExpr : public OverloadExpr { +class UnresolvedLookupExpr final + : public OverloadExpr, + private llvm::TrailingObjects< + UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { /// True if these lookup results should be extended by /// argument-dependent lookup if this is the operand of a function /// call. @@ -2514,6 +2658,10 @@ class UnresolvedLookupExpr : public OverloadExpr { /// against the qualified-lookup bits. CXXRecordDecl *NamingClass; + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; + } + UnresolvedLookupExpr(const ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, @@ -2533,6 +2681,8 @@ class UnresolvedLookupExpr : public OverloadExpr { RequiresADL(false), Overloaded(false), NamingClass(nullptr) {} + friend TrailingObjects; + friend class OverloadExpr; friend class ASTStmtReader; public: @@ -2585,7 +2735,9 @@ public: return getNameInfo().getLocEnd(); } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } static bool classof(const Stmt *T) { return T->getStmtClass() == UnresolvedLookupExprClass; @@ -2606,7 +2758,11 @@ public: /// qualifier (X<T>::) and the name of the entity being referenced /// ("value"). Such expressions will instantiate to a DeclRefExpr once the /// declaration can be found. -class DependentScopeDeclRefExpr : public Expr { +class DependentScopeDeclRefExpr final + : public Expr, + private llvm::TrailingObjects<DependentScopeDeclRefExpr, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { /// \brief The nested-name-specifier that qualifies this unresolved /// declaration name. NestedNameSpecifierLoc QualifierLoc; @@ -2618,15 +2774,8 @@ class DependentScopeDeclRefExpr : public Expr { /// keyword and arguments. bool HasTemplateKWAndArgsInfo; - /// \brief Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return nullptr; - return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); - } - /// \brief Return the optional template keyword and arguments info. - const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { - return const_cast<DependentScopeDeclRefExpr*>(this) - ->getTemplateKWAndArgsInfo(); + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; } DependentScopeDeclRefExpr(QualType T, @@ -2671,21 +2820,21 @@ public: /// this name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// \brief Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->LAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// \brief Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->RAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } /// Determines whether the name was preceded by the template keyword. @@ -2694,42 +2843,26 @@ public: /// Determines whether this lookup had explicit template arguments. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - // Note that, inconsistently with the explicit-template-argument AST - // nodes, users are *forbidden* from calling these methods on objects - // without explicit template arguments. - - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<ASTTemplateArgumentListInfo*>(this + 1); - } - - /// Gets a reference to the explicit template argument list. - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<const ASTTemplateArgumentListInfo*>(this + 1); - } - - /// \brief Retrieves the optional explicit template arguments. - /// - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return nullptr; - return &getExplicitTemplateArgs(); - } - /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - getExplicitTemplateArgs().copyInto(List); + if (hasExplicitTemplateArgs()) + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( + getTrailingObjects<TemplateArgumentLoc>(), List); } TemplateArgumentLoc const *getTemplateArgs() const { - return getExplicitTemplateArgs().getTemplateArgs(); + if (!hasExplicitTemplateArgs()) + return nullptr; + + return getTrailingObjects<TemplateArgumentLoc>(); } unsigned getNumTemplateArgs() const { - return getExplicitTemplateArgs().NumTemplateArgs; + if (!hasExplicitTemplateArgs()) + return 0; + + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; } /// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr, @@ -2747,8 +2880,11 @@ public: return T->getStmtClass() == DependentScopeDeclRefExprClass; } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; }; @@ -2951,7 +3087,11 @@ public: /// Like UnresolvedMemberExprs, these can be either implicit or /// explicit accesses. It is only possible to get one of these with /// an implicit access if a qualifier is provided. -class CXXDependentScopeMemberExpr : public Expr { +class CXXDependentScopeMemberExpr final + : public Expr, + private llvm::TrailingObjects<CXXDependentScopeMemberExpr, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { /// \brief The expression for the base pointer or class reference, /// e.g., the \c x in x.f. Can be null in implicit accesses. Stmt *Base; @@ -2989,15 +3129,8 @@ class CXXDependentScopeMemberExpr : public Expr { /// FIXME: could also be a template-id DeclarationNameInfo MemberNameInfo; - /// \brief Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return nullptr; - return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); - } - /// \brief Return the optional template keyword and arguments info. - const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { - return const_cast<CXXDependentScopeMemberExpr*>(this) - ->getTemplateKWAndArgsInfo(); + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; } CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, @@ -3093,21 +3226,21 @@ public: /// member name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// \brief Retrieve the location of the left angle bracket starting the /// explicit template argument list following the member name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->LAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// \brief Retrieve the location of the right angle bracket ending the /// explicit template argument list following the member name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); - return getTemplateKWAndArgsInfo()->RAngleLoc; + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } /// Determines whether the member name was preceded by the template keyword. @@ -3117,50 +3250,30 @@ public: /// template argument list explicitly specified, e.g., x.f<int>. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); - return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const { - return const_cast<CXXDependentScopeMemberExpr *>(this) - ->getExplicitTemplateArgs(); - } - - /// \brief Retrieves the optional explicit template arguments. - /// - /// This points to the same data as getExplicitTemplateArgs(), but - /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return nullptr; - return &getExplicitTemplateArgs(); - } - /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - getExplicitTemplateArgs().copyInto(List); - } - - /// \brief Initializes the template arguments using the given structure. - void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) { - getExplicitTemplateArgs().initializeFrom(List); + if (hasExplicitTemplateArgs()) + getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( + getTrailingObjects<TemplateArgumentLoc>(), List); } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - return getExplicitTemplateArgs().getTemplateArgs(); + if (!hasExplicitTemplateArgs()) + return nullptr; + + return getTrailingObjects<TemplateArgumentLoc>(); } /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { - return getExplicitTemplateArgs().NumTemplateArgs; + if (!hasExplicitTemplateArgs()) + return 0; + + return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; } SourceLocation getLocStart() const LLVM_READONLY { @@ -3169,8 +3282,8 @@ public: if (getQualifier()) return getQualifierLoc().getBeginLoc(); return MemberNameInfo.getBeginLoc(); - } + SourceLocation getLocEnd() const LLVM_READONLY { if (hasExplicitTemplateArgs()) return getRAngleLoc(); @@ -3183,10 +3296,12 @@ public: // Iterators child_range children() { - if (isImplicitAccess()) return child_range(); + if (isImplicitAccess()) + return child_range(child_iterator(), child_iterator()); return child_range(&Base, &Base + 1); } + friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; }; @@ -3206,7 +3321,10 @@ public: /// In the final AST, an explicit access always becomes a MemberExpr. /// An implicit access may become either a MemberExpr or a /// DeclRefExpr, depending on whether the member is static. -class UnresolvedMemberExpr : public OverloadExpr { +class UnresolvedMemberExpr final + : public OverloadExpr, + private llvm::TrailingObjects< + UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { /// \brief Whether this member expression used the '->' operator or /// the '.' operator. bool IsArrow : 1; @@ -3227,6 +3345,10 @@ class UnresolvedMemberExpr : public OverloadExpr { /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; + size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return HasTemplateKWAndArgsInfo ? 1 : 0; + } + UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, @@ -3240,6 +3362,8 @@ class UnresolvedMemberExpr : public OverloadExpr { : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), HasUnresolvedUsing(false), Base(nullptr) { } + friend TrailingObjects; + friend class OverloadExpr; friend class ASTStmtReader; public: @@ -3325,11 +3449,34 @@ public: // Iterators child_range children() { - if (isImplicitAccess()) return child_range(); + if (isImplicitAccess()) + return child_range(child_iterator(), child_iterator()); return child_range(&Base, &Base + 1); } }; +inline ASTTemplateKWAndArgsInfo * +OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() { + if (!HasTemplateKWAndArgsInfo) + return nullptr; + + if (isa<UnresolvedLookupExpr>(this)) + return cast<UnresolvedLookupExpr>(this) + ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); + else + return cast<UnresolvedMemberExpr>(this) + ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); +} + +inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { + if (isa<UnresolvedLookupExpr>(this)) + return cast<UnresolvedLookupExpr>(this) + ->getTrailingObjects<TemplateArgumentLoc>(); + else + return cast<UnresolvedMemberExpr>(this) + ->getTrailingObjects<TemplateArgumentLoc>(); +} + /// \brief Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]). /// /// The noexcept expression tests whether a given expression might throw. Its @@ -3451,15 +3598,6 @@ public: } }; -inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return nullptr; - if (isa<UnresolvedLookupExpr>(this)) - return reinterpret_cast<ASTTemplateKWAndArgsInfo*> - (cast<UnresolvedLookupExpr>(this) + 1); - else - return reinterpret_cast<ASTTemplateKWAndArgsInfo*> - (cast<UnresolvedMemberExpr>(this) + 1); -} /// \brief Represents an expression that computes the length of a parameter /// pack. @@ -3482,43 +3620,51 @@ class SizeOfPackExpr : public Expr { /// \brief The length of the parameter pack, if known. /// - /// When this expression is value-dependent, the length of the parameter pack - /// is unknown. When this expression is not value-dependent, the length is - /// known. + /// When this expression is not value-dependent, this is the length of + /// the pack. When the expression was parsed rather than instantiated + /// (and thus is value-dependent), this is zero. + /// + /// After partial substitution into a sizeof...(X) expression (for instance, + /// within an alias template or during function template argument deduction), + /// we store a trailing array of partially-substituted TemplateArguments, + /// and this is the length of that array. unsigned Length; - /// \brief The parameter pack itself. + /// \brief The parameter pack. NamedDecl *Pack; friend class ASTStmtReader; friend class ASTStmtWriter; -public: - /// \brief Create a value-dependent expression that computes the length of - /// the given parameter pack. - SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, - SourceLocation PackLoc, SourceLocation RParenLoc) - : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, - /*TypeDependent=*/false, /*ValueDependent=*/true, - /*InstantiationDependent=*/true, - /*ContainsUnexpandedParameterPack=*/false), - OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), - Length(0), Pack(Pack) { } - /// \brief Create an expression that computes the length of - /// the given parameter pack, which is already known. + /// the given parameter pack. SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, - unsigned Length) - : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, - /*TypeDependent=*/false, /*ValueDependent=*/false, - /*InstantiationDependent=*/false, - /*ContainsUnexpandedParameterPack=*/false), - OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), - Length(Length), Pack(Pack) { } + Optional<unsigned> Length, ArrayRef<TemplateArgument> PartialArgs) + : Expr(SizeOfPackExprClass, SizeType, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, /*ValueDependent=*/!Length, + /*InstantiationDependent=*/!Length, + /*ContainsUnexpandedParameterPack=*/false), + OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), + Length(Length ? *Length : PartialArgs.size()), Pack(Pack) { + assert((!Length || PartialArgs.empty()) && + "have partial args for non-dependent sizeof... expression"); + TemplateArgument *Args = reinterpret_cast<TemplateArgument *>(this + 1); + std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args); + } /// \brief Create an empty expression. - SizeOfPackExpr(EmptyShell Empty) : Expr(SizeOfPackExprClass, Empty) { } + SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs) + : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs), Pack() {} + +public: + static SizeOfPackExpr *Create(ASTContext &Context, SourceLocation OperatorLoc, + NamedDecl *Pack, SourceLocation PackLoc, + SourceLocation RParenLoc, + Optional<unsigned> Length = None, + ArrayRef<TemplateArgument> PartialArgs = None); + static SizeOfPackExpr *CreateDeserialized(ASTContext &Context, + unsigned NumPartialArgs); /// \brief Determine the location of the 'sizeof' keyword. SourceLocation getOperatorLoc() const { return OperatorLoc; } @@ -3542,6 +3688,23 @@ public: return Length; } + /// \brief Determine whether this represents a partially-substituted sizeof... + /// expression, such as is produced for: + /// + /// template<typename ...Ts> using X = int[sizeof...(Ts)]; + /// template<typename ...Us> void f(X<Us..., 1, 2, 3, Us...>); + bool isPartiallySubstituted() const { + return isValueDependent() && Length; + } + + /// \brief Get + ArrayRef<TemplateArgument> getPartialArguments() const { + assert(isPartiallySubstituted()); + const TemplateArgument *Args = + reinterpret_cast<const TemplateArgument *>(this + 1); + return llvm::makeArrayRef(Args, Args + Length); + } + SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } @@ -3550,7 +3713,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Represents a reference to a non-type template parameter @@ -3653,7 +3818,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Represents a reference to a function parameter pack that has been @@ -3682,7 +3849,7 @@ class FunctionParmPackExpr : public Expr { FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, unsigned NumParams, - Decl * const *Params); + ParmVarDecl *const *Params); friend class ASTReader; friend class ASTStmtReader; @@ -3691,7 +3858,7 @@ public: static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, - ArrayRef<Decl *> Params); + ArrayRef<ParmVarDecl *> Params); static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context, unsigned NumParams); @@ -3720,7 +3887,9 @@ public: return T->getStmtClass() == FunctionParmPackExprClass; } - child_range children() { return child_range(); } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } }; /// \brief Represents a prvalue temporary that is written into memory so that @@ -3901,6 +4070,136 @@ public: child_range children() { return child_range(SubExprs, SubExprs + 2); } }; +/// \brief Represents an expression that might suspend coroutine execution; +/// either a co_await or co_yield expression. +/// +/// Evaluation of this expression first evaluates its 'ready' expression. If +/// that returns 'false': +/// -- execution of the coroutine is suspended +/// -- the 'suspend' expression is evaluated +/// -- if the 'suspend' expression returns 'false', the coroutine is +/// resumed +/// -- otherwise, control passes back to the resumer. +/// If the coroutine is not suspended, or when it is resumed, the 'resume' +/// expression is evaluated, and its result is the result of the overall +/// expression. +class CoroutineSuspendExpr : public Expr { + SourceLocation KeywordLoc; + + enum SubExpr { Common, Ready, Suspend, Resume, Count }; + Stmt *SubExprs[SubExpr::Count]; + + friend class ASTStmtReader; +public: + CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Common, + Expr *Ready, Expr *Suspend, Expr *Resume) + : Expr(SC, Resume->getType(), Resume->getValueKind(), + Resume->getObjectKind(), Resume->isTypeDependent(), + Resume->isValueDependent(), Common->isInstantiationDependent(), + Common->containsUnexpandedParameterPack()), + KeywordLoc(KeywordLoc) { + SubExprs[SubExpr::Common] = Common; + SubExprs[SubExpr::Ready] = Ready; + SubExprs[SubExpr::Suspend] = Suspend; + SubExprs[SubExpr::Resume] = Resume; + } + CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, QualType Ty, + Expr *Common) + : Expr(SC, Ty, VK_RValue, OK_Ordinary, true, true, true, + Common->containsUnexpandedParameterPack()), + KeywordLoc(KeywordLoc) { + assert(Common->isTypeDependent() && Ty->isDependentType() && + "wrong constructor for non-dependent co_await/co_yield expression"); + SubExprs[SubExpr::Common] = Common; + SubExprs[SubExpr::Ready] = nullptr; + SubExprs[SubExpr::Suspend] = nullptr; + SubExprs[SubExpr::Resume] = nullptr; + } + CoroutineSuspendExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { + SubExprs[SubExpr::Common] = nullptr; + SubExprs[SubExpr::Ready] = nullptr; + SubExprs[SubExpr::Suspend] = nullptr; + SubExprs[SubExpr::Resume] = nullptr; + } + + SourceLocation getKeywordLoc() const { return KeywordLoc; } + Expr *getCommonExpr() const { + return static_cast<Expr*>(SubExprs[SubExpr::Common]); + } + + Expr *getReadyExpr() const { + return static_cast<Expr*>(SubExprs[SubExpr::Ready]); + } + Expr *getSuspendExpr() const { + return static_cast<Expr*>(SubExprs[SubExpr::Suspend]); + } + Expr *getResumeExpr() const { + return static_cast<Expr*>(SubExprs[SubExpr::Resume]); + } + + SourceLocation getLocStart() const LLVM_READONLY { + return KeywordLoc; + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getCommonExpr()->getLocEnd(); + } + + child_range children() { + return child_range(SubExprs, SubExprs + SubExpr::Count); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoawaitExprClass || + T->getStmtClass() == CoyieldExprClass; + } +}; + +/// \brief Represents a 'co_await' expression. +class CoawaitExpr : public CoroutineSuspendExpr { + friend class ASTStmtReader; +public: + CoawaitExpr(SourceLocation CoawaitLoc, Expr *Operand, Expr *Ready, + Expr *Suspend, Expr *Resume) + : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Operand, Ready, + Suspend, Resume) {} + CoawaitExpr(SourceLocation CoawaitLoc, QualType Ty, Expr *Operand) + : CoroutineSuspendExpr(CoawaitExprClass, CoawaitLoc, Ty, Operand) {} + CoawaitExpr(EmptyShell Empty) + : CoroutineSuspendExpr(CoawaitExprClass, Empty) {} + + Expr *getOperand() const { + // FIXME: Dig out the actual operand or store it. + return getCommonExpr(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoawaitExprClass; + } +}; + +/// \brief Represents a 'co_yield' expression. +class CoyieldExpr : public CoroutineSuspendExpr { + friend class ASTStmtReader; +public: + CoyieldExpr(SourceLocation CoyieldLoc, Expr *Operand, Expr *Ready, + Expr *Suspend, Expr *Resume) + : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Operand, Ready, + Suspend, Resume) {} + CoyieldExpr(SourceLocation CoyieldLoc, QualType Ty, Expr *Operand) + : CoroutineSuspendExpr(CoyieldExprClass, CoyieldLoc, Ty, Operand) {} + CoyieldExpr(EmptyShell Empty) + : CoroutineSuspendExpr(CoyieldExprClass, Empty) {} + + Expr *getOperand() const { + // FIXME: Dig out the actual operand or store it. + return getCommonExpr(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CoyieldExprClass; + } +}; + } // end namespace clang #endif |