summaryrefslogtreecommitdiffstats
path: root/include/clang/AST
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
committerdim <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
commit3176e97f130184ece0e1a21352c8124cc83ff24a (patch)
tree0a5b74c0b9ca73aded34df95c91fcaf3815230d8 /include/clang/AST
parent1e9b8d38881c3213d1e67b0c47ab9b2c00721a5c (diff)
downloadFreeBSD-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')
-rw-r--r--include/clang/AST/ASTContext.h178
-rw-r--r--include/clang/AST/ASTMutationListener.h12
-rw-r--r--include/clang/AST/ASTTypeTraits.h122
-rw-r--r--include/clang/AST/Attr.h10
-rw-r--r--include/clang/AST/BuiltinTypes.def23
-rw-r--r--include/clang/AST/CXXInheritance.h22
-rw-r--r--include/clang/AST/CharUnits.h20
-rw-r--r--include/clang/AST/CommentSema.h8
-rw-r--r--include/clang/AST/DataRecursiveASTVisitor.h2691
-rw-r--r--include/clang/AST/Decl.h311
-rw-r--r--include/clang/AST/DeclBase.h35
-rw-r--r--include/clang/AST/DeclCXX.h75
-rw-r--r--include/clang/AST/DeclFriend.h24
-rw-r--r--include/clang/AST/DeclGroup.h15
-rw-r--r--include/clang/AST/DeclObjC.h40
-rw-r--r--include/clang/AST/DeclOpenMP.h13
-rw-r--r--include/clang/AST/DeclTemplate.h250
-rw-r--r--include/clang/AST/EvaluatedExprVisitor.h4
-rw-r--r--include/clang/AST/Expr.h651
-rw-r--r--include/clang/AST/ExprCXX.h689
-rw-r--r--include/clang/AST/ExprObjC.h36
-rw-r--r--include/clang/AST/ExprOpenMP.h129
-rw-r--r--include/clang/AST/ExternalASTSource.h75
-rw-r--r--include/clang/AST/Mangle.h3
-rw-r--r--include/clang/AST/NestedNameSpecifier.h3
-rw-r--r--include/clang/AST/OpenMPClause.h1027
-rw-r--r--include/clang/AST/OperationKinds.h3
-rw-r--r--include/clang/AST/PrettyPrinter.h9
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h464
-rw-r--r--include/clang/AST/Redeclarable.h16
-rw-r--r--include/clang/AST/Stmt.h241
-rw-r--r--include/clang/AST/StmtCXX.h135
-rw-r--r--include/clang/AST/StmtIterator.h80
-rw-r--r--include/clang/AST/StmtOpenMP.h647
-rw-r--r--include/clang/AST/StmtVisitor.h4
-rw-r--r--include/clang/AST/TemplateBase.h116
-rw-r--r--include/clang/AST/TemplateName.h53
-rw-r--r--include/clang/AST/Type.h730
-rw-r--r--include/clang/AST/TypeLoc.h22
-rw-r--r--include/clang/AST/VTableBuilder.h71
40 files changed, 4231 insertions, 4826 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index a2bd55a..b66009e 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -28,6 +28,7 @@
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SanitizerBlacklist.h"
@@ -70,6 +71,7 @@ namespace clang {
class VTableContextBase;
namespace Builtin { class Context; }
+ enum BuiltinTemplateKind : int;
namespace comments {
class FullComment;
@@ -176,8 +178,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
ClassScopeSpecializationPattern;
/// \brief Mapping from materialized temporaries with static storage duration
- /// that appear in constant initializers to their evaluated values.
- llvm::DenseMap<const MaterializeTemporaryExpr*, APValue>
+ /// that appear in constant initializers to their evaluated values. These are
+ /// allocated in a std::map because their address must be stable.
+ llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *>
MaterializedTemporaryValues;
/// \brief Representation of a "canonical" template template parameter that
@@ -215,6 +218,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// __builtin_va_list type.
mutable TypedefDecl *BuiltinVaListDecl;
+ /// The typedef for the predefined \c __builtin_ms_va_list type.
+ mutable TypedefDecl *BuiltinMSVaListDecl;
+
/// \brief The typedef for the predefined \c id type.
mutable TypedefDecl *ObjCIdDecl;
@@ -242,6 +248,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// The identifier 'NSCopying'.
IdentifierInfo *NSCopyingName = nullptr;
+ /// The identifier '__make_integer_seq'.
+ mutable IdentifierInfo *MakeIntegerSeqName = nullptr;
+
QualType ObjCConstantStringType;
mutable RecordDecl *CFConstantStringTypeDecl;
@@ -395,6 +404,7 @@ private:
TranslationUnitDecl *TUDecl;
mutable ExternCContextDecl *ExternCContext;
+ mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;
/// \brief The associated SourceManager object.a
SourceManager &SourceMgr;
@@ -433,6 +443,7 @@ private:
friend class CXXRecordDecl;
const TargetInfo *Target;
+ const TargetInfo *AuxTarget;
clang::PrintingPolicy PrintingPolicy;
public:
@@ -446,10 +457,59 @@ public:
/// \brief Contains parents of a node.
typedef llvm::SmallVector<ast_type_traits::DynTypedNode, 2> ParentVector;
- /// \brief Maps from a node to its parents.
+ /// \brief Maps from a node to its parents. This is used for nodes that have
+ /// pointer identity only, which are more common and we can save space by
+ /// only storing a unique pointer to them.
typedef llvm::DenseMap<const void *,
- llvm::PointerUnion<ast_type_traits::DynTypedNode *,
- ParentVector *>> ParentMap;
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *,
+ ParentVector *>> ParentMapPointers;
+
+ /// Parent map for nodes without pointer identity. We store a full
+ /// DynTypedNode for all keys.
+ typedef llvm::DenseMap<
+ ast_type_traits::DynTypedNode,
+ llvm::PointerUnion4<const Decl *, const Stmt *,
+ ast_type_traits::DynTypedNode *, ParentVector *>>
+ ParentMapOtherNodes;
+
+ /// Container for either a single DynTypedNode or for an ArrayRef to
+ /// DynTypedNode. For use with ParentMap.
+ class DynTypedNodeList {
+ typedef ast_type_traits::DynTypedNode DynTypedNode;
+ llvm::AlignedCharArrayUnion<ast_type_traits::DynTypedNode,
+ ArrayRef<DynTypedNode>> Storage;
+ bool IsSingleNode;
+
+ public:
+ DynTypedNodeList(const DynTypedNode &N) : IsSingleNode(true) {
+ new (Storage.buffer) DynTypedNode(N);
+ }
+ DynTypedNodeList(ArrayRef<DynTypedNode> A) : IsSingleNode(false) {
+ new (Storage.buffer) ArrayRef<DynTypedNode>(A);
+ }
+
+ const ast_type_traits::DynTypedNode *begin() const {
+ if (!IsSingleNode)
+ return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+ ->begin();
+ return reinterpret_cast<const DynTypedNode *>(Storage.buffer);
+ }
+
+ const ast_type_traits::DynTypedNode *end() const {
+ if (!IsSingleNode)
+ return reinterpret_cast<const ArrayRef<DynTypedNode> *>(Storage.buffer)
+ ->end();
+ return reinterpret_cast<const DynTypedNode *>(Storage.buffer) + 1;
+ }
+
+ size_t size() const { return end() - begin(); }
+ bool empty() const { return begin() == end(); }
+ const DynTypedNode &operator[](size_t N) const {
+ assert(N < size() && "Out of bounds!");
+ return *(begin() + N);
+ }
+ };
/// \brief Returns the parents of the given node.
///
@@ -475,13 +535,11 @@ public:
///
/// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
/// NestedNameSpecifier or NestedNameSpecifierLoc.
- template <typename NodeT>
- ArrayRef<ast_type_traits::DynTypedNode> getParents(const NodeT &Node) {
+ template <typename NodeT> DynTypedNodeList getParents(const NodeT &Node) {
return getParents(ast_type_traits::DynTypedNode::create(Node));
}
- ArrayRef<ast_type_traits::DynTypedNode>
- getParents(const ast_type_traits::DynTypedNode &Node);
+ DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node);
const clang::PrintingPolicy &getPrintingPolicy() const {
return PrintingPolicy;
@@ -501,6 +559,9 @@ public:
void *Allocate(size_t Size, unsigned Align = 8) const {
return BumpAlloc.Allocate(Size, Align);
}
+ template <typename T> T *Allocate(size_t Num = 1) const {
+ return static_cast<T *>(Allocate(Num * sizeof(T), llvm::alignOf<T>()));
+ }
void Deallocate(void *Ptr) const { }
/// Return the total amount of physical memory allocated for representing
@@ -516,7 +577,8 @@ public:
}
const TargetInfo &getTargetInfo() const { return *Target; }
-
+ const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
+
/// getIntTypeForBitwidth -
/// sets integer QualTy according to specified details:
/// bitwidth, signed/unsigned.
@@ -812,6 +874,7 @@ public:
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
ExternCContextDecl *getExternCContextDecl() const;
+ BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
// Builtin Types.
CanQualType VoidTy;
@@ -835,17 +898,21 @@ public:
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
CanQualType ObjCBuiltinBoolTy;
CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy;
- CanQualType OCLImage2dTy, OCLImage2dArrayTy;
+ CanQualType OCLImage2dTy, OCLImage2dArrayTy, OCLImage2dDepthTy;
+ CanQualType OCLImage2dArrayDepthTy, OCLImage2dMSAATy, OCLImage2dArrayMSAATy;
+ CanQualType OCLImage2dMSAADepthTy, OCLImage2dArrayMSAADepthTy;
CanQualType OCLImage3dTy;
- CanQualType OCLSamplerTy, OCLEventTy;
+ CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
+ CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy;
+ CanQualType OMPArraySectionTy;
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
mutable QualType AutoDeductTy; // Deduction against 'auto'.
mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'.
- // Type used to help define __builtin_va_list for some targets.
- // The type is built when constructing 'BuiltinVaListDecl'.
- mutable QualType VaListTagTy;
+ // Decl used to help define __builtin_va_list for some targets.
+ // The decl is built when constructing 'BuiltinVaListDecl'.
+ mutable Decl *VaListTagDecl;
ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
SelectorTable &sels, Builtin::Context &builtins);
@@ -881,6 +948,9 @@ public:
void PrintStats() const;
const SmallVectorImpl<Type *>& getTypes() const { return Types; }
+ BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
+ const IdentifierInfo *II) const;
+
/// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl
/// declaration.
RecordDecl *buildImplicitRecord(StringRef Name,
@@ -955,6 +1025,9 @@ public:
const FunctionType *adjustFunctionType(const FunctionType *Fn,
FunctionType::ExtInfo EInfo);
+ /// Adjust the given function result type.
+ CanQualType getCanonicalFunctionResultType(QualType ResultType) const;
+
/// \brief Change the result type of a function type once it is deduced.
void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
@@ -1227,7 +1300,7 @@ public:
UnaryTransformType::UTTKind UKind) const;
/// \brief C++11 deduced auto type.
- QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,
+ QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
bool IsDependent) const;
/// \brief C++11 deduction pattern for 'auto' type.
@@ -1381,6 +1454,12 @@ public:
return NSCopyingName;
}
+ IdentifierInfo *getMakeIntegerSeqName() const {
+ if (!MakeIntegerSeqName)
+ MakeIntegerSeqName = &Idents.get("__make_integer_seq");
+ return MakeIntegerSeqName;
+ }
+
/// \brief Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
QualType getObjCInstanceType() {
@@ -1569,7 +1648,16 @@ public:
/// \brief Retrieve the C type declaration corresponding to the predefined
/// \c __va_list_tag type used to help define the \c __builtin_va_list type
/// for some targets.
- QualType getVaListTagType() const;
+ Decl *getVaListTagDecl() const;
+
+ /// Retrieve the C type declaration corresponding to the predefined
+ /// \c __builtin_ms_va_list type.
+ TypedefDecl *getBuiltinMSVaListDecl() const;
+
+ /// Retrieve the type of the \c __builtin_ms_va_list type.
+ QualType getBuiltinMSVaListType() const {
+ return getTypeDeclType(getBuiltinMSVaListDecl());
+ }
/// \brief Return a type with additional \c const, \c volatile, or
/// \c restrict qualifiers.
@@ -1774,7 +1862,6 @@ public:
/// record (struct/union/class) \p D, which indicates its size and field
/// position information.
const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
- const ASTRecordLayout *BuildMicrosoftASTRecordLayout(const RecordDecl *D) const;
/// \brief Get or compute information about the layout of the specified
/// Objective-C interface.
@@ -2170,9 +2257,7 @@ public:
const FunctionProtoType *FromFunctionType,
const FunctionProtoType *ToFunctionType);
- void ResetObjCLayout(const ObjCContainerDecl *CD) {
- ObjCLayouts[CD] = nullptr;
- }
+ void ResetObjCLayout(const ObjCContainerDecl *CD);
//===--------------------------------------------------------------------===//
// Integer Predicates
@@ -2188,16 +2273,6 @@ public:
QualType getCorrespondingUnsignedType(QualType T) const;
//===--------------------------------------------------------------------===//
- // Type Iterators.
- //===--------------------------------------------------------------------===//
- typedef llvm::iterator_range<SmallVectorImpl<Type *>::const_iterator>
- type_const_range;
-
- type_const_range types() const {
- return type_const_range(Types.begin(), Types.end());
- }
-
- //===--------------------------------------------------------------------===//
// Integer Values
//===--------------------------------------------------------------------===//
@@ -2233,16 +2308,11 @@ public:
/// \brief Get the duplicate declaration of a ObjCMethod in the same
/// interface, or null if none exists.
- const ObjCMethodDecl *getObjCMethodRedeclaration(
- const ObjCMethodDecl *MD) const {
- return ObjCMethodRedecls.lookup(MD);
- }
+ const ObjCMethodDecl *
+ getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const;
void setObjCMethodRedeclaration(const ObjCMethodDecl *MD,
- const ObjCMethodDecl *Redecl) {
- assert(!getObjCMethodRedeclaration(MD) && "MD already has a redeclaration");
- ObjCMethodRedecls[MD] = Redecl;
- }
+ const ObjCMethodDecl *Redecl);
/// \brief Returns the Objective-C interface that \p ND belongs to if it is
/// an Objective-C method/property/ivar etc. that is part of an interface,
@@ -2307,6 +2377,14 @@ public:
Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
unsigned ParmIdx);
+ void addTypedefNameForUnnamedTagDecl(TagDecl *TD, TypedefNameDecl *TND);
+
+ TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD);
+
+ void addDeclaratorForUnnamedTagDecl(TagDecl *TD, DeclaratorDecl *DD);
+
+ DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD);
+
void setManglingNumber(const NamedDecl *ND, unsigned Number);
unsigned getManglingNumber(const NamedDecl *ND) const;
@@ -2388,9 +2466,10 @@ public:
/// This routine may only be invoked once for a given ASTContext object.
/// It is normally invoked after ASTContext construction.
///
- /// \param Target The target
- void InitBuiltinTypes(const TargetInfo &Target);
-
+ /// \param Target The target
+ void InitBuiltinTypes(const TargetInfo &Target,
+ const TargetInfo *AuxTarget = nullptr);
+
private:
void InitBuiltinType(CanQualType &R, BuiltinType::Kind K);
@@ -2429,9 +2508,15 @@ private:
/// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.
- typedef llvm::SmallDenseMap<void(*)(void*), llvm::SmallVector<void*, 16> >
- DeallocationMap;
- DeallocationMap Deallocations;
+ // FIXME: We really should have a better mechanism in the ASTContext to
+ // manage running destructors for types which do variable sized allocation
+ // within the AST. In some places we thread the AST bump pointer allocator
+ // into the datastructures which avoids this mess during deallocation but is
+ // wasteful of memory, and here we require a lot of error prone book keeping
+ // in order to track and run destructors while we're tearing things down.
+ typedef llvm::SmallVector<std::pair<void (*)(void *), void *>, 16>
+ DeallocationFunctionsAndArguments;
+ DeallocationFunctionsAndArguments Deallocations;
// FIXME: This currently contains the set of StoredDeclMaps used
// by DeclContext objects. This probably should not be in ASTContext,
@@ -2443,7 +2528,8 @@ private:
void ReleaseDeclContextMaps();
void ReleaseParentMapEntries();
- std::unique_ptr<ParentMap> AllParents;
+ std::unique_ptr<ParentMapPointers> PointerParents;
+ std::unique_ptr<ParentMapOtherNodes> OtherParents;
std::unique_ptr<VTableContextBase> VTContext;
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
index f4026e9..3ff392d 100644
--- a/include/clang/AST/ASTMutationListener.h
+++ b/include/clang/AST/ASTMutationListener.h
@@ -92,18 +92,6 @@ public:
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {}
- /// \brief A objc class extension redeclared or introduced a property.
- ///
- /// \param Prop the property in the class extension
- ///
- /// \param OrigProp the property from the original interface that was declared
- /// or null if the property was introduced.
- ///
- /// \param ClassExt the class extension.
- virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
- const ObjCPropertyDecl *OrigProp,
- const ObjCCategoryDecl *ClassExt) {}
-
/// \brief A declaration is marked used which was not previously marked used.
///
/// \param D the declaration marked used
diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h
index dc3c34f..dcaac80 100644
--- a/include/clang/AST/ASTTypeTraits.h
+++ b/include/clang/AST/ASTTypeTraits.h
@@ -106,18 +106,25 @@ public:
}
};
+ /// Check if the given ASTNodeKind identifies a type that offers pointer
+ /// identity. This is useful for the fast path in DynTypedNode.
+ bool hasPointerIdentity() const {
+ return KindId > NKI_LastKindWithoutPointerIdentity;
+ }
+
private:
/// \brief Kind ids.
///
/// Includes all possible base and derived kinds.
enum NodeKindId {
NKI_None,
- NKI_CXXCtorInitializer,
NKI_TemplateArgument,
- NKI_NestedNameSpecifier,
NKI_NestedNameSpecifierLoc,
NKI_QualType,
NKI_TypeLoc,
+ NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
+ NKI_CXXCtorInitializer,
+ NKI_NestedNameSpecifier,
NKI_Decl,
#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
#include "clang/AST/DeclNodes.inc"
@@ -238,7 +245,11 @@ public:
/// Note that this is not supported by all AST nodes. For AST nodes
/// that don't have a pointer-defined identity inside the AST, this
/// method returns NULL.
- const void *getMemoizationData() const { return MemoizationData; }
+ const void *getMemoizationData() const {
+ return NodeKind.hasPointerIdentity()
+ ? *reinterpret_cast<void *const *>(Storage.buffer)
+ : nullptr;
+ }
/// \brief Prints the node to the given output stream.
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
@@ -257,6 +268,32 @@ public:
/// FIXME: Implement comparsion for other node types (currently
/// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
bool operator<(const DynTypedNode &Other) const {
+ if (!NodeKind.isSame(Other.NodeKind))
+ return NodeKind < Other.NodeKind;
+
+ if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
+ return getUnchecked<QualType>().getAsOpaquePtr() <
+ Other.getUnchecked<QualType>().getAsOpaquePtr();
+
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) {
+ auto TLA = getUnchecked<TypeLoc>();
+ auto TLB = Other.getUnchecked<TypeLoc>();
+ return std::make_pair(TLA.getType().getAsOpaquePtr(),
+ TLA.getOpaqueData()) <
+ std::make_pair(TLB.getType().getAsOpaquePtr(),
+ TLB.getOpaqueData());
+ }
+
+ if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
+ NodeKind)) {
+ auto NNSLA = getUnchecked<NestedNameSpecifierLoc>();
+ auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>();
+ return std::make_pair(NNSLA.getNestedNameSpecifier(),
+ NNSLA.getOpaqueData()) <
+ std::make_pair(NNSLB.getNestedNameSpecifier(),
+ NNSLB.getOpaqueData());
+ }
+
assert(getMemoizationData() && Other.getMemoizationData());
return getMemoizationData() < Other.getMemoizationData();
}
@@ -270,6 +307,13 @@ public:
if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind))
+ return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>();
+
+ if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind))
+ return getUnchecked<NestedNameSpecifierLoc>() ==
+ Other.getUnchecked<NestedNameSpecifierLoc>();
+
assert(getMemoizationData() && Other.getMemoizationData());
return getMemoizationData() == Other.getMemoizationData();
}
@@ -278,6 +322,47 @@ public:
}
/// @}
+ /// \brief Hooks for using DynTypedNode as a key in a DenseMap.
+ struct DenseMapInfo {
+ static inline DynTypedNode getEmptyKey() {
+ DynTypedNode Node;
+ Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey();
+ return Node;
+ }
+ static inline DynTypedNode getTombstoneKey() {
+ DynTypedNode Node;
+ Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey();
+ return Node;
+ }
+ static unsigned getHashValue(const DynTypedNode &Val) {
+ // FIXME: Add hashing support for the remaining types.
+ if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) {
+ auto TL = Val.getUnchecked<TypeLoc>();
+ return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
+ TL.getOpaqueData());
+ }
+
+ if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
+ Val.NodeKind)) {
+ auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>();
+ return llvm::hash_combine(NNSL.getNestedNameSpecifier(),
+ NNSL.getOpaqueData());
+ }
+
+ assert(Val.getMemoizationData());
+ return llvm::hash_value(Val.getMemoizationData());
+ }
+ static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) {
+ auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey();
+ auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey();
+ return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) &&
+ ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) ||
+ (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) &&
+ ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) ||
+ LHS == RHS;
+ }
+ };
+
private:
/// \brief Takes care of converting from and to \c T.
template <typename T, typename EnablerT = void> struct BaseConverter;
@@ -286,18 +371,18 @@ private:
template <typename T, typename BaseT> struct DynCastPtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
- return cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
+ return &getUnchecked(NodeKind, Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
- return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
+ return *cast<T>(static_cast<const BaseT *>(
+ *reinterpret_cast<const void *const *>(Storage)));
}
static DynTypedNode create(const BaseT &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNode(Node);
- Result.MemoizationData = &Node;
- new (Result.Storage.buffer) const BaseT * (&Node);
+ new (Result.Storage.buffer) const void *(&Node);
return Result;
}
};
@@ -306,18 +391,18 @@ private:
template <typename T> struct PtrConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
- return *reinterpret_cast<T *const *>(Storage);
+ return &getUnchecked(NodeKind, Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
- return **reinterpret_cast<T *const *>(Storage);
+ return *static_cast<const T *>(
+ *reinterpret_cast<const void *const *>(Storage));
}
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
- Result.MemoizationData = &Node;
- new (Result.Storage.buffer) const T * (&Node);
+ new (Result.Storage.buffer) const void *(&Node);
return Result;
}
};
@@ -336,14 +421,12 @@ private:
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
- Result.MemoizationData = nullptr;
new (Result.Storage.buffer) T(Node);
return Result;
}
};
ASTNodeKind NodeKind;
- const void *MemoizationData;
/// \brief Stores the data of the node.
///
@@ -353,12 +436,9 @@ private:
/// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
/// \c TemplateArguments on the other hand do not have storage or unique
/// pointers and thus need to be stored by value.
- typedef llvm::AlignedCharArrayUnion<
- Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *>
- KindsByPointer;
- llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument,
- NestedNameSpecifierLoc, QualType, TypeLoc>
- Storage;
+ llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
+ NestedNameSpecifierLoc, QualType,
+ TypeLoc> Storage;
};
template <typename T>
@@ -420,6 +500,10 @@ template <>
struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind>
: clang::ast_type_traits::ASTNodeKind::DenseMapInfo {};
+template <>
+struct DenseMapInfo<clang::ast_type_traits::DynTypedNode>
+ : clang::ast_type_traits::DynTypedNode::DenseMapInfo {};
+
} // end namespace llvm
#endif
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 4e282d6..8b80e9f 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -56,21 +56,21 @@ protected:
bool IsLateParsed : 1;
bool DuplicatesAllowed : 1;
- void* operator new(size_t bytes) throw() {
+ void *operator new(size_t bytes) LLVM_NOEXCEPT {
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
}
- void operator delete(void* data) throw() {
+ void operator delete(void *data) LLVM_NOEXCEPT {
llvm_unreachable("Attrs cannot be released with regular 'delete'.");
}
public:
// Forward so that the regular new and delete do not hide global ones.
- void* operator new(size_t Bytes, ASTContext &C,
- size_t Alignment = 8) throw() {
+ void *operator new(size_t Bytes, ASTContext &C,
+ size_t Alignment = 8) LLVM_NOEXCEPT {
return ::operator new(Bytes, C, Alignment);
}
void operator delete(void *Ptr, ASTContext &C,
- size_t Alignment) throw() {
+ size_t Alignment) LLVM_NOEXCEPT {
return ::operator delete(Ptr, C, Alignment);
}
diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def
index 488cace..85e237a 100644
--- a/include/clang/AST/BuiltinTypes.def
+++ b/include/clang/AST/BuiltinTypes.def
@@ -160,6 +160,12 @@ BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy)
BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy)
BUILTIN_TYPE(OCLImage2d, OCLImage2dTy)
BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy)
+BUILTIN_TYPE(OCLImage2dDepth, OCLImage2dDepthTy)
+BUILTIN_TYPE(OCLImage2dArrayDepth, OCLImage2dArrayDepthTy)
+BUILTIN_TYPE(OCLImage2dMSAA, OCLImage2dMSAATy)
+BUILTIN_TYPE(OCLImage2dArrayMSAA, OCLImage2dArrayMSAATy)
+BUILTIN_TYPE(OCLImage2dMSAADepth, OCLImage2dMSAADepthTy)
+BUILTIN_TYPE(OCLImage2dArrayMSAADepth, OCLImage2dArrayMSAADepthTy)
BUILTIN_TYPE(OCLImage3d, OCLImage3dTy)
// OpenCL sampler_t.
@@ -168,6 +174,18 @@ BUILTIN_TYPE(OCLSampler, OCLSamplerTy)
// OpenCL event_t.
BUILTIN_TYPE(OCLEvent, OCLEventTy)
+// OpenCL clk_event_t.
+BUILTIN_TYPE(OCLClkEvent, OCLClkEventTy)
+
+// OpenCL queue_t.
+BUILTIN_TYPE(OCLQueue, OCLQueueTy)
+
+// OpenCL ndrange_t.
+BUILTIN_TYPE(OCLNDRange, OCLNDRangeTy)
+
+// OpenCL reserve_id_t.
+BUILTIN_TYPE(OCLReserveID, OCLReserveIDTy)
+
// This represents the type of an expression whose type is
// totally unknown, e.g. 'T::foo'. It is permitted for this to
// appear in situations where the structure of the type is
@@ -227,8 +245,11 @@ PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
// context.
PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
+// A placeholder type for OpenMP array sections.
+PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)
+
#ifdef LAST_BUILTIN_TYPE
-LAST_BUILTIN_TYPE(ARCUnbridgedCast)
+LAST_BUILTIN_TYPE(OMPArraySection)
#undef LAST_BUILTIN_TYPE
#endif
diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h
index f7612f2..8587260 100644
--- a/include/clang/AST/CXXInheritance.h
+++ b/include/clang/AST/CXXInheritance.h
@@ -155,17 +155,16 @@ class CXXBasePaths {
/// \brief Array of the declarations that have been found. This
/// array is constructed only if needed, e.g., to iterate over the
/// results within LookupResult.
- NamedDecl **DeclsFound;
+ std::unique_ptr<NamedDecl *[]> DeclsFound;
unsigned NumDeclsFound;
friend class CXXRecordDecl;
void ComputeDeclsFound();
- bool lookupInBases(ASTContext &Context,
- const CXXRecordDecl *Record,
- CXXRecordDecl::BaseMatchesCallback *BaseMatches,
- void *UserData);
+ bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record,
+ CXXRecordDecl::BaseMatchesCallback BaseMatches);
+
public:
typedef std::list<CXXBasePath>::iterator paths_iterator;
typedef std::list<CXXBasePath>::const_iterator const_paths_iterator;
@@ -173,15 +172,12 @@ public:
/// BasePaths - Construct a new BasePaths structure to record the
/// paths for a derived-to-base search.
- explicit CXXBasePaths(bool FindAmbiguities = true,
- bool RecordPaths = true,
+ explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true,
bool DetectVirtual = true)
- : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
- DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
- DeclsFound(nullptr), NumDeclsFound(0) { }
-
- ~CXXBasePaths() { delete [] DeclsFound; }
-
+ : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
+ DetectVirtual(DetectVirtual), DetectedVirtual(nullptr),
+ NumDeclsFound(0) {}
+
paths_iterator begin() { return Paths.begin(); }
paths_iterator end() { return Paths.end(); }
const_paths_iterator begin() const { return Paths.begin(); }
diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h
index 72ca9f5..1d22bcc 100644
--- a/include/clang/AST/CharUnits.h
+++ b/include/clang/AST/CharUnits.h
@@ -130,6 +130,14 @@ namespace clang {
return (Quantity & -Quantity) == Quantity;
}
+ /// Test whether this is a multiple of the other value.
+ ///
+ /// Among other things, this promises that
+ /// self.RoundUpToAlignment(N) will just return self.
+ bool isMultipleOf(CharUnits N) const {
+ return (*this % N) == 0;
+ }
+
// Arithmetic operators.
CharUnits operator* (QuantityType N) const {
return CharUnits(Quantity * N);
@@ -172,10 +180,20 @@ namespace clang {
/// Given that this is a non-zero alignment value, what is the
/// alignment at the given offset?
- CharUnits alignmentAtOffset(CharUnits offset) {
+ CharUnits alignmentAtOffset(CharUnits offset) const {
+ assert(Quantity != 0 && "offsetting from unknown alignment?");
return CharUnits(llvm::MinAlign(Quantity, offset.Quantity));
}
+ /// Given that this is the alignment of the first element of an
+ /// array, return the minimum alignment of any element in the array.
+ CharUnits alignmentOfArrayElement(CharUnits elementSize) const {
+ // Since we don't track offsetted alignments, the alignment of
+ // the second element (or any odd element) will be minimally
+ // aligned.
+ return alignmentAtOffset(elementSize);
+ }
+
}; // class CharUnit
} // namespace clang
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 9b05d39..6a80383 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -79,12 +79,8 @@ public:
/// Returns a copy of array, owned by Sema's allocator.
template<typename T>
ArrayRef<T> copyArray(ArrayRef<T> Source) {
- size_t Size = Source.size();
- if (Size != 0) {
- T *Mem = Allocator.Allocate<T>(Size);
- std::uninitialized_copy(Source.begin(), Source.end(), Mem);
- return llvm::makeArrayRef(Mem, Size);
- }
+ if (!Source.empty())
+ return Source.copy(Allocator);
return None;
}
diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
deleted file mode 100644
index dd167fe..0000000
--- a/include/clang/AST/DataRecursiveASTVisitor.h
+++ /dev/null
@@ -1,2691 +0,0 @@
-//===--- DataRecursiveASTVisitor.h - Data-Recursive AST Visitor -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the DataRecursiveASTVisitor interface, which recursively
-// traverses the entire AST, using data recursion for Stmts/Exprs.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_H
-#define LLVM_CLANG_AST_DATARECURSIVEASTVISITOR_H
-
-#include "clang/AST/Attr.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclFriend.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclOpenMP.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/AST/NestedNameSpecifier.h"
-#include "clang/AST/Stmt.h"
-#include "clang/AST/StmtCXX.h"
-#include "clang/AST/StmtObjC.h"
-#include "clang/AST/StmtOpenMP.h"
-#include "clang/AST/TemplateBase.h"
-#include "clang/AST/TemplateName.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/TypeLoc.h"
-
-// The following three macros are used for meta programming. The code
-// using them is responsible for defining macro OPERATOR().
-
-// All unary operators.
-#define UNARYOP_LIST() \
- OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \
- OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \
- OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \
- OPERATOR(Extension)
-
-// All binary operators (excluding compound assign operators).
-#define BINOP_LIST() \
- OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) \
- OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) \
- OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \
- OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) OPERATOR(LAnd) \
- OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma)
-
-// All compound assign operators.
-#define CAO_LIST() \
- OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \
- OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor)
-
-namespace clang {
-
-// Reduce the diff between RecursiveASTVisitor / DataRecursiveASTVisitor to
-// make it easier to track changes and keep the two in sync.
-#define RecursiveASTVisitor DataRecursiveASTVisitor
-
-// A helper macro to implement short-circuiting when recursing. It
-// invokes CALL_EXPR, which must be a method call, on the derived
-// object (s.t. a user of RecursiveASTVisitor can override the method
-// in CALL_EXPR).
-#define TRY_TO(CALL_EXPR) \
- do { \
- if (!getDerived().CALL_EXPR) \
- return false; \
- } while (0)
-
-/// \brief A class that does preorder depth-first traversal on the
-/// entire Clang AST and visits each node.
-///
-/// This class performs three distinct tasks:
-/// 1. traverse the AST (i.e. go to each node);
-/// 2. at a given node, walk up the class hierarchy, starting from
-/// the node's dynamic type, until the top-most class (e.g. Stmt,
-/// Decl, or Type) is reached.
-/// 3. given a (node, class) combination, where 'class' is some base
-/// class of the dynamic type of 'node', call a user-overridable
-/// function to actually visit the node.
-///
-/// These tasks are done by three groups of methods, respectively:
-/// 1. TraverseDecl(Decl *x) does task #1. It is the entry point
-/// for traversing an AST rooted at x. This method simply
-/// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo
-/// is the dynamic type of *x, which calls WalkUpFromFoo(x) and
-/// then recursively visits the child nodes of x.
-/// TraverseStmt(Stmt *x) and TraverseType(QualType x) work
-/// similarly.
-/// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit
-/// any child node of x. Instead, it first calls WalkUpFromBar(x)
-/// where Bar is the direct parent class of Foo (unless Foo has
-/// no parent), and then calls VisitFoo(x) (see the next list item).
-/// 3. VisitFoo(Foo *x) does task #3.
-///
-/// These three method groups are tiered (Traverse* > WalkUpFrom* >
-/// Visit*). A method (e.g. Traverse*) may call methods from the same
-/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*).
-/// It may not call methods from a higher tier.
-///
-/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar
-/// is Foo's super class) before calling VisitFoo(), the result is
-/// that the Visit*() methods for a given node are called in the
-/// top-down order (e.g. for a node of type NamespaceDecl, the order will
-/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()).
-///
-/// This scheme guarantees that all Visit*() calls for the same AST
-/// node are grouped together. In other words, Visit*() methods for
-/// different nodes are never interleaved.
-///
-/// Stmts are traversed internally using a data queue to avoid a stack overflow
-/// with hugely nested ASTs.
-///
-/// Clients of this visitor should subclass the visitor (providing
-/// themselves as the template argument, using the curiously recurring
-/// template pattern) and override any of the Traverse*, WalkUpFrom*,
-/// and Visit* methods for declarations, types, statements,
-/// expressions, or other AST nodes where the visitor should customize
-/// behavior. Most users only need to override Visit*. Advanced
-/// users may override Traverse* and WalkUpFrom* to implement custom
-/// traversal strategies. Returning false from one of these overridden
-/// functions will abort the entire traversal.
-///
-/// By default, this visitor tries to visit every part of the explicit
-/// source code exactly once. The default policy towards templates
-/// is to descend into the 'pattern' class or function body, not any
-/// explicit or implicit instantiations. Explicit specializations
-/// are still visited, and the patterns of partial specializations
-/// are visited separately. This behavior can be changed by
-/// overriding shouldVisitTemplateInstantiations() in the derived class
-/// to return true, in which case all known implicit and explicit
-/// instantiations will be visited at the same time as the pattern
-/// from which they were produced.
-template <typename Derived> class RecursiveASTVisitor {
-public:
- /// \brief Return a reference to the derived class.
- Derived &getDerived() { return *static_cast<Derived *>(this); }
-
- /// \brief Return whether this visitor should recurse into
- /// template instantiations.
- bool shouldVisitTemplateInstantiations() const { return false; }
-
- /// \brief Return whether this visitor should recurse into the types of
- /// TypeLocs.
- bool shouldWalkTypesOfTypeLocs() const { return true; }
-
- /// \brief Recursively visit a statement or expression, by
- /// dispatching to Traverse*() based on the argument's dynamic type.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is NULL).
- bool TraverseStmt(Stmt *S);
-
- /// \brief Recursively visit a type, by dispatching to
- /// Traverse*Type() based on the argument's getTypeClass() property.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is a Null type).
- bool TraverseType(QualType T);
-
- /// \brief Recursively visit a type with location, by dispatching to
- /// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is a Null type location).
- bool TraverseTypeLoc(TypeLoc TL);
-
- /// \brief Recursively visit an attribute, by dispatching to
- /// Traverse*Attr() based on the argument's dynamic type.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is a Null type location).
- bool TraverseAttr(Attr *At);
-
- /// \brief Recursively visit a declaration, by dispatching to
- /// Traverse*Decl() based on the argument's dynamic type.
- ///
- /// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is NULL).
- bool TraverseDecl(Decl *D);
-
- /// \brief Recursively visit a C++ nested-name-specifier.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
-
- /// \brief Recursively visit a C++ nested-name-specifier with location
- /// information.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
-
- /// \brief Recursively visit a name with its location information.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
-
- /// \brief Recursively visit a template name and dispatch to the
- /// appropriate method.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseTemplateName(TemplateName Template);
-
- /// \brief Recursively visit a template argument and dispatch to the
- /// appropriate method for the argument type.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- // FIXME: migrate callers to TemplateArgumentLoc instead.
- bool TraverseTemplateArgument(const TemplateArgument &Arg);
-
- /// \brief Recursively visit a template argument location and dispatch to the
- /// appropriate method for the argument type.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
-
- /// \brief Recursively visit a set of template arguments.
- /// This can be overridden by a subclass, but it's not expected that
- /// will be needed -- this visitor always dispatches to another.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
- bool TraverseTemplateArguments(const TemplateArgument *Args,
- unsigned NumArgs);
-
- /// \brief Recursively visit a constructor initializer. This
- /// automatically dispatches to another visitor for the initializer
- /// expression, but not for the name of the initializer, so may
- /// be overridden for clients that need access to the name.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
-
- /// \brief Recursively visit a lambda capture.
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C);
-
- /// \brief Recursively visit the body of a lambda expression.
- ///
- /// This provides a hook for visitors that need more context when visiting
- /// \c LE->getBody().
- ///
- /// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaBody(LambdaExpr *LE);
-
- // ---- Methods on Attrs ----
-
- // \brief Visit an attribute.
- bool VisitAttr(Attr *A) { return true; }
-
-// Declare Traverse* and empty Visit* for all Attr classes.
-#define ATTR_VISITOR_DECLS_ONLY
-#include "clang/AST/AttrVisitor.inc"
-#undef ATTR_VISITOR_DECLS_ONLY
-
-// ---- Methods on Stmts ----
-
-// Declare Traverse*() for all concrete Stmt classes.
-#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S);
-#include "clang/AST/StmtNodes.inc"
- // The above header #undefs ABSTRACT_STMT and STMT upon exit.
-
- // Define WalkUpFrom*() and empty Visit*() for all Stmt classes.
- bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); }
- bool VisitStmt(Stmt *S) { return true; }
-#define STMT(CLASS, PARENT) \
- bool WalkUpFrom##CLASS(CLASS *S) { \
- TRY_TO(WalkUpFrom##PARENT(S)); \
- TRY_TO(Visit##CLASS(S)); \
- return true; \
- } \
- bool Visit##CLASS(CLASS *S) { return true; }
-#include "clang/AST/StmtNodes.inc"
-
-// Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
-// operator methods. Unary operators are not classes in themselves
-// (they're all opcodes in UnaryOperator) but do have visitors.
-#define OPERATOR(NAME) \
- bool TraverseUnary##NAME(UnaryOperator *S) { \
- TRY_TO(WalkUpFromUnary##NAME(S)); \
- StmtQueueAction StmtQueue(*this); \
- StmtQueue.queue(S->getSubExpr()); \
- return true; \
- } \
- bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
- TRY_TO(WalkUpFromUnaryOperator(S)); \
- TRY_TO(VisitUnary##NAME(S)); \
- return true; \
- } \
- bool VisitUnary##NAME(UnaryOperator *S) { return true; }
-
- UNARYOP_LIST()
-#undef OPERATOR
-
-// Define Traverse*(), WalkUpFrom*(), and Visit*() for binary
-// operator methods. Binary operators are not classes in themselves
-// (they're all opcodes in BinaryOperator) but do have visitors.
-#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
- bool TraverseBin##NAME(BINOP_TYPE *S) { \
- TRY_TO(WalkUpFromBin##NAME(S)); \
- StmtQueueAction StmtQueue(*this); \
- StmtQueue.queue(S->getLHS()); \
- StmtQueue.queue(S->getRHS()); \
- return true; \
- } \
- bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
- TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \
- TRY_TO(VisitBin##NAME(S)); \
- return true; \
- } \
- bool VisitBin##NAME(BINOP_TYPE *S) { return true; }
-
-#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator)
- BINOP_LIST()
-#undef OPERATOR
-
-// Define Traverse*(), WalkUpFrom*(), and Visit*() for compound
-// assignment methods. Compound assignment operators are not
-// classes in themselves (they're all opcodes in
-// CompoundAssignOperator) but do have visitors.
-#define OPERATOR(NAME) \
- GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator)
-
- CAO_LIST()
-#undef OPERATOR
-#undef GENERAL_BINOP_FALLBACK
-
-// ---- Methods on Types ----
-// FIXME: revamp to take TypeLoc's rather than Types.
-
-// Declare Traverse*() for all concrete Type classes.
-#define ABSTRACT_TYPE(CLASS, BASE)
-#define TYPE(CLASS, BASE) bool Traverse##CLASS##Type(CLASS##Type *T);
-#include "clang/AST/TypeNodes.def"
- // The above header #undefs ABSTRACT_TYPE and TYPE upon exit.
-
- // Define WalkUpFrom*() and empty Visit*() for all Type classes.
- bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); }
- bool VisitType(Type *T) { return true; }
-#define TYPE(CLASS, BASE) \
- bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \
- TRY_TO(WalkUpFrom##BASE(T)); \
- TRY_TO(Visit##CLASS##Type(T)); \
- return true; \
- } \
- bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
-#include "clang/AST/TypeNodes.def"
-
-// ---- Methods on TypeLocs ----
-// FIXME: this currently just calls the matching Type methods
-
-// Declare Traverse*() for all concrete TypeLoc classes.
-#define ABSTRACT_TYPELOC(CLASS, BASE)
-#define TYPELOC(CLASS, BASE) bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
-#include "clang/AST/TypeLocNodes.def"
- // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit.
-
- // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes.
- bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); }
- bool VisitTypeLoc(TypeLoc TL) { return true; }
-
- // QualifiedTypeLoc and UnqualTypeLoc are not declared in
- // TypeNodes.def and thus need to be handled specially.
- bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) {
- return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
- }
- bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; }
- bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) {
- return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
- }
- bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; }
-
-// Note that BASE includes trailing 'Type' which CLASS doesn't.
-#define TYPE(CLASS, BASE) \
- bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
- TRY_TO(WalkUpFrom##BASE##Loc(TL)); \
- TRY_TO(Visit##CLASS##TypeLoc(TL)); \
- return true; \
- } \
- bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
-#include "clang/AST/TypeNodes.def"
-
-// ---- Methods on Decls ----
-
-// Declare Traverse*() for all concrete Decl classes.
-#define ABSTRACT_DECL(DECL)
-#define DECL(CLASS, BASE) bool Traverse##CLASS##Decl(CLASS##Decl *D);
-#include "clang/AST/DeclNodes.inc"
- // The above header #undefs ABSTRACT_DECL and DECL upon exit.
-
- // Define WalkUpFrom*() and empty Visit*() for all Decl classes.
- bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); }
- bool VisitDecl(Decl *D) { return true; }
-#define DECL(CLASS, BASE) \
- bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \
- TRY_TO(WalkUpFrom##BASE(D)); \
- TRY_TO(Visit##CLASS##Decl(D)); \
- return true; \
- } \
- bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
-#include "clang/AST/DeclNodes.inc"
-
-private:
- // These are helper methods used by more than one Traverse* method.
- bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
- bool TraverseClassInstantiations(ClassTemplateDecl *D);
- bool TraverseVariableInstantiations(VarTemplateDecl *D);
- bool TraverseFunctionInstantiations(FunctionTemplateDecl *D);
- bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
- unsigned Count);
- bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
- bool TraverseRecordHelper(RecordDecl *D);
- bool TraverseCXXRecordHelper(CXXRecordDecl *D);
- bool TraverseDeclaratorHelper(DeclaratorDecl *D);
- bool TraverseDeclContextHelper(DeclContext *DC);
- bool TraverseFunctionHelper(FunctionDecl *D);
- bool TraverseVarHelper(VarDecl *D);
- bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
- bool TraverseOMPLoopDirective(OMPLoopDirective *S);
- bool TraverseOMPClause(OMPClause *C);
-#define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
-#include "clang/Basic/OpenMPKinds.def"
- /// \brief Process clauses with list of variables.
- template <typename T> bool VisitOMPClauseList(T *Node);
-
- typedef SmallVector<Stmt *, 16> StmtsTy;
- typedef SmallVector<StmtsTy *, 4> QueuesTy;
-
- QueuesTy Queues;
-
- class NewQueueRAII {
- RecursiveASTVisitor &RAV;
-
- public:
- NewQueueRAII(StmtsTy &queue, RecursiveASTVisitor &RAV) : RAV(RAV) {
- RAV.Queues.push_back(&queue);
- }
- ~NewQueueRAII() { RAV.Queues.pop_back(); }
- };
-
- StmtsTy &getCurrentQueue() {
- assert(!Queues.empty() && "base TraverseStmt was never called?");
- return *Queues.back();
- }
-
-public:
- class StmtQueueAction {
- StmtsTy &CurrQueue;
-
- public:
- explicit StmtQueueAction(RecursiveASTVisitor &RAV)
- : CurrQueue(RAV.getCurrentQueue()) {}
-
- void queue(Stmt *S) { CurrQueue.push_back(S); }
- };
-};
-
-#define DISPATCH(NAME, CLASS, VAR) \
- return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
- if (!S)
- return true;
-
- StmtsTy Queue, StmtsToEnqueue;
- Queue.push_back(S);
- NewQueueRAII NQ(StmtsToEnqueue, *this);
-
- while (!Queue.empty()) {
- S = Queue.pop_back_val();
- if (!S)
- continue;
-
- StmtsToEnqueue.clear();
-
-#define DISPATCH_STMT(NAME, CLASS, VAR) \
- TRY_TO(Traverse##NAME(static_cast<CLASS *>(VAR))); \
- break
-
- // If we have a binary expr, dispatch to the subcode of the binop. A smart
- // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
- // below.
- if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
- switch (BinOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case BO_##NAME: \
- DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
-
- BINOP_LIST()
-#undef OPERATOR
-#undef BINOP_LIST
-
-#define OPERATOR(NAME) \
- case BO_##NAME##Assign: \
- DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
-
- CAO_LIST()
-#undef OPERATOR
-#undef CAO_LIST
- }
- } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
- switch (UnOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case UO_##NAME: \
- DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
-
- UNARYOP_LIST()
-#undef OPERATOR
-#undef UNARYOP_LIST
- }
- } else {
-
- // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
- switch (S->getStmtClass()) {
- case Stmt::NoStmtClass:
- break;
-#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) \
- case Stmt::CLASS##Class: \
- DISPATCH_STMT(CLASS, CLASS, S);
-#include "clang/AST/StmtNodes.inc"
- }
- }
-
- Queue.append(StmtsToEnqueue.rbegin(), StmtsToEnqueue.rend());
- }
-
- return true;
-}
-
-#undef DISPATCH_STMT
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
- if (T.isNull())
- return true;
-
- switch (T->getTypeClass()) {
-#define ABSTRACT_TYPE(CLASS, BASE)
-#define TYPE(CLASS, BASE) \
- case Type::CLASS: \
- DISPATCH(CLASS##Type, CLASS##Type, const_cast<Type *>(T.getTypePtr()));
-#include "clang/AST/TypeNodes.def"
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) {
- if (TL.isNull())
- return true;
-
- switch (TL.getTypeLocClass()) {
-#define ABSTRACT_TYPELOC(CLASS, BASE)
-#define TYPELOC(CLASS, BASE) \
- case TypeLoc::CLASS: \
- return getDerived().Traverse##CLASS##TypeLoc(TL.castAs<CLASS##TypeLoc>());
-#include "clang/AST/TypeLocNodes.def"
- }
-
- return true;
-}
-
-// Define the Traverse*Attr(Attr* A) methods
-#define VISITORCLASS RecursiveASTVisitor
-#include "clang/AST/AttrVisitor.inc"
-#undef VISITORCLASS
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
- if (!D)
- return true;
-
- // As a syntax visitor, we want to ignore declarations for
- // implicitly-defined declarations (ones not typed explicitly by the
- // user).
- if (D->isImplicit())
- return true;
-
- switch (D->getKind()) {
-#define ABSTRACT_DECL(DECL)
-#define DECL(CLASS, BASE) \
- case Decl::CLASS: \
- if (!getDerived().Traverse##CLASS##Decl(static_cast<CLASS##Decl *>(D))) \
- return false; \
- break;
-#include "clang/AST/DeclNodes.inc"
- }
-
- // Visit any attributes attached to this declaration.
- for (auto *I : D->attrs()) {
- if (!getDerived().TraverseAttr(I))
- return false;
- }
- return true;
-}
-
-#undef DISPATCH
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
- NestedNameSpecifier *NNS) {
- if (!NNS)
- return true;
-
- if (NNS->getPrefix())
- TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix()));
-
- switch (NNS->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- return true;
-
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- TRY_TO(TraverseType(QualType(NNS->getAsType(), 0)));
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
- NestedNameSpecifierLoc NNS) {
- if (!NNS)
- return true;
-
- if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
- TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
-
- switch (NNS.getNestedNameSpecifier()->getKind()) {
- case NestedNameSpecifier::Identifier:
- case NestedNameSpecifier::Namespace:
- case NestedNameSpecifier::NamespaceAlias:
- case NestedNameSpecifier::Global:
- case NestedNameSpecifier::Super:
- return true;
-
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- TRY_TO(TraverseTypeLoc(NNS.getTypeLoc()));
- break;
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
- DeclarationNameInfo NameInfo) {
- switch (NameInfo.getName().getNameKind()) {
- case DeclarationName::CXXConstructorName:
- case DeclarationName::CXXDestructorName:
- case DeclarationName::CXXConversionFunctionName:
- if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
- TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc()));
-
- break;
-
- case DeclarationName::Identifier:
- case DeclarationName::ObjCZeroArgSelector:
- case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- case DeclarationName::CXXOperatorName:
- case DeclarationName::CXXLiteralOperatorName:
- case DeclarationName::CXXUsingDirective:
- break;
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
- if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
- TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
- else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
- TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier()));
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
- const TemplateArgument &Arg) {
- switch (Arg.getKind()) {
- case TemplateArgument::Null:
- case TemplateArgument::Declaration:
- case TemplateArgument::Integral:
- case TemplateArgument::NullPtr:
- return true;
-
- case TemplateArgument::Type:
- return getDerived().TraverseType(Arg.getAsType());
-
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- return getDerived().TraverseTemplateName(
- Arg.getAsTemplateOrTemplatePattern());
-
- case TemplateArgument::Expression:
- return getDerived().TraverseStmt(Arg.getAsExpr());
-
- case TemplateArgument::Pack:
- return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
- Arg.pack_size());
- }
-
- return true;
-}
-
-// FIXME: no template name location?
-// FIXME: no source locations for a template argument pack?
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
- const TemplateArgumentLoc &ArgLoc) {
- const TemplateArgument &Arg = ArgLoc.getArgument();
-
- switch (Arg.getKind()) {
- case TemplateArgument::Null:
- case TemplateArgument::Declaration:
- case TemplateArgument::Integral:
- case TemplateArgument::NullPtr:
- return true;
-
- case TemplateArgument::Type: {
- // FIXME: how can TSI ever be NULL?
- if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
- return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
- else
- return getDerived().TraverseType(Arg.getAsType());
- }
-
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- if (ArgLoc.getTemplateQualifierLoc())
- TRY_TO(getDerived().TraverseNestedNameSpecifierLoc(
- ArgLoc.getTemplateQualifierLoc()));
- return getDerived().TraverseTemplateName(
- Arg.getAsTemplateOrTemplatePattern());
-
- case TemplateArgument::Expression:
- return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
-
- case TemplateArgument::Pack:
- return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
- Arg.pack_size());
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
- const TemplateArgument *Args, unsigned NumArgs) {
- for (unsigned I = 0; I != NumArgs; ++I) {
- TRY_TO(TraverseTemplateArgument(Args[I]));
- }
-
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
- CXXCtorInitializer *Init) {
- if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo())
- TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
-
- if (Init->isWritten())
- TRY_TO(TraverseStmt(Init->getInit()));
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
- const LambdaCapture *C) {
- if (LE->isInitCapture(C))
- TRY_TO(TraverseDecl(C->getCapturedVar()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
- StmtQueueAction StmtQueue(*this);
- StmtQueue.queue(LE->getBody());
- return true;
-}
-
-// ----------------- Type traversal -----------------
-
-// This macro makes available a variable T, the passed-in type.
-#define DEF_TRAVERSE_TYPE(TYPE, CODE) \
- template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##TYPE(TYPE *T) { \
- TRY_TO(WalkUpFrom##TYPE(T)); \
- { CODE; } \
- return true; \
- }
-
-DEF_TRAVERSE_TYPE(BuiltinType, {})
-
-DEF_TRAVERSE_TYPE(ComplexType, { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(PointerType, { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(BlockPointerType,
- { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(LValueReferenceType,
- { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(RValueReferenceType,
- { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(MemberPointerType, {
- TRY_TO(TraverseType(QualType(T->getClass(), 0)));
- TRY_TO(TraverseType(T->getPointeeType()));
-})
-
-DEF_TRAVERSE_TYPE(AdjustedType, { TRY_TO(TraverseType(T->getOriginalType())); })
-
-DEF_TRAVERSE_TYPE(DecayedType, { TRY_TO(TraverseType(T->getOriginalType())); })
-
-DEF_TRAVERSE_TYPE(ConstantArrayType,
- { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(IncompleteArrayType,
- { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(VariableArrayType, {
- TRY_TO(TraverseType(T->getElementType()));
- TRY_TO(TraverseStmt(T->getSizeExpr()));
-})
-
-DEF_TRAVERSE_TYPE(DependentSizedArrayType, {
- TRY_TO(TraverseType(T->getElementType()));
- if (T->getSizeExpr())
- TRY_TO(TraverseStmt(T->getSizeExpr()));
-})
-
-DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, {
- if (T->getSizeExpr())
- TRY_TO(TraverseStmt(T->getSizeExpr()));
- TRY_TO(TraverseType(T->getElementType()));
-})
-
-DEF_TRAVERSE_TYPE(VectorType, { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(ExtVectorType, { TRY_TO(TraverseType(T->getElementType())); })
-
-DEF_TRAVERSE_TYPE(FunctionNoProtoType,
- { TRY_TO(TraverseType(T->getReturnType())); })
-
-DEF_TRAVERSE_TYPE(FunctionProtoType, {
- TRY_TO(TraverseType(T->getReturnType()));
-
- for (const auto &A : T->param_types()) {
- TRY_TO(TraverseType(A));
- }
-
- for (const auto &E : T->exceptions()) {
- TRY_TO(TraverseType(E));
- }
-
- if (Expr *NE = T->getNoexceptExpr())
- TRY_TO(TraverseStmt(NE));
-})
-
-DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
-DEF_TRAVERSE_TYPE(TypedefType, {})
-
-DEF_TRAVERSE_TYPE(TypeOfExprType,
- { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
-
-DEF_TRAVERSE_TYPE(TypeOfType, { TRY_TO(TraverseType(T->getUnderlyingType())); })
-
-DEF_TRAVERSE_TYPE(DecltypeType,
- { TRY_TO(TraverseStmt(T->getUnderlyingExpr())); })
-
-DEF_TRAVERSE_TYPE(UnaryTransformType, {
- TRY_TO(TraverseType(T->getBaseType()));
- TRY_TO(TraverseType(T->getUnderlyingType()));
-})
-
-DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); })
-
-DEF_TRAVERSE_TYPE(RecordType, {})
-DEF_TRAVERSE_TYPE(EnumType, {})
-DEF_TRAVERSE_TYPE(TemplateTypeParmType, {})
-DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, {})
-DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {})
-
-DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
- TRY_TO(TraverseTemplateName(T->getTemplateName()));
- TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
-})
-
-DEF_TRAVERSE_TYPE(InjectedClassNameType, {})
-
-DEF_TRAVERSE_TYPE(AttributedType,
- { TRY_TO(TraverseType(T->getModifiedType())); })
-
-DEF_TRAVERSE_TYPE(ParenType, { TRY_TO(TraverseType(T->getInnerType())); })
-
-DEF_TRAVERSE_TYPE(ElaboratedType, {
- if (T->getQualifier()) {
- TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
- }
- TRY_TO(TraverseType(T->getNamedType()));
-})
-
-DEF_TRAVERSE_TYPE(DependentNameType,
- { TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); })
-
-DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
- TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
- TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
-})
-
-DEF_TRAVERSE_TYPE(PackExpansionType, { TRY_TO(TraverseType(T->getPattern())); })
-
-DEF_TRAVERSE_TYPE(ObjCInterfaceType, {})
-
-DEF_TRAVERSE_TYPE(ObjCObjectType, {
- // We have to watch out here because an ObjCInterfaceType's base
- // type is itself.
- if (T->getBaseType().getTypePtr() != T)
- TRY_TO(TraverseType(T->getBaseType()));
- for (auto typeArg : T->getTypeArgsAsWritten()) {
- TRY_TO(TraverseType(typeArg));
- }
-})
-
-DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
- { TRY_TO(TraverseType(T->getPointeeType())); })
-
-DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
-
-#undef DEF_TRAVERSE_TYPE
-
-// ----------------- TypeLoc traversal -----------------
-
-// This macro makes available a variable TL, the passed-in TypeLoc.
-// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc,
-// in addition to WalkUpFrom* for the TypeLoc itself, such that existing
-// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods
-// continue to work.
-#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \
- template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \
- if (getDerived().shouldWalkTypesOfTypeLocs()) \
- TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE *>(TL.getTypePtr()))); \
- TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
- { CODE; } \
- return true; \
- }
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) {
- // Move this over to the 'main' typeloc tree. Note that this is a
- // move -- we pretend that we were really looking at the unqualified
- // typeloc all along -- rather than a recursion, so we don't follow
- // the normal CRTP plan of going through
- // getDerived().TraverseTypeLoc. If we did, we'd be traversing
- // twice for the same type (once as a QualifiedTypeLoc version of
- // the type, once as an UnqualifiedTypeLoc version of the type),
- // which in effect means we'd call VisitTypeLoc twice with the
- // 'same' type. This solves that problem, at the cost of never
- // seeing the qualified version of the type (unless the client
- // subclasses TraverseQualifiedTypeLoc themselves). It's not a
- // perfect solution. A perfect solution probably requires making
- // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a
- // wrapper around Type* -- rather than being its own class in the
- // type hierarchy.
- return TraverseTypeLoc(TL.getUnqualifiedLoc());
-}
-
-DEF_TRAVERSE_TYPELOC(BuiltinType, {})
-
-// FIXME: ComplexTypeLoc is unfinished
-DEF_TRAVERSE_TYPELOC(ComplexType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
-})
-
-DEF_TRAVERSE_TYPELOC(PointerType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-DEF_TRAVERSE_TYPELOC(BlockPointerType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-DEF_TRAVERSE_TYPELOC(LValueReferenceType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-DEF_TRAVERSE_TYPELOC(RValueReferenceType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-// FIXME: location of base class?
-// We traverse this in the type case as well, but how is it not reached through
-// the pointee type?
-DEF_TRAVERSE_TYPELOC(MemberPointerType, {
- TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
- TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(AdjustedType,
- { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
-
-DEF_TRAVERSE_TYPELOC(DecayedType,
- { TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); })
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
- // This isn't available for ArrayType, but is for the ArrayTypeLoc.
- TRY_TO(TraverseStmt(TL.getSizeExpr()));
- return true;
-}
-
-DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
-})
-
-DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
-})
-
-DEF_TRAVERSE_TYPELOC(VariableArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
-})
-
-DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
- TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- return TraverseArrayTypeLocHelper(TL);
-})
-
-// FIXME: order? why not size expr first?
-// FIXME: base VectorTypeLoc is unfinished
-DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, {
- if (TL.getTypePtr()->getSizeExpr())
- TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
- TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
-})
-
-// FIXME: VectorTypeLoc is unfinished
-DEF_TRAVERSE_TYPELOC(VectorType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
-})
-
-// FIXME: size and attributes
-// FIXME: base VectorTypeLoc is unfinished
-DEF_TRAVERSE_TYPELOC(ExtVectorType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
-})
-
-DEF_TRAVERSE_TYPELOC(FunctionNoProtoType,
- { TRY_TO(TraverseTypeLoc(TL.getReturnLoc())); })
-
-// FIXME: location of exception specifications (attributes?)
-DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
- TRY_TO(TraverseTypeLoc(TL.getReturnLoc()));
-
- const FunctionProtoType *T = TL.getTypePtr();
-
- for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) {
- if (TL.getParam(I)) {
- TRY_TO(TraverseDecl(TL.getParam(I)));
- } else if (I < T->getNumParams()) {
- TRY_TO(TraverseType(T->getParamType(I)));
- }
- }
-
- for (const auto &E : T->exceptions()) {
- TRY_TO(TraverseType(E));
- }
-
- if (Expr *NE = T->getNoexceptExpr())
- TRY_TO(TraverseStmt(NE));
-})
-
-DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
-DEF_TRAVERSE_TYPELOC(TypedefType, {})
-
-DEF_TRAVERSE_TYPELOC(TypeOfExprType,
- { TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); })
-
-DEF_TRAVERSE_TYPELOC(TypeOfType, {
- TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
-})
-
-// FIXME: location of underlying expr
-DEF_TRAVERSE_TYPELOC(DecltypeType, {
- TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
-})
-
-DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
- TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(AutoType, {
- TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
-})
-
-DEF_TRAVERSE_TYPELOC(RecordType, {})
-DEF_TRAVERSE_TYPELOC(EnumType, {})
-DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, {})
-DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, {})
-DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, {})
-
-// FIXME: use the loc for the template name?
-DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
- TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName()));
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
- TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
- }
-})
-
-DEF_TRAVERSE_TYPELOC(InjectedClassNameType, {})
-
-DEF_TRAVERSE_TYPELOC(ParenType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); })
-
-DEF_TRAVERSE_TYPELOC(AttributedType,
- { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); })
-
-DEF_TRAVERSE_TYPELOC(ElaboratedType, {
- if (TL.getQualifierLoc()) {
- TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
- }
- TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(DependentNameType, {
- TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
- if (TL.getQualifierLoc()) {
- TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
- }
-
- for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
- TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
- }
-})
-
-DEF_TRAVERSE_TYPELOC(PackExpansionType,
- { TRY_TO(TraverseTypeLoc(TL.getPatternLoc())); })
-
-DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, {})
-
-DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
- // We have to watch out here because an ObjCInterfaceType's base
- // type is itself.
- if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
- TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
- for (unsigned i = 0, n = TL.getNumTypeArgs(); i != n; ++i)
- TRY_TO(TraverseTypeLoc(TL.getTypeArgTInfo(i)->getTypeLoc()));
-})
-
-DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
- { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); })
-
-DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
-
-#undef DEF_TRAVERSE_TYPELOC
-
-// ----------------- Decl traversal -----------------
-//
-// For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing
-// the children that come from the DeclContext associated with it.
-// Therefore each Traverse* only needs to worry about children other
-// than those.
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
- if (!DC)
- return true;
-
- for (auto *Child : DC->decls()) {
- // BlockDecls and CapturedDecls are traversed through BlockExprs and
- // CapturedStmts respectively.
- if (!isa<BlockDecl>(Child) && !isa<CapturedDecl>(Child))
- TRY_TO(TraverseDecl(Child));
- }
-
- return true;
-}
-
-// This macro makes available a variable D, the passed-in decl.
-#define DEF_TRAVERSE_DECL(DECL, CODE) \
- template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##DECL(DECL *D) { \
- TRY_TO(WalkUpFrom##DECL(D)); \
- { CODE; } \
- TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \
- return true; \
- }
-
-DEF_TRAVERSE_DECL(AccessSpecDecl, {})
-
-DEF_TRAVERSE_DECL(BlockDecl, {
- if (TypeSourceInfo *TInfo = D->getSignatureAsWritten())
- TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
- TRY_TO(TraverseStmt(D->getBody()));
- for (const auto &I : D->captures()) {
- if (I.hasCopyExpr()) {
- TRY_TO(TraverseStmt(I.getCopyExpr()));
- }
- }
- // This return statement makes sure the traversal of nodes in
- // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
- // is skipped - don't remove it.
- return true;
-})
-
-DEF_TRAVERSE_DECL(CapturedDecl, {
- TRY_TO(TraverseStmt(D->getBody()));
- // This return statement makes sure the traversal of nodes in
- // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
- // is skipped - don't remove it.
- return true;
-})
-
-DEF_TRAVERSE_DECL(EmptyDecl, {})
-
-DEF_TRAVERSE_DECL(FileScopeAsmDecl,
- { TRY_TO(TraverseStmt(D->getAsmString())); })
-
-DEF_TRAVERSE_DECL(ImportDecl, {})
-
-DEF_TRAVERSE_DECL(FriendDecl, {
- // Friend is either decl or a type.
- if (D->getFriendType())
- TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
- else
- TRY_TO(TraverseDecl(D->getFriendDecl()));
-})
-
-DEF_TRAVERSE_DECL(FriendTemplateDecl, {
- if (D->getFriendType())
- TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
- else
- TRY_TO(TraverseDecl(D->getFriendDecl()));
- for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) {
- TemplateParameterList *TPL = D->getTemplateParameterList(I);
- for (TemplateParameterList::iterator ITPL = TPL->begin(), ETPL = TPL->end();
- ITPL != ETPL; ++ITPL) {
- TRY_TO(TraverseDecl(*ITPL));
- }
- }
-})
-
-DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl,
- { TRY_TO(TraverseDecl(D->getSpecialization())); })
-
-DEF_TRAVERSE_DECL(LinkageSpecDecl, {})
-
-DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {// FIXME: implement this
- })
-
-DEF_TRAVERSE_DECL(StaticAssertDecl, {
- TRY_TO(TraverseStmt(D->getAssertExpr()));
- TRY_TO(TraverseStmt(D->getMessage()));
-})
-
-DEF_TRAVERSE_DECL(
- TranslationUnitDecl,
- {// Code in an unnamed namespace shows up automatically in
- // decls_begin()/decls_end(). Thus we don't need to recurse on
- // D->getAnonymousNamespace().
- })
-
-DEF_TRAVERSE_DECL(ExternCContextDecl, {})
-
-DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
- // We shouldn't traverse an aliased namespace, since it will be
- // defined (and, therefore, traversed) somewhere else.
- //
- // This return statement makes sure the traversal of nodes in
- // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
- // is skipped - don't remove it.
- return true;
-})
-
-DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl.
- })
-
-DEF_TRAVERSE_DECL(
- NamespaceDecl,
- {// Code in an unnamed namespace shows up automatically in
- // decls_begin()/decls_end(). Thus we don't need to recurse on
- // D->getAnonymousNamespace().
- })
-
-DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {// FIXME: implement
- })
-
-DEF_TRAVERSE_DECL(ObjCCategoryDecl, {// FIXME: implement
- if (ObjCTypeParamList *typeParamList = D->getTypeParamList()) {
- for (auto typeParam : *typeParamList) {
- TRY_TO(TraverseObjCTypeParamDecl(typeParam));
- }
- }
- return true;
-})
-
-DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {// FIXME: implement
- })
-
-DEF_TRAVERSE_DECL(ObjCImplementationDecl, {// FIXME: implement
- })
-
-DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {// FIXME: implement
- if (ObjCTypeParamList *typeParamList = D->getTypeParamListAsWritten()) {
- for (auto typeParam : *typeParamList) {
- TRY_TO(TraverseObjCTypeParamDecl(typeParam));
- }
- }
-
- if (TypeSourceInfo *superTInfo = D->getSuperClassTInfo()) {
- TRY_TO(TraverseTypeLoc(superTInfo->getTypeLoc()));
- }
-})
-
-DEF_TRAVERSE_DECL(ObjCProtocolDecl, {// FIXME: implement
- })
-
-DEF_TRAVERSE_DECL(ObjCMethodDecl, {
- if (D->getReturnTypeSourceInfo()) {
- TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc()));
- }
- for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- if (D->isThisDeclarationADefinition()) {
- TRY_TO(TraverseStmt(D->getBody()));
- }
- return true;
-})
-
-DEF_TRAVERSE_DECL(ObjCTypeParamDecl, {
- if (D->hasExplicitBound()) {
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the type alias, not something that was written in the
- // source.
- }
-})
-
-DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
- if (D->getTypeSourceInfo())
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- else
- TRY_TO(TraverseType(D->getType()));
- return true;
-})
-
-DEF_TRAVERSE_DECL(UsingDecl, {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
-})
-
-DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
-})
-
-DEF_TRAVERSE_DECL(UsingShadowDecl, {})
-
-DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, {
- for (auto *I : D->varlists()) {
- TRY_TO(TraverseStmt(I));
- }
-})
-
-// A helper method for TemplateDecl's children.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
- TemplateParameterList *TPL) {
- if (TPL) {
- for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- }
- return true;
-}
-
-// A helper method for traversing the implicit instantiations of a
-// class template.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
- ClassTemplateDecl *D) {
- for (auto *SD : D->specializations()) {
- for (auto *RD : SD->redecls()) {
- // We don't want to visit injected-class-names in this traversal.
- if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
- continue;
-
- switch (
- cast<ClassTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
- // Visit the implicit instantiations with the requested pattern.
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- TRY_TO(TraverseDecl(RD));
- break;
-
- // We don't need to do anything on an explicit instantiation
- // or explicit specialization because there will be an explicit
- // node for it elsewhere.
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- case TSK_ExplicitSpecialization:
- break;
- }
- }
- }
-
- return true;
-}
-
-DEF_TRAVERSE_DECL(ClassTemplateDecl, {
- CXXRecordDecl *TempDecl = D->getTemplatedDecl();
- TRY_TO(TraverseDecl(TempDecl));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
- // By default, we do not traverse the instantiations of
- // class templates since they do not appear in the user code. The
- // following code optionally traverses them.
- //
- // We only traverse the class instantiations when we see the canonical
- // declaration of the template, to ensure we only visit them once.
- if (getDerived().shouldVisitTemplateInstantiations() &&
- D == D->getCanonicalDecl())
- TRY_TO(TraverseClassInstantiations(D));
-
- // Note that getInstantiatedFromMemberTemplate() is just a link
- // from a template instantiation back to the template from which
- // it was instantiated, and thus should not be traversed.
-})
-
-// A helper method for traversing the implicit instantiations of a
-// class template.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations(
- VarTemplateDecl *D) {
- for (auto *SD : D->specializations()) {
- for (auto *RD : SD->redecls()) {
- switch (
- cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
- // Visit the implicit instantiations with the requested pattern.
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- TRY_TO(TraverseDecl(RD));
- break;
-
- // We don't need to do anything on an explicit instantiation
- // or explicit specialization because there will be an explicit
- // node for it elsewhere.
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- case TSK_ExplicitSpecialization:
- break;
- }
- }
- }
-
- return true;
-}
-
-DEF_TRAVERSE_DECL(VarTemplateDecl, {
- VarDecl *TempDecl = D->getTemplatedDecl();
- TRY_TO(TraverseDecl(TempDecl));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
- // By default, we do not traverse the instantiations of
- // variable templates since they do not appear in the user code. The
- // following code optionally traverses them.
- //
- // We only traverse the variable instantiations when we see the canonical
- // declaration of the template, to ensure we only visit them once.
- if (getDerived().shouldVisitTemplateInstantiations() &&
- D == D->getCanonicalDecl())
- TRY_TO(TraverseVariableInstantiations(D));
-
- // Note that getInstantiatedFromMemberTemplate() is just a link
- // from a template instantiation back to the template from which
- // it was instantiated, and thus should not be traversed.
-})
-
-// A helper method for traversing the instantiations of a
-// function while skipping its specializations.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
- FunctionTemplateDecl *D) {
- for (auto *FD : D->specializations()) {
- for (auto *RD : FD->redecls()) {
- switch (RD->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- // We don't know what kind of FunctionDecl this is.
- TRY_TO(TraverseDecl(RD));
- break;
-
- // No need to visit explicit instantiations, we'll find the node
- // eventually.
- // FIXME: This is incorrect; there is no other node for an explicit
- // instantiation of a function template specialization.
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- break;
-
- case TSK_ExplicitSpecialization:
- break;
- }
- }
- }
-
- return true;
-}
-
-DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
- TRY_TO(TraverseDecl(D->getTemplatedDecl()));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
- // By default, we do not traverse the instantiations of
- // function templates since they do not appear in the user code. The
- // following code optionally traverses them.
- //
- // We only traverse the function instantiations when we see the canonical
- // declaration of the template, to ensure we only visit them once.
- if (getDerived().shouldVisitTemplateInstantiations() &&
- D == D->getCanonicalDecl())
- TRY_TO(TraverseFunctionInstantiations(D));
-})
-
-DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
- // D is the "T" in something like
- // template <template <typename> class T> class container { };
- TRY_TO(TraverseDecl(D->getTemplatedDecl()));
- if (D->hasDefaultArgument()) {
- TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
- }
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-})
-
-DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
- // D is the "T" in something like "template<typename T> class vector;"
- if (D->getTypeForDecl())
- TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
- if (D->hasDefaultArgument())
- TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_DECL(TypedefDecl, {
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the typedef, not something that was written in the
- // source.
-})
-
-DEF_TRAVERSE_DECL(TypeAliasDecl, {
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the type alias, not something that was written in the
- // source.
-})
-
-DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, {
- TRY_TO(TraverseDecl(D->getTemplatedDecl()));
- TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-})
-
-DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
- // A dependent using declaration which was marked with 'typename'.
- // template<class T> class A : public B<T> { using typename B<T>::foo; };
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the type, not something that was written in the
- // source.
-})
-
-DEF_TRAVERSE_DECL(EnumDecl, {
- if (D->getTypeForDecl())
- TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
-
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- // The enumerators are already traversed by
- // decls_begin()/decls_end().
-})
-
-// Helper methods for RecordDecl and its children.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(RecordDecl *D) {
- // We shouldn't traverse D->getTypeForDecl(); it's a result of
- // declaring the type, not something that was written in the source.
-
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(CXXRecordDecl *D) {
- if (!TraverseRecordHelper(D))
- return false;
- if (D->isCompleteDefinition()) {
- for (const auto &I : D->bases()) {
- TRY_TO(TraverseTypeLoc(I.getTypeSourceInfo()->getTypeLoc()));
- }
- // We don't traverse the friends or the conversions, as they are
- // already in decls_begin()/decls_end().
- }
- return true;
-}
-
-DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); })
-
-DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); })
-
-DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
- // For implicit instantiations ("set<int> x;"), we don't want to
- // recurse at all, since the instatiated class isn't written in
- // the source code anywhere. (Note the instatiated *type* --
- // set<int> -- is written, and will still get a callback of
- // TemplateSpecializationType). For explicit instantiations
- // ("template set<int>;"), we do need a callback, since this
- // is the only callback that's made for this instantiation.
- // We use getTypeAsWritten() to distinguish.
- if (TypeSourceInfo *TSI = D->getTypeAsWritten())
- TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
-
- if (!getDerived().shouldVisitTemplateInstantiations() &&
- D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
- // Returning from here skips traversing the
- // declaration context of the ClassTemplateSpecializationDecl
- // (embedded in the DEF_TRAVERSE_DECL() macro)
- // which contains the instantiated members of the class.
- return true;
-})
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
- const TemplateArgumentLoc *TAL, unsigned Count) {
- for (unsigned I = 0; I < Count; ++I) {
- TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
- }
- return true;
-}
-
-DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
- // The partial specialization.
- if (TemplateParameterList *TPL = D->getTemplateParameters()) {
- for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- }
- // The args that remains unspecialized.
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- D->getTemplateArgsAsWritten()->getTemplateArgs(),
- D->getTemplateArgsAsWritten()->NumTemplateArgs));
-
- // Don't need the ClassTemplatePartialSpecializationHelper, even
- // though that's our parent class -- we already visit all the
- // template args here.
- TRY_TO(TraverseCXXRecordHelper(D));
-
- // Instantiations will have been visited with the primary template.
-})
-
-DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); })
-
-DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
- // Like UnresolvedUsingTypenameDecl, but without the 'typename':
- // template <class T> Class A : public Base<T> { using Base<T>::foo; };
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
-})
-
-DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- if (D->getTypeSourceInfo())
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
- else
- TRY_TO(TraverseType(D->getType()));
- return true;
-}
-
-DEF_TRAVERSE_DECL(MSPropertyDecl, { TRY_TO(TraverseDeclaratorHelper(D)); })
-
-DEF_TRAVERSE_DECL(FieldDecl, {
- TRY_TO(TraverseDeclaratorHelper(D));
- if (D->isBitField())
- TRY_TO(TraverseStmt(D->getBitWidth()));
- else if (D->hasInClassInitializer())
- TRY_TO(TraverseStmt(D->getInClassInitializer()));
-})
-
-DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {
- TRY_TO(TraverseDeclaratorHelper(D));
- if (D->isBitField())
- TRY_TO(TraverseStmt(D->getBitWidth()));
- // FIXME: implement the rest.
-})
-
-DEF_TRAVERSE_DECL(ObjCIvarDecl, {
- TRY_TO(TraverseDeclaratorHelper(D));
- if (D->isBitField())
- TRY_TO(TraverseStmt(D->getBitWidth()));
- // FIXME: implement the rest.
-})
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
- TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
-
- // If we're an explicit template specialization, iterate over the
- // template args that were explicitly specified. If we were doing
- // this in typing order, we'd do it between the return type and
- // the function args, but both are handled by the FunctionTypeLoc
- // above, so we have to choose one side. I've decided to do before.
- if (const FunctionTemplateSpecializationInfo *FTSI =
- D->getTemplateSpecializationInfo()) {
- if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
- FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
- // A specialization might not have explicit template arguments if it has
- // a templated return type and concrete arguments.
- if (const ASTTemplateArgumentListInfo *TALI =
- FTSI->TemplateArgumentsAsWritten) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
- TALI->NumTemplateArgs));
- }
- }
- }
-
- // Visit the function type itself, which can be either
- // FunctionNoProtoType or FunctionProtoType, or a typedef. This
- // also covers the return type and the function parameters,
- // including exception specifications.
- TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
-
- if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
- // Constructor initializers.
- for (auto *I : Ctor->inits()) {
- TRY_TO(TraverseConstructorInitializer(I));
- }
- }
-
- if (D->isThisDeclarationADefinition()) {
- TRY_TO(TraverseStmt(D->getBody())); // Function body.
- }
- return true;
-}
-
-DEF_TRAVERSE_DECL(FunctionDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-DEF_TRAVERSE_DECL(CXXMethodDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-DEF_TRAVERSE_DECL(CXXConstructorDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-// CXXConversionDecl is the declaration of a type conversion operator.
-// It's not a cast expression.
-DEF_TRAVERSE_DECL(CXXConversionDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-DEF_TRAVERSE_DECL(CXXDestructorDecl, {
- // We skip decls_begin/decls_end, which are already covered by
- // TraverseFunctionHelper().
- return TraverseFunctionHelper(D);
-})
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
- TRY_TO(TraverseDeclaratorHelper(D));
- // Default params are taken care of when we traverse the ParmVarDecl.
- if (!isa<ParmVarDecl>(D))
- TRY_TO(TraverseStmt(D->getInit()));
- return true;
-}
-
-DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); })
-
-DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, {
- // For implicit instantiations, we don't want to
- // recurse at all, since the instatiated class isn't written in
- // the source code anywhere.
- if (TypeSourceInfo *TSI = D->getTypeAsWritten())
- TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
-
- if (!getDerived().shouldVisitTemplateInstantiations() &&
- D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
- // Returning from here skips traversing the
- // declaration context of the VarTemplateSpecializationDecl
- // (embedded in the DEF_TRAVERSE_DECL() macro).
- return true;
-})
-
-DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl, {
- // The partial specialization.
- if (TemplateParameterList *TPL = D->getTemplateParameters()) {
- for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
- }
- }
- // The args that remains unspecialized.
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- D->getTemplateArgsAsWritten()->getTemplateArgs(),
- D->getTemplateArgsAsWritten()->NumTemplateArgs));
-
- // Don't need the VarTemplatePartialSpecializationHelper, even
- // though that's our parent class -- we already visit all the
- // template args here.
- TRY_TO(TraverseVarHelper(D));
-
- // Instantiations will have been visited with the primary
- // template.
-})
-
-DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); })
-
-DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
- // A non-type template parameter, e.g. "S" in template<int S> class Foo ...
- TRY_TO(TraverseDeclaratorHelper(D));
- TRY_TO(TraverseStmt(D->getDefaultArgument()));
-})
-
-DEF_TRAVERSE_DECL(ParmVarDecl, {
- TRY_TO(TraverseVarHelper(D));
-
- if (D->hasDefaultArg() && D->hasUninstantiatedDefaultArg() &&
- !D->hasUnparsedDefaultArg())
- TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg()));
-
- if (D->hasDefaultArg() && !D->hasUninstantiatedDefaultArg() &&
- !D->hasUnparsedDefaultArg())
- TRY_TO(TraverseStmt(D->getDefaultArg()));
-})
-
-#undef DEF_TRAVERSE_DECL
-
-// ----------------- Stmt traversal -----------------
-//
-// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating
-// over the children defined in children() (every stmt defines these,
-// though sometimes the range is empty). Each individual Traverse*
-// method only needs to worry about children other than those. To see
-// what children() does for a given class, see, e.g.,
-// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
-
-// This macro makes available a variable S, the passed-in stmt.
-#define DEF_TRAVERSE_STMT(STMT, CODE) \
- template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \
- TRY_TO(WalkUpFrom##STMT(S)); \
- StmtQueueAction StmtQueue(*this); \
- { CODE; } \
- for (Stmt *SubStmt : S->children()) { \
- StmtQueue.queue(SubStmt); \
- } \
- return true; \
- }
-
-DEF_TRAVERSE_STMT(GCCAsmStmt, {
- StmtQueue.queue(S->getAsmString());
- for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
- StmtQueue.queue(S->getInputConstraintLiteral(I));
- }
- for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
- StmtQueue.queue(S->getOutputConstraintLiteral(I));
- }
- for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
- StmtQueue.queue(S->getClobberStringLiteral(I));
- }
- // children() iterates over inputExpr and outputExpr.
-})
-
-DEF_TRAVERSE_STMT(
- MSAsmStmt,
- {// FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once
- // added this needs to be implemented.
- })
-
-DEF_TRAVERSE_STMT(CXXCatchStmt, {
- TRY_TO(TraverseDecl(S->getExceptionDecl()));
- // children() iterates over the handler block.
-})
-
-DEF_TRAVERSE_STMT(DeclStmt, {
- for (auto *I : S->decls()) {
- TRY_TO(TraverseDecl(I));
- }
- // Suppress the default iteration over children() by
- // returning. Here's why: A DeclStmt looks like 'type var [=
- // initializer]'. The decls above already traverse over the
- // initializers, so we don't have to do it again (which
- // children() would do).
- return true;
-})
-
-// These non-expr stmts (most of them), do not need any action except
-// iterating over the children.
-DEF_TRAVERSE_STMT(BreakStmt, {})
-DEF_TRAVERSE_STMT(CXXTryStmt, {})
-DEF_TRAVERSE_STMT(CaseStmt, {})
-DEF_TRAVERSE_STMT(CompoundStmt, {})
-DEF_TRAVERSE_STMT(ContinueStmt, {})
-DEF_TRAVERSE_STMT(DefaultStmt, {})
-DEF_TRAVERSE_STMT(DoStmt, {})
-DEF_TRAVERSE_STMT(ForStmt, {})
-DEF_TRAVERSE_STMT(GotoStmt, {})
-DEF_TRAVERSE_STMT(IfStmt, {})
-DEF_TRAVERSE_STMT(IndirectGotoStmt, {})
-DEF_TRAVERSE_STMT(LabelStmt, {})
-DEF_TRAVERSE_STMT(AttributedStmt, {})
-DEF_TRAVERSE_STMT(NullStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtCatchStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtThrowStmt, {})
-DEF_TRAVERSE_STMT(ObjCAtTryStmt, {})
-DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {})
-DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {})
-DEF_TRAVERSE_STMT(CXXForRangeStmt, {})
-DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
-})
-DEF_TRAVERSE_STMT(ReturnStmt, {})
-DEF_TRAVERSE_STMT(SwitchStmt, {})
-DEF_TRAVERSE_STMT(WhileStmt, {})
-
-DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
- if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
- }
-})
-
-DEF_TRAVERSE_STMT(DeclRefExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
-})
-
-DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
- if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- S->getExplicitTemplateArgs().getTemplateArgs(),
- S->getNumTemplateArgs()));
- }
-})
-
-DEF_TRAVERSE_STMT(MemberExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
-})
-
-DEF_TRAVERSE_STMT(
- ImplicitCastExpr,
- {// We don't traverse the cast type, as it's not written in the
- // source code.
- })
-
-DEF_TRAVERSE_STMT(CStyleCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXConstCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXDynamicCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default. We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
- if (InitListExpr *Syn = S->getSyntacticForm())
- S = Syn;
- TRY_TO(WalkUpFromInitListExpr(S));
- StmtQueueAction StmtQueue(*this);
- // All we need are the default actions. FIXME: use a helper function.
- for (Stmt *SubStmt : S->children()) {
- StmtQueue.queue(SubStmt);
- }
- return true;
-}
-
-// GenericSelectionExpr is a special case because the types and expressions
-// are interleaved. We also need to watch out for null types (default
-// generic associations).
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr(
- GenericSelectionExpr *S) {
- TRY_TO(WalkUpFromGenericSelectionExpr(S));
- StmtQueueAction StmtQueue(*this);
- StmtQueue.queue(S->getControllingExpr());
- for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
- if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
- TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
- StmtQueue.queue(S->getAssocExpr(i));
- }
- return true;
-}
-
-// PseudoObjectExpr is a special case because of the wierdness with
-// syntactic expressions and opaque values.
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) {
- TRY_TO(WalkUpFromPseudoObjectExpr(S));
- StmtQueueAction StmtQueue(*this);
- StmtQueue.queue(S->getSyntacticForm());
- for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(),
- e = S->semantics_end();
- i != e; ++i) {
- Expr *sub = *i;
- if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
- sub = OVE->getSourceExpr();
- StmtQueue.queue(sub);
- }
- return true;
-}
-
-DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
- // This is called for code like 'return T()' where T is a built-in
- // (i.e. non-class) type.
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXNewExpr, {
- // The child-iterator will pick up the other arguments.
- TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(OffsetOfExpr, {
- // The child-iterator will pick up the expression representing
- // the field.
- // FIMXE: for code like offsetof(Foo, a.b.c), should we get
- // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c?
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, {
- // The child-iterator will pick up the arg if it's an expression,
- // but not if it's a type.
- if (S->isArgumentType())
- TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXTypeidExpr, {
- // The child-iterator will pick up the arg if it's an expression,
- // but not if it's a type.
- if (S->isTypeOperand())
- TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(MSPropertyRefExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXUuidofExpr, {
- // The child-iterator will pick up the arg if it's an expression,
- // but not if it's a type.
- if (S->isTypeOperand())
- TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(TypeTraitExpr, {
- for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I)
- TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
- TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(ExpressionTraitExpr,
- { StmtQueue.queue(S->getQueriedExpression()); })
-
-DEF_TRAVERSE_STMT(VAArgExpr, {
- // The child-iterator will pick up the expression argument.
- TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
-})
-
-DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
- // This is called for code like 'return T()' where T is a class type.
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-
-// Walk only the visible parts of lambda expressions.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
- TRY_TO(WalkUpFromLambdaExpr(S));
-
- for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
- CEnd = S->explicit_capture_end();
- C != CEnd; ++C) {
- TRY_TO(TraverseLambdaCapture(S, C));
- }
-
- TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
- FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();
-
- if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
- // Visit the whole type.
- TRY_TO(TraverseTypeLoc(TL));
- } else {
- if (S->hasExplicitParameters()) {
- // Visit parameters.
- for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
- TRY_TO(TraverseDecl(Proto.getParam(I)));
- }
- } else if (S->hasExplicitResultType()) {
- TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
- }
-
- auto *T = Proto.getTypePtr();
- for (const auto &E : T->exceptions()) {
- TRY_TO(TraverseType(E));
- }
-
- if (Expr *NE = T->getNoexceptExpr())
- TRY_TO(TraverseStmt(NE));
- }
-
- TRY_TO(TraverseLambdaBody(S));
- return true;
-}
-
-DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
- // This is called for code like 'T()', where T is a template argument.
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-
-// These expressions all might take explicit template arguments.
-// We traverse those if so. FIXME: implement these.
-DEF_TRAVERSE_STMT(CXXConstructExpr, {})
-DEF_TRAVERSE_STMT(CallExpr, {})
-DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
-
-// These exprs (most of them), do not need any action except iterating
-// over the children.
-DEF_TRAVERSE_STMT(AddrLabelExpr, {})
-DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
-DEF_TRAVERSE_STMT(BlockExpr, {
- TRY_TO(TraverseDecl(S->getBlockDecl()));
- return true; // no child statements to loop through.
-})
-DEF_TRAVERSE_STMT(ChooseExpr, {})
-DEF_TRAVERSE_STMT(CompoundLiteralExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, {})
-DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, {})
-DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {})
-DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {})
-DEF_TRAVERSE_STMT(CXXDeleteExpr, {})
-DEF_TRAVERSE_STMT(ExprWithCleanups, {})
-DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {})
-DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {})
-DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
- TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc()));
- if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
- TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(CXXThisExpr, {})
-DEF_TRAVERSE_STMT(CXXThrowExpr, {})
-DEF_TRAVERSE_STMT(UserDefinedLiteral, {})
-DEF_TRAVERSE_STMT(DesignatedInitExpr, {})
-DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {})
-DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
-DEF_TRAVERSE_STMT(GNUNullExpr, {})
-DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
-DEF_TRAVERSE_STMT(NoInitExpr, {})
-DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
-DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
- if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
- TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(ObjCIsaExpr, {})
-DEF_TRAVERSE_STMT(ObjCIvarRefExpr, {})
-DEF_TRAVERSE_STMT(ObjCMessageExpr, {
- if (TypeSourceInfo *TInfo = S->getClassReceiverTypeInfo())
- TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, {})
-DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, {})
-DEF_TRAVERSE_STMT(ObjCProtocolExpr, {})
-DEF_TRAVERSE_STMT(ObjCSelectorExpr, {})
-DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {})
-DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, {
- TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
-})
-DEF_TRAVERSE_STMT(ParenExpr, {})
-DEF_TRAVERSE_STMT(ParenListExpr, {})
-DEF_TRAVERSE_STMT(PredefinedExpr, {})
-DEF_TRAVERSE_STMT(ShuffleVectorExpr, {})
-DEF_TRAVERSE_STMT(ConvertVectorExpr, {})
-DEF_TRAVERSE_STMT(StmtExpr, {})
-DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
- }
-})
-
-DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
- TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
- if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
- S->getNumTemplateArgs()));
- }
-})
-
-DEF_TRAVERSE_STMT(SEHTryStmt, {})
-DEF_TRAVERSE_STMT(SEHExceptStmt, {})
-DEF_TRAVERSE_STMT(SEHFinallyStmt, {})
-DEF_TRAVERSE_STMT(SEHLeaveStmt, {})
-DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
-
-DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
-DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
-DEF_TRAVERSE_STMT(TypoExpr, {})
-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, {})
-DEF_TRAVERSE_STMT(CompoundAssignOperator, {})
-DEF_TRAVERSE_STMT(CXXNoexceptExpr, {})
-DEF_TRAVERSE_STMT(PackExpansionExpr, {})
-DEF_TRAVERSE_STMT(SizeOfPackExpr, {})
-DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
-DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
-DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
-DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
-DEF_TRAVERSE_STMT(CXXFoldExpr, {})
-DEF_TRAVERSE_STMT(AtomicExpr, {})
-
-// These literals (all of them) do not need any action.
-DEF_TRAVERSE_STMT(IntegerLiteral, {})
-DEF_TRAVERSE_STMT(CharacterLiteral, {})
-DEF_TRAVERSE_STMT(FloatingLiteral, {})
-DEF_TRAVERSE_STMT(ImaginaryLiteral, {})
-DEF_TRAVERSE_STMT(StringLiteral, {})
-DEF_TRAVERSE_STMT(ObjCStringLiteral, {})
-DEF_TRAVERSE_STMT(ObjCBoxedExpr, {})
-DEF_TRAVERSE_STMT(ObjCArrayLiteral, {})
-DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, {})
-
-// Traverse OpenCL: AsType, Convert.
-DEF_TRAVERSE_STMT(AsTypeExpr, {})
-
-// OpenMP directives.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective(
- OMPExecutableDirective *S) {
- for (auto *C : S->clauses()) {
- TRY_TO(TraverseOMPClause(C));
- }
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) {
- return TraverseOMPExecutableDirective(S);
-}
-
-DEF_TRAVERSE_STMT(OMPParallelDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPSimdDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPForDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPForSimdDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPSectionsDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPSectionDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPSingleDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPMasterDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPCriticalDirective, {
- TRY_TO(TraverseDeclarationNameInfo(S->getDirectiveName()));
- TRY_TO(TraverseOMPExecutableDirective(S));
-})
-
-DEF_TRAVERSE_STMT(OMPParallelForDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTaskDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTaskyieldDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPBarrierDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTaskgroupDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPCancellationPointDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPCancelDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPFlushDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPOrderedDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPAtomicDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTargetDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-DEF_TRAVERSE_STMT(OMPTeamsDirective,
- { TRY_TO(TraverseOMPExecutableDirective(S)); })
-
-// OpenMP clauses.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
- if (!C)
- return true;
- switch (C->getClauseKind()) {
-#define OPENMP_CLAUSE(Name, Class) \
- case OMPC_##Name: \
- TRY_TO(Visit##Class(static_cast<Class *>(C))); \
- break;
-#include "clang/Basic/OpenMPKinds.def"
- case OMPC_threadprivate:
- case OMPC_unknown:
- break;
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPIfClause(OMPIfClause *C) {
- TRY_TO(TraverseStmt(C->getCondition()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPFinalClause(OMPFinalClause *C) {
- TRY_TO(TraverseStmt(C->getCondition()));
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
- TRY_TO(TraverseStmt(C->getNumThreads()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
- TRY_TO(TraverseStmt(C->getSafelen()));
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) {
- TRY_TO(TraverseStmt(C->getNumForLoops()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPProcBindClause(OMPProcBindClause *) {
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
- TRY_TO(TraverseStmt(C->getChunkSize()));
- TRY_TO(TraverseStmt(C->getHelperChunkSize()));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPNowaitClause(OMPNowaitClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPUntiedClause(OMPUntiedClause *) {
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) {
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
- return true;
-}
-
-template <typename Derived>
-template <typename T>
-bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
- for (auto *E : Node->varlists()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->private_copies()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause(
- OMPFirstprivateClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->private_copies()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->inits()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause(
- OMPLastprivateClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->private_copies()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->source_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->destination_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->assignment_ops()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
- TRY_TO(TraverseStmt(C->getStep()));
- TRY_TO(TraverseStmt(C->getCalcStep()));
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->inits()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->updates()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->finals()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) {
- TRY_TO(TraverseStmt(C->getAlignment()));
- TRY_TO(VisitOMPClauseList(C));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->source_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->destination_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->assignment_ops()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
- OMPCopyprivateClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->source_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->destination_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->assignment_ops()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
- TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
- TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
- TRY_TO(VisitOMPClauseList(C));
- for (auto *E : C->lhs_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->rhs_exprs()) {
- TRY_TO(TraverseStmt(E));
- }
- for (auto *E : C->reduction_ops()) {
- TRY_TO(TraverseStmt(E));
- }
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPFlushClause(OMPFlushClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- return true;
-}
-
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
- TRY_TO(VisitOMPClauseList(C));
- return true;
-}
-
-// FIXME: look at the following tricky-seeming exprs to see if we
-// need to recurse on anything. These are ones that have methods
-// returning decls or qualtypes or nestednamespecifier -- though I'm
-// not sure if they own them -- or just seemed very complicated, or
-// had lots of sub-types to explore.
-//
-// VisitOverloadExpr and its children: recurse on template args? etc?
-
-// FIXME: go through all the stmts and exprs again, and see which of them
-// create new types, and recurse on the types (TypeLocs?) of those.
-// Candidates:
-//
-// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html
-// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html
-// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html
-// Every class that has getQualifier.
-
-#undef DEF_TRAVERSE_STMT
-
-#undef TRY_TO
-
-#undef RecursiveASTVisitor
-
-} // end namespace clang
-
-#endif // LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index e06b58b..046ce70 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -21,11 +21,13 @@
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Linkage.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/TrailingObjects.h"
namespace clang {
struct ASTTemplateArgumentListInfo;
@@ -37,7 +39,6 @@ class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class LabelStmt;
class MemberSpecializationInfo;
-class Module;
class NestedNameSpecifier;
class ParmVarDecl;
class Stmt;
@@ -318,7 +319,8 @@ public:
NamedDecl *getUnderlyingDecl() {
// Fast-path the common case.
if (this->getKind() != UsingShadow &&
- this->getKind() != ObjCCompatibleAlias)
+ this->getKind() != ObjCCompatibleAlias &&
+ this->getKind() != NamespaceAlias)
return this;
return getUnderlyingDeclImpl();
@@ -462,25 +464,15 @@ public:
}
/// \brief Get the original (first) namespace declaration.
- NamespaceDecl *getOriginalNamespace() {
- if (isFirstDecl())
- return this;
-
- return AnonOrFirstNamespaceAndInline.getPointer();
- }
+ NamespaceDecl *getOriginalNamespace();
/// \brief Get the original (first) namespace declaration.
- const NamespaceDecl *getOriginalNamespace() const {
- if (isFirstDecl())
- return this;
-
- return AnonOrFirstNamespaceAndInline.getPointer();
- }
+ const NamespaceDecl *getOriginalNamespace() const;
/// \brief Return true if this declaration is an original (first) declaration
/// of the namespace. This is false for non-original (subsequent) namespace
/// declarations and anonymous namespaces.
- bool isOriginalNamespace() const { return isFirstDecl(); }
+ bool isOriginalNamespace() const;
/// \brief Retrieve the anonymous namespace nested inside this namespace,
/// if any.
@@ -572,8 +564,7 @@ struct QualifierInfo {
/// setTemplateParameterListsInfo - Sets info about "outer" template
/// parameter lists.
void setTemplateParameterListsInfo(ASTContext &Context,
- unsigned NumTPLists,
- TemplateParameterList **TPLists);
+ ArrayRef<TemplateParameterList *> TPLists);
private:
// Copy constructor and copy assignment are disabled.
@@ -658,8 +649,8 @@ public:
assert(index < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[index];
}
- void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
- TemplateParameterList **TPLists);
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ ArrayRef<TemplateParameterList *> TPLists);
SourceLocation getTypeSpecStartLoc() const;
@@ -728,17 +719,14 @@ public:
};
protected:
- /// \brief Placeholder type used in Init to denote an unparsed C++ default
- /// argument.
- struct UnparsedDefaultArgument;
-
- /// \brief Placeholder type used in Init to denote an uninstantiated C++
- /// default argument.
- struct UninstantiatedDefaultArgument;
-
- typedef llvm::PointerUnion4<Stmt *, EvaluatedStmt *,
- UnparsedDefaultArgument *,
- UninstantiatedDefaultArgument *> InitType;
+ // A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we
+ // have allocated the auxilliary struct of information there.
+ //
+ // TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for
+ // this as *many* VarDecls are ParmVarDecls that don't have default
+ // arguments. We could save some space by moving this pointer union to be
+ // allocated in trailing space when necessary.
+ typedef llvm::PointerUnion<Stmt *, EvaluatedStmt *> InitType;
/// \brief The initializer for this variable or, for a ParmVarDecl, the
/// C++ default argument.
@@ -762,6 +750,13 @@ private:
protected:
enum { NumParameterIndexBits = 8 };
+ enum DefaultArgKind {
+ DAK_None,
+ DAK_Unparsed,
+ DAK_Uninstantiated,
+ DAK_Normal
+ };
+
class ParmVarDeclBitfields {
friend class ParmVarDecl;
friend class ASTDeclReader;
@@ -772,6 +767,12 @@ protected:
/// prior declaration.
unsigned HasInheritedDefaultArg : 1;
+ /// Describes the kind of default argument for this parameter. By default
+ /// this is none. If this is normal, then the default argument is stored in
+ /// the \c VarDecl initalizer expression unless we were unble to parse
+ /// (even an invalid) expression for the default argument.
+ unsigned DefaultArgKind : 2;
+
/// Whether this parameter undergoes K&R argument promotion.
unsigned IsKNRPromoted : 1;
@@ -815,6 +816,9 @@ protected:
/// \brief Whether this variable is (C++0x) constexpr.
unsigned IsConstexpr : 1;
+ /// \brief Whether this variable is a (C++ Concepts TS) concept.
+ unsigned IsConcept : 1;
+
/// \brief Whether this variable is the implicit variable for a lambda
/// init-capture.
unsigned IsInitCapture : 1;
@@ -1062,47 +1066,14 @@ public:
/// declaration it is attached to. Also get that declaration.
const Expr *getAnyInitializer(const VarDecl *&D) const;
- bool hasInit() const {
- return !Init.isNull() && (Init.is<Stmt *>() || Init.is<EvaluatedStmt *>());
- }
+ bool hasInit() const;
const Expr *getInit() const {
- if (Init.isNull())
- return nullptr;
-
- const Stmt *S = Init.dyn_cast<Stmt *>();
- if (!S) {
- if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
- S = ES->Value;
- }
- return (const Expr*) S;
- }
- Expr *getInit() {
- if (Init.isNull())
- return nullptr;
-
- Stmt *S = Init.dyn_cast<Stmt *>();
- if (!S) {
- if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
- S = ES->Value;
- }
-
- return (Expr*) S;
+ return const_cast<VarDecl *>(this)->getInit();
}
+ Expr *getInit();
/// \brief Retrieve the address of the initializer expression.
- Stmt **getInitAddress() {
- if (EvaluatedStmt *ES = Init.dyn_cast<EvaluatedStmt*>())
- return &ES->Value;
-
- // This union hack tip-toes around strict-aliasing rules.
- union {
- InitType *InitPtr;
- Stmt **StmtPtr;
- };
-
- InitPtr = &Init;
- return StmtPtr;
- }
+ Stmt **getInitAddress();
void setInit(Expr *I);
@@ -1124,33 +1095,18 @@ public:
/// \brief Return the already-evaluated value of this variable's
/// initializer, or NULL if the value is not yet known. Returns pointer
/// to untyped APValue if the value could not be evaluated.
- APValue *getEvaluatedValue() const {
- if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
- if (Eval->WasEvaluated)
- return &Eval->Evaluated;
-
- return nullptr;
- }
+ APValue *getEvaluatedValue() const;
/// \brief Determines whether it is already known whether the
/// initializer is an integral constant expression or not.
- bool isInitKnownICE() const {
- if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
- return Eval->CheckedICE;
-
- return false;
- }
+ bool isInitKnownICE() const;
/// \brief Determines whether the initializer is an integral constant
/// expression, or in C++11, whether the initializer is a constant
/// expression.
///
/// \pre isInitKnownICE()
- bool isInitICE() const {
- assert(isInitKnownICE() &&
- "Check whether we already know that the initializer is an ICE");
- return Init.get<EvaluatedStmt *>()->IsICE;
- }
+ bool isInitICE() const;
/// \brief Determine whether the value of the initializer attached to this
/// declaration is an integral constant expression.
@@ -1238,6 +1194,15 @@ public:
NonParmVarDeclBits.IsConstexpr = IC;
}
+ /// Whether this variable is (C++ Concepts TS) concept.
+ bool isConcept() const {
+ return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConcept;
+ }
+ void setConcept(bool IC) {
+ assert(!isa<ParmVarDecl>(this));
+ NonParmVarDeclBits.IsConcept = IC;
+ }
+
/// Whether this variable is the implicit variable for a lambda init-capture.
bool isInitCapture() const {
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture;
@@ -1342,6 +1307,7 @@ protected:
TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
: VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) {
assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
+ assert(ParmVarDeclBits.DefaultArgKind == DAK_None);
assert(ParmVarDeclBits.IsKNRPromoted == false);
assert(ParmVarDeclBits.IsObjCMethodParam == false);
setDefaultArg(DefArg);
@@ -1416,29 +1382,20 @@ public:
return const_cast<ParmVarDecl *>(this)->getDefaultArg();
}
- void setDefaultArg(Expr *defarg) {
- Init = reinterpret_cast<Stmt *>(defarg);
- }
+ void setDefaultArg(Expr *defarg);
/// \brief Retrieve the source range that covers the entire default
/// argument.
SourceRange getDefaultArgRange() const;
- void setUninstantiatedDefaultArg(Expr *arg) {
- Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg);
- }
- Expr *getUninstantiatedDefaultArg() {
- return (Expr *)Init.get<UninstantiatedDefaultArgument *>();
- }
+ void setUninstantiatedDefaultArg(Expr *arg);
+ Expr *getUninstantiatedDefaultArg();
const Expr *getUninstantiatedDefaultArg() const {
- return (const Expr *)Init.get<UninstantiatedDefaultArgument *>();
+ return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg();
}
/// hasDefaultArg - Determines whether this parameter has a default argument,
/// either parsed or not.
- bool hasDefaultArg() const {
- return getInit() || hasUnparsedDefaultArg() ||
- hasUninstantiatedDefaultArg();
- }
+ bool hasDefaultArg() const;
/// hasUnparsedDefaultArg - Determines whether this parameter has a
/// default argument that has not yet been parsed. This will occur
@@ -1451,11 +1408,11 @@ public:
/// }; // x has a regular default argument now
/// @endcode
bool hasUnparsedDefaultArg() const {
- return Init.is<UnparsedDefaultArgument*>();
+ return ParmVarDeclBits.DefaultArgKind == DAK_Unparsed;
}
bool hasUninstantiatedDefaultArg() const {
- return Init.is<UninstantiatedDefaultArgument*>();
+ return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated;
}
/// setUnparsedDefaultArg - Specify that this parameter has an
@@ -1463,7 +1420,9 @@ public:
/// real default argument via setDefaultArg when the class
/// definition enclosing the function declaration that owns this
/// default argument is completed.
- void setUnparsedDefaultArg() { Init = (UnparsedDefaultArgument *)nullptr; }
+ void setUnparsedDefaultArg() {
+ ParmVarDeclBits.DefaultArgKind = DAK_Unparsed;
+ }
bool hasInheritedDefaultArg() const {
return ParmVarDeclBits.HasInheritedDefaultArg;
@@ -1546,25 +1505,25 @@ private:
LazyDeclStmtPtr Body;
- // FIXME: This can be packed into the bitfields in Decl.
- // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
+ // FIXME: This can be packed into the bitfields in DeclContext.
+ // NOTE: VC++ packs bitfields poorly if the types differ.
unsigned SClass : 2;
- bool IsInline : 1;
- bool IsInlineSpecified : 1;
- bool IsVirtualAsWritten : 1;
- bool IsPure : 1;
- bool HasInheritedPrototype : 1;
- bool HasWrittenPrototype : 1;
- bool IsDeleted : 1;
- bool IsTrivial : 1; // sunk from CXXMethodDecl
- bool IsDefaulted : 1; // sunk from CXXMethoDecl
- bool IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
- bool HasImplicitReturnZero : 1;
- bool IsLateTemplateParsed : 1;
- bool IsConstexpr : 1;
+ unsigned IsInline : 1;
+ unsigned IsInlineSpecified : 1;
+ unsigned IsVirtualAsWritten : 1;
+ unsigned IsPure : 1;
+ unsigned HasInheritedPrototype : 1;
+ unsigned HasWrittenPrototype : 1;
+ unsigned IsDeleted : 1;
+ unsigned IsTrivial : 1; // sunk from CXXMethodDecl
+ unsigned IsDefaulted : 1; // sunk from CXXMethoDecl
+ unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
+ unsigned HasImplicitReturnZero : 1;
+ unsigned IsLateTemplateParsed : 1;
+ unsigned IsConstexpr : 1;
/// \brief Indicates if the function uses __try.
- bool UsesSEHTry : 1;
+ unsigned UsesSEHTry : 1;
/// \brief Indicates if the function was a definition but its body was
/// skipped.
@@ -1835,7 +1794,7 @@ public:
bool isConstexpr() const { return IsConstexpr; }
void setConstexpr(bool IC) { IsConstexpr = IC; }
- /// Whether this is a (C++11) constexpr function or constexpr constructor.
+ /// \brief Indicates the function uses __try.
bool usesSEHTry() const { return UsesSEHTry; }
void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
@@ -2084,9 +2043,7 @@ public:
/// \brief If this function is an instantiation of a member function of a
/// class template specialization, retrieves the member specialization
/// information.
- MemberSpecializationInfo *getMemberSpecializationInfo() const {
- return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
- }
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
/// \brief Specify that this record is an instantiation of the
/// member function FD.
@@ -2107,13 +2064,9 @@ public:
/// FunctionDecl that describes the function template,
/// getDescribedFunctionTemplate() retrieves the
/// FunctionTemplateDecl from a FunctionDecl.
- FunctionTemplateDecl *getDescribedFunctionTemplate() const {
- return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl*>();
- }
+ FunctionTemplateDecl *getDescribedFunctionTemplate() const;
- void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
- TemplateOrSpecialization = Template;
- }
+ void setDescribedFunctionTemplate(FunctionTemplateDecl *Template);
/// \brief Determine whether this function is a function template
/// specialization.
@@ -2128,10 +2081,7 @@ public:
/// \brief If this function is actually a function template specialization,
/// retrieve information about this function template specialization.
/// Otherwise, returns NULL.
- FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const {
- return TemplateOrSpecialization.
- dyn_cast<FunctionTemplateSpecializationInfo*>();
- }
+ FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const;
/// \brief Determines whether this function is a function template
/// specialization or a member of a class template specialization that can
@@ -2208,10 +2158,7 @@ public:
const TemplateArgumentListInfo &TemplateArgs);
DependentFunctionTemplateSpecializationInfo *
- getDependentSpecializationInfo() const {
- return TemplateOrSpecialization.
- dyn_cast<DependentFunctionTemplateSpecializationInfo*>();
- }
+ getDependentSpecializationInfo() const;
/// \brief Determine what kind of template instantiation this function
/// represents.
@@ -2487,7 +2434,8 @@ public:
/// IndirectFieldDecl - An instance of this class is created to represent a
/// field injected from an anonymous union/struct into the parent scope.
/// IndirectFieldDecl are always implicit.
-class IndirectFieldDecl : public ValueDecl {
+class IndirectFieldDecl : public ValueDecl,
+ public Mergeable<IndirectFieldDecl> {
void anchor() override;
NamedDecl **Chaining;
unsigned ChainingSize;
@@ -2525,6 +2473,9 @@ public:
return dyn_cast<VarDecl>(*chain_begin());
}
+ IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
+ const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == IndirectField; }
@@ -2762,12 +2713,12 @@ private:
/// declaration specifier for variables, it points to the first VarDecl (used
/// for mangling);
/// otherwise, it is a null (TypedefNameDecl) pointer.
- llvm::PointerUnion<NamedDecl *, ExtInfo *> NamedDeclOrQualifier;
+ llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier;
- bool hasExtInfo() const { return NamedDeclOrQualifier.is<ExtInfo *>(); }
- ExtInfo *getExtInfo() { return NamedDeclOrQualifier.get<ExtInfo *>(); }
+ bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); }
+ ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); }
const ExtInfo *getExtInfo() const {
- return NamedDeclOrQualifier.get<ExtInfo *>();
+ return TypedefNameDeclOrQualifier.get<ExtInfo *>();
}
protected:
@@ -2778,7 +2729,7 @@ protected:
TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false),
IsEmbeddedInDeclarator(false), IsFreeStanding(false),
IsCompleteDefinitionRequired(false),
- NamedDeclOrQualifier((NamedDecl *)nullptr) {
+ TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
assert((DK != Enum || TK == TTK_Enum) &&
"EnumDecl not matched with TTK_Enum");
setPreviousDecl(PrevDecl);
@@ -2925,22 +2876,11 @@ public:
return (getDeclName() || getTypedefNameForAnonDecl());
}
- bool hasDeclaratorForAnonDecl() const {
- return dyn_cast_or_null<DeclaratorDecl>(
- NamedDeclOrQualifier.get<NamedDecl *>());
- }
- DeclaratorDecl *getDeclaratorForAnonDecl() const {
- return hasExtInfo() ? nullptr : dyn_cast_or_null<DeclaratorDecl>(
- NamedDeclOrQualifier.get<NamedDecl *>());
- }
-
TypedefNameDecl *getTypedefNameForAnonDecl() const {
- return hasExtInfo() ? nullptr : dyn_cast_or_null<TypedefNameDecl>(
- NamedDeclOrQualifier.get<NamedDecl *>());
+ return hasExtInfo() ? nullptr
+ : TypedefNameDeclOrQualifier.get<TypedefNameDecl *>();
}
- void setDeclaratorForAnonDecl(DeclaratorDecl *DD) { NamedDeclOrQualifier = DD; }
-
void setTypedefNameForAnonDecl(TypedefNameDecl *TDD);
/// \brief Retrieve the nested-name-specifier that qualifies the name of this
@@ -2967,8 +2907,8 @@ public:
assert(i < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[i];
}
- void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists,
- TemplateParameterList **TPLists);
+ void setTemplateParameterListsInfo(ASTContext &Context,
+ ArrayRef<TemplateParameterList *> TPLists);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -3301,7 +3241,14 @@ public:
bool hasVolatileMember() const { return HasVolatileMember; }
void setHasVolatileMember (bool val) { HasVolatileMember = val; }
-
+
+ bool hasLoadedFieldsFromExternalStorage() const {
+ return LoadedFieldsFromExternalStorage;
+ }
+ void setHasLoadedFieldsFromExternalStorage(bool val) {
+ LoadedFieldsFromExternalStorage = val;
+ }
+
/// \brief Determines whether this declaration represents the
/// injected class name.
///
@@ -3475,7 +3422,7 @@ private:
Stmt *Body;
TypeSourceInfo *SignatureAsWritten;
- Capture *Captures;
+ const Capture *Captures;
unsigned NumCaptures;
unsigned ManglingNumber;
@@ -3581,10 +3528,8 @@ public:
bool capturesVariable(const VarDecl *var) const;
- void setCaptures(ASTContext &Context,
- const Capture *begin,
- const Capture *end,
- bool capturesCXXThis);
+ void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
+ bool CapturesCXXThis);
unsigned getBlockManglingNumber() const {
return ManglingNumber;
@@ -3613,7 +3558,15 @@ public:
/// \brief This represents the body of a CapturedStmt, and serves as its
/// DeclContext.
-class CapturedDecl : public Decl, public DeclContext {
+class CapturedDecl final
+ : public Decl,
+ public DeclContext,
+ private llvm::TrailingObjects<CapturedDecl, ImplicitParamDecl *> {
+protected:
+ size_t numTrailingObjects(OverloadToken<ImplicitParamDecl>) {
+ return NumParams;
+ }
+
private:
/// \brief The number of parameters to the outlined function.
unsigned NumParams;
@@ -3622,13 +3575,14 @@ private:
/// \brief The body of the outlined function.
llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow;
- explicit CapturedDecl(DeclContext *DC, unsigned NumParams)
- : Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
- NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) { }
+ explicit CapturedDecl(DeclContext *DC, unsigned NumParams);
+
+ ImplicitParamDecl *const *getParams() const {
+ return getTrailingObjects<ImplicitParamDecl *>();
+ }
- ImplicitParamDecl **getParams() const {
- return reinterpret_cast<ImplicitParamDecl **>(
- const_cast<CapturedDecl *>(this) + 1);
+ ImplicitParamDecl **getParams() {
+ return getTrailingObjects<ImplicitParamDecl *>();
}
public:
@@ -3637,11 +3591,11 @@ public:
static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned NumParams);
- Stmt *getBody() const override { return BodyAndNothrow.getPointer(); }
- void setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }
+ Stmt *getBody() const override;
+ void setBody(Stmt *B);
- bool isNothrow() const { return BodyAndNothrow.getInt(); }
- void setNothrow(bool Nothrow = true) { BodyAndNothrow.setInt(Nothrow); }
+ bool isNothrow() const;
+ void setNothrow(bool Nothrow = true);
unsigned getNumParams() const { return NumParams; }
@@ -3666,7 +3620,7 @@ public:
}
unsigned getContextParamPosition() const { return ContextParam; }
- typedef ImplicitParamDecl **param_iterator;
+ typedef ImplicitParamDecl *const *param_iterator;
typedef llvm::iterator_range<param_iterator> param_range;
/// \brief Retrieve an iterator pointing to the first parameter decl.
@@ -3689,6 +3643,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
};
/// \brief Describes a module import declaration, which makes the contents
@@ -3701,7 +3656,8 @@ public:
///
/// Import declarations can also be implicitly generated from
/// \#include/\#import directives.
-class ImportDecl : public Decl {
+class ImportDecl final : public Decl,
+ llvm::TrailingObjects<ImportDecl, SourceLocation> {
/// \brief The imported module, along with a bit that indicates whether
/// we have source-location information for each identifier in the module
/// name.
@@ -3717,7 +3673,8 @@ class ImportDecl : public Decl {
friend class ASTReader;
friend class ASTDeclReader;
friend class ASTContext;
-
+ friend TrailingObjects;
+
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs);
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 6b6ac3f..05b2a12 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -70,8 +70,15 @@ namespace clang {
/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
///
+/// Note: There are objects tacked on before the *beginning* of Decl
+/// (and its subclasses) in its Decl::operator new(). Proper alignment
+/// of all subclasses (not requiring more than DeclObjAlignment) is
+/// asserted in DeclBase.cpp.
class Decl {
public:
+ /// \brief Alignment guaranteed when allocating Decl and any subtypes.
+ enum { DeclObjAlignment = llvm::AlignOf<uint64_t>::Alignment };
+
/// \brief Lists the kind of concrete classes of Decl.
enum Kind {
#define DECL(DERIVED, BASE) DERIVED,
@@ -468,8 +475,7 @@ public:
template <typename T>
llvm::iterator_range<specific_attr_iterator<T>> specific_attrs() const {
- return llvm::iterator_range<specific_attr_iterator<T>>(
- specific_attr_begin<T>(), specific_attr_end<T>());
+ return llvm::make_range(specific_attr_begin<T>(), specific_attr_end<T>());
}
template <typename T>
@@ -721,6 +727,15 @@ public:
return getParentFunctionOrMethod() == nullptr;
}
+ /// \brief Returns true if this declaration lexically is inside a function.
+ /// It recognizes non-defining declarations as well as members of local
+ /// classes:
+ /// \code
+ /// void foo() { void bar(); }
+ /// void foo2() { class ABC { void bar(); }; }
+ /// \endcode
+ bool isLexicallyWithinFunctionOrMethod() const;
+
/// \brief If this decl is defined inside a function/method/block it returns
/// the corresponding DeclContext, otherwise it returns null.
const DeclContext *getParentFunctionOrMethod() const;
@@ -1126,6 +1141,11 @@ class DeclContext {
/// that are missing from the lookup table.
mutable bool HasLazyExternalLexicalLookups : 1;
+ /// \brief If \c true, lookups should only return identifier from
+ /// DeclContext scope (for example TranslationUnit). Used in
+ /// LookupQualifiedName()
+ mutable bool UseQualifiedLookup : 1;
+
/// \brief Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
/// dependent context). We maintain the invariant that, if the map
@@ -1160,6 +1180,7 @@ protected:
ExternalVisibleStorage(false),
NeedToReconcileExternalVisibleStorage(false),
HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false),
+ UseQualifiedLookup(false),
LookupPtr(nullptr), FirstDecl(nullptr), LastDecl(nullptr) {}
public:
@@ -1740,6 +1761,16 @@ public:
D == LastDecl);
}
+ bool setUseQualifiedLookup(bool use = true) {
+ bool old_value = UseQualifiedLookup;
+ UseQualifiedLookup = use;
+ return old_value;
+ }
+
+ bool shouldUseQualifiedLookup() const {
+ return UseQualifiedLookup;
+ }
+
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 08451c0..7c54901 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -1344,9 +1344,7 @@ public:
/// \brief If this class is an instantiation of a member class of a
/// class template specialization, retrieves the member specialization
/// information.
- MemberSpecializationInfo *getMemberSpecializationInfo() const {
- return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
- }
+ MemberSpecializationInfo *getMemberSpecializationInfo() const;
/// \brief Specify that this record is an instantiation of the
/// member class \p RD.
@@ -1364,13 +1362,9 @@ public:
/// CXXRecordDecl that from a ClassTemplateDecl, while
/// getDescribedClassTemplate() retrieves the ClassTemplateDecl from
/// a CXXRecordDecl.
- ClassTemplateDecl *getDescribedClassTemplate() const {
- return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl*>();
- }
+ ClassTemplateDecl *getDescribedClassTemplate() const;
- void setDescribedClassTemplate(ClassTemplateDecl *Template) {
- TemplateOrInstantiation = Template;
- }
+ void setDescribedClassTemplate(ClassTemplateDecl *Template);
/// \brief Determine whether this particular class is a specialization or
/// instantiation of a class template or member class of a class template,
@@ -1468,8 +1462,8 @@ public:
/// \param BaseDefinition the definition of the base class
///
/// \returns true if this base matched the search criteria
- typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition,
- void *UserData);
+ typedef llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>
+ ForallBasesCallback;
/// \brief Determines if the given callback holds for all the direct
/// or indirect base classes of this type.
@@ -1481,13 +1475,10 @@ public:
/// class of this type, or if \p AllowShortCircuit is true then until a call
/// returns false.
///
- /// \param UserData Passed as the second argument of every call to
- /// \p BaseMatches.
- ///
/// \param AllowShortCircuit if false, forces the callback to be called
/// for every base class, even if a dependent or non-matching base was
/// found.
- bool forallBases(ForallBasesCallback *BaseMatches, void *UserData,
+ bool forallBases(ForallBasesCallback BaseMatches,
bool AllowShortCircuit = true) const;
/// \brief Function type used by lookupInBases() to determine whether a
@@ -1499,13 +1490,9 @@ public:
/// \param Path the current path, from the most-derived class down to the
/// base named by the \p Specifier.
///
- /// \param UserData a single pointer to user-specified data, provided to
- /// lookupInBases().
- ///
/// \returns true if this base matched the search criteria, false otherwise.
- typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path,
- void *UserData);
+ typedef llvm::function_ref<bool(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path)> BaseMatchesCallback;
/// \brief Look for entities within the base classes of this C++ class,
/// transitively searching all base class subobjects.
@@ -1520,14 +1507,12 @@ public:
/// \param BaseMatches callback function used to determine whether a given
/// base matches the user-defined search criteria.
///
- /// \param UserData user data pointer that will be provided to \p BaseMatches.
- ///
/// \param Paths used to record the paths from this class to its base class
/// subobjects that match the search criteria.
///
/// \returns true if there exists any path from this class to a base class
/// subobject that matches the search criteria.
- bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData,
+ bool lookupInBases(BaseMatchesCallback BaseMatches,
CXXBasePaths &Paths) const;
/// \brief Base-class lookup callback that determines whether the given
@@ -1535,10 +1520,10 @@ public:
///
/// This callback can be used with \c lookupInBases() to determine whether
/// a given derived class has is a base class subobject of a particular type.
- /// The user data pointer should refer to the canonical CXXRecordDecl of the
+ /// The base record pointer should refer to the canonical CXXRecordDecl of the
/// base class that we are searching for.
static bool FindBaseClass(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *BaseRecord);
+ CXXBasePath &Path, const CXXRecordDecl *BaseRecord);
/// \brief Base-class lookup callback that determines whether the
/// given base class specifier refers to a specific class
@@ -1546,39 +1531,38 @@ public:
///
/// This callback can be used with \c lookupInBases() to determine
/// whether a given derived class has is a virtual base class
- /// subobject of a particular type. The user data pointer should
+ /// subobject of a particular type. The base record pointer should
/// refer to the canonical CXXRecordDecl of the base class that we
/// are searching for.
static bool FindVirtualBaseClass(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *BaseRecord);
+ CXXBasePath &Path,
+ const CXXRecordDecl *BaseRecord);
/// \brief Base-class lookup callback that determines whether there exists
/// a tag with the given name.
///
/// This callback can be used with \c lookupInBases() to find tag members
- /// of the given name within a C++ class hierarchy. The user data pointer
- /// is an opaque \c DeclarationName pointer.
+ /// of the given name within a C++ class hierarchy.
static bool FindTagMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *Name);
+ CXXBasePath &Path, DeclarationName Name);
/// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name.
///
/// This callback can be used with \c lookupInBases() to find members
- /// of the given name within a C++ class hierarchy. The user data pointer
- /// is an opaque \c DeclarationName pointer.
+ /// of the given name within a C++ class hierarchy.
static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier,
- CXXBasePath &Path, void *Name);
+ CXXBasePath &Path, DeclarationName Name);
/// \brief Base-class lookup callback that determines whether there exists
/// a member with the given name that can be used in a nested-name-specifier.
///
- /// This callback can be used with \c lookupInBases() to find membes of
+ /// This callback can be used with \c lookupInBases() to find members of
/// the given name within a C++ class hierarchy that can occur within
/// nested-name-specifiers.
static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,
CXXBasePath &Path,
- void *UserData);
+ DeclarationName Name);
/// \brief Retrieve the final overriders for each virtual member
/// function in the class hierarchy where this class is the
@@ -1898,7 +1882,8 @@ public:
/// B(A& a) : A(a), f(3.14159) { }
/// };
/// \endcode
-class CXXCtorInitializer {
+class CXXCtorInitializer final
+ : private llvm::TrailingObjects<CXXCtorInitializer, VarDecl *> {
/// \brief Either the base class name/delegating constructor type (stored as
/// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field
/// (IndirectFieldDecl*) being initialized.
@@ -2114,24 +2099,26 @@ public:
/// describe an array member initialization.
VarDecl *getArrayIndex(unsigned I) {
assert(I < getNumArrayIndices() && "Out of bounds member array index");
- return reinterpret_cast<VarDecl **>(this + 1)[I];
+ return getTrailingObjects<VarDecl *>()[I];
}
const VarDecl *getArrayIndex(unsigned I) const {
assert(I < getNumArrayIndices() && "Out of bounds member array index");
- return reinterpret_cast<const VarDecl * const *>(this + 1)[I];
+ return getTrailingObjects<VarDecl *>()[I];
}
void setArrayIndex(unsigned I, VarDecl *Index) {
assert(I < getNumArrayIndices() && "Out of bounds member array index");
- reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
+ getTrailingObjects<VarDecl *>()[I] = Index;
}
ArrayRef<VarDecl *> getArrayIndexes() {
assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init");
- return llvm::makeArrayRef(reinterpret_cast<VarDecl **>(this + 1),
+ return llvm::makeArrayRef(getTrailingObjects<VarDecl *>(),
getNumArrayIndices());
}
/// \brief Get the initializer.
Expr *getInit() const { return static_cast<Expr*>(Init); }
+
+ friend TrailingObjects;
};
/// \brief Represents a C++ constructor within a class.
@@ -2289,14 +2276,14 @@ public:
}
/// \brief Determine whether this constructor is a move constructor
- /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ /// (C++11 [class.copy]p3), which can be used to move values of the class.
///
/// \param TypeQuals If this constructor is a move constructor, will be set
/// to the type qualifiers on the referent of the first parameter's type.
bool isMoveConstructor(unsigned &TypeQuals) const;
/// \brief Determine whether this constructor is a move constructor
- /// (C++0x [class.copy]p3), which can be used to move values of the class.
+ /// (C++11 [class.copy]p3), which can be used to move values of the class.
bool isMoveConstructor() const {
unsigned TypeQuals = 0;
return isMoveConstructor(TypeQuals);
@@ -2406,7 +2393,7 @@ class CXXConversionDecl : public CXXMethodDecl {
void anchor() override;
/// Whether this conversion function declaration is marked
/// "explicit", meaning that it can only be applied when the user
- /// explicitly wrote a cast. This is a C++0x feature.
+ /// explicitly wrote a cast. This is a C++11 feature.
bool IsExplicitSpecified : 1;
CXXConversionDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 12b93b4..27b0388 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -37,7 +37,9 @@ namespace clang {
/// @endcode
///
/// The semantic context of a friend decl is its declaring class.
-class FriendDecl : public Decl {
+class FriendDecl final
+ : public Decl,
+ private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
virtual void anchor();
public:
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
@@ -62,14 +64,6 @@ private:
// template <class T> friend class A<T>::B;
unsigned NumTPLists : 31;
- // The tail-allocated friend type template parameter lists (if any).
- TemplateParameterList* const *getTPLists() const {
- return reinterpret_cast<TemplateParameterList* const *>(this + 1);
- }
- TemplateParameterList **getTPLists() {
- return reinterpret_cast<TemplateParameterList**>(this + 1);
- }
-
friend class CXXRecordDecl::friend_iterator;
friend class CXXRecordDecl;
@@ -83,7 +77,7 @@ private:
UnsupportedFriend(false),
NumTPLists(FriendTypeTPLists.size()) {
for (unsigned i = 0; i < NumTPLists; ++i)
- getTPLists()[i] = FriendTypeTPLists[i];
+ getTrailingObjects<TemplateParameterList *>()[i] = FriendTypeTPLists[i];
}
FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
@@ -118,7 +112,7 @@ public:
}
TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
assert(N < NumTPLists);
- return getTPLists()[N];
+ return getTrailingObjects<TemplateParameterList *>()[N];
}
/// If this friend declaration doesn't name a type, return the inner
@@ -148,9 +142,10 @@ public:
return SourceRange(getFriendLoc(), ND->getLocEnd());
}
else if (TypeSourceInfo *TInfo = getFriendType()) {
- SourceLocation StartL = (NumTPLists == 0)
- ? getFriendLoc()
- : getTPLists()[0]->getTemplateLoc();
+ SourceLocation StartL =
+ (NumTPLists == 0) ? getFriendLoc()
+ : getTrailingObjects<TemplateParameterList *>()[0]
+ ->getTemplateLoc();
return SourceRange(StartL, TInfo->getTypeLoc().getEndLoc());
}
else
@@ -171,6 +166,7 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
};
/// An iterator over the friend declarations of a class.
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index bd3dbd8..c84bb5e 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECLGROUP_H
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/TrailingObjects.h"
#include <cassert>
namespace clang {
@@ -24,13 +25,9 @@ class Decl;
class DeclGroup;
class DeclGroupIterator;
-class DeclGroup {
+class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> {
// FIXME: Include a TypeSpecifier object.
- union {
- unsigned NumDecls;
-
- Decl *Aligner;
- };
+ unsigned NumDecls;
private:
DeclGroup() : NumDecls(0) {}
@@ -43,13 +40,15 @@ public:
Decl*& operator[](unsigned i) {
assert (i < NumDecls && "Out-of-bounds access.");
- return ((Decl**) (this+1))[i];
+ return getTrailingObjects<Decl *>()[i];
}
Decl* const& operator[](unsigned i) const {
assert (i < NumDecls && "Out-of-bounds access.");
- return ((Decl* const*) (this+1))[i];
+ return getTrailingObjects<Decl *>()[i];
}
+
+ friend TrailingObjects;
};
class DeclGroupRef {
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index c42764b..f46078f 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -612,7 +612,8 @@ public:
/// @interface NSArray<T> // stores the <T>
/// @end
/// \endcode
-class ObjCTypeParamList {
+class ObjCTypeParamList final
+ : private llvm::TrailingObjects<ObjCTypeParamList, ObjCTypeParamDecl *> {
/// Stores the components of a SourceRange as a POD.
struct PODSourceRange {
unsigned Begin;
@@ -644,7 +645,7 @@ public:
/// Iterate through the type parameters in the list.
typedef ObjCTypeParamDecl **iterator;
- iterator begin() { return reinterpret_cast<ObjCTypeParamDecl **>(this + 1); }
+ iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); }
iterator end() { return begin() + size(); }
@@ -655,7 +656,7 @@ public:
typedef ObjCTypeParamDecl * const *const_iterator;
const_iterator begin() const {
- return reinterpret_cast<ObjCTypeParamDecl * const *>(this + 1);
+ return getTrailingObjects<ObjCTypeParamDecl *>();
}
const_iterator end() const {
@@ -685,6 +686,7 @@ public:
/// Gather the default set of type arguments to be substituted for
/// these type parameters when dealing with an unspecialized type.
void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
+ friend TrailingObjects;
};
/// ObjCContainerDecl - Represents a container for method declarations.
@@ -1202,13 +1204,8 @@ public:
// might bring in a definition.
// Note: a null value indicates that we don't have a definition and that
// modules are enabled.
- if (!Data.getOpaqueValue()) {
- if (IdentifierInfo *II = getIdentifier()) {
- if (II->isOutOfDate()) {
- updateOutOfDate(*II);
- }
- }
- }
+ if (!Data.getOpaqueValue())
+ getMostRecentDecl();
return Data.getPointer();
}
@@ -1851,13 +1848,8 @@ public:
// might bring in a definition.
// Note: a null value indicates that we don't have a definition and that
// modules are enabled.
- if (!Data.getOpaqueValue()) {
- if (IdentifierInfo *II = getIdentifier()) {
- if (II->isOutOfDate()) {
- updateOutOfDate(*II);
- }
- }
- }
+ if (!Data.getOpaqueValue())
+ getMostRecentDecl();
return Data.getPointer();
}
@@ -2519,26 +2511,18 @@ public:
void setPropertyAttributes(PropertyAttributeKind PRVal) {
PropertyAttributes |= PRVal;
}
+ void overwritePropertyAttributes(unsigned PRVal) {
+ PropertyAttributes = PRVal;
+ }
PropertyAttributeKind getPropertyAttributesAsWritten() const {
return PropertyAttributeKind(PropertyAttributesAsWritten);
}
- bool hasWrittenStorageAttribute() const {
- return PropertyAttributesAsWritten & (OBJC_PR_assign | OBJC_PR_copy |
- OBJC_PR_unsafe_unretained | OBJC_PR_retain | OBJC_PR_strong |
- OBJC_PR_weak);
- }
-
void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
PropertyAttributesAsWritten = PRVal;
}
- void makeitReadWriteAttribute() {
- PropertyAttributes &= ~OBJC_PR_readonly;
- PropertyAttributes |= OBJC_PR_readwrite;
- }
-
// Helper methods for accessing attributes.
/// isReadOnly - Return true iff the property has a setter.
diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h
index 7f0616f..598f418 100644
--- a/include/clang/AST/DeclOpenMP.h
+++ b/include/clang/AST/DeclOpenMP.h
@@ -33,8 +33,12 @@ class Expr;
/// };
/// \endcode
///
-class OMPThreadPrivateDecl : public Decl {
+class OMPThreadPrivateDecl final
+ : public Decl,
+ private llvm::TrailingObjects<OMPThreadPrivateDecl, Expr *> {
friend class ASTDeclReader;
+ friend TrailingObjects;
+
unsigned NumVars;
virtual void anchor();
@@ -43,14 +47,11 @@ class OMPThreadPrivateDecl : public Decl {
Decl(DK, DC, L), NumVars(0) { }
ArrayRef<const Expr *> getVars() const {
- return llvm::makeArrayRef(reinterpret_cast<const Expr * const *>(this + 1),
- NumVars);
+ return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
}
MutableArrayRef<Expr *> getVars() {
- return MutableArrayRef<Expr *>(
- reinterpret_cast<Expr **>(this + 1),
- NumVars);
+ return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
}
void setVars(ArrayRef<Expr *> VL);
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 0fc9b49..a9109ef 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -20,10 +20,12 @@
#include "clang/AST/TemplateBase.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/TrailingObjects.h"
#include <limits>
namespace clang {
+enum BuiltinTemplateKind : int;
class TemplateParameterList;
class TemplateDecl;
class RedeclarableTemplateDecl;
@@ -43,7 +45,9 @@ typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
/// \brief Stores a list of template parameters for a TemplateDecl and its
/// derived classes.
-class TemplateParameterList {
+class TemplateParameterList final
+ : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *> {
+
/// The location of the 'template' keyword.
SourceLocation TemplateLoc;
@@ -59,16 +63,18 @@ class TemplateParameterList {
unsigned ContainsUnexpandedParameterPack : 1;
protected:
+ size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
+ return NumParams;
+ }
+
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
- NamedDecl **Params, unsigned NumParams,
- SourceLocation RAngleLoc);
+ ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc);
public:
static TemplateParameterList *Create(const ASTContext &C,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- NamedDecl **Params,
- unsigned NumParams,
+ ArrayRef<NamedDecl *> Params,
SourceLocation RAngleLoc);
/// \brief Iterates through the template parameters in this list.
@@ -77,10 +83,8 @@ public:
/// \brief Iterates through the template parameters in this list.
typedef NamedDecl* const* const_iterator;
- iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); }
- const_iterator begin() const {
- return reinterpret_cast<NamedDecl * const *>(this + 1);
- }
+ iterator begin() { return getTrailingObjects<NamedDecl *>(); }
+ const_iterator begin() const { return getTrailingObjects<NamedDecl *>(); }
iterator end() { return begin() + NumParams; }
const_iterator end() const { return begin() + NumParams; }
@@ -130,29 +134,45 @@ public:
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(TemplateLoc, RAngleLoc);
}
+
+ friend TrailingObjects;
+ template <size_t N> friend class FixedSizeTemplateParameterListStorage;
};
/// \brief Stores a list of template parameters for a TemplateDecl and its
/// derived classes. Suitable for creating on the stack.
-template<size_t N>
-class FixedSizeTemplateParameterList : public TemplateParameterList {
+template <size_t N> class FixedSizeTemplateParameterListStorage {
+ // This is kinda ugly: TemplateParameterList usually gets allocated
+ // in a block of memory with NamedDecls appended to it. Here, to get
+ // it stack allocated, we include the params as a separate
+ // variable. After allocation, the TemplateParameterList object
+ // treats them as part of itself.
+ TemplateParameterList List;
NamedDecl *Params[N];
public:
- FixedSizeTemplateParameterList(SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- NamedDecl **Params, SourceLocation RAngleLoc) :
- TemplateParameterList(TemplateLoc, LAngleLoc, Params, N, RAngleLoc) {
- }
+ FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params,
+ SourceLocation RAngleLoc)
+ : List(TemplateLoc, LAngleLoc, Params, RAngleLoc) {
+ // Because we're doing an evil layout hack above, have some
+ // asserts, just to double-check everything is laid out like
+ // expected.
+ assert(sizeof(*this) ==
+ TemplateParameterList::totalSizeToAlloc<NamedDecl *>(N) &&
+ "Object layout not as expected");
+ assert(this->Params == List.getTrailingObjects<NamedDecl *>() &&
+ "Object layout not as expected");
+ }
+ TemplateParameterList *get() { return &List; }
};
/// \brief A template argument list.
-class TemplateArgumentList {
+class TemplateArgumentList final
+ : private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> {
/// \brief The template argument list.
- ///
- /// The integer value will be non-zero to indicate that this
- /// template argument list does own the pointer.
- llvm::PointerIntPair<const TemplateArgument *, 1> Arguments;
+ const TemplateArgument *Arguments;
/// \brief The number of template arguments in this template
/// argument list.
@@ -161,9 +181,9 @@ class TemplateArgumentList {
TemplateArgumentList(const TemplateArgumentList &Other) = delete;
void operator=(const TemplateArgumentList &Other) = delete;
- TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs,
- bool Owned)
- : Arguments(Args, Owned), NumArguments(NumArgs) { }
+ // Constructs an instance with an internal Argument list, containing
+ // a copy of the Args array. (Called by CreateCopy)
+ TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs);
public:
/// \brief Type used to indicate that the template argument list itself is a
@@ -180,9 +200,9 @@ public:
///
/// The template argument list does not own the template arguments
/// provided.
- explicit TemplateArgumentList(OnStackType,
- const TemplateArgument *Args, unsigned NumArgs)
- : Arguments(Args, false), NumArguments(NumArgs) { }
+ explicit TemplateArgumentList(OnStackType, const TemplateArgument *Args,
+ unsigned NumArgs)
+ : Arguments(Args), NumArguments(NumArgs) {}
/// \brief Produces a shallow copy of the given template argument list.
///
@@ -191,7 +211,7 @@ public:
/// constructor, since this really really isn't safe to use that
/// way.
explicit TemplateArgumentList(const TemplateArgumentList *Other)
- : Arguments(Other->data(), false), NumArguments(Other->size()) { }
+ : Arguments(Other->data()), NumArguments(Other->size()) {}
/// \brief Retrieve the template argument at a given index.
const TemplateArgument &get(unsigned Idx) const {
@@ -212,9 +232,9 @@ public:
unsigned size() const { return NumArguments; }
/// \brief Retrieve a pointer to the template argument list.
- const TemplateArgument *data() const {
- return Arguments.getPointer();
- }
+ const TemplateArgument *data() const { return Arguments; }
+
+ friend TrailingObjects;
};
void *allocateDefaultArgStorageChain(const ASTContext &C);
@@ -426,17 +446,8 @@ public:
/// explicit instantiation declaration, or explicit instantiation
/// definition.
bool isExplicitInstantiationOrSpecialization() const {
- switch (getTemplateSpecializationKind()) {
- case TSK_ExplicitSpecialization:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- return true;
-
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- return false;
- }
- llvm_unreachable("bad template specialization kind");
+ return isTemplateExplicitInstantiationOrSpecialization(
+ getTemplateSpecializationKind());
}
/// \brief Set the template specialization kind.
@@ -542,56 +553,52 @@ public:
/// friend void foo<>(T);
/// };
/// \endcode
-class DependentFunctionTemplateSpecializationInfo {
- struct CA {
- /// The number of potential template candidates.
- unsigned NumTemplates;
+class DependentFunctionTemplateSpecializationInfo final
+ : private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo,
+ TemplateArgumentLoc,
+ FunctionTemplateDecl *> {
+ /// The number of potential template candidates.
+ unsigned NumTemplates;
- /// The number of template arguments.
- unsigned NumArgs;
- };
-
- union {
- // Force sizeof to be a multiple of sizeof(void*) so that the
- // trailing data is aligned.
- void *Aligner;
- struct CA d;
- };
+ /// The number of template arguments.
+ unsigned NumArgs;
/// The locations of the left and right angle brackets.
SourceRange AngleLocs;
- FunctionTemplateDecl * const *getTemplates() const {
- return reinterpret_cast<FunctionTemplateDecl*const*>(this+1);
+ size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
+ return NumArgs;
+ }
+ size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const {
+ return NumTemplates;
}
-public:
DependentFunctionTemplateSpecializationInfo(
const UnresolvedSetImpl &Templates,
const TemplateArgumentListInfo &TemplateArgs);
+public:
+ static DependentFunctionTemplateSpecializationInfo *
+ Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
+ const TemplateArgumentListInfo &TemplateArgs);
+
/// \brief Returns the number of function templates that this might
/// be a specialization of.
- unsigned getNumTemplates() const {
- return d.NumTemplates;
- }
+ unsigned getNumTemplates() const { return NumTemplates; }
/// \brief Returns the i'th template candidate.
FunctionTemplateDecl *getTemplate(unsigned I) const {
assert(I < getNumTemplates() && "template index out of range");
- return getTemplates()[I];
+ return getTrailingObjects<FunctionTemplateDecl *>()[I];
}
/// \brief Returns the explicit template arguments that were given.
const TemplateArgumentLoc *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgumentLoc*>(
- &getTemplates()[getNumTemplates()]);
+ return getTrailingObjects<TemplateArgumentLoc>();
}
/// \brief Returns the number of explicit template arguments that were given.
- unsigned getNumTemplateArgs() const {
- return d.NumArgs;
- }
+ unsigned getNumTemplateArgs() const { return NumArgs; }
/// \brief Returns the nth template argument.
const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
@@ -606,6 +613,8 @@ public:
SourceLocation getRAngleLoc() const {
return AngleLocs.getEnd();
}
+
+ friend TrailingObjects;
};
/// Declaration of a redeclarable template.
@@ -926,7 +935,7 @@ public:
return const_cast<FunctionTemplateDecl*>(this)->getMostRecentDecl();
}
- FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
+ FunctionTemplateDecl *getInstantiatedFromMemberTemplate() const {
return cast_or_null<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
@@ -1120,8 +1129,11 @@ public:
/// @code
/// template<int Size> class array { };
/// @endcode
-class NonTypeTemplateParmDecl
- : public DeclaratorDecl, protected TemplateParmPosition {
+class NonTypeTemplateParmDecl final
+ : public DeclaratorDecl,
+ protected TemplateParmPosition,
+ private llvm::TrailingObjects<NonTypeTemplateParmDecl,
+ std::pair<QualType, TypeSourceInfo *>> {
/// \brief The default template argument, if any, and whether or not
/// it was inherited.
typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage;
@@ -1141,6 +1153,11 @@ class NonTypeTemplateParmDecl
/// \brief The number of types in an expanded parameter pack.
unsigned NumExpandedTypes;
+ size_t numTrailingObjects(
+ OverloadToken<std::pair<QualType, TypeSourceInfo *>>) const {
+ return NumExpandedTypes;
+ }
+
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, unsigned D, unsigned P,
IdentifierInfo *Id, QualType T,
@@ -1159,6 +1176,7 @@ class NonTypeTemplateParmDecl
TypeSourceInfo **ExpandedTInfos);
friend class ASTDeclReader;
+ friend TrailingObjects;
public:
static NonTypeTemplateParmDecl *
@@ -1274,16 +1292,18 @@ public:
/// pack.
QualType getExpansionType(unsigned I) const {
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
- void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
- return QualType::getFromOpaquePtr(TypesAndInfos[2*I]);
+ auto TypesAndInfos =
+ getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
+ return TypesAndInfos[I].first;
}
/// \brief Retrieve a particular expansion type source info within an
/// expanded parameter pack.
TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const {
assert(I < NumExpandedTypes && "Out-of-range expansion type index");
- void * const *TypesAndInfos = reinterpret_cast<void * const*>(this + 1);
- return static_cast<TypeSourceInfo *>(TypesAndInfos[2*I+1]);
+ auto TypesAndInfos =
+ getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
+ return TypesAndInfos[I].second;
}
// Implement isa/cast/dyncast/etc.
@@ -1298,9 +1318,11 @@ public:
/// @endcode
/// A template template parameter is a TemplateDecl because it defines the
/// name of a template and the template parameters allowable for substitution.
-class TemplateTemplateParmDecl : public TemplateDecl,
- protected TemplateParmPosition
-{
+class TemplateTemplateParmDecl final
+ : public TemplateDecl,
+ protected TemplateParmPosition,
+ private llvm::TrailingObjects<TemplateTemplateParmDecl,
+ TemplateParameterList *> {
void anchor() override;
/// \brief The default template argument, if any.
@@ -1404,7 +1426,7 @@ public:
/// pack.
TemplateParameterList *getExpansionTemplateParameters(unsigned I) const {
assert(I < NumExpandedParams && "Out-of-range expansion type index");
- return reinterpret_cast<TemplateParameterList *const *>(this + 1)[I];
+ return getTrailingObjects<TemplateParameterList *>()[I];
}
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
@@ -1454,6 +1476,36 @@ public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
+ friend TrailingObjects;
+};
+
+/// \brief Represents the builtin template declaration which is used to
+/// implement __make_integer_seq. It serves no real purpose beyond existing as
+/// a place to hold template parameters.
+class BuiltinTemplateDecl : public TemplateDecl {
+ void anchor() override;
+
+ BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
+ DeclarationName Name, BuiltinTemplateKind BTK);
+
+ BuiltinTemplateKind BTK;
+
+public:
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == BuiltinTemplate; }
+
+ static BuiltinTemplateDecl *Create(const ASTContext &C, DeclContext *DC,
+ DeclarationName Name,
+ BuiltinTemplateKind BTK) {
+ return new (C, DC) BuiltinTemplateDecl(C, DC, Name, BTK);
+ }
+
+ SourceRange getSourceRange() const override LLVM_READONLY {
+ return SourceRange();
+ }
+
+ BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
};
/// \brief Represents a class template specialization, which refers to
@@ -1580,17 +1632,8 @@ public:
/// explicit instantiation declaration, or explicit instantiation
/// definition.
bool isExplicitInstantiationOrSpecialization() const {
- switch (getTemplateSpecializationKind()) {
- case TSK_ExplicitSpecialization:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- return true;
-
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- return false;
- }
- llvm_unreachable("bad template specialization kind");
+ return isTemplateExplicitInstantiationOrSpecialization(
+ getTemplateSpecializationKind());
}
void setSpecializationKind(TemplateSpecializationKind TSK) {
@@ -1819,8 +1862,8 @@ public:
/// template partial specialization \c Outer<T>::Inner<U*>. Given
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
- ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
- ClassTemplatePartialSpecializationDecl *First =
+ ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
+ const ClassTemplatePartialSpecializationDecl *First =
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
@@ -2000,7 +2043,7 @@ public:
return const_cast<ClassTemplateDecl*>(this)->getMostRecentDecl();
}
- ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
+ ClassTemplateDecl *getInstantiatedFromMemberTemplate() const {
return cast_or_null<ClassTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
@@ -2230,7 +2273,7 @@ public:
this)->getPreviousDecl());
}
- TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() {
+ TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() const {
return cast_or_null<TypeAliasTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
@@ -2435,17 +2478,8 @@ public:
/// explicit instantiation declaration, or explicit instantiation
/// definition.
bool isExplicitInstantiationOrSpecialization() const {
- switch (getTemplateSpecializationKind()) {
- case TSK_ExplicitSpecialization:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- return true;
-
- case TSK_Undeclared:
- case TSK_ImplicitInstantiation:
- return false;
- }
- llvm_unreachable("bad template specialization kind");
+ return isTemplateExplicitInstantiationOrSpecialization(
+ getTemplateSpecializationKind());
}
void setSpecializationKind(TemplateSpecializationKind TSK) {
@@ -2668,8 +2702,8 @@ public:
/// variable template partial specialization \c Outer<T>::Inner<U*>. Given
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
- VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
- VarTemplatePartialSpecializationDecl *First =
+ VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const {
+ const VarTemplatePartialSpecializationDecl *First =
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
@@ -2833,7 +2867,7 @@ public:
return const_cast<VarTemplateDecl *>(this)->getMostRecentDecl();
}
- VarTemplateDecl *getInstantiatedFromMemberTemplate() {
+ VarTemplateDecl *getInstantiatedFromMemberTemplate() const {
return cast_or_null<VarTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
}
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
index ad52873..aad7726 100644
--- a/include/clang/AST/EvaluatedExprVisitor.h
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -88,8 +88,8 @@ public:
void VisitLambdaExpr(PTR(LambdaExpr) LE) {
// Only visit the capture initializers, and not the body.
- for (LambdaExpr::capture_init_iterator I = LE->capture_init_begin(),
- E = LE->capture_init_end();
+ for (LambdaExpr::const_capture_init_iterator I = LE->capture_init_begin(),
+ E = LE->capture_init_end();
I != E; ++I)
if (*I)
this->Visit(*I);
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 2a5b4c0..f9f1995 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -23,6 +23,7 @@
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
@@ -61,7 +62,6 @@ struct SubobjectAdjustment {
MemberPointerAdjustment
} Kind;
-
struct DTB {
const CastExpr *BasePath;
const CXXRecordDecl *DerivedClass;
@@ -148,8 +148,6 @@ public:
/// \brief Set whether this expression is value-dependent or not.
void setValueDependent(bool VD) {
ExprBits.ValueDependent = VD;
- if (VD)
- ExprBits.InstantiationDependent = true;
}
/// isTypeDependent - Determines whether this expression is
@@ -168,8 +166,6 @@ public:
/// \brief Set whether this expression is type-dependent or not.
void setTypeDependent(bool TD) {
ExprBits.TypeDependent = TD;
- if (TD)
- ExprBits.InstantiationDependent = true;
}
/// \brief Whether this expression is instantiation-dependent, meaning that
@@ -458,6 +454,10 @@ public:
/// \brief Returns whether this expression refers to a vector element.
bool refersToVectorElement() const;
+ /// \brief Returns whether this expression refers to a global register
+ /// variable.
+ bool refersToGlobalRegisterVar() const;
+
/// \brief Returns whether this expression has a placeholder type.
bool hasPlaceholderType() const {
return getType()->isPlaceholderType();
@@ -529,10 +529,15 @@ public:
/// EvalStatus is a struct with detailed info about an evaluation in progress.
struct EvalStatus {
- /// HasSideEffects - Whether the evaluated expression has side effects.
+ /// \brief Whether the evaluated expression has side effects.
/// For example, (f() && 0) can be folded, but it still has side effects.
bool HasSideEffects;
+ /// \brief Whether the evaluation hit undefined behavior.
+ /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior.
+ /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB.
+ bool HasUndefinedBehavior;
+
/// Diag - If this is non-null, it will be filled in with a stack of notes
/// indicating why evaluation failed (or why it failed to produce a constant
/// expression).
@@ -542,7 +547,8 @@ public:
/// expression *is* a constant expression, no notes will be produced.
SmallVectorImpl<PartialDiagnosticAt> *Diag;
- EvalStatus() : HasSideEffects(false), Diag(nullptr) {}
+ EvalStatus()
+ : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {}
// hasSideEffects - Return true if the evaluated expression has
// side effects.
@@ -575,7 +581,12 @@ public:
/// side-effects.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
- enum SideEffectsKind { SE_NoSideEffects, SE_AllowSideEffects };
+ enum SideEffectsKind {
+ SE_NoSideEffects, ///< Strictly evaluate the expression.
+ SE_AllowUndefinedBehavior, ///< Allow UB that we can give a value, but not
+ ///< arbitrary unmodeled side effects.
+ SE_AllowSideEffects ///< Allow any unmodeled side effect.
+ };
/// EvaluateAsInt - Return true if this is a constant which we can fold and
/// convert to an integer, using any crazy technique that we want to.
@@ -584,7 +595,8 @@ public:
/// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
/// constant folded without side-effects, but discard the result.
- bool isEvaluatable(const ASTContext &Ctx) const;
+ bool isEvaluatable(const ASTContext &Ctx,
+ SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
/// HasSideEffects - This routine returns true for all those expressions
/// which have any effect other than producing a value. Example is a function
@@ -628,6 +640,16 @@ public:
const FunctionDecl *Callee,
ArrayRef<const Expr*> Args) const;
+ /// \brief If the current Expr is a pointer, this will try to statically
+ /// determine the number of bytes available where the pointer is pointing.
+ /// Returns true if all of the above holds and we were able to figure out the
+ /// size, false otherwise.
+ ///
+ /// \param Type - How to evaluate the size of the Expr, as defined by the
+ /// "type" parameter of __builtin_object_size
+ bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx,
+ unsigned Type) const;
+
/// \brief Enumeration used to describe the kind of Null pointer constant
/// returned from \c isNullPointerConstant().
enum NullPointerConstantKind {
@@ -806,7 +828,6 @@ public:
}
};
-
//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
@@ -856,7 +877,9 @@ public:
return Loc;
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
/// The source expression of an opaque value expression is the
/// expression which originally generated the value. This is
@@ -896,7 +919,11 @@ public:
/// DeclRefExprBits.RefersToEnclosingVariableOrCapture
/// Specifies when this declaration reference expression (validly)
/// refers to an enclosed local or a captured variable.
-class DeclRefExpr : public Expr {
+class DeclRefExpr final
+ : public Expr,
+ private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc,
+ NamedDecl *, ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
/// \brief The declaration that we are referencing.
ValueDecl *D;
@@ -907,36 +934,22 @@ class DeclRefExpr : public Expr {
/// embedded in D.
DeclarationNameLoc DNLoc;
- /// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
- NestedNameSpecifierLoc &getInternalQualifierLoc() {
- assert(hasQualifier());
- return *reinterpret_cast<NestedNameSpecifierLoc *>(this + 1);
+ size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
+ return hasQualifier() ? 1 : 0;
+ }
+
+ size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
+ return hasFoundDecl() ? 1 : 0;
}
- /// \brief Helper to retrieve the optional NestedNameSpecifierLoc.
- const NestedNameSpecifierLoc &getInternalQualifierLoc() const {
- return const_cast<DeclRefExpr *>(this)->getInternalQualifierLoc();
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return hasTemplateKWAndArgsInfo() ? 1 : 0;
}
/// \brief Test whether there is a distinct FoundDecl attached to the end of
/// this DRE.
bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
- /// \brief Helper to retrieve the optional NamedDecl through which this
- /// reference occurred.
- NamedDecl *&getInternalFoundDecl() {
- assert(hasFoundDecl());
- if (hasQualifier())
- return *reinterpret_cast<NamedDecl **>(&getInternalQualifierLoc() + 1);
- return *reinterpret_cast<NamedDecl **>(this + 1);
- }
-
- /// \brief Helper to retrieve the optional NamedDecl through which this
- /// reference occurred.
- NamedDecl *getInternalFoundDecl() const {
- return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl();
- }
-
DeclRefExpr(const ASTContext &Ctx,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
@@ -1009,21 +1022,17 @@ public:
bool hasQualifier() const { return DeclRefExprBits.HasQualifier; }
/// \brief If the name was qualified, retrieves the nested-name-specifier
- /// that precedes the name. Otherwise, returns NULL.
- NestedNameSpecifier *getQualifier() const {
- if (!hasQualifier())
- return nullptr;
-
- return getInternalQualifierLoc().getNestedNameSpecifier();
- }
-
- /// \brief If the name was qualified, retrieves the nested-name-specifier
/// that precedes the name, with source-location information.
NestedNameSpecifierLoc getQualifierLoc() const {
if (!hasQualifier())
return NestedNameSpecifierLoc();
+ return *getTrailingObjects<NestedNameSpecifierLoc>();
+ }
- return getInternalQualifierLoc();
+ /// \brief If the name was qualified, retrieves the nested-name-specifier
+ /// that precedes the name. Otherwise, returns NULL.
+ NestedNameSpecifier *getQualifier() const {
+ return getQualifierLoc().getNestedNameSpecifier();
}
/// \brief Get the NamedDecl through which this reference occurred.
@@ -1031,60 +1040,40 @@ public:
/// This Decl may be different from the ValueDecl actually referred to in the
/// presence of using declarations, etc. It always returns non-NULL, and may
/// simple return the ValueDecl when appropriate.
+
NamedDecl *getFoundDecl() {
- return hasFoundDecl() ? getInternalFoundDecl() : D;
+ return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
}
/// \brief Get the NamedDecl through which this reference occurred.
/// See non-const variant.
const NamedDecl *getFoundDecl() const {
- return hasFoundDecl() ? getInternalFoundDecl() : D;
+ return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D;
}
bool hasTemplateKWAndArgsInfo() const {
return DeclRefExprBits.HasTemplateKWAndArgsInfo;
}
- /// \brief Return the optional template keyword and arguments info.
- ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
- if (!hasTemplateKWAndArgsInfo())
- return nullptr;
-
- if (hasFoundDecl())
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
- &getInternalFoundDecl() + 1);
-
- if (hasQualifier())
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
- &getInternalQualifierLoc() + 1);
-
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);
- }
-
- /// \brief Return the optional template keyword and arguments info.
- const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
- return const_cast<DeclRefExpr*>(this)->getTemplateKWAndArgsInfo();
- }
-
/// \brief Retrieve the location of the template keyword preceding
/// 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;
}
/// \brief Determines whether the name in this declaration reference
@@ -1095,32 +1084,12 @@ public:
/// explicit template argument list.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name.
- ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
- assert(hasExplicitTemplateArgs());
- return *getTemplateKWAndArgsInfo();
- }
-
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name.
- const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
- return const_cast<DeclRefExpr *>(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 {
if (hasExplicitTemplateArgs())
- getExplicitTemplateArgs().copyInto(List);
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
}
/// \brief Retrieve the template arguments provided as part of this
@@ -1129,7 +1098,7 @@ public:
if (!hasExplicitTemplateArgs())
return nullptr;
- return getExplicitTemplateArgs().getTemplateArgs();
+ return getTrailingObjects<TemplateArgumentLoc>();
}
/// \brief Retrieve the number of template arguments provided as part of this
@@ -1138,7 +1107,7 @@ public:
if (!hasExplicitTemplateArgs())
return 0;
- return getExplicitTemplateArgs().NumTemplateArgs;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
}
/// \brief Returns true if this expression refers to a function that
@@ -1164,8 +1133,11 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ friend TrailingObjects;
friend class ASTStmtReader;
friend class ASTStmtWriter;
};
@@ -1310,7 +1282,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
class CharacterLiteral : public Expr {
@@ -1357,7 +1331,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
class FloatingLiteral : public Expr, private APFloatStorage {
@@ -1419,7 +1395,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ImaginaryLiteral - We support imaginary integer and floating point literals,
@@ -1596,13 +1574,15 @@ public:
/// and can have escape sequences in them in addition to the usual trigraph
/// and escaped newline business. This routine handles this complexity.
///
- SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
- const LangOptions &Features,
- const TargetInfo &Target) const;
+ SourceLocation
+ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
+ const LangOptions &Features, const TargetInfo &Target,
+ unsigned *StartToken = nullptr,
+ unsigned *StartTokenByteOffset = nullptr) const;
typedef const SourceLocation *tokloc_iterator;
tokloc_iterator tokloc_begin() const { return TokLocs; }
- tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; }
+ tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; }
SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; }
SourceLocation getLocEnd() const LLVM_READONLY {
@@ -1614,7 +1594,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ParenExpr - This represents a parethesized expression, e.g. "(1)". This
@@ -1658,7 +1640,6 @@ public:
child_range children() { return child_range(&Val, &Val+1); }
};
-
/// UnaryOperator - This represents the unary-expression's (except sizeof and
/// alignof), the postinc/postdec operators from postfix-expression, and various
/// extensions.
@@ -1768,6 +1749,99 @@ public:
child_range children() { return child_range(&Val, &Val+1); }
};
+/// Helper class for OffsetOfExpr.
+
+// __builtin_offsetof(type, identifier(.identifier|[expr])*)
+class OffsetOfNode {
+public:
+ /// \brief The kind of offsetof node we have.
+ enum Kind {
+ /// \brief An index into an array.
+ Array = 0x00,
+ /// \brief A field.
+ Field = 0x01,
+ /// \brief A field in a dependent type, known only by its name.
+ Identifier = 0x02,
+ /// \brief An implicit indirection through a C++ base class, when the
+ /// field found is in a base class.
+ Base = 0x03
+ };
+
+private:
+ enum { MaskBits = 2, Mask = 0x03 };
+
+ /// \brief The source range that covers this part of the designator.
+ SourceRange Range;
+
+ /// \brief The data describing the designator, which comes in three
+ /// different forms, depending on the lower two bits.
+ /// - An unsigned index into the array of Expr*'s stored after this node
+ /// in memory, for [constant-expression] designators.
+ /// - A FieldDecl*, for references to a known field.
+ /// - An IdentifierInfo*, for references to a field with a given name
+ /// when the class type is dependent.
+ /// - A CXXBaseSpecifier*, for references that look at a field in a
+ /// base class.
+ uintptr_t Data;
+
+public:
+ /// \brief Create an offsetof node that refers to an array element.
+ OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
+ SourceLocation RBracketLoc)
+ : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {}
+
+ /// \brief Create an offsetof node that refers to a field.
+ OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc)
+ : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
+ Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {}
+
+ /// \brief Create an offsetof node that refers to an identifier.
+ OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
+ SourceLocation NameLoc)
+ : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc),
+ Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {}
+
+ /// \brief Create an offsetof node that refers into a C++ base class.
+ explicit OffsetOfNode(const CXXBaseSpecifier *Base)
+ : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
+
+ /// \brief Determine what kind of offsetof node this is.
+ Kind getKind() const { return static_cast<Kind>(Data & Mask); }
+
+ /// \brief For an array element node, returns the index into the array
+ /// of expressions.
+ unsigned getArrayExprIndex() const {
+ assert(getKind() == Array);
+ return Data >> 2;
+ }
+
+ /// \brief For a field offsetof node, returns the field.
+ FieldDecl *getField() const {
+ assert(getKind() == Field);
+ return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
+ }
+
+ /// \brief For a field or identifier offsetof node, returns the name of
+ /// the field.
+ IdentifierInfo *getFieldName() const;
+
+ /// \brief For a base class node, returns the base specifier.
+ CXXBaseSpecifier *getBase() const {
+ assert(getKind() == Base);
+ return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
+ }
+
+ /// \brief Retrieve the source range that covers this offsetof node.
+ ///
+ /// For an array element node, the source range contains the locations of
+ /// the square brackets. For a field or identifier node, the source range
+ /// contains the location of the period (if there is one) and the
+ /// identifier.
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
+};
+
/// OffsetOfExpr - [C99 7.17] - This represents an expression of the form
/// offsetof(record-type, member-designator). For example, given:
/// @code
@@ -1782,104 +1856,9 @@ public:
/// @endcode
/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d).
-class OffsetOfExpr : public Expr {
-public:
- // __builtin_offsetof(type, identifier(.identifier|[expr])*)
- class OffsetOfNode {
- public:
- /// \brief The kind of offsetof node we have.
- enum Kind {
- /// \brief An index into an array.
- Array = 0x00,
- /// \brief A field.
- Field = 0x01,
- /// \brief A field in a dependent type, known only by its name.
- Identifier = 0x02,
- /// \brief An implicit indirection through a C++ base class, when the
- /// field found is in a base class.
- Base = 0x03
- };
-
- private:
- enum { MaskBits = 2, Mask = 0x03 };
-
- /// \brief The source range that covers this part of the designator.
- SourceRange Range;
-
- /// \brief The data describing the designator, which comes in three
- /// different forms, depending on the lower two bits.
- /// - An unsigned index into the array of Expr*'s stored after this node
- /// in memory, for [constant-expression] designators.
- /// - A FieldDecl*, for references to a known field.
- /// - An IdentifierInfo*, for references to a field with a given name
- /// when the class type is dependent.
- /// - A CXXBaseSpecifier*, for references that look at a field in a
- /// base class.
- uintptr_t Data;
-
- public:
- /// \brief Create an offsetof node that refers to an array element.
- OffsetOfNode(SourceLocation LBracketLoc, unsigned Index,
- SourceLocation RBracketLoc)
- : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { }
-
- /// \brief Create an offsetof node that refers to a field.
- OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field,
- SourceLocation NameLoc)
- : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
- Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { }
-
- /// \brief Create an offsetof node that refers to an identifier.
- OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name,
- SourceLocation NameLoc)
- : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc),
- Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { }
-
- /// \brief Create an offsetof node that refers into a C++ base class.
- explicit OffsetOfNode(const CXXBaseSpecifier *Base)
- : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {}
-
- /// \brief Determine what kind of offsetof node this is.
- Kind getKind() const {
- return static_cast<Kind>(Data & Mask);
- }
-
- /// \brief For an array element node, returns the index into the array
- /// of expressions.
- unsigned getArrayExprIndex() const {
- assert(getKind() == Array);
- return Data >> 2;
- }
-
- /// \brief For a field offsetof node, returns the field.
- FieldDecl *getField() const {
- assert(getKind() == Field);
- return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask);
- }
-
- /// \brief For a field or identifier offsetof node, returns the name of
- /// the field.
- IdentifierInfo *getFieldName() const;
-
- /// \brief For a base class node, returns the base specifier.
- CXXBaseSpecifier *getBase() const {
- assert(getKind() == Base);
- return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask);
- }
-
- /// \brief Retrieve the source range that covers this offsetof node.
- ///
- /// For an array element node, the source range contains the locations of
- /// the square brackets. For a field or identifier node, the source range
- /// contains the location of the period (if there is one) and the
- /// identifier.
- SourceRange getSourceRange() const LLVM_READONLY { return Range; }
- SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
- };
-
-private:
-
+class OffsetOfExpr final
+ : public Expr,
+ private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> {
SourceLocation OperatorLoc, RParenLoc;
// Base type;
TypeSourceInfo *TSInfo;
@@ -1888,6 +1867,10 @@ private:
// Number of sub-expressions (i.e. array subscript expressions).
unsigned NumExprs;
+ size_t numTrailingObjects(OverloadToken<OffsetOfNode>) const {
+ return NumComps;
+ }
+
OffsetOfExpr(const ASTContext &C, QualType type,
SourceLocation OperatorLoc, TypeSourceInfo *tsi,
ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs,
@@ -1924,12 +1907,12 @@ public:
const OffsetOfNode &getComponent(unsigned Idx) const {
assert(Idx < NumComps && "Subscript out of range");
- return reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx];
+ return getTrailingObjects<OffsetOfNode>()[Idx];
}
void setComponent(unsigned Idx, OffsetOfNode ON) {
assert(Idx < NumComps && "Subscript out of range");
- reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON;
+ getTrailingObjects<OffsetOfNode>()[Idx] = ON;
}
unsigned getNumComponents() const {
@@ -1938,17 +1921,17 @@ public:
Expr* getIndexExpr(unsigned Idx) {
assert(Idx < NumExprs && "Subscript out of range");
- return reinterpret_cast<Expr **>(
- reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx];
+ return getTrailingObjects<Expr *>()[Idx];
}
+
const Expr *getIndexExpr(unsigned Idx) const {
- return const_cast<OffsetOfExpr*>(this)->getIndexExpr(Idx);
+ assert(Idx < NumExprs && "Subscript out of range");
+ return getTrailingObjects<Expr *>()[Idx];
}
void setIndexExpr(unsigned Idx, Expr* E) {
assert(Idx < NumComps && "Subscript out of range");
- reinterpret_cast<Expr **>(
- reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E;
+ getTrailingObjects<Expr *>()[Idx] = E;
}
unsigned getNumExpressions() const {
@@ -1964,11 +1947,10 @@ public:
// Iterators
child_range children() {
- Stmt **begin =
- reinterpret_cast<Stmt**>(reinterpret_cast<OffsetOfNode*>(this + 1)
- + NumComps);
+ Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
return child_range(begin, begin + NumExprs);
}
+ friend TrailingObjects;
};
/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated)
@@ -2142,7 +2124,6 @@ public:
}
};
-
/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
/// while its subclasses may represent alternative syntax that (semantically)
@@ -2298,20 +2279,24 @@ public:
}
};
+/// Extra data stored in some MemberExpr objects.
+struct MemberExprNameQualifier {
+ /// \brief The nested-name-specifier that qualifies the name, including
+ /// source-location information.
+ NestedNameSpecifierLoc QualifierLoc;
+
+ /// \brief The DeclAccessPair through which the MemberDecl was found due to
+ /// name qualifiers.
+ DeclAccessPair FoundDecl;
+};
+
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
-class MemberExpr : public Expr {
- /// Extra data stored in some member expressions.
- struct MemberNameQualifier {
- /// \brief The nested-name-specifier that qualifies the name, including
- /// source-location information.
- NestedNameSpecifierLoc QualifierLoc;
-
- /// \brief The DeclAccessPair through which the MemberDecl was found due to
- /// name qualifiers.
- DeclAccessPair FoundDecl;
- };
-
+class MemberExpr final
+ : public Expr,
+ private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc> {
/// Base - the expression for the base pointer or structure references. In
/// X.F, this is "X".
Stmt *Base;
@@ -2335,7 +2320,7 @@ class MemberExpr : public Expr {
/// \brief True if this member expression used a nested-name-specifier to
/// refer to the member, e.g., "x->Base::f", or found its member via a using
- /// declaration. When true, a MemberNameQualifier
+ /// declaration. When true, a MemberExprNameQualifier
/// structure is allocated immediately after the MemberExpr.
bool HasQualifierOrFoundDecl : 1;
@@ -2343,24 +2328,19 @@ class MemberExpr : public Expr {
/// and/or a template argument list explicitly, e.g., x->f<int>,
/// x->template f, x->template f<int>.
/// When true, an ASTTemplateKWAndArgsInfo structure and its
- /// TemplateArguments (if any) are allocated immediately after
- /// the MemberExpr or, if the member expression also has a qualifier,
- /// after the MemberNameQualifier structure.
+ /// TemplateArguments (if any) are present.
bool HasTemplateKWAndArgsInfo : 1;
/// \brief True if this member expression refers to a method that
/// was resolved from an overloaded set having size greater than 1.
bool HadMultipleCandidates : 1;
- /// \brief Retrieve the qualifier that preceded the member name, if any.
- MemberNameQualifier *getMemberQualifier() {
- assert(HasQualifierOrFoundDecl);
- return reinterpret_cast<MemberNameQualifier *> (this + 1);
+ size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const {
+ return HasQualifierOrFoundDecl ? 1 : 0;
}
- /// \brief Retrieve the qualifier that preceded the member name, if any.
- const MemberNameQualifier *getMemberQualifier() const {
- return const_cast<MemberExpr *>(this)->getMemberQualifier();
+ size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
+ return HasTemplateKWAndArgsInfo ? 1 : 0;
}
public:
@@ -2416,7 +2396,7 @@ public:
if (!HasQualifierOrFoundDecl)
return DeclAccessPair::make(getMemberDecl(),
getMemberDecl()->getAccess());
- return getMemberQualifier()->FoundDecl;
+ return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl;
}
/// \brief Determines whether this member expression actually had
@@ -2425,61 +2405,41 @@ public:
bool hasQualifier() const { return getQualifier() != nullptr; }
/// \brief If the member name was qualified, retrieves the
- /// nested-name-specifier that precedes the member name. Otherwise, returns
- /// NULL.
- NestedNameSpecifier *getQualifier() const {
- if (!HasQualifierOrFoundDecl)
- return nullptr;
-
- return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier();
- }
-
- /// \brief If the member name was qualified, retrieves the
/// nested-name-specifier that precedes the member name, with source-location
/// information.
NestedNameSpecifierLoc getQualifierLoc() const {
- if (!hasQualifier())
- return NestedNameSpecifierLoc();
-
- return getMemberQualifier()->QualifierLoc;
- }
-
- /// \brief Return the optional template keyword and arguments info.
- ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() {
- if (!HasTemplateKWAndArgsInfo)
- return nullptr;
-
if (!HasQualifierOrFoundDecl)
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1);
+ return NestedNameSpecifierLoc();
- return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(
- getMemberQualifier() + 1);
+ return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc;
}
- /// \brief Return the optional template keyword and arguments info.
- const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const {
- return const_cast<MemberExpr*>(this)->getTemplateKWAndArgsInfo();
+ /// \brief If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name. Otherwise, returns
+ /// NULL.
+ NestedNameSpecifier *getQualifier() const {
+ return getQualifierLoc().getNestedNameSpecifier();
}
/// \brief Retrieve the location of the template keyword preceding
/// the 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.
@@ -2493,30 +2453,8 @@ public:
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
if (hasExplicitTemplateArgs())
- getExplicitTemplateArgs().copyInto(List);
- }
-
- /// \brief Retrieve the explicit template argument list that
- /// follow the member template name. This must only be called on an
- /// expression with explicit template arguments.
- ASTTemplateArgumentListInfo &getExplicitTemplateArgs() {
- assert(hasExplicitTemplateArgs());
- return *getTemplateKWAndArgsInfo();
- }
-
- /// \brief Retrieve the explicit template argument list that
- /// followed the member template name. This must only be called on
- /// an expression with explicit template arguments.
- const ASTTemplateArgumentListInfo &getExplicitTemplateArgs() const {
- return const_cast<MemberExpr *>(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();
+ getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto(
+ getTrailingObjects<TemplateArgumentLoc>(), List);
}
/// \brief Retrieve the template arguments provided as part of this
@@ -2525,7 +2463,7 @@ public:
if (!hasExplicitTemplateArgs())
return nullptr;
- return getExplicitTemplateArgs().getTemplateArgs();
+ return getTrailingObjects<TemplateArgumentLoc>();
}
/// \brief Retrieve the number of template arguments provided as part of this
@@ -2534,7 +2472,7 @@ public:
if (!hasExplicitTemplateArgs())
return 0;
- return getExplicitTemplateArgs().NumTemplateArgs;
+ return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs;
}
/// \brief Retrieve the member declaration name info.
@@ -2575,6 +2513,14 @@ public:
HadMultipleCandidates = V;
}
+ /// \brief Returns true if virtual dispatch is performed.
+ /// If the member access is fully qualified, (i.e. X::f()), virtual
+ /// dispatching is not performed. In -fapple-kext mode qualified
+ /// calls to virtual method will still go through the vtable.
+ bool performsVirtualDispatch(const LangOptions &LO) const {
+ return LO.AppleKext || !hasQualifier();
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == MemberExprClass;
}
@@ -2582,6 +2528,7 @@ public:
// Iterators
child_range children() { return child_range(&Base, &Base+1); }
+ friend TrailingObjects;
friend class ASTReader;
friend class ASTStmtWriter;
};
@@ -2731,8 +2678,6 @@ public:
path_const_iterator path_begin() const { return path_buffer(); }
path_const_iterator path_end() const { return path_buffer() + path_size(); }
- void setCastPath(const CXXCastPath &Path);
-
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCastExprConstant &&
T->getStmtClass() <= lastCastExprConstant;
@@ -2762,7 +2707,9 @@ public:
/// // to an xvalue of type Base
/// }
/// @endcode
-class ImplicitCastExpr : public CastExpr {
+class ImplicitCastExpr final
+ : public CastExpr,
+ private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> {
private:
ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
unsigned BasePathLength, ExprValueKind VK)
@@ -2798,6 +2745,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitCastExprClass;
}
+
+ friend TrailingObjects;
+ friend class CastExpr;
};
inline Expr *Expr::IgnoreImpCasts() {
@@ -2857,7 +2807,9 @@ public:
/// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style
/// cast in C++ (C++ [expr.cast]), which uses the syntax
/// (Type)expr. For example: @c (int)f.
-class CStyleCastExpr : public ExplicitCastExpr {
+class CStyleCastExpr final
+ : public ExplicitCastExpr,
+ private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
@@ -2895,6 +2847,9 @@ public:
static bool classof(const Stmt *T) {
return T->getStmtClass() == CStyleCastExprClass;
}
+
+ friend TrailingObjects;
+ friend class CastExpr;
};
/// \brief A builtin binary operation expression such as "x + y" or "x <= y".
@@ -2989,7 +2944,10 @@ public:
/// predicates to categorize the respective opcodes.
bool isPtrMemOp() const { return Opc == BO_PtrMemD || Opc == BO_PtrMemI; }
- bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; }
+ static bool isMultiplicativeOp(Opcode Opc) {
+ return Opc >= BO_Mul && Opc <= BO_Rem;
+ }
+ bool isMultiplicativeOp() const { return isMultiplicativeOp(getOpcode()); }
static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; }
bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); }
static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; }
@@ -3384,7 +3342,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
@@ -3429,7 +3389,6 @@ public:
child_range children() { return child_range(&SubStmt, &SubStmt+1); }
};
-
/// ShuffleVectorExpr - clang-specific builtin-in function
/// __builtin_shufflevector.
/// This AST node represents a operator that does a constant
@@ -3663,36 +3622,40 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
-/// VAArgExpr, used for the builtin function __builtin_va_arg.
+/// Represents a call to the builtin function \c __builtin_va_arg.
class VAArgExpr : public Expr {
Stmt *Val;
- TypeSourceInfo *TInfo;
+ llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfo;
SourceLocation BuiltinLoc, RParenLoc;
public:
- VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo,
- SourceLocation RPLoc, QualType t)
- : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary,
- t->isDependentType(), false,
- (TInfo->getType()->isInstantiationDependentType() ||
- e->isInstantiationDependent()),
- (TInfo->getType()->containsUnexpandedParameterPack() ||
- e->containsUnexpandedParameterPack())),
- Val(e), TInfo(TInfo),
- BuiltinLoc(BLoc),
- RParenLoc(RPLoc) { }
-
- /// \brief Create an empty __builtin_va_arg expression.
- explicit VAArgExpr(EmptyShell Empty) : Expr(VAArgExprClass, Empty) { }
+ VAArgExpr(SourceLocation BLoc, Expr *e, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc, QualType t, bool IsMS)
+ : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, t->isDependentType(),
+ false, (TInfo->getType()->isInstantiationDependentType() ||
+ e->isInstantiationDependent()),
+ (TInfo->getType()->containsUnexpandedParameterPack() ||
+ e->containsUnexpandedParameterPack())),
+ Val(e), TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) {}
+
+ /// Create an empty __builtin_va_arg expression.
+ explicit VAArgExpr(EmptyShell Empty)
+ : Expr(VAArgExprClass, Empty), Val(nullptr), TInfo(nullptr, false) {}
const Expr *getSubExpr() const { return cast<Expr>(Val); }
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
- TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; }
- void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; }
+ /// Returns whether this is really a Win64 ABI va_arg expression.
+ bool isMicrosoftABI() const { return TInfo.getInt(); }
+ void setIsMicrosoftABI(bool IsMS) { TInfo.setInt(IsMS); }
+
+ TypeSourceInfo *getWrittenTypeInfo() const { return TInfo.getPointer(); }
+ void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo.setPointer(TI); }
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
@@ -3791,6 +3754,10 @@ public:
/// \brief Retrieve the set of initializers.
Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); }
+ ArrayRef<Expr *> inits() {
+ return llvm::makeArrayRef(getInits(), getNumInits());
+ }
+
const Expr *getInit(unsigned Init) const {
assert(Init < getNumInits() && "Initializer access out of range!");
return cast_or_null<Expr>(InitExprs[Init]);
@@ -3916,7 +3883,8 @@ public:
// Iterators
child_range children() {
// FIXME: This does not include the array filler expression.
- if (InitExprs.empty()) return child_range();
+ if (InitExprs.empty())
+ return child_range(child_iterator(), child_iterator());
return child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size());
}
@@ -4293,7 +4261,9 @@ public:
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
// In cases like:
@@ -4367,10 +4337,11 @@ public:
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
-
class ParenListExpr : public Expr {
Stmt **Exprs;
unsigned NumExprs;
@@ -4397,6 +4368,10 @@ public:
Expr **getExprs() { return reinterpret_cast<Expr **>(Exprs); }
+ ArrayRef<Expr *> exprs() {
+ return llvm::makeArrayRef(getExprs(), getNumExprs());
+ }
+
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -4416,7 +4391,6 @@ public:
friend class ASTStmtWriter;
};
-
/// \brief Represents a C11 generic selection.
///
/// A generic selection (C11 6.5.1.1) contains an unevaluated controlling
@@ -4532,7 +4506,6 @@ public:
// Clang Extensions
//===----------------------------------------------------------------------===//
-
/// ExtVectorElementExpr - This represents access to specific elements of a
/// vector, and may occur on the left hand side or right hand side. For example
/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector.
@@ -4577,7 +4550,7 @@ public:
/// getEncodedElementAccess - Encode the elements accessed into an llvm
/// aggregate Constant of ConstantInt(s).
- void getEncodedElementAccess(SmallVectorImpl<unsigned> &Elts) const;
+ void getEncodedElementAccess(SmallVectorImpl<uint32_t> &Elts) const;
SourceLocation getLocStart() const LLVM_READONLY {
return getBase()->getLocStart();
@@ -4596,7 +4569,6 @@ public:
child_range children() { return child_range(&Base, &Base+1); }
};
-
/// BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
/// ^{ statement-body } or ^(int arg1, float arg2){ statement-body }
class BlockExpr : public Expr {
@@ -4633,7 +4605,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2]
@@ -4789,6 +4763,14 @@ public:
const_semantics_iterator semantics_end() const {
return getSubExprsBuffer() + getNumSubExprs();
}
+
+ llvm::iterator_range<semantics_iterator> semantics() {
+ return llvm::make_range(semantics_begin(), semantics_end());
+ }
+ llvm::iterator_range<const_semantics_iterator> semantics() const {
+ return llvm::make_range(semantics_begin(), semantics_end());
+ }
+
Expr *getSemanticExpr(unsigned index) {
assert(index + 1 < getNumSubExprs());
return getSubExprsBuffer()[index + 1];
@@ -4935,10 +4917,17 @@ public:
assert(T->isDependentType() && "TypoExpr given a non-dependent type");
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == TypoExprClass;
+ }
+
};
-} // end namespace clang
+} // end namespace clang
-#endif
+#endif // LLVM_CLANG_AST_EXPR_H
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
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index f28e519..38fa718 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -82,7 +82,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ObjCBoxedExpr - used for generalized expression boxing.
@@ -341,6 +343,8 @@ public:
child_range children() {
// Note: we're taking advantage of the layout of the KeyValuePair struct
// here. If that struct changes, this code will need to change as well.
+ static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2,
+ "KeyValuePair is expected size");
return child_range(reinterpret_cast<Stmt **>(this + 1),
reinterpret_cast<Stmt **>(this + 1) + NumElements * 2);
}
@@ -389,7 +393,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ObjCSelectorExpr used for \@selector in Objective-C.
@@ -424,7 +430,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// ObjCProtocolExpr used for protocol expression in Objective-C.
@@ -464,7 +472,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;
@@ -713,7 +723,7 @@ public:
Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack!
return child_range(begin, begin+1);
}
- return child_range();
+ return child_range(child_iterator(), child_iterator());
}
private:
@@ -1350,6 +1360,14 @@ public:
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
+ llvm::iterator_range<arg_iterator> arguments() {
+ return llvm::make_range(arg_begin(), arg_end());
+ }
+
+ llvm::iterator_range<const_arg_iterator> arguments() const {
+ return llvm::make_range(arg_begin(), arg_end());
+ }
+
arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); }
arg_iterator arg_end() {
return reinterpret_cast<Stmt **>(getArgs() + NumArgs);
@@ -1503,11 +1521,15 @@ public:
/// \code
/// NSString *str = (__bridge_transfer NSString *)CFCreateString();
/// \endcode
-class ObjCBridgedCastExpr : public ExplicitCastExpr {
+class ObjCBridgedCastExpr final
+ : public ExplicitCastExpr,
+ private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> {
SourceLocation LParenLoc;
SourceLocation BridgeKeywordLoc;
unsigned Kind : 2;
-
+
+ friend TrailingObjects;
+ friend class CastExpr;
friend class ASTStmtReader;
friend class ASTStmtWriter;
diff --git a/include/clang/AST/ExprOpenMP.h b/include/clang/AST/ExprOpenMP.h
new file mode 100644
index 0000000..2d71a3a
--- /dev/null
+++ b/include/clang/AST/ExprOpenMP.h
@@ -0,0 +1,129 @@
+//===--- ExprOpenMP.h - Classes for representing expressions ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Expr interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_EXPROPENMP_H
+#define LLVM_CLANG_AST_EXPROPENMP_H
+
+#include "clang/AST/Expr.h"
+
+namespace clang {
+/// \brief OpenMP 4.0 [2.4, Array Sections].
+/// To specify an array section in an OpenMP construct, array subscript
+/// expressions are extended with the following syntax:
+/// \code
+/// [ lower-bound : length ]
+/// [ lower-bound : ]
+/// [ : length ]
+/// [ : ]
+/// \endcode
+/// The array section must be a subset of the original array.
+/// Array sections are allowed on multidimensional arrays. Base language array
+/// subscript expressions can be used to specify length-one dimensions of
+/// multidimensional array sections.
+/// The lower-bound and length are integral type expressions. When evaluated
+/// they represent a set of integer values as follows:
+/// \code
+/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length -
+/// 1 }
+/// \endcode
+/// The lower-bound and length must evaluate to non-negative integers.
+/// When the size of the array dimension is not known, the length must be
+/// specified explicitly.
+/// When the length is absent, it defaults to the size of the array dimension
+/// minus the lower-bound.
+/// When the lower-bound is absent it defaults to 0.
+class OMPArraySectionExpr : public Expr {
+ enum { BASE, LOWER_BOUND, LENGTH, END_EXPR };
+ Stmt *SubExprs[END_EXPR];
+ SourceLocation ColonLoc;
+ SourceLocation RBracketLoc;
+
+public:
+ OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
+ ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation ColonLoc, SourceLocation RBracketLoc)
+ : Expr(
+ OMPArraySectionExprClass, Type, VK, OK,
+ Base->isTypeDependent() ||
+ (LowerBound && LowerBound->isTypeDependent()) ||
+ (Length && Length->isTypeDependent()),
+ Base->isValueDependent() ||
+ (LowerBound && LowerBound->isValueDependent()) ||
+ (Length && Length->isValueDependent()),
+ Base->isInstantiationDependent() ||
+ (LowerBound && LowerBound->isInstantiationDependent()) ||
+ (Length && Length->isInstantiationDependent()),
+ Base->containsUnexpandedParameterPack() ||
+ (LowerBound && LowerBound->containsUnexpandedParameterPack()) ||
+ (Length && Length->containsUnexpandedParameterPack())),
+ ColonLoc(ColonLoc), RBracketLoc(RBracketLoc) {
+ SubExprs[BASE] = Base;
+ SubExprs[LOWER_BOUND] = LowerBound;
+ SubExprs[LENGTH] = Length;
+ }
+
+ /// \brief Create an empty array section expression.
+ explicit OMPArraySectionExpr(EmptyShell Shell)
+ : Expr(OMPArraySectionExprClass, Shell) {}
+
+ /// An array section can be written only as Base[LowerBound:Length].
+
+ /// \brief Get base of the array section.
+ Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
+ const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
+ /// \brief Set base of the array section.
+ void setBase(Expr *E) { SubExprs[BASE] = E; }
+
+ /// \brief Return original type of the base expression for array section.
+ static QualType getBaseOriginalType(Expr *Base);
+
+ /// \brief Get lower bound of array section.
+ Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
+ const Expr *getLowerBound() const {
+ return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
+ }
+ /// \brief Set lower bound of the array section.
+ void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
+
+ /// \brief Get length of array section.
+ Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+ const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+ /// \brief Set length of the array section.
+ void setLength(Expr *E) { SubExprs[LENGTH] = E; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBase()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
+
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ 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() == OMPArraySectionExprClass;
+ }
+
+ child_range children() {
+ return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
+ }
+};
+} // end namespace clang
+
+#endif
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index 08c2e0c..81cf631 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -33,20 +33,6 @@ class Selector;
class Stmt;
class TagDecl;
-/// \brief Enumeration describing the result of loading information from
-/// an external source.
-enum ExternalLoadResult {
- /// \brief Loading the external information has succeeded.
- ELR_Success,
-
- /// \brief Loading the external information has failed.
- ELR_Failure,
-
- /// \brief The external information has already been loaded, and therefore
- /// no additional processing is required.
- ELR_AlreadyLoaded
-};
-
/// \brief Abstract interface for external sources of AST nodes.
///
/// External AST sources provide AST nodes constructed from some
@@ -156,47 +142,50 @@ public:
/// \brief Retrieve the module that corresponds to the given module ID.
virtual Module *getModule(unsigned ID) { return nullptr; }
- /// \brief Holds everything needed to generate debug info for an
- /// imported module or precompiled header file.
- struct ASTSourceDescriptor {
- std::string ModuleName;
- std::string Path;
- std::string ASTFile;
- uint64_t Signature;
+ /// Abstracts clang modules and precompiled header files and holds
+ /// everything needed to generate debug info for an imported module
+ /// or PCH.
+ class ASTSourceDescriptor {
+ StringRef PCHModuleName;
+ StringRef Path;
+ StringRef ASTFile;
+ uint64_t Signature = 0;
+ const Module *ClangModule = nullptr;
+
+ public:
+ ASTSourceDescriptor(){};
+ ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
+ uint64_t Signature)
+ : PCHModuleName(std::move(Name)), Path(std::move(Path)),
+ ASTFile(std::move(ASTFile)), Signature(Signature){};
+ ASTSourceDescriptor(const Module &M);
+ std::string getModuleName() const;
+ StringRef getPath() const { return Path; }
+ StringRef getASTFile() const { return ASTFile; }
+ uint64_t getSignature() const { return Signature; }
+ const Module *getModuleOrNull() const { return ClangModule; }
};
- /// \brief Return a descriptor for the corresponding module, if one exists.
+ /// Return a descriptor for the corresponding module, if one exists.
virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
- /// \brief Return a descriptor for the module.
- virtual ASTSourceDescriptor getSourceDescriptor(const Module &M);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
///
- /// \param isKindWeWant a predicate function that returns true if the passed
- /// declaration kind is one we are looking for. If NULL, all declarations
- /// are returned.
- ///
- /// \return an indication of whether the load succeeded or failed.
+ /// \param IsKindWeWant a predicate function that returns true if the passed
+ /// declaration kind is one we are looking for.
///
/// The default implementation of this method is a no-op.
- virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- bool (*isKindWeWant)(Decl::Kind),
- SmallVectorImpl<Decl*> &Result);
+ virtual void
+ FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext.
- ///
- /// \return true if an error occurred
- ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC,
- SmallVectorImpl<Decl*> &Result) {
- return FindExternalLexicalDecls(DC, nullptr, Result);
- }
-
- template <typename DeclTy>
- ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC,
- SmallVectorImpl<Decl*> &Result) {
- return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
+ void FindExternalLexicalDecls(const DeclContext *DC,
+ SmallVectorImpl<Decl *> &Result) {
+ FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result);
}
/// \brief Get the decls that are contained in a file in the Offset/Length
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index 735ae11..7b725b6 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -144,9 +144,6 @@ public:
/// across translation units so it can be used with LTO.
virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
- virtual void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
- raw_ostream &) = 0;
-
/// @}
};
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 4da17b0..b1ff9bd 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -217,7 +217,8 @@ public:
/// \brief Dump the nested name specifier to standard output to aid
/// in debugging.
- void dump(const LangOptions &LO);
+ void dump(const LangOptions &LO) const;
+ void dump() const;
};
/// \brief A C++ nested-name-specifier augmented with source location
diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index fcfa1dd..bb982f3 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/include/clang/AST/OpenMPClause.h
@@ -57,9 +57,15 @@ public:
bool isImplicit() const { return StartLoc.isInvalid(); }
- StmtRange children();
- ConstStmtRange children() const {
- return const_cast<OMPClause *>(this)->children();
+ typedef StmtIterator child_iterator;
+ typedef ConstStmtIterator const_child_iterator;
+ typedef llvm::iterator_range<child_iterator> child_range;
+ typedef llvm::iterator_range<const_child_iterator> const_child_range;
+
+ child_range children();
+ const_child_range children() const {
+ auto Children = const_cast<OMPClause *>(this)->children();
+ return const_child_range(Children.begin(), Children.end());
}
static bool classof(const OMPClause *) { return true; }
};
@@ -146,10 +152,10 @@ public:
/// \brief This represents 'if' clause in the '#pragma omp ...' directive.
///
/// \code
-/// #pragma omp parallel if(a > 5)
+/// #pragma omp parallel if(parallel:a > 5)
/// \endcode
-/// In this example directive '#pragma omp parallel' has simple 'if'
-/// clause with condition 'a > 5'.
+/// In this example directive '#pragma omp parallel' has simple 'if' clause with
+/// condition 'a > 5' and directive name modifier 'parallel'.
///
class OMPIfClause : public OMPClause {
friend class OMPClauseReader;
@@ -157,43 +163,73 @@ class OMPIfClause : public OMPClause {
SourceLocation LParenLoc;
/// \brief Condition of the 'if' clause.
Stmt *Condition;
+ /// \brief Location of ':' (if any).
+ SourceLocation ColonLoc;
+ /// \brief Directive name modifier for the clause.
+ OpenMPDirectiveKind NameModifier;
+ /// \brief Name modifier location.
+ SourceLocation NameModifierLoc;
/// \brief Set condition.
///
void setCondition(Expr *Cond) { Condition = Cond; }
+ /// \brief Set directive name modifier for the clause.
+ ///
+ void setNameModifier(OpenMPDirectiveKind NM) { NameModifier = NM; }
+ /// \brief Set location of directive name modifier for the clause.
+ ///
+ void setNameModifierLoc(SourceLocation Loc) { NameModifierLoc = Loc; }
+ /// \brief Set location of ':'.
+ ///
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
public:
/// \brief Build 'if' clause with condition \a Cond.
///
+ /// \param NameModifier [OpenMP 4.1] Directive name modifier of clause.
+ /// \param Cond Condition of the clause.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
- /// \param Cond Condition of the clause.
+ /// \param NameModifierLoc Location of directive name modifier.
+ /// \param ColonLoc [OpenMP 4.1] Location of ':'.
/// \param EndLoc Ending location of the clause.
///
- OMPIfClause(Expr *Cond, SourceLocation StartLoc, SourceLocation LParenLoc,
+ OMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Cond,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation NameModifierLoc, SourceLocation ColonLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_if, StartLoc, EndLoc), LParenLoc(LParenLoc),
- Condition(Cond) {}
+ Condition(Cond), ColonLoc(ColonLoc), NameModifier(NameModifier),
+ NameModifierLoc(NameModifierLoc) {}
/// \brief Build an empty clause.
///
OMPIfClause()
- : OMPClause(OMPC_if, SourceLocation(), SourceLocation()),
- LParenLoc(SourceLocation()), Condition(nullptr) {}
+ : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), LParenLoc(),
+ Condition(nullptr), ColonLoc(), NameModifier(OMPD_unknown),
+ NameModifierLoc() {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return the location of ':'.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
/// \brief Returns condition.
Expr *getCondition() const { return cast_or_null<Expr>(Condition); }
+ /// \brief Return directive name modifier associated with the clause.
+ OpenMPDirectiveKind getNameModifier() const { return NameModifier; }
+
+ /// \brief Return the location of directive name modifier.
+ SourceLocation getNameModifierLoc() const { return NameModifierLoc; }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_if;
}
- StmtRange children() { return StmtRange(&Condition, &Condition + 1); }
+ child_range children() { return child_range(&Condition, &Condition + 1); }
};
/// \brief This represents 'final' clause in the '#pragma omp ...' directive.
@@ -246,7 +282,7 @@ public:
return T->getClauseKind() == OMPC_final;
}
- StmtRange children() { return StmtRange(&Condition, &Condition + 1); }
+ child_range children() { return child_range(&Condition, &Condition + 1); }
};
/// \brief This represents 'num_threads' clause in the '#pragma omp ...'
@@ -300,7 +336,7 @@ public:
return T->getClauseKind() == OMPC_num_threads;
}
- StmtRange children() { return StmtRange(&NumThreads, &NumThreads + 1); }
+ child_range children() { return child_range(&NumThreads, &NumThreads + 1); }
};
/// \brief This represents 'safelen' clause in the '#pragma omp ...'
@@ -356,7 +392,62 @@ public:
return T->getClauseKind() == OMPC_safelen;
}
- StmtRange children() { return StmtRange(&Safelen, &Safelen + 1); }
+ child_range children() { return child_range(&Safelen, &Safelen + 1); }
+};
+
+/// \brief This represents 'simdlen' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp simd simdlen(4)
+/// \endcode
+/// In this example directive '#pragma omp simd' has clause 'simdlen'
+/// with single expression '4'.
+/// If the 'simdlen' clause is used then it specifies the preferred number of
+/// iterations to be executed concurrently. The parameter of the 'simdlen'
+/// clause must be a constant positive integer expression.
+///
+class OMPSimdlenClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *Simdlen;
+
+ /// \brief Set simdlen.
+ void setSimdlen(Expr *Len) { Simdlen = Len; }
+
+public:
+ /// \brief Build 'simdlen' clause.
+ ///
+ /// \param Len Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPSimdlenClause(Expr *Len, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_simdlen, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Simdlen(Len) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPSimdlenClause()
+ : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Simdlen(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getSimdlen() const { return cast_or_null<Expr>(Simdlen); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_simdlen;
+ }
+
+ child_range children() { return child_range(&Simdlen, &Simdlen + 1); }
};
/// \brief This represents 'collapse' clause in the '#pragma omp ...'
@@ -412,7 +503,7 @@ public:
return T->getClauseKind() == OMPC_collapse;
}
- StmtRange children() { return StmtRange(&NumForLoops, &NumForLoops + 1); }
+ child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
};
/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
@@ -481,7 +572,9 @@ public:
return T->getClauseKind() == OMPC_default;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'proc_bind' clause in the '#pragma omp ...'
@@ -552,7 +645,9 @@ public:
return T->getClauseKind() == OMPC_proc_bind;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'schedule' clause in the '#pragma omp ...' directive.
@@ -569,6 +664,11 @@ class OMPScheduleClause : public OMPClause {
SourceLocation LParenLoc;
/// \brief A kind of the 'schedule' clause.
OpenMPScheduleClauseKind Kind;
+ /// \brief Modifiers for 'schedule' clause.
+ enum {FIRST, SECOND, NUM_MODIFIERS};
+ OpenMPScheduleClauseModifier Modifiers[NUM_MODIFIERS];
+ /// \brief Locations of modifiers.
+ SourceLocation ModifiersLoc[NUM_MODIFIERS];
/// \brief Start location of the schedule ind in source code.
SourceLocation KindLoc;
/// \brief Location of ',' (if any).
@@ -583,6 +683,42 @@ class OMPScheduleClause : public OMPClause {
/// \param K Schedule kind.
///
void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; }
+ /// \brief Set the first schedule modifier.
+ ///
+ /// \param M Schedule modifier.
+ ///
+ void setFirstScheduleModifier(OpenMPScheduleClauseModifier M) {
+ Modifiers[FIRST] = M;
+ }
+ /// \brief Set the second schedule modifier.
+ ///
+ /// \param M Schedule modifier.
+ ///
+ void setSecondScheduleModifier(OpenMPScheduleClauseModifier M) {
+ Modifiers[SECOND] = M;
+ }
+ /// \brief Set location of the first schedule modifier.
+ ///
+ void setFirstScheduleModifierLoc(SourceLocation Loc) {
+ ModifiersLoc[FIRST] = Loc;
+ }
+ /// \brief Set location of the second schedule modifier.
+ ///
+ void setSecondScheduleModifierLoc(SourceLocation Loc) {
+ ModifiersLoc[SECOND] = Loc;
+ }
+ /// \brief Set schedule modifier location.
+ ///
+ /// \param M Schedule modifier location.
+ ///
+ void setScheduleModifer(OpenMPScheduleClauseModifier M) {
+ if (Modifiers[FIRST] == OMPC_SCHEDULE_MODIFIER_unknown)
+ Modifiers[FIRST] = M;
+ else {
+ assert(Modifiers[SECOND] == OMPC_SCHEDULE_MODIFIER_unknown);
+ Modifiers[SECOND] = M;
+ }
+ }
/// \brief Sets the location of '('.
///
/// \param Loc Location of '('.
@@ -621,15 +757,25 @@ public:
/// \param Kind Schedule kind.
/// \param ChunkSize Chunk size.
/// \param HelperChunkSize Helper chunk size for combined directives.
+ /// \param M1 The first modifier applied to 'schedule' clause.
+ /// \param M1Loc Location of the first modifier
+ /// \param M2 The second modifier applied to 'schedule' clause.
+ /// \param M2Loc Location of the second modifier
///
OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation KLoc, SourceLocation CommaLoc,
SourceLocation EndLoc, OpenMPScheduleClauseKind Kind,
- Expr *ChunkSize, Expr *HelperChunkSize)
+ Expr *ChunkSize, Expr *HelperChunkSize,
+ OpenMPScheduleClauseModifier M1, SourceLocation M1Loc,
+ OpenMPScheduleClauseModifier M2, SourceLocation M2Loc)
: OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) {
ChunkSizes[CHUNK_SIZE] = ChunkSize;
ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize;
+ Modifiers[FIRST] = M1;
+ Modifiers[SECOND] = M2;
+ ModifiersLoc[FIRST] = M1Loc;
+ ModifiersLoc[SECOND] = M2Loc;
}
/// \brief Build an empty clause.
@@ -639,17 +785,39 @@ public:
Kind(OMPC_SCHEDULE_unknown) {
ChunkSizes[CHUNK_SIZE] = nullptr;
ChunkSizes[HELPER_CHUNK_SIZE] = nullptr;
+ Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown;
+ Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown;
}
/// \brief Get kind of the clause.
///
OpenMPScheduleClauseKind getScheduleKind() const { return Kind; }
+ /// \brief Get the first modifier of the clause.
+ ///
+ OpenMPScheduleClauseModifier getFirstScheduleModifier() const {
+ return Modifiers[FIRST];
+ }
+ /// \brief Get the second modifier of the clause.
+ ///
+ OpenMPScheduleClauseModifier getSecondScheduleModifier() const {
+ return Modifiers[SECOND];
+ }
/// \brief Get location of '('.
///
SourceLocation getLParenLoc() { return LParenLoc; }
/// \brief Get kind location.
///
SourceLocation getScheduleKindLoc() { return KindLoc; }
+ /// \brief Get the first modifier location.
+ ///
+ SourceLocation getFirstScheduleModifierLoc() const {
+ return ModifiersLoc[FIRST];
+ }
+ /// \brief Get the second modifier location.
+ ///
+ SourceLocation getSecondScheduleModifierLoc() const {
+ return ModifiersLoc[SECOND];
+ }
/// \brief Get location of ','.
///
SourceLocation getCommaLoc() { return CommaLoc; }
@@ -676,38 +844,61 @@ public:
return T->getClauseKind() == OMPC_schedule;
}
- StmtRange children() {
- return StmtRange(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
+ child_range children() {
+ return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
}
};
/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive.
///
/// \code
-/// #pragma omp for ordered
+/// #pragma omp for ordered (2)
/// \endcode
-/// In this example directive '#pragma omp for' has 'ordered' clause.
+/// In this example directive '#pragma omp for' has 'ordered' clause with
+/// parameter 2.
///
class OMPOrderedClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Number of for-loops.
+ Stmt *NumForLoops;
+
+ /// \brief Set the number of associated for-loops.
+ void setNumForLoops(Expr *Num) { NumForLoops = Num; }
+
public:
/// \brief Build 'ordered' clause.
///
+ /// \param Num Expression, possibly associated with this clause.
/// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
///
- OMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc)
- : OMPClause(OMPC_ordered, StartLoc, EndLoc) {}
+ OMPOrderedClause(Expr *Num, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumForLoops(Num) {}
/// \brief Build an empty clause.
///
- OMPOrderedClause()
- : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {}
+ explicit OMPOrderedClause()
+ : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumForLoops(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return the number of associated for-loops.
+ Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_ordered;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); }
};
/// \brief This represents 'nowait' clause in the '#pragma omp ...' directive.
@@ -736,7 +927,9 @@ public:
return T->getClauseKind() == OMPC_nowait;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'untied' clause in the '#pragma omp ...' directive.
@@ -765,7 +958,9 @@ public:
return T->getClauseKind() == OMPC_untied;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'mergeable' clause in the '#pragma omp ...'
@@ -795,7 +990,9 @@ public:
return T->getClauseKind() == OMPC_mergeable;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'read' clause in the '#pragma omp atomic' directive.
@@ -823,7 +1020,9 @@ public:
return T->getClauseKind() == OMPC_read;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'write' clause in the '#pragma omp atomic' directive.
@@ -852,7 +1051,9 @@ public:
return T->getClauseKind() == OMPC_write;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'update' clause in the '#pragma omp atomic'
@@ -882,7 +1083,9 @@ public:
return T->getClauseKind() == OMPC_update;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'capture' clause in the '#pragma omp atomic'
@@ -912,7 +1115,9 @@ public:
return T->getClauseKind() == OMPC_capture;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic'
@@ -942,7 +1147,9 @@ public:
return T->getClauseKind() == OMPC_seq_cst;
}
- StmtRange children() { return StmtRange(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
@@ -1026,9 +1233,9 @@ public:
getPrivateCopies().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1147,9 +1354,9 @@ public:
return inits_const_range(getInits().begin(), getInits().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1332,9 +1539,9 @@ public:
getAssignmentOps().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1391,9 +1598,9 @@ public:
///
static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N);
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1455,16 +1662,29 @@ class OMPReductionClause : public OMPVarListClause<OMPReductionClause> {
void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
/// \brief Set list of helper expressions, required for proper codegen of the
+ /// clause. These expressions represent private copy of the reduction
+ /// variable.
+ void setPrivates(ArrayRef<Expr *> Privates);
+
+ /// \brief Get the list of helper privates.
+ MutableArrayRef<Expr *> getPrivates() {
+ return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getPrivates() const {
+ return llvm::makeArrayRef(varlist_end(), varlist_size());
+ }
+
+ /// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent LHS expression in the final
/// reduction expression performed by the reduction clause.
void setLHSExprs(ArrayRef<Expr *> LHSExprs);
/// \brief Get the list of helper LHS expressions.
MutableArrayRef<Expr *> getLHSExprs() {
- return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
+ return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
}
ArrayRef<const Expr *> getLHSExprs() const {
- return llvm::makeArrayRef(varlist_end(), varlist_size());
+ return llvm::makeArrayRef(getPrivates().end(), varlist_size());
}
/// \brief Set list of helper expressions, required for proper codegen of the
@@ -1506,6 +1726,8 @@ public:
/// \param VL The variables in the clause.
/// \param QualifierLoc The nested-name qualifier with location information
/// \param NameInfo The full name info for reduction identifier.
+ /// \param Privates List of helper expressions for proper generation of
+ /// private copies.
/// \param LHSExprs List of helper expressions for proper generation of
/// assignment operation required for copyprivate clause. This list represents
/// LHSs of the reduction expressions.
@@ -1528,8 +1750,9 @@ public:
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
NestedNameSpecifierLoc QualifierLoc,
- const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> LHSExprs,
- ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps);
+ const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> Privates,
+ ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
+ ArrayRef<Expr *> ReductionOps);
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
@@ -1550,6 +1773,12 @@ public:
typedef llvm::iterator_range<helper_expr_const_iterator>
helper_expr_const_range;
+ helper_expr_const_range privates() const {
+ return helper_expr_const_range(getPrivates().begin(), getPrivates().end());
+ }
+ helper_expr_range privates() {
+ return helper_expr_range(getPrivates().begin(), getPrivates().end());
+ }
helper_expr_const_range lhs_exprs() const {
return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end());
}
@@ -1571,9 +1800,9 @@ public:
getReductionOps().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1592,6 +1821,10 @@ public:
///
class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
friend class OMPClauseReader;
+ /// \brief Modifier of 'linear' clause.
+ OpenMPLinearClauseKind Modifier;
+ /// \brief Location of linear modifier if any.
+ SourceLocation ModifierLoc;
/// \brief Location of ':'.
SourceLocation ColonLoc;
@@ -1610,11 +1843,12 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
/// \param NumVars Number of variables.
///
OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
SourceLocation ColonLoc, SourceLocation EndLoc,
unsigned NumVars)
: OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc,
EndLoc, NumVars),
- ColonLoc(ColonLoc) {}
+ Modifier(Modifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {}
/// \brief Build an empty clause.
///
@@ -1624,7 +1858,7 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
: OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(),
SourceLocation(), SourceLocation(),
NumVars),
- ColonLoc(SourceLocation()) {}
+ Modifier(OMPC_LINEAR_val), ModifierLoc(), ColonLoc() {}
/// \brief Gets the list of initial values for linear variables.
///
@@ -1636,16 +1870,23 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
/// expressions - linear step and a helper to calculate it before the
/// loop body (used when the linear step is not constant):
///
- /// { Vars[] /* in OMPVarListClause */; Inits[]; Updates[]; Finals[];
- /// Step; CalcStep; }
+ /// { Vars[] /* in OMPVarListClause */; Privates[]; Inits[]; Updates[];
+ /// Finals[]; Step; CalcStep; }
///
- MutableArrayRef<Expr *> getInits() {
+ MutableArrayRef<Expr *> getPrivates() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
- ArrayRef<const Expr *> getInits() const {
+ ArrayRef<const Expr *> getPrivates() const {
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
+ MutableArrayRef<Expr *> getInits() {
+ return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size());
+ }
+ ArrayRef<const Expr *> getInits() const {
+ return llvm::makeArrayRef(getPrivates().end(), varlist_size());
+ }
+
/// \brief Sets the list of update expressions for linear variables.
MutableArrayRef<Expr *> getUpdates() {
return MutableArrayRef<Expr *>(getInits().end(), varlist_size());
@@ -1662,6 +1903,10 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
return llvm::makeArrayRef(getUpdates().end(), varlist_size());
}
+ /// \brief Sets the list of the copies of original linear variables.
+ /// \param PL List of expressions.
+ void setPrivates(ArrayRef<Expr *> PL);
+
/// \brief Sets the list of the initial values for linear variables.
/// \param IL List of expressions.
void setInits(ArrayRef<Expr *> IL);
@@ -1673,17 +1918,20 @@ public:
/// \param C AST Context.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
+ /// \param Modifier Modifier of 'linear' clause.
+ /// \param ModifierLoc Modifier location.
/// \param ColonLoc Location of ':'.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
+ /// \param PL List of private copies of original variables.
/// \param IL List of initial values for the variables.
/// \param Step Linear step.
/// \param CalcStep Calculation of the linear step.
- static OMPLinearClause *Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc, SourceLocation EndLoc,
- ArrayRef<Expr *> VL, ArrayRef<Expr *> IL,
- Expr *Step, Expr *CalcStep);
+ static OMPLinearClause *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep);
/// \brief Creates an empty clause with the place for \a NumVars variables.
///
@@ -1692,9 +1940,19 @@ public:
///
static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
+ /// \brief Set modifier.
+ void setModifier(OpenMPLinearClauseKind Kind) { Modifier = Kind; }
+ /// \brief Return modifier.
+ OpenMPLinearClauseKind getModifier() const { return Modifier; }
+
+ /// \brief Set modifier location.
+ void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; }
+ /// \brief Return modifier location.
+ SourceLocation getModifierLoc() const { return ModifierLoc; }
+
/// \brief Sets the location of ':'.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
- /// \brief Returns the location of '('.
+ /// \brief Returns the location of ':'.
SourceLocation getColonLoc() const { return ColonLoc; }
/// \brief Returns linear step.
@@ -1714,6 +1972,18 @@ public:
/// \param FL List of expressions.
void setFinals(ArrayRef<Expr *> FL);
+ typedef MutableArrayRef<Expr *>::iterator privates_iterator;
+ typedef ArrayRef<const Expr *>::iterator privates_const_iterator;
+ typedef llvm::iterator_range<privates_iterator> privates_range;
+ typedef llvm::iterator_range<privates_const_iterator> privates_const_range;
+
+ privates_range privates() {
+ return privates_range(getPrivates().begin(), getPrivates().end());
+ }
+ privates_const_range privates() const {
+ return privates_const_range(getPrivates().begin(), getPrivates().end());
+ }
+
typedef MutableArrayRef<Expr *>::iterator inits_iterator;
typedef ArrayRef<const Expr *>::iterator inits_const_iterator;
typedef llvm::iterator_range<inits_iterator> inits_range;
@@ -1750,9 +2020,9 @@ public:
return finals_const_range(getFinals().begin(), getFinals().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1835,9 +2105,9 @@ public:
/// \brief Returns alignment.
const Expr *getAlignment() const { return *varlist_end(); }
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -1993,9 +2263,9 @@ public:
getAssignmentOps().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -2138,9 +2408,9 @@ public:
getAssignmentOps().end());
}
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -2202,9 +2472,9 @@ public:
///
static OMPFlushClause *CreateEmpty(const ASTContext &C, unsigned N);
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -2290,9 +2560,9 @@ public:
/// \brief Get colon location.
SourceLocation getColonLoc() const { return ColonLoc; }
- StmtRange children() {
- return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
- reinterpret_cast<Stmt **>(varlist_end()));
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
}
static bool classof(const OMPClause *T) {
@@ -2300,7 +2570,590 @@ public:
}
};
-} // end namespace clang
+/// \brief This represents 'device' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp target device(a)
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'device'
+/// with single expression 'a'.
+///
+class OMPDeviceClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Device number.
+ Stmt *Device;
+ /// \brief Set the device number.
+ ///
+ /// \param E Device number.
+ ///
+ void setDevice(Expr *E) { Device = E; }
+
+public:
+ /// \brief Build 'device' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPDeviceClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_device, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Device(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPDeviceClause()
+ : OMPClause(OMPC_device, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Device(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return device number.
+ Expr *getDevice() { return cast<Expr>(Device); }
+ /// \brief Return device number.
+ Expr *getDevice() const { return cast<Expr>(Device); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_device;
+ }
+
+ child_range children() { return child_range(&Device, &Device + 1); }
+};
+
+/// \brief This represents 'threads' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp ordered threads
+/// \endcode
+/// In this example directive '#pragma omp ordered' has simple 'threads' clause.
+///
+class OMPThreadsClause : public OMPClause {
+public:
+ /// \brief Build 'threads' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_threads, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPThreadsClause()
+ : OMPClause(OMPC_threads, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_threads;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'simd' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp ordered simd
+/// \endcode
+/// In this example directive '#pragma omp ordered' has simple 'simd' clause.
+///
+class OMPSIMDClause : public OMPClause {
+public:
+ /// \brief Build 'simd' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_simd, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_simd;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents clause 'map' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp target map(a,b)
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'map'
+/// with the variables 'a' and 'b'.
+///
+class OMPMapClause : public OMPVarListClause<OMPMapClause> {
+ friend class OMPClauseReader;
+
+ /// \brief Map type modifier for the 'map' clause.
+ OpenMPMapClauseKind MapTypeModifier;
+ /// \brief Map type for the 'map' clause.
+ OpenMPMapClauseKind MapType;
+ /// \brief Location of the map type.
+ SourceLocation MapLoc;
+ /// \brief Colon location.
+ SourceLocation ColonLoc;
+
+ /// \brief Set type modifier for the clause.
+ ///
+ /// \param T Type Modifier for the clause.
+ ///
+ void setMapTypeModifier(OpenMPMapClauseKind T) { MapTypeModifier = T; }
+
+ /// \brief Set type for the clause.
+ ///
+ /// \param T Type for the clause.
+ ///
+ void setMapType(OpenMPMapClauseKind T) { MapType = T; }
+
+ /// \brief Set type location.
+ ///
+ /// \param TLoc Type location.
+ ///
+ void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; }
+
+ /// \brief Set colon location.
+ void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+
+ /// \brief Build clause with number of variables \a N.
+ ///
+ /// \param MapTypeModifier Map type modifier.
+ /// \param MapType Map type.
+ /// \param MapLoc Location of the map type.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ /// \param N Number of the variables in the clause.
+ ///
+ explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType, SourceLocation MapLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned N)
+ : OMPVarListClause<OMPMapClause>(OMPC_map, StartLoc, LParenLoc, EndLoc, N),
+ MapTypeModifier(MapTypeModifier), MapType(MapType), MapLoc(MapLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param N Number of variables.
+ ///
+ explicit OMPMapClause(unsigned N)
+ : OMPVarListClause<OMPMapClause>(OMPC_map, SourceLocation(),
+ SourceLocation(), SourceLocation(), N),
+ MapTypeModifier(OMPC_MAP_unknown), MapType(OMPC_MAP_unknown), MapLoc() {}
+
+public:
+ /// \brief Creates clause with a list of variables \a VL.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ /// \param VL List of references to the variables.
+ /// \param TypeModifier Map type modifier.
+ /// \param Type Map type.
+ /// \param TypeLoc Location of the map type.
+ ///
+ static OMPMapClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc, ArrayRef<Expr *> VL,
+ OpenMPMapClauseKind TypeModifier,
+ OpenMPMapClauseKind Type, SourceLocation TypeLoc);
+ /// \brief Creates an empty clause with the place for \a N variables.
+ ///
+ /// \param C AST context.
+ /// \param N The number of variables.
+ ///
+ static OMPMapClause *CreateEmpty(const ASTContext &C, unsigned N);
+
+ /// \brief Fetches mapping kind for the clause.
+ OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; }
+
+ /// \brief Fetches the map type modifier for the clause.
+ OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY {
+ return MapTypeModifier;
+ }
+
+ /// \brief Fetches location of clause mapping kind.
+ SourceLocation getMapLoc() const LLVM_READONLY { return MapLoc; }
+
+ /// \brief Get colon location.
+ SourceLocation getColonLoc() const { return ColonLoc; }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_map;
+ }
+
+ child_range children() {
+ return child_range(
+ reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+};
+
+/// \brief This represents 'num_teams' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp teams num_teams(n)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'num_teams'
+/// with single expression 'n'.
+///
+class OMPNumTeamsClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief NumTeams number.
+ Stmt *NumTeams;
+ /// \brief Set the NumTeams number.
+ ///
+ /// \param E NumTeams number.
+ ///
+ void setNumTeams(Expr *E) { NumTeams = E; }
+
+public:
+ /// \brief Build 'num_teams' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNumTeamsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_num_teams, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumTeams(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPNumTeamsClause()
+ : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumTeams(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return NumTeams number.
+ Expr *getNumTeams() { return cast<Expr>(NumTeams); }
+ /// \brief Return NumTeams number.
+ Expr *getNumTeams() const { return cast<Expr>(NumTeams); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_num_teams;
+ }
+
+ child_range children() { return child_range(&NumTeams, &NumTeams + 1); }
+};
+
+/// \brief This represents 'thread_limit' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp teams thread_limit(n)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'thread_limit'
+/// with single expression 'n'.
+///
+class OMPThreadLimitClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief ThreadLimit number.
+ Stmt *ThreadLimit;
+ /// \brief Set the ThreadLimit number.
+ ///
+ /// \param E ThreadLimit number.
+ ///
+ void setThreadLimit(Expr *E) { ThreadLimit = E; }
+
+public:
+ /// \brief Build 'thread_limit' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPThreadLimitClause(Expr *E, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_thread_limit, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ ThreadLimit(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPThreadLimitClause()
+ : OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), ThreadLimit(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return ThreadLimit number.
+ Expr *getThreadLimit() { return cast<Expr>(ThreadLimit); }
+ /// \brief Return ThreadLimit number.
+ Expr *getThreadLimit() const { return cast<Expr>(ThreadLimit); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_thread_limit;
+ }
+
+ child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); }
+};
+
+/// \brief This represents 'priority' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp task priority(n)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'priority' with
+/// single expression 'n'.
+///
+class OMPPriorityClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Priority number.
+ Stmt *Priority;
+ /// \brief Set the Priority number.
+ ///
+ /// \param E Priority number.
+ ///
+ void setPriority(Expr *E) { Priority = E; }
+
+public:
+ /// \brief Build 'priority' clause.
+ ///
+ /// \param E Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPPriorityClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Priority(E) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPPriorityClause()
+ : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Priority(nullptr) {}
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+ /// \brief Return Priority number.
+ Expr *getPriority() { return cast<Expr>(Priority); }
+ /// \brief Return Priority number.
+ Expr *getPriority() const { return cast<Expr>(Priority); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_priority;
+ }
+
+ child_range children() { return child_range(&Priority, &Priority + 1); }
+};
+
+/// \brief This represents 'grainsize' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp taskloop grainsize(4)
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has clause 'grainsize'
+/// with single expression '4'.
+///
+class OMPGrainsizeClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *Grainsize;
+
+ /// \brief Set safelen.
+ void setGrainsize(Expr *Size) { Grainsize = Size; }
+
+public:
+ /// \brief Build 'grainsize' clause.
+ ///
+ /// \param Size Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPGrainsizeClause(Expr *Size, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Grainsize(Size) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPGrainsizeClause()
+ : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Grainsize(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getGrainsize() const { return cast_or_null<Expr>(Grainsize); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_grainsize;
+ }
-#endif
+ child_range children() { return child_range(&Grainsize, &Grainsize + 1); }
+};
+
+/// \brief This represents 'nogroup' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp taskloop nogroup
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has 'nogroup' clause.
+///
+class OMPNogroupClause : public OMPClause {
+public:
+ /// \brief Build 'nogroup' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_nogroup, StartLoc, EndLoc) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPNogroupClause()
+ : OMPClause(OMPC_nogroup, SourceLocation(), SourceLocation()) {}
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_nogroup;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+};
+
+/// \brief This represents 'num_tasks' clause in the '#pragma omp ...'
+/// directive.
+///
+/// \code
+/// #pragma omp taskloop num_tasks(4)
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has clause 'num_tasks'
+/// with single expression '4'.
+///
+class OMPNumTasksClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Safe iteration space distance.
+ Stmt *NumTasks;
+
+ /// \brief Set safelen.
+ void setNumTasks(Expr *Size) { NumTasks = Size; }
+
+public:
+ /// \brief Build 'num_tasks' clause.
+ ///
+ /// \param Size Expression associated with this clause.
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPNumTasksClause(Expr *Size, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumTasks(Size) {}
+
+ /// \brief Build an empty clause.
+ ///
+ explicit OMPNumTasksClause()
+ : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), NumTasks(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Return safe iteration space distance.
+ Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_num_tasks;
+ }
+
+ child_range children() { return child_range(&NumTasks, &NumTasks + 1); }
+};
+
+/// \brief This represents 'hint' clause in the '#pragma omp ...' directive.
+///
+/// \code
+/// #pragma omp critical (name) hint(6)
+/// \endcode
+/// In this example directive '#pragma omp critical' has name 'name' and clause
+/// 'hint' with argument '6'.
+///
+class OMPHintClause : public OMPClause {
+ friend class OMPClauseReader;
+ /// \brief Location of '('.
+ SourceLocation LParenLoc;
+ /// \brief Hint expression of the 'hint' clause.
+ Stmt *Hint;
+
+ /// \brief Set hint expression.
+ ///
+ void setHint(Expr *H) { Hint = H; }
+
+public:
+ /// \brief Build 'hint' clause with expression \a Hint.
+ ///
+ /// \param Hint Hint expression.
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ ///
+ OMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ Hint(Hint) {}
+
+ /// \brief Build an empty clause.
+ ///
+ OMPHintClause()
+ : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()),
+ LParenLoc(SourceLocation()), Hint(nullptr) {}
+
+ /// \brief Sets the location of '('.
+ void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
+ /// \brief Returns the location of '('.
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ /// \brief Returns number of threads.
+ Expr *getHint() const { return cast_or_null<Expr>(Hint); }
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_hint;
+ }
+
+ child_range children() { return child_range(&Hint, &Hint + 1); }
+};
+
+} // end namespace clang
+#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
index e3f0126..2235c10 100644
--- a/include/clang/AST/OperationKinds.h
+++ b/include/clang/AST/OperationKinds.h
@@ -334,7 +334,8 @@ enum UnaryOperatorKind {
UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic
UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic
UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension.
- UO_Extension // __extension__ marker.
+ UO_Extension, // __extension__ marker.
+ UO_Coawait // [C++ Coroutines] co_await operator
};
/// \brief The kind of bridging performed by the Objective-C bridge cast.
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index 35ceabb..8ab3f617 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -42,7 +42,7 @@ struct PrintingPolicy {
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
- IncludeNewlines(true) { }
+ IncludeNewlines(true), MSVCFormatting(false) { }
/// \brief What language we're printing.
LangOptions LangOpts;
@@ -109,7 +109,7 @@ struct PrintingPolicy {
/// \brief Whether we should print the sizes of constant array expressions
/// as written in the sources.
///
- /// This flag is determines whether arrays types declared as
+ /// This flag determines whether array types declared as
///
/// \code
/// int a[4+10*10];
@@ -163,6 +163,11 @@ struct PrintingPolicy {
/// \brief When true, include newlines after statements like "break", etc.
unsigned IncludeNewlines : 1;
+
+ /// \brief Use whitespace and punctuation like MSVC does. In particular, this
+ /// prints anonymous namespaces as `anonymous namespace' and does not insert
+ /// spaces after template arguments.
+ bool MSVCFormatting : 1;
};
} // end namespace clang
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 1017656..e6f7583 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -14,6 +14,8 @@
#ifndef LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
#define LLVM_CLANG_AST_RECURSIVEASTVISITOR_H
+#include <type_traits>
+
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -24,6 +26,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
@@ -42,7 +45,7 @@
OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) \
OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) \
OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) \
- OPERATOR(Extension)
+ OPERATOR(Extension) OPERATOR(Coawait)
// All binary operators (excluding compound assign operators).
#define BINOP_LIST() \
@@ -132,6 +135,12 @@ namespace clang {
/// from which they were produced.
template <typename Derived> class RecursiveASTVisitor {
public:
+ /// A queue used for performing data recursion over statements.
+ /// Parameters involving this type are used to implement data
+ /// recursion over Stmts and Exprs within this class, and should
+ /// typically not be explicitly specified by derived classes.
+ typedef SmallVectorImpl<Stmt *> DataRecursionQueue;
+
/// \brief Return a reference to the derived class.
Derived &getDerived() { return *static_cast<Derived *>(this); }
@@ -147,19 +156,12 @@ public:
/// code, e.g., implicit constructors and destructors.
bool shouldVisitImplicitCode() const { return false; }
- /// \brief Return whether \param S should be traversed using data recursion
- /// to avoid a stack overflow with extreme cases.
- bool shouldUseDataRecursionFor(Stmt *S) const {
- return isa<BinaryOperator>(S) || isa<UnaryOperator>(S) ||
- isa<CaseStmt>(S) || isa<CXXOperatorCallExpr>(S);
- }
-
/// \brief Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type.
///
/// \returns false if the visitation was terminated early, true
- /// otherwise (including when the argument is NULL).
- bool TraverseStmt(Stmt *S);
+ /// otherwise (including when the argument is nullptr).
+ bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr);
/// \brief Recursively visit a type, by dispatching to
/// Traverse*Type() based on the argument's getTypeClass() property.
@@ -252,7 +254,14 @@ public:
/// \c LE->getBody().
///
/// \returns false if the visitation was terminated early, true otherwise.
- bool TraverseLambdaBody(LambdaExpr *LE);
+ bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr);
+
+ /// \brief Recursively visit the syntactic or semantic form of an
+ /// initialization list.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseSynOrSemInitListExpr(InitListExpr *S,
+ DataRecursionQueue *Queue = nullptr);
// ---- Methods on Attrs ----
@@ -266,9 +275,44 @@ public:
// ---- Methods on Stmts ----
+private:
+ template<typename T, typename U>
+ struct has_same_member_pointer_type : std::false_type {};
+ template<typename T, typename U, typename R, typename... P>
+ struct has_same_member_pointer_type<R (T::*)(P...), R (U::*)(P...)>
+ : std::true_type {};
+
+ // Traverse the given statement. If the most-derived traverse function takes a
+ // data recursion queue, pass it on; otherwise, discard it. Note that the
+ // first branch of this conditional must compile whether or not the derived
+ // class can take a queue, so if we're taking the second arm, make the first
+ // arm call our function rather than the derived class version.
+#define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \
+ (has_same_member_pointer_type<decltype( \
+ &RecursiveASTVisitor::Traverse##NAME), \
+ decltype(&Derived::Traverse##NAME)>::value \
+ ? static_cast<typename std::conditional< \
+ has_same_member_pointer_type< \
+ decltype(&RecursiveASTVisitor::Traverse##NAME), \
+ decltype(&Derived::Traverse##NAME)>::value, \
+ Derived &, RecursiveASTVisitor &>::type>(*this) \
+ .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \
+ : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)))
+
+// Try to traverse the given statement, or enqueue it if we're performing data
+// recursion in the middle of traversing another statement. Can only be called
+// from within a DEF_TRAVERSE_STMT body or similar context.
+#define TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S) \
+ do { \
+ if (!TRAVERSE_STMT_BASE(Stmt, Stmt, S, Queue)) \
+ return false; \
+ } while (0)
+
+public:
// Declare Traverse*() for all concrete Stmt classes.
#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) bool Traverse##CLASS(CLASS *S);
+#define STMT(CLASS, PARENT) \
+ bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr);
#include "clang/AST/StmtNodes.inc"
// The above header #undefs ABSTRACT_STMT and STMT upon exit.
@@ -288,9 +332,10 @@ public:
// operator methods. Unary operators are not classes in themselves
// (they're all opcodes in UnaryOperator) but do have visitors.
#define OPERATOR(NAME) \
- bool TraverseUnary##NAME(UnaryOperator *S) { \
+ bool TraverseUnary##NAME(UnaryOperator *S, \
+ DataRecursionQueue *Queue = nullptr) { \
TRY_TO(WalkUpFromUnary##NAME(S)); \
- TRY_TO(TraverseStmt(S->getSubExpr())); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \
return true; \
} \
bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
@@ -307,10 +352,10 @@ public:
// operator methods. Binary operators are not classes in themselves
// (they're all opcodes in BinaryOperator) but do have visitors.
#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
- bool TraverseBin##NAME(BINOP_TYPE *S) { \
+ bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \
TRY_TO(WalkUpFromBin##NAME(S)); \
- TRY_TO(TraverseStmt(S->getLHS())); \
- TRY_TO(TraverseStmt(S->getRHS())); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \
return true; \
} \
bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
@@ -436,98 +481,45 @@ private:
/// \brief Process clauses with list of variables.
template <typename T> bool VisitOMPClauseList(T *Node);
- struct EnqueueJob {
- Stmt *S;
- Stmt::child_iterator StmtIt;
-
- EnqueueJob(Stmt *S) : S(S), StmtIt() {}
- };
- bool dataTraverse(Stmt *S);
- bool dataTraverseNode(Stmt *S, bool &EnqueueChildren);
+ bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue);
};
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::dataTraverse(Stmt *S) {
-
- SmallVector<EnqueueJob, 16> Queue;
- Queue.push_back(S);
-
- while (!Queue.empty()) {
- EnqueueJob &job = Queue.back();
- Stmt *CurrS = job.S;
- if (!CurrS) {
- Queue.pop_back();
- continue;
- }
-
- if (getDerived().shouldUseDataRecursionFor(CurrS)) {
- if (job.StmtIt == Stmt::child_iterator()) {
- bool EnqueueChildren = true;
- if (!dataTraverseNode(CurrS, EnqueueChildren))
- return false;
- if (!EnqueueChildren) {
- Queue.pop_back();
- continue;
- }
- job.StmtIt = CurrS->child_begin();
- } else {
- ++job.StmtIt;
- }
-
- if (job.StmtIt != CurrS->child_end())
- Queue.push_back(*job.StmtIt);
- else
- Queue.pop_back();
- continue;
- }
-
- Queue.pop_back();
- TRY_TO(TraverseStmt(CurrS));
- }
-
- return true;
-}
-
-template <typename Derived>
bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
- bool &EnqueueChildren) {
-
-// Dispatch to the corresponding WalkUpFrom* function only if the derived
-// class didn't override Traverse* (and thus the traversal is trivial).
-#define DISPATCH_WALK(NAME, CLASS, VAR) \
- { \
- bool (Derived::*DerivedFn)(CLASS *) = &Derived::Traverse##NAME; \
- bool (Derived::*BaseFn)(CLASS *) = &RecursiveASTVisitor::Traverse##NAME; \
- if (DerivedFn == BaseFn) \
- return getDerived().WalkUpFrom##NAME(static_cast<CLASS *>(VAR)); \
- } \
- EnqueueChildren = false; \
- return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR));
+ DataRecursionQueue *Queue) {
+#define DISPATCH_STMT(NAME, CLASS, VAR) \
+ return TRAVERSE_STMT_BASE(NAME, CLASS, VAR, Queue);
+ // If we have a binary expr, dispatch to the subcode of the binop. A smart
+ // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
+ // below.
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \
case BO_##NAME: \
- DISPATCH_WALK(Bin##NAME, BinaryOperator, S);
+ DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
BINOP_LIST()
#undef OPERATOR
+#undef BINOP_LIST
#define OPERATOR(NAME) \
case BO_##NAME##Assign: \
- DISPATCH_WALK(Bin##NAME##Assign, CompoundAssignOperator, S);
+ DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
CAO_LIST()
#undef OPERATOR
+#undef CAO_LIST
}
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
#define OPERATOR(NAME) \
case UO_##NAME: \
- DISPATCH_WALK(Unary##NAME, UnaryOperator, S);
+ DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
UNARYOP_LIST()
#undef OPERATOR
+#undef UNARYOP_LIST
}
}
@@ -538,76 +530,43 @@ bool RecursiveASTVisitor<Derived>::dataTraverseNode(Stmt *S,
#define ABSTRACT_STMT(STMT)
#define STMT(CLASS, PARENT) \
case Stmt::CLASS##Class: \
- DISPATCH_WALK(CLASS, CLASS, S);
+ DISPATCH_STMT(CLASS, CLASS, S);
#include "clang/AST/StmtNodes.inc"
}
-#undef DISPATCH_WALK
-
return true;
}
-#define DISPATCH(NAME, CLASS, VAR) \
- return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
+#undef DISPATCH_STMT
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
+bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S,
+ DataRecursionQueue *Queue) {
if (!S)
return true;
-#define DISPATCH_STMT(NAME, CLASS, VAR) DISPATCH(NAME, CLASS, VAR)
-
- if (getDerived().shouldUseDataRecursionFor(S))
- return dataTraverse(S);
-
- // If we have a binary expr, dispatch to the subcode of the binop. A smart
- // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
- // below.
- if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
- switch (BinOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case BO_##NAME: \
- DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
-
- BINOP_LIST()
-#undef OPERATOR
-#undef BINOP_LIST
+ if (Queue) {
+ Queue->push_back(S);
+ return true;
+ }
-#define OPERATOR(NAME) \
- case BO_##NAME##Assign: \
- DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
+ SmallVector<Stmt *, 8> LocalQueue;
+ LocalQueue.push_back(S);
- CAO_LIST()
-#undef OPERATOR
-#undef CAO_LIST
- }
- } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
- switch (UnOp->getOpcode()) {
-#define OPERATOR(NAME) \
- case UO_##NAME: \
- DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
+ while (!LocalQueue.empty()) {
+ Stmt *CurrS = LocalQueue.pop_back_val();
- UNARYOP_LIST()
-#undef OPERATOR
-#undef UNARYOP_LIST
- }
- }
-
- // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
- switch (S->getStmtClass()) {
- case Stmt::NoStmtClass:
- break;
-#define ABSTRACT_STMT(STMT)
-#define STMT(CLASS, PARENT) \
- case Stmt::CLASS##Class: \
- DISPATCH_STMT(CLASS, CLASS, S);
-#include "clang/AST/StmtNodes.inc"
+ size_t N = LocalQueue.size();
+ TRY_TO(dataTraverseNode(CurrS, &LocalQueue));
+ // Process new children in the order they were added.
+ std::reverse(LocalQueue.begin() + N, LocalQueue.end());
}
return true;
}
-#undef DISPATCH_STMT
+#define DISPATCH(NAME, CLASS, VAR) \
+ return getDerived().Traverse##NAME(static_cast<CLASS *>(VAR))
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
@@ -863,8 +822,9 @@ RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
}
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(LambdaExpr *LE) {
- TRY_TO(TraverseStmt(LE->getBody()));
+bool RecursiveASTVisitor<Derived>::TraverseLambdaBody(
+ LambdaExpr *LE, DataRecursionQueue *Queue) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(LE->getBody());
return true;
}
@@ -1364,6 +1324,8 @@ DEF_TRAVERSE_DECL(
DEF_TRAVERSE_DECL(ExternCContextDecl, {})
DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+
// We shouldn't traverse an aliased namespace, since it will be
// defined (and, therefore, traversed) somewhere else.
//
@@ -1596,6 +1558,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
})
+DEF_TRAVERSE_DECL(BuiltinTemplateDecl, {
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+})
+
DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
// D is the "T" in something like "template<typename T> class vector;"
if (D->getTypeForDecl())
@@ -1906,25 +1872,26 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
// This macro makes available a variable S, the passed-in stmt.
#define DEF_TRAVERSE_STMT(STMT, CODE) \
template <typename Derived> \
- bool RecursiveASTVisitor<Derived>::Traverse##STMT(STMT *S) { \
+ bool RecursiveASTVisitor<Derived>::Traverse##STMT( \
+ STMT *S, DataRecursionQueue *Queue) { \
TRY_TO(WalkUpFrom##STMT(S)); \
{ CODE; } \
for (Stmt *SubStmt : S->children()) { \
- TRY_TO(TraverseStmt(SubStmt)); \
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \
} \
return true; \
}
DEF_TRAVERSE_STMT(GCCAsmStmt, {
- TRY_TO(TraverseStmt(S->getAsmString()));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAsmString());
for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
- TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I)));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getInputConstraintLiteral(I));
}
for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
- TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I)));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOutputConstraintLiteral(I));
}
for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
- TRY_TO(TraverseStmt(S->getClobberStringLiteral(I)));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getClobberStringLiteral(I));
}
// children() iterates over inputExpr and outputExpr.
})
@@ -1977,9 +1944,9 @@ DEF_TRAVERSE_STMT(ObjCForCollectionStmt, {})
DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, {})
DEF_TRAVERSE_STMT(CXXForRangeStmt, {
if (!getDerived().shouldVisitImplicitCode()) {
- TRY_TO(TraverseStmt(S->getLoopVarStmt()));
- TRY_TO(TraverseStmt(S->getRangeInit()));
- TRY_TO(TraverseStmt(S->getBody()));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLoopVarStmt());
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit());
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
// Visit everything else only if shouldVisitImplicitCode().
return true;
}
@@ -2012,9 +1979,8 @@ DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
if (S->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- S->getExplicitTemplateArgs().getTemplateArgs(),
- S->getNumTemplateArgs()));
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
}
})
@@ -2055,64 +2021,60 @@ DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
})
-// InitListExpr is a tricky one, because we want to do all our work on
-// the syntactic form of the listexpr, but this method takes the
-// semantic form by default. We can't use the macro helper because it
-// calls WalkUp*() on the semantic form, before our code can convert
-// to the syntactic form.
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
- InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
- if (Syn) {
- TRY_TO(WalkUpFromInitListExpr(Syn));
+bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
+ InitListExpr *S, DataRecursionQueue *Queue) {
+ if (S) {
+ TRY_TO(WalkUpFromInitListExpr(S));
// All we need are the default actions. FIXME: use a helper function.
- for (Stmt *SubStmt : Syn->children()) {
- TRY_TO(TraverseStmt(SubStmt));
- }
- }
- InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
- if (Sem) {
- TRY_TO(WalkUpFromInitListExpr(Sem));
- for (Stmt *SubStmt : Sem->children()) {
- TRY_TO(TraverseStmt(SubStmt));
+ for (Stmt *SubStmt : S->children()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt);
}
}
return true;
}
+// This method is called once for each pair of syntactic and semantic
+// InitListExpr, and it traverses the subtrees defined by the two forms. This
+// may cause some of the children to be visited twice, if they appear both in
+// the syntactic and the semantic form.
+//
+// There is no guarantee about which form \p S takes when this method is called.
+DEF_TRAVERSE_STMT(InitListExpr, {
+ TRY_TO(TraverseSynOrSemInitListExpr(
+ S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
+ TRY_TO(TraverseSynOrSemInitListExpr(
+ S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
+ return true;
+})
+
// GenericSelectionExpr is a special case because the types and expressions
// are interleaved. We also need to watch out for null types (default
// generic associations).
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseGenericSelectionExpr(
- GenericSelectionExpr *S) {
- TRY_TO(WalkUpFromGenericSelectionExpr(S));
+DEF_TRAVERSE_STMT(GenericSelectionExpr, {
TRY_TO(TraverseStmt(S->getControllingExpr()));
for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
- TRY_TO(TraverseStmt(S->getAssocExpr(i)));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i));
}
return true;
-}
+})
-// PseudoObjectExpr is a special case because of the wierdness with
+// PseudoObjectExpr is a special case because of the weirdness with
// syntactic expressions and opaque values.
-template <typename Derived>
-bool
-RecursiveASTVisitor<Derived>::TraversePseudoObjectExpr(PseudoObjectExpr *S) {
- TRY_TO(WalkUpFromPseudoObjectExpr(S));
- TRY_TO(TraverseStmt(S->getSyntacticForm()));
+DEF_TRAVERSE_STMT(PseudoObjectExpr, {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSyntacticForm());
for (PseudoObjectExpr::semantics_iterator i = S->semantics_begin(),
e = S->semantics_end();
i != e; ++i) {
Expr *sub = *i;
if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
sub = OVE->getSourceExpr();
- TRY_TO(TraverseStmt(sub));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub);
}
return true;
-}
+})
DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
// This is called for code like 'return T()' where T is a built-in
@@ -2151,6 +2113,8 @@ DEF_TRAVERSE_STMT(MSPropertyRefExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
})
+DEF_TRAVERSE_STMT(MSPropertySubscriptExpr, {})
+
DEF_TRAVERSE_STMT(CXXUuidofExpr, {
// The child-iterator will pick up the arg if it's an expression,
// but not if it's a type.
@@ -2168,7 +2132,7 @@ DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
})
DEF_TRAVERSE_STMT(ExpressionTraitExpr,
- { TRY_TO(TraverseStmt(S->getQueriedExpression())); })
+ { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getQueriedExpression()); })
DEF_TRAVERSE_STMT(VAArgExpr, {
// The child-iterator will pick up the expression argument.
@@ -2181,10 +2145,7 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
})
// Walk only the visible parts of lambda expressions.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
- TRY_TO(WalkUpFromLambdaExpr(S));
-
+DEF_TRAVERSE_STMT(LambdaExpr, {
for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
CEnd = S->explicit_capture_end();
C != CEnd; ++C) {
@@ -2213,12 +2174,11 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
}
if (Expr *NE = T->getNoexceptExpr())
- TRY_TO(TraverseStmt(NE));
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE);
}
- TRY_TO(TraverseLambdaBody(S));
- return true;
-}
+ return TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue);
+})
DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
// This is called for code like 'T()', where T is a template argument.
@@ -2235,6 +2195,7 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
+DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})
DEF_TRAVERSE_STMT(BlockExpr, {
TRY_TO(TraverseDecl(S->getBlockDecl()));
return true; // no child statements to loop through.
@@ -2336,6 +2297,34 @@ DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
DEF_TRAVERSE_STMT(CXXFoldExpr, {})
DEF_TRAVERSE_STMT(AtomicExpr, {})
+// For coroutines expressions, traverse either the operand
+// as written or the implied calls, depending on what the
+// derived class requests.
+DEF_TRAVERSE_STMT(CoroutineBodyStmt, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody());
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(CoreturnStmt, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(CoawaitExpr, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
+ return true;
+ }
+})
+DEF_TRAVERSE_STMT(CoyieldExpr, {
+ if (!getDerived().shouldVisitImplicitCode()) {
+ TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand());
+ return true;
+ }
+})
+
// These literals (all of them) do not need any action.
DEF_TRAVERSE_STMT(IntegerLiteral, {})
DEF_TRAVERSE_STMT(CharacterLiteral, {})
@@ -2437,9 +2426,21 @@ DEF_TRAVERSE_STMT(OMPAtomicDirective,
DEF_TRAVERSE_STMT(OMPTargetDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPTargetDataDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPTeamsDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPTaskLoopDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPDistributeDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
// OpenMP clauses.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
@@ -2484,6 +2485,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
+ TRY_TO(TraverseStmt(C->getSimdlen()));
+ return true;
+}
+
+template <typename Derived>
bool
RecursiveASTVisitor<Derived>::VisitOMPCollapseClause(OMPCollapseClause *C) {
TRY_TO(TraverseStmt(C->getNumForLoops()));
@@ -2509,7 +2516,8 @@ RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
}
template <typename Derived>
-bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *) {
+bool RecursiveASTVisitor<Derived>::VisitOMPOrderedClause(OMPOrderedClause *C) {
+ TRY_TO(TraverseStmt(C->getNumForLoops()));
return true;
}
@@ -2555,6 +2563,21 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) {
}
template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPThreadsClause(OMPThreadsClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPSIMDClause(OMPSIMDClause *) {
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNogroupClause(OMPNogroupClause *) {
+ return true;
+}
+
+template <typename Derived>
template <typename T>
bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) {
for (auto *E : Node->varlists()) {
@@ -2615,6 +2638,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
TRY_TO(TraverseStmt(C->getStep()));
TRY_TO(TraverseStmt(C->getCalcStep()));
TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->privates()) {
+ TRY_TO(TraverseStmt(E));
+ }
for (auto *E : C->inits()) {
TRY_TO(TraverseStmt(E));
}
@@ -2671,6 +2697,9 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
TRY_TO(VisitOMPClauseList(C));
+ for (auto *E : C->privates()) {
+ TRY_TO(TraverseStmt(E));
+ }
for (auto *E : C->lhs_exprs()) {
TRY_TO(TraverseStmt(E));
}
@@ -2695,6 +2724,59 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPDeviceClause(OMPDeviceClause *C) {
+ TRY_TO(TraverseStmt(C->getDevice()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPMapClause(OMPMapClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNumTeamsClause(
+ OMPNumTeamsClause *C) {
+ TRY_TO(TraverseStmt(C->getNumTeams()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPThreadLimitClause(
+ OMPThreadLimitClause *C) {
+ TRY_TO(TraverseStmt(C->getThreadLimit()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPPriorityClause(
+ OMPPriorityClause *C) {
+ TRY_TO(TraverseStmt(C->getPriority()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPGrainsizeClause(
+ OMPGrainsizeClause *C) {
+ TRY_TO(TraverseStmt(C->getGrainsize()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause(
+ OMPNumTasksClause *C) {
+ TRY_TO(TraverseStmt(C->getNumTasks()));
+ return true;
+}
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) {
+ TRY_TO(TraverseStmt(C->getHint()));
+ return true;
+}
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
@@ -2713,6 +2795,8 @@ bool RecursiveASTVisitor<Derived>::VisitOMPDependClause(OMPDependClause *C) {
// Every class that has getQualifier.
#undef DEF_TRAVERSE_STMT
+#undef TRAVERSE_STMT
+#undef TRAVERSE_STMT_BASE
#undef TRY_TO
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index 92046d5..eaa22f8 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -20,6 +20,7 @@
#include <iterator>
namespace clang {
+class ASTContext;
/// \brief Provides common interface for the Decls that can be redeclared.
template<typename decl_type>
@@ -32,7 +33,11 @@ protected:
&ExternalASTSource::CompleteRedeclChain>
KnownLatest;
- typedef const ASTContext *UninitializedLatest;
+ /// We store a pointer to the ASTContext in the UninitializedLatest
+ /// pointer, but to avoid circular type dependencies when we steal the low
+ /// bits of this pointer, we use a raw void* here.
+ typedef const void *UninitializedLatest;
+
typedef Decl *Previous;
/// A pointer to either an uninitialized latest declaration (where either
@@ -47,7 +52,7 @@ protected:
enum LatestTag { LatestLink };
DeclLink(LatestTag, const ASTContext &Ctx)
- : Next(NotKnownLatest(&Ctx)) {}
+ : Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {}
DeclLink(PreviousTag, decl_type *D)
: Next(NotKnownLatest(Previous(D))) {}
@@ -67,7 +72,8 @@ protected:
return static_cast<decl_type*>(NKL.get<Previous>());
// Allocate the generational 'most recent' cache now, if needed.
- Next = KnownLatest(*NKL.get<UninitializedLatest>(),
+ Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ NKL.get<UninitializedLatest>()),
const_cast<decl_type *>(D));
}
@@ -83,7 +89,9 @@ protected:
assert(NextIsLatest() && "decl became canonical unexpectedly");
if (Next.is<NotKnownLatest>()) {
NotKnownLatest NKL = Next.get<NotKnownLatest>();
- Next = KnownLatest(*NKL.get<UninitializedLatest>(), D);
+ Next = KnownLatest(*reinterpret_cast<const ASTContext *>(
+ NKL.get<UninitializedLatest>()),
+ D);
} else {
auto Latest = Next.get<KnownLatest>();
Latest.set(D);
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index ce9449d..e48b7dc 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -22,6 +22,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <string>
@@ -49,57 +50,6 @@ namespace clang {
class Token;
class VarDecl;
- //===--------------------------------------------------------------------===//
- // ExprIterator - Iterators for iterating over Stmt* arrays that contain
- // only Expr*. This is needed because AST nodes use Stmt* arrays to store
- // references to children (to be compatible with StmtIterator).
- //===--------------------------------------------------------------------===//
-
- class Stmt;
- class Expr;
-
- class ExprIterator : public std::iterator<std::forward_iterator_tag,
- Expr *&, ptrdiff_t,
- Expr *&, Expr *&> {
- Stmt** I;
- public:
- ExprIterator(Stmt** i) : I(i) {}
- ExprIterator() : I(nullptr) {}
- ExprIterator& operator++() { ++I; return *this; }
- ExprIterator operator-(size_t i) { return I-i; }
- ExprIterator operator+(size_t i) { return I+i; }
- Expr* operator[](size_t idx);
- // FIXME: Verify that this will correctly return a signed distance.
- signed operator-(const ExprIterator& R) const { return I - R.I; }
- Expr* operator*() const;
- Expr* operator->() const;
- bool operator==(const ExprIterator& R) const { return I == R.I; }
- bool operator!=(const ExprIterator& R) const { return I != R.I; }
- bool operator>(const ExprIterator& R) const { return I > R.I; }
- bool operator>=(const ExprIterator& R) const { return I >= R.I; }
- };
-
- class ConstExprIterator : public std::iterator<std::forward_iterator_tag,
- const Expr *&, ptrdiff_t,
- const Expr *&,
- const Expr *&> {
- const Stmt * const *I;
- public:
- ConstExprIterator(const Stmt * const *i) : I(i) {}
- ConstExprIterator() : I(nullptr) {}
- ConstExprIterator& operator++() { ++I; return *this; }
- ConstExprIterator operator+(size_t i) const { return I+i; }
- ConstExprIterator operator-(size_t i) const { return I-i; }
- const Expr * operator[](size_t idx) const;
- signed operator-(const ConstExprIterator& R) const { return I - R.I; }
- const Expr * operator*() const;
- const Expr * operator->() const;
- bool operator==(const ConstExprIterator& R) const { return I == R.I; }
- bool operator!=(const ConstExprIterator& R) const { return I != R.I; }
- bool operator>(const ConstExprIterator& R) const { return I > R.I; }
- bool operator>=(const ConstExprIterator& R) const { return I >= R.I; }
- };
-
//===----------------------------------------------------------------------===//
// AST classes for statements.
//===----------------------------------------------------------------------===//
@@ -121,10 +71,10 @@ public:
// Make vanilla 'new' and 'delete' illegal for Stmts.
protected:
- void* operator new(size_t bytes) throw() {
+ void *operator new(size_t bytes) LLVM_NOEXCEPT {
llvm_unreachable("Stmts cannot be allocated with regular 'new'.");
}
- void operator delete(void* data) throw() {
+ void operator delete(void *data) LLVM_NOEXCEPT {
llvm_unreachable("Stmts cannot be released with regular 'delete'.");
}
@@ -322,14 +272,12 @@ public:
return operator new(bytes, *C, alignment);
}
- void* operator new(size_t bytes, void* mem) throw() {
- return mem;
- }
+ void *operator new(size_t bytes, void *mem) LLVM_NOEXCEPT { return mem; }
- void operator delete(void*, const ASTContext&, unsigned) throw() { }
- void operator delete(void*, const ASTContext*, unsigned) throw() { }
- void operator delete(void*, size_t) throw() { }
- void operator delete(void*, void*) throw() { }
+ void operator delete(void *, const ASTContext &, unsigned) LLVM_NOEXCEPT {}
+ void operator delete(void *, const ASTContext *, unsigned) LLVM_NOEXCEPT {}
+ void operator delete(void *, size_t) LLVM_NOEXCEPT {}
+ void operator delete(void *, void *) LLVM_NOEXCEPT {}
public:
/// \brief A placeholder type used to construct an empty shell of a
@@ -337,6 +285,39 @@ public:
/// de-serialization).
struct EmptyShell { };
+protected:
+ /// Iterator for iterating over Stmt * arrays that contain only Expr *
+ ///
+ /// This is needed because AST nodes use Stmt* arrays to store
+ /// references to children (to be compatible with StmtIterator).
+ struct ExprIterator
+ : llvm::iterator_adaptor_base<ExprIterator, Stmt **,
+ std::random_access_iterator_tag, Expr *> {
+ ExprIterator() : iterator_adaptor_base(nullptr) {}
+ ExprIterator(Stmt **I) : iterator_adaptor_base(I) {}
+
+ reference operator*() const {
+ assert((*I)->getStmtClass() >= firstExprConstant &&
+ (*I)->getStmtClass() <= lastExprConstant);
+ return *reinterpret_cast<Expr **>(I);
+ }
+ };
+
+ /// Const iterator for iterating over Stmt * arrays that contain only Expr *
+ struct ConstExprIterator
+ : llvm::iterator_adaptor_base<ConstExprIterator, const Stmt *const *,
+ std::random_access_iterator_tag,
+ const Expr *const> {
+ ConstExprIterator() : iterator_adaptor_base(nullptr) {}
+ ConstExprIterator(const Stmt *const *I) : iterator_adaptor_base(I) {}
+
+ reference operator*() const {
+ assert((*I)->getStmtClass() >= firstExprConstant &&
+ (*I)->getStmtClass() <= lastExprConstant);
+ return *reinterpret_cast<const Expr *const *>(I);
+ }
+ };
+
private:
/// \brief Whether statistic collection is enabled.
static bool StatisticsEnabled;
@@ -411,19 +392,20 @@ public:
typedef StmtIterator child_iterator;
typedef ConstStmtIterator const_child_iterator;
- typedef StmtRange child_range;
- typedef ConstStmtRange const_child_range;
+ typedef llvm::iterator_range<child_iterator> child_range;
+ typedef llvm::iterator_range<const_child_iterator> const_child_range;
child_range children();
const_child_range children() const {
- return const_cast<Stmt*>(this)->children();
+ auto Children = const_cast<Stmt *>(this)->children();
+ return const_child_range(Children.begin(), Children.end());
}
- child_iterator child_begin() { return children().first; }
- child_iterator child_end() { return children().second; }
+ child_iterator child_begin() { return children().begin(); }
+ child_iterator child_end() { return children().end(); }
- const_child_iterator child_begin() const { return children().first; }
- const_child_iterator child_end() const { return children().second; }
+ const_child_iterator child_begin() const { return children().begin(); }
+ const_child_iterator child_end() const { return children().end(); }
/// \brief Produce a unique representation of the given statement.
///
@@ -544,7 +526,9 @@ public:
return T->getStmtClass() == NullStmtClass;
}
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
friend class ASTStmtReader;
friend class ASTStmtWriter;
@@ -574,7 +558,7 @@ public:
CompoundStmtBits.NumStmts = 0;
}
- void setStmts(const ASTContext &C, Stmt **Stmts, unsigned NumStmts);
+ void setStmts(const ASTContext &C, ArrayRef<Stmt *> Stmts);
bool body_empty() const { return CompoundStmtBits.NumStmts == 0; }
unsigned size() const { return CompoundStmtBits.NumStmts; }
@@ -643,7 +627,8 @@ public:
}
const_child_range children() const {
- return child_range(Body, Body + CompoundStmtBits.NumStmts);
+ return const_child_range(child_iterator(Body),
+ child_iterator(Body + CompoundStmtBits.NumStmts));
}
};
@@ -840,18 +825,20 @@ class AttributedStmt : public Stmt {
AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
: Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
NumAttrs(Attrs.size()) {
- memcpy(getAttrArrayPtr(), Attrs.data(), Attrs.size() * sizeof(Attr *));
+ std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr());
}
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
: Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
- memset(getAttrArrayPtr(), 0, NumAttrs * sizeof(Attr *));
+ std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr);
}
- Attr *const *getAttrArrayPtr() const {
- return reinterpret_cast<Attr *const *>(this + 1);
+ const Attr *const *getAttrArrayPtr() const {
+ return reinterpret_cast<const Attr *const *>(this + 1);
+ }
+ const Attr **getAttrArrayPtr() {
+ return reinterpret_cast<const Attr **>(this + 1);
}
- Attr **getAttrArrayPtr() { return reinterpret_cast<Attr **>(this + 1); }
public:
static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
@@ -1239,7 +1226,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// IndirectGotoStmt - This represents an indirect goto.
@@ -1307,7 +1296,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// BreakStmt - This represents a break.
@@ -1335,7 +1326,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
@@ -1390,7 +1383,7 @@ public:
// Iterators
child_range children() {
if (RetExpr) return child_range(&RetExpr, &RetExpr+1);
- return child_range();
+ return child_range(child_iterator(), child_iterator());
}
};
@@ -1974,7 +1967,9 @@ public:
}
// Iterators
- child_range children() { return child_range(); }
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
};
/// \brief This captures a statement into a function. For example, the following
@@ -1993,6 +1988,7 @@ public:
enum VariableCaptureKind {
VCK_This,
VCK_ByRef,
+ VCK_ByCopy,
VCK_VLAType,
};
@@ -2012,24 +2008,10 @@ public:
/// \param Var The variable being captured, or null if capturing this.
///
Capture(SourceLocation Loc, VariableCaptureKind Kind,
- VarDecl *Var = nullptr)
- : VarAndKind(Var, Kind), Loc(Loc) {
- switch (Kind) {
- case VCK_This:
- assert(!Var && "'this' capture cannot have a variable!");
- break;
- case VCK_ByRef:
- assert(Var && "capturing by reference must have a variable!");
- break;
- case VCK_VLAType:
- assert(!Var &&
- "Variable-length array type capture cannot have a variable!");
- break;
- }
- }
+ VarDecl *Var = nullptr);
/// \brief Determine the kind of capture.
- VariableCaptureKind getCaptureKind() const { return VarAndKind.getInt(); }
+ VariableCaptureKind getCaptureKind() const;
/// \brief Retrieve the source location at which the variable or 'this' was
/// first used.
@@ -2038,9 +2020,14 @@ public:
/// \brief Determine whether this capture handles the C++ 'this' pointer.
bool capturesThis() const { return getCaptureKind() == VCK_This; }
- /// \brief Determine whether this capture handles a variable.
+ /// \brief Determine whether this capture handles a variable (by reference).
bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; }
+ /// \brief Determine whether this capture handles a variable by copy.
+ bool capturesVariableByCopy() const {
+ return getCaptureKind() == VCK_ByCopy;
+ }
+
/// \brief Determine whether this capture handles a variable-length array
/// type.
bool capturesVariableArrayType() const {
@@ -2050,11 +2037,8 @@ public:
/// \brief Retrieve the declaration of the variable being captured.
///
/// This operation is only valid if this capture captures a variable.
- VarDecl *getCapturedVar() const {
- assert(capturesVariable() &&
- "No variable available for 'this' or VAT capture");
- return VarAndKind.getPointer();
- }
+ VarDecl *getCapturedVar() const;
+
friend class ASTStmtReader;
};
@@ -2076,8 +2060,10 @@ private:
/// \brief Construct an empty captured statement.
CapturedStmt(EmptyShell Empty, unsigned NumCaptures);
- Stmt **getStoredStmts() const {
- return reinterpret_cast<Stmt **>(const_cast<CapturedStmt *>(this) + 1);
+ Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); }
+
+ Stmt *const *getStoredStmts() const {
+ return reinterpret_cast<Stmt *const *>(this + 1);
}
Capture *getStoredCaptures() const;
@@ -2096,31 +2082,20 @@ public:
/// \brief Retrieve the statement being captured.
Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; }
- const Stmt *getCapturedStmt() const {
- return const_cast<CapturedStmt *>(this)->getCapturedStmt();
- }
+ const Stmt *getCapturedStmt() const { return getStoredStmts()[NumCaptures]; }
/// \brief Retrieve the outlined function declaration.
- CapturedDecl *getCapturedDecl() { return CapDeclAndKind.getPointer(); }
- const CapturedDecl *getCapturedDecl() const {
- return const_cast<CapturedStmt *>(this)->getCapturedDecl();
- }
+ CapturedDecl *getCapturedDecl();
+ const CapturedDecl *getCapturedDecl() const;
/// \brief Set the outlined function declaration.
- void setCapturedDecl(CapturedDecl *D) {
- assert(D && "null CapturedDecl");
- CapDeclAndKind.setPointer(D);
- }
+ void setCapturedDecl(CapturedDecl *D);
/// \brief Retrieve the captured region kind.
- CapturedRegionKind getCapturedRegionKind() const {
- return CapDeclAndKind.getInt();
- }
+ CapturedRegionKind getCapturedRegionKind() const;
/// \brief Set the captured region kind.
- void setCapturedRegionKind(CapturedRegionKind Kind) {
- CapDeclAndKind.setInt(Kind);
- }
+ void setCapturedRegionKind(CapturedRegionKind Kind);
/// \brief Retrieve the record declaration for captured variables.
const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; }
@@ -2164,18 +2139,36 @@ public:
typedef Expr **capture_init_iterator;
typedef llvm::iterator_range<capture_init_iterator> capture_init_range;
- capture_init_range capture_inits() const {
+ /// \brief Const iterator that walks over the capture initialization
+ /// arguments.
+ typedef Expr *const *const_capture_init_iterator;
+ typedef llvm::iterator_range<const_capture_init_iterator>
+ const_capture_init_range;
+
+ capture_init_range capture_inits() {
return capture_init_range(capture_init_begin(), capture_init_end());
}
+ const_capture_init_range capture_inits() const {
+ return const_capture_init_range(capture_init_begin(), capture_init_end());
+ }
+
/// \brief Retrieve the first initialization argument.
- capture_init_iterator capture_init_begin() const {
+ capture_init_iterator capture_init_begin() {
return reinterpret_cast<Expr **>(getStoredStmts());
}
+ 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.
- capture_init_iterator capture_init_end() const {
+ capture_init_iterator capture_init_end() {
+ return capture_init_begin() + NumCaptures;
+ }
+
+ const_capture_init_iterator capture_init_end() const {
return capture_init_begin() + NumCaptures;
}
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 567a772..1ca73e2 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -131,12 +131,16 @@ class CXXForRangeStmt : public Stmt {
// SubExprs[RANGE] is an expression or declstmt.
// SubExprs[COND] and SubExprs[INC] are expressions.
Stmt *SubExprs[END];
+ SourceLocation CoawaitLoc;
SourceLocation ColonLoc;
SourceLocation RParenLoc;
+
+ friend class ASTStmtReader;
public:
CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd,
Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body,
- SourceLocation FL, SourceLocation CL, SourceLocation RPL);
+ SourceLocation FL, SourceLocation CAL, SourceLocation CL,
+ SourceLocation RPL);
CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
@@ -181,13 +185,10 @@ public:
void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; }
void setBody(Stmt *S) { SubExprs[BODY] = S; }
-
SourceLocation getForLoc() const { return ForLoc; }
- void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
+ SourceLocation getCoawaitLoc() const { return CoawaitLoc; }
SourceLocation getColonLoc() const { return ColonLoc; }
- void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
- void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
@@ -287,6 +288,130 @@ public:
}
};
+/// \brief Represents the body of a coroutine. This wraps the normal function
+/// body and holds the additional semantic context required to set up and tear
+/// down the coroutine frame.
+class CoroutineBodyStmt : public Stmt {
+ enum SubStmt {
+ Body, ///< The body of the coroutine.
+ Promise, ///< The promise statement.
+ InitSuspend, ///< The initial suspend statement, run before the body.
+ FinalSuspend, ///< The final suspend statement, run after the body.
+ OnException, ///< Handler for exceptions thrown in the body.
+ OnFallthrough, ///< Handler for control flow falling off the body.
+ ReturnValue, ///< Return value for thunk function.
+ FirstParamMove ///< First offset for move construction of parameter copies.
+ };
+ Stmt *SubStmts[SubStmt::FirstParamMove];
+
+ friend class ASTStmtReader;
+public:
+ CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend,
+ Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough,
+ Expr *ReturnValue, ArrayRef<Expr *> ParamMoves)
+ : Stmt(CoroutineBodyStmtClass) {
+ SubStmts[CoroutineBodyStmt::Body] = Body;
+ SubStmts[CoroutineBodyStmt::Promise] = Promise;
+ SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend;
+ SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend;
+ SubStmts[CoroutineBodyStmt::OnException] = OnException;
+ SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough;
+ SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue;
+ // FIXME: Tail-allocate space for parameter move expressions and store them.
+ assert(ParamMoves.empty() && "not implemented yet");
+ }
+
+ /// \brief Retrieve the body of the coroutine as written. This will be either
+ /// a CompoundStmt or a TryStmt.
+ Stmt *getBody() const {
+ return SubStmts[SubStmt::Body];
+ }
+
+ Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; }
+ VarDecl *getPromiseDecl() const {
+ return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl());
+ }
+
+ Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; }
+ Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; }
+
+ Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; }
+ Stmt *getFallthroughHandler() const {
+ return SubStmts[SubStmt::OnFallthrough];
+ }
+
+ Expr *getReturnValueInit() const {
+ return cast<Expr>(SubStmts[SubStmt::ReturnValue]);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBody()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getBody()->getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoroutineBodyStmtClass;
+ }
+};
+
+/// \brief Represents a 'co_return' statement in the C++ Coroutines TS.
+///
+/// This statament models the initialization of the coroutine promise
+/// (encapsulating the eventual notional return value) from an expression
+/// (or braced-init-list), followed by termination of the coroutine.
+///
+/// This initialization is modeled by the evaluation of the operand
+/// followed by a call to one of:
+/// <promise>.return_value(<operand>)
+/// <promise>.return_void()
+/// which we name the "promise call".
+class CoreturnStmt : public Stmt {
+ SourceLocation CoreturnLoc;
+
+ enum SubStmt { Operand, PromiseCall, Count };
+ Stmt *SubStmts[SubStmt::Count];
+
+ friend class ASTStmtReader;
+public:
+ CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall)
+ : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) {
+ SubStmts[SubStmt::Operand] = Operand;
+ SubStmts[SubStmt::PromiseCall] = PromiseCall;
+ }
+
+ SourceLocation getKeywordLoc() const { return CoreturnLoc; }
+
+ /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr
+ /// if none was specified.
+ Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); }
+
+ /// \brief Retrieve the promise call that results from this 'co_return'
+ /// statement. Will be nullptr if either the coroutine has not yet been
+ /// finalized or the coroutine has no eventual return type.
+ Expr *getPromiseCall() const {
+ return static_cast<Expr*>(SubStmts[PromiseCall]);
+ }
+
+ SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; }
+ SourceLocation getLocEnd() const LLVM_READONLY {
+ return getOperand()->getLocEnd();
+ }
+
+ child_range children() {
+ return child_range(SubStmts, SubStmts + SubStmt::Count);
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == CoreturnStmtClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index a5a57af..81f8ad43 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -139,86 +139,6 @@ struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
};
-/// A range of statement iterators.
-///
-/// This class provides some extra functionality beyond std::pair
-/// in order to allow the following idiom:
-/// for (StmtRange range = stmt->children(); range; ++range)
-struct StmtRange : std::pair<StmtIterator,StmtIterator> {
- StmtRange() {}
- StmtRange(const StmtIterator &begin, const StmtIterator &end)
- : std::pair<StmtIterator,StmtIterator>(begin, end) {}
-
- bool empty() const { return first == second; }
- explicit operator bool() const { return !empty(); }
-
- Stmt *operator->() const { return first.operator->(); }
- Stmt *&operator*() const { return first.operator*(); }
-
- StmtRange &operator++() {
- assert(!empty() && "incrementing on empty range");
- ++first;
- return *this;
- }
-
- StmtRange operator++(int) {
- assert(!empty() && "incrementing on empty range");
- StmtRange copy = *this;
- ++first;
- return copy;
- }
-
- friend const StmtIterator &begin(const StmtRange &range) {
- return range.first;
- }
- friend const StmtIterator &end(const StmtRange &range) {
- return range.second;
- }
-};
-
-/// A range of const statement iterators.
-///
-/// This class provides some extra functionality beyond std::pair
-/// in order to allow the following idiom:
-/// for (ConstStmtRange range = stmt->children(); range; ++range)
-struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
- ConstStmtRange() {}
- ConstStmtRange(const ConstStmtIterator &begin,
- const ConstStmtIterator &end)
- : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
- ConstStmtRange(const StmtRange &range)
- : std::pair<ConstStmtIterator,ConstStmtIterator>(range.first, range.second)
- {}
- ConstStmtRange(const StmtIterator &begin, const StmtIterator &end)
- : std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
-
- bool empty() const { return first == second; }
- explicit operator bool() const { return !empty(); }
-
- const Stmt *operator->() const { return first.operator->(); }
- const Stmt *operator*() const { return first.operator*(); }
-
- ConstStmtRange &operator++() {
- assert(!empty() && "incrementing on empty range");
- ++first;
- return *this;
- }
-
- ConstStmtRange operator++(int) {
- assert(!empty() && "incrementing on empty range");
- ConstStmtRange copy = *this;
- ++first;
- return copy;
- }
-
- friend const ConstStmtIterator &begin(const ConstStmtRange &range) {
- return range.first;
- }
- friend const ConstStmtIterator &end(const ConstStmtRange &range) {
- return range.second;
- }
-};
-
} // end namespace clang
#endif
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index 708b866..1ba859c 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -92,65 +92,78 @@ public:
/// \brief Iterates over a filtered subrange of clauses applied to a
/// directive.
///
- /// This iterator visits only those declarations that meet some run-time
- /// criteria.
- template <class FilterPredicate> class filtered_clause_iterator {
- protected:
- ArrayRef<OMPClause *>::const_iterator Current;
+ /// This iterator visits only clauses of type SpecificClause.
+ template <typename SpecificClause>
+ class specific_clause_iterator
+ : public llvm::iterator_adaptor_base<
+ specific_clause_iterator<SpecificClause>,
+ ArrayRef<OMPClause *>::const_iterator, std::forward_iterator_tag,
+ const SpecificClause *, ptrdiff_t, const SpecificClause *,
+ const SpecificClause *> {
ArrayRef<OMPClause *>::const_iterator End;
- FilterPredicate Pred;
+
void SkipToNextClause() {
- while (Current != End && !Pred(*Current))
- ++Current;
+ while (this->I != End && !isa<SpecificClause>(*this->I))
+ ++this->I;
}
public:
- typedef const OMPClause *value_type;
- filtered_clause_iterator() : Current(), End() {}
- filtered_clause_iterator(ArrayRef<OMPClause *> Arr, FilterPredicate Pred)
- : Current(Arr.begin()), End(Arr.end()), Pred(std::move(Pred)) {
+ explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses)
+ : specific_clause_iterator::iterator_adaptor_base(Clauses.begin()),
+ End(Clauses.end()) {
SkipToNextClause();
}
- value_type operator*() const { return *Current; }
- value_type operator->() const { return *Current; }
- filtered_clause_iterator &operator++() {
- ++Current;
- SkipToNextClause();
- return *this;
- }
- filtered_clause_iterator operator++(int) {
- filtered_clause_iterator tmp(*this);
- ++(*this);
- return tmp;
+ const SpecificClause *operator*() const {
+ return cast<SpecificClause>(*this->I);
}
+ const SpecificClause *operator->() const { return **this; }
- bool operator!() { return Current == End; }
- explicit operator bool() { return Current != End; }
- bool empty() const { return Current == End; }
+ specific_clause_iterator &operator++() {
+ ++this->I;
+ SkipToNextClause();
+ return *this;
+ }
};
- template <typename Fn>
- filtered_clause_iterator<Fn> getFilteredClauses(Fn &&fn) const {
- return filtered_clause_iterator<Fn>(clauses(), std::move(fn));
+ template <typename SpecificClause>
+ static llvm::iterator_range<specific_clause_iterator<SpecificClause>>
+ getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
+ return {specific_clause_iterator<SpecificClause>(Clauses),
+ specific_clause_iterator<SpecificClause>(
+ llvm::makeArrayRef(Clauses.end(), 0))};
}
- struct ClauseKindFilter {
- OpenMPClauseKind Kind;
- bool operator()(const OMPClause *clause) const {
- return clause->getClauseKind() == Kind;
- }
- };
- filtered_clause_iterator<ClauseKindFilter>
- getClausesOfKind(OpenMPClauseKind Kind) const {
- return getFilteredClauses(ClauseKindFilter{Kind});
+
+ template <typename SpecificClause>
+ llvm::iterator_range<specific_clause_iterator<SpecificClause>>
+ getClausesOfKind() const {
+ return getClausesOfKind<SpecificClause>(clauses());
}
- /// \brief Gets a single clause of the specified kind \a K associated with the
+ /// Gets a single clause of the specified kind associated with the
/// current directive iff there is only one clause of this kind (and assertion
/// is fired if there is more than one clause is associated with the
- /// directive). Returns nullptr if no clause of kind \a K is associated with
+ /// directive). Returns nullptr if no clause of this kind is associated with
/// the directive.
- const OMPClause *getSingleClause(OpenMPClauseKind K) const;
+ template <typename SpecificClause>
+ const SpecificClause *getSingleClause() const {
+ auto Clauses = getClausesOfKind<SpecificClause>();
+
+ if (Clauses.begin() != Clauses.end()) {
+ assert(std::next(Clauses.begin()) == Clauses.end() &&
+ "There are at least 2 clauses of the specified kind");
+ return *Clauses.begin();
+ }
+ return nullptr;
+ }
+
+ /// Returns true if the current directive has one or more clauses of a
+ /// specific kind.
+ template <typename SpecificClause>
+ bool hasClausesOfKind() const {
+ auto Clauses = getClausesOfKind<SpecificClause>();
+ return Clauses.begin() != Clauses.end();
+ }
/// \brief Returns starting location of directive kind.
SourceLocation getLocStart() const { return StartLoc; }
@@ -195,7 +208,7 @@ public:
child_range children() {
if (!hasAssociatedStmt())
- return child_range();
+ return child_range(child_iterator(), child_iterator());
Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end());
return child_range(ChildStorage, ChildStorage + NumChildren);
}
@@ -217,6 +230,10 @@ public:
/// variables 'c' and 'd'.
///
class OMPParallelDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief true if the construct has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive (directive keyword).
@@ -225,7 +242,8 @@ class OMPParallelDirective : public OMPExecutableDirective {
OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
- StartLoc, EndLoc, NumClauses, 1) {}
+ StartLoc, EndLoc, NumClauses, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -234,7 +252,11 @@ class OMPParallelDirective : public OMPExecutableDirective {
explicit OMPParallelDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
SourceLocation(), SourceLocation(), NumClauses,
- 1) {}
+ 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -244,10 +266,11 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement associated with the directive.
+ /// \param HasCancel true if this directive has inner cancel directive.
///
static OMPParallelDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive with the place for \a N clauses.
///
@@ -257,6 +280,9 @@ public:
static OMPParallelDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelDirectiveClass;
}
@@ -311,11 +337,18 @@ class OMPLoopDirective : public OMPExecutableDirective {
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
+ /// \brief Get the private counters storage.
+ MutableArrayRef<Expr *> getPrivateCounters() {
+ Expr **Storage = reinterpret_cast<Expr **>(&*std::next(
+ child_begin(), getArraysOffset(getDirectiveKind()) + CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
/// \brief Get the updates storage.
MutableArrayRef<Expr *> getInits() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
- getArraysOffset(getDirectiveKind()) + CollapsedNum));
+ getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
@@ -323,7 +356,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
MutableArrayRef<Expr *> getUpdates() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
- getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum));
+ getArraysOffset(getDirectiveKind()) + 3 * CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
@@ -331,7 +364,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
MutableArrayRef<Expr *> getFinals() {
Expr **Storage = reinterpret_cast<Expr **>(
&*std::next(child_begin(),
- getArraysOffset(getDirectiveKind()) + 3 * CollapsedNum));
+ getArraysOffset(getDirectiveKind()) + 4 * CollapsedNum));
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
@@ -358,15 +391,19 @@ protected:
/// \brief Offset to the start of children expression arrays.
static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
- return isOpenMPWorksharingDirective(Kind) ? WorksharingEnd
- : DefaultEnd;
+ return (isOpenMPWorksharingDirective(Kind) ||
+ isOpenMPTaskLoopDirective(Kind) ||
+ isOpenMPDistributeDirective(Kind))
+ ? WorksharingEnd
+ : DefaultEnd;
}
/// \brief Children number.
static unsigned numLoopChildren(unsigned CollapsedNum,
OpenMPDirectiveKind Kind) {
- return getArraysOffset(Kind) +
- 4 * CollapsedNum; // Counters, Inits, Updates and Finals
+ return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters,
+ // PrivateCounters, Inits,
+ // Updates and Finals
}
void setIterationVariable(Expr *IV) {
@@ -387,41 +424,56 @@ protected:
void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; }
void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; }
void setIsLastIterVariable(Expr *IL) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), IsLastIterVariableOffset) = IL;
}
void setLowerBoundVariable(Expr *LB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), LowerBoundVariableOffset) = LB;
}
void setUpperBoundVariable(Expr *UB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), UpperBoundVariableOffset) = UB;
}
void setStrideVariable(Expr *ST) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), StrideVariableOffset) = ST;
}
void setEnsureUpperBound(Expr *EUB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), EnsureUpperBoundOffset) = EUB;
}
void setNextLowerBound(Expr *NLB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), NextLowerBoundOffset) = NLB;
}
void setNextUpperBound(Expr *NUB) {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind()) ||
+ isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
*std::next(child_begin(), NextUpperBoundOffset) = NUB;
}
void setCounters(ArrayRef<Expr *> A);
+ void setPrivateCounters(ArrayRef<Expr *> A);
void setInits(ArrayRef<Expr *> A);
void setUpdates(ArrayRef<Expr *> A);
void setFinals(ArrayRef<Expr *> A);
@@ -462,6 +514,8 @@ public:
Expr *NUB;
/// \brief Counters Loop counters.
SmallVector<Expr *, 4> Counters;
+ /// \brief PrivateCounters Loop counters.
+ SmallVector<Expr *, 4> PrivateCounters;
/// \brief Expressions for loop counters inits for CodeGen.
SmallVector<Expr *, 4> Inits;
/// \brief Expressions for loop counters update for CodeGen.
@@ -495,11 +549,13 @@ public:
NLB = nullptr;
NUB = nullptr;
Counters.resize(Size);
+ PrivateCounters.resize(Size);
Inits.resize(Size);
Updates.resize(Size);
Finals.resize(Size);
for (unsigned i = 0; i < Size; ++i) {
Counters[i] = nullptr;
+ PrivateCounters[i] = nullptr;
Inits[i] = nullptr;
Updates[i] = nullptr;
Finals[i] = nullptr;
@@ -539,43 +595,50 @@ public:
reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset)));
}
Expr *getIsLastIterVariable() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), IsLastIterVariableOffset)));
}
Expr *getLowerBoundVariable() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), LowerBoundVariableOffset)));
}
Expr *getUpperBoundVariable() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), UpperBoundVariableOffset)));
}
Expr *getStrideVariable() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), StrideVariableOffset)));
}
Expr *getEnsureUpperBound() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), EnsureUpperBoundOffset)));
}
Expr *getNextLowerBound() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), NextLowerBoundOffset)));
}
Expr *getNextUpperBound() const {
- assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+ assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
+ isOpenMPTaskLoopDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), NextUpperBoundOffset)));
@@ -597,6 +660,12 @@ public:
return const_cast<OMPLoopDirective *>(this)->getCounters();
}
+ ArrayRef<Expr *> private_counters() { return getPrivateCounters(); }
+
+ ArrayRef<Expr *> private_counters() const {
+ return const_cast<OMPLoopDirective *>(this)->getPrivateCounters();
+ }
+
ArrayRef<Expr *> inits() { return getInits(); }
ArrayRef<Expr *> inits() const {
@@ -620,7 +689,10 @@ public:
T->getStmtClass() == OMPForDirectiveClass ||
T->getStmtClass() == OMPForSimdDirectiveClass ||
T->getStmtClass() == OMPParallelForDirectiveClass ||
- T->getStmtClass() == OMPParallelForSimdDirectiveClass;
+ T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
+ T->getStmtClass() == OMPTaskLoopDirectiveClass ||
+ T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
+ T->getStmtClass() == OMPDistributeDirectiveClass;
}
};
@@ -700,6 +772,10 @@ public:
///
class OMPForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -710,7 +786,8 @@ class OMPForDirective : public OMPLoopDirective {
OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc,
- CollapsedNum, NumClauses) {}
+ CollapsedNum, NumClauses),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -719,7 +796,11 @@ class OMPForDirective : public OMPLoopDirective {
///
explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(),
- SourceLocation(), CollapsedNum, NumClauses) {}
+ SourceLocation(), CollapsedNum, NumClauses),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -731,12 +812,13 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
+ /// \param HasCancel true if current directive has inner cancel directive.
///
static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc, unsigned CollapsedNum,
ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt,
- const HelperExprs &Exprs);
+ Stmt *AssociatedStmt, const HelperExprs &Exprs,
+ bool HasCancel);
/// \brief Creates an empty directive with the place
/// for \a NumClauses clauses.
@@ -748,6 +830,9 @@ public:
static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
unsigned CollapsedNum, EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPForDirectiveClass;
}
@@ -829,6 +914,10 @@ public:
///
class OMPSectionsDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -838,7 +927,8 @@ class OMPSectionsDirective : public OMPExecutableDirective {
OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections,
- StartLoc, EndLoc, NumClauses, 1) {}
+ StartLoc, EndLoc, NumClauses, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -847,7 +937,11 @@ class OMPSectionsDirective : public OMPExecutableDirective {
explicit OMPSectionsDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPSectionsDirectiveClass, OMPD_sections,
SourceLocation(), SourceLocation(), NumClauses,
- 1) {}
+ 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -857,10 +951,11 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true if current directive has inner directive.
///
static OMPSectionsDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive with the place for \a NumClauses
/// clauses.
@@ -871,6 +966,9 @@ public:
static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPSectionsDirectiveClass;
}
@@ -884,6 +982,10 @@ public:
///
class OMPSectionDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -891,13 +993,15 @@ class OMPSectionDirective : public OMPExecutableDirective {
///
OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section,
- StartLoc, EndLoc, 0, 1) {}
+ StartLoc, EndLoc, 0, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
explicit OMPSectionDirective()
: OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section,
- SourceLocation(), SourceLocation(), 0, 1) {}
+ SourceLocation(), SourceLocation(), 0, 1),
+ HasCancel(false) {}
public:
/// \brief Creates directive.
@@ -906,11 +1010,12 @@ public:
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true if current directive has inner directive.
///
static OMPSectionDirective *Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
- Stmt *AssociatedStmt);
+ Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive.
///
@@ -918,6 +1023,12 @@ public:
///
static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
+
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPSectionDirectiveClass;
}
@@ -1042,18 +1153,22 @@ class OMPCriticalDirective : public OMPExecutableDirective {
/// \param Name Name of the directive.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
///
OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
- SourceLocation EndLoc)
+ SourceLocation EndLoc, unsigned NumClauses)
: OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
- StartLoc, EndLoc, 0, 1),
+ StartLoc, EndLoc, NumClauses, 1),
DirName(Name) {}
/// \brief Build an empty directive.
///
- explicit OMPCriticalDirective()
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPCriticalDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
- SourceLocation(), SourceLocation(), 0, 1),
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1),
DirName() {}
/// \brief Set name of the directive.
@@ -1069,17 +1184,21 @@ public:
/// \param Name Name of the directive.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
///
static OMPCriticalDirective *
Create(const ASTContext &C, const DeclarationNameInfo &Name,
- SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt);
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
/// \brief Creates an empty directive.
///
/// \param C AST context.
+ /// \param NumClauses Number of clauses.
///
- static OMPCriticalDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+ static OMPCriticalDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
/// \brief Return name of the directive.
///
@@ -1101,6 +1220,10 @@ public:
///
class OMPParallelForDirective : public OMPLoopDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current region has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -1111,7 +1234,8 @@ class OMPParallelForDirective : public OMPLoopDirective {
OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
- StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+ StartLoc, EndLoc, CollapsedNum, NumClauses),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -1121,7 +1245,11 @@ class OMPParallelForDirective : public OMPLoopDirective {
explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses)
: OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
SourceLocation(), SourceLocation(), CollapsedNum,
- NumClauses) {}
+ NumClauses),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -1133,11 +1261,12 @@ public:
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
/// \param Exprs Helper expressions for CodeGen.
+ /// \param HasCancel true if current directive has inner cancel directive.
///
static OMPParallelForDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt, const HelperExprs &Exprs);
+ Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
/// \brief Creates an empty directive with the place
/// for \a NumClauses clauses.
@@ -1151,6 +1280,9 @@ public:
unsigned CollapsedNum,
EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelForDirectiveClass;
}
@@ -1236,6 +1368,10 @@ public:
///
class OMPParallelSectionsDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
+
+ /// \brief true if current directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -1246,7 +1382,8 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective {
unsigned NumClauses)
: OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass,
OMPD_parallel_sections, StartLoc, EndLoc,
- NumClauses, 1) {}
+ NumClauses, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -1255,7 +1392,11 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective {
explicit OMPParallelSectionsDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPParallelSectionsDirectiveClass,
OMPD_parallel_sections, SourceLocation(),
- SourceLocation(), NumClauses, 1) {}
+ SourceLocation(), NumClauses, 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -1265,10 +1406,11 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true if current directive has inner cancel directive.
///
static OMPParallelSectionsDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
- ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive with the place for \a NumClauses
/// clauses.
@@ -1279,6 +1421,9 @@ public:
static OMPParallelSectionsDirective *
CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPParallelSectionsDirectiveClass;
}
@@ -1294,6 +1439,9 @@ public:
///
class OMPTaskDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
+ /// \brief true if this directive has inner cancel directive.
+ bool HasCancel;
+
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@@ -1303,7 +1451,8 @@ class OMPTaskDirective : public OMPExecutableDirective {
OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task, StartLoc,
- EndLoc, NumClauses, 1) {}
+ EndLoc, NumClauses, 1),
+ HasCancel(false) {}
/// \brief Build an empty directive.
///
@@ -1312,7 +1461,11 @@ class OMPTaskDirective : public OMPExecutableDirective {
explicit OMPTaskDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPTaskDirectiveClass, OMPD_task,
SourceLocation(), SourceLocation(), NumClauses,
- 1) {}
+ 1),
+ HasCancel(false) {}
+
+ /// \brief Set cancel state.
+ void setHasCancel(bool Has) { HasCancel = Has; }
public:
/// \brief Creates directive with a list of \a Clauses.
@@ -1322,11 +1475,12 @@ public:
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
+ /// \param HasCancel true, if current directive has inner cancel directive.
///
static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses,
- Stmt *AssociatedStmt);
+ Stmt *AssociatedStmt, bool HasCancel);
/// \brief Creates an empty directive with the place for \a NumClauses
/// clauses.
@@ -1337,6 +1491,9 @@ public:
static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
EmptyShell);
+ /// \brief Return true if current directive has inner cancel directive.
+ bool hasCancel() const { return HasCancel; }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTaskDirectiveClass;
}
@@ -1592,16 +1749,21 @@ class OMPOrderedDirective : public OMPExecutableDirective {
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
///
- OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
: OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
- StartLoc, EndLoc, 0, 1) {}
+ StartLoc, EndLoc, NumClauses, 1) {}
/// \brief Build an empty directive.
///
- explicit OMPOrderedDirective()
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPOrderedDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
- SourceLocation(), SourceLocation(), 0, 1) {}
+ SourceLocation(), SourceLocation(), NumClauses,
+ 1) {}
public:
/// \brief Creates directive.
@@ -1609,18 +1771,20 @@ public:
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
///
- static OMPOrderedDirective *Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- Stmt *AssociatedStmt);
+ static OMPOrderedDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
/// \brief Creates an empty directive.
///
/// \param C AST context.
+ /// \param NumClauses Number of clauses.
///
- static OMPOrderedDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+ static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPOrderedDirectiveClass;
@@ -1817,6 +1981,64 @@ public:
}
};
+/// \brief This represents '#pragma omp target data' directive.
+///
+/// \code
+/// #pragma omp target data device(0) if(a) map(b[:])
+/// \endcode
+/// In this example directive '#pragma omp target data' has clauses 'device'
+/// with the value '0', 'if' with condition 'a' and 'map' with array
+/// section 'b[:]'.
+///
+class OMPTargetDataDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param NumClauses The number of clauses.
+ ///
+ OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
+ OMPD_target_data, StartLoc, EndLoc, NumClauses,
+ 1) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTargetDataDirective(unsigned NumClauses)
+ : OMPExecutableDirective(this, OMPTargetDataDirectiveClass,
+ OMPD_target_data, SourceLocation(),
+ SourceLocation(), NumClauses, 1) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ ///
+ static OMPTargetDataDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
+
+ /// \brief Creates an empty directive with the place for \a N clauses.
+ ///
+ /// \param C AST context.
+ /// \param N The number of clauses.
+ ///
+ static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTargetDataDirectiveClass;
+ }
+};
+
/// \brief This represents '#pragma omp teams' directive.
///
/// \code
@@ -1947,17 +2169,21 @@ class OMPCancelDirective : public OMPExecutableDirective {
///
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
+ /// \param NumClauses Number of clauses.
///
- OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned NumClauses)
: OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel,
- StartLoc, EndLoc, 0, 0),
+ StartLoc, EndLoc, NumClauses, 0),
CancelRegion(OMPD_unknown) {}
/// \brief Build an empty directive.
///
- explicit OMPCancelDirective()
+ /// \param NumClauses Number of clauses.
+ explicit OMPCancelDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPCancelDirectiveClass, OMPD_cancel,
- SourceLocation(), SourceLocation(), 0, 0),
+ SourceLocation(), SourceLocation(), NumClauses,
+ 0),
CancelRegion(OMPD_unknown) {}
/// \brief Set cancel region for current cancellation point.
@@ -1970,17 +2196,19 @@ public:
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
+ /// \param Clauses List of clauses.
///
- static OMPCancelDirective *Create(const ASTContext &C,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- OpenMPDirectiveKind CancelRegion);
+ static OMPCancelDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion);
/// \brief Creates an empty directive.
///
/// \param C AST context.
+ /// \param NumClauses Number of clauses.
///
- static OMPCancelDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+ static OMPCancelDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
/// \brief Get cancellation region for the current cancellation point.
OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
@@ -1990,6 +2218,205 @@ public:
}
};
+/// \brief This represents '#pragma omp taskloop' directive.
+///
+/// \code
+/// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num)
+/// \endcode
+/// In this example directive '#pragma omp taskloop' has clauses 'private'
+/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
+/// 'num_tasks' with expression 'num'.
+///
+class OMPTaskLoopDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop,
+ StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTaskLoopDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTaskLoopDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTaskLoopDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskLoopDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp taskloop simd' directive.
+///
+/// \code
+/// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num)
+/// \endcode
+/// In this example directive '#pragma omp taskloop simd' has clauses 'private'
+/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
+/// 'num_tasks' with expression 'num'.
+///
+class OMPTaskLoopSimdDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass,
+ OMPD_taskloop_simd, StartLoc, EndLoc, CollapsedNum,
+ NumClauses) {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPTaskLoopSimdDirectiveClass,
+ OMPD_taskloop_simd, SourceLocation(), SourceLocation(),
+ CollapsedNum, NumClauses) {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPTaskLoopSimdDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum,
+ EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPTaskLoopSimdDirectiveClass;
+ }
+};
+
+/// \brief This represents '#pragma omp distribute' directive.
+///
+/// \code
+/// #pragma omp distribute private(a,b)
+/// \endcode
+/// In this example directive '#pragma omp distribute' has clauses 'private'
+/// with the variables 'a' and 'b'
+///
+class OMPDistributeDirective : public OMPLoopDirective {
+ friend class ASTStmtReader;
+
+ /// \brief Build directive with the given start and end location.
+ ///
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending location of the directive.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute,
+ StartLoc, EndLoc, CollapsedNum, NumClauses)
+ {}
+
+ /// \brief Build an empty directive.
+ ///
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ explicit OMPDistributeDirective(unsigned CollapsedNum, unsigned NumClauses)
+ : OMPLoopDirective(this, OMPDistributeDirectiveClass, OMPD_distribute,
+ SourceLocation(), SourceLocation(), CollapsedNum,
+ NumClauses)
+ {}
+
+public:
+ /// \brief Creates directive with a list of \a Clauses.
+ ///
+ /// \param C AST context.
+ /// \param StartLoc Starting location of the directive kind.
+ /// \param EndLoc Ending Location of the directive.
+ /// \param CollapsedNum Number of collapsed loops.
+ /// \param Clauses List of clauses.
+ /// \param AssociatedStmt Statement, associated with the directive.
+ /// \param Exprs Helper expressions for CodeGen.
+ ///
+ static OMPDistributeDirective *
+ Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
+ Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+ /// \brief Creates an empty directive with the place
+ /// for \a NumClauses clauses.
+ ///
+ /// \param C AST context.
+ /// \param CollapsedNum Number of collapsed nested loops.
+ /// \param NumClauses Number of clauses.
+ ///
+ static OMPDistributeDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ unsigned CollapsedNum, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPDistributeDirectiveClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h
index c71af38..df4a2d8 100644
--- a/include/clang/AST/StmtVisitor.h
+++ b/include/clang/AST/StmtVisitor.h
@@ -16,6 +16,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtOpenMP.h"
@@ -93,6 +94,7 @@ public:
case UO_Real: DISPATCH(UnaryReal, UnaryOperator);
case UO_Imag: DISPATCH(UnaryImag, UnaryOperator);
case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator);
+ case UO_Coawait: DISPATCH(UnaryCoawait, UnaryOperator);
}
}
@@ -157,7 +159,7 @@ public:
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
- UNARYOP_FALLBACK(Extension)
+ UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(Coawait)
#undef UNARYOP_FALLBACK
// Base case, ignore it. :)
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 1d01753..f87171a 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -22,6 +22,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TrailingObjects.h"
namespace llvm {
class FoldingSetNodeID;
@@ -198,22 +199,19 @@ public:
///
/// We assume that storage for the template arguments provided
/// outlives the TemplateArgument itself.
- TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) {
+ explicit TemplateArgument(ArrayRef<TemplateArgument> Args) {
this->Args.Kind = Pack;
- this->Args.Args = Args;
- this->Args.NumArgs = NumArgs;
+ this->Args.Args = Args.data();
+ this->Args.NumArgs = Args.size();
}
- static TemplateArgument getEmptyPack() {
- return TemplateArgument((TemplateArgument*)nullptr, 0);
- }
+ static TemplateArgument getEmptyPack() { return TemplateArgument(None); }
/// \brief Create a new template argument pack by copying the given set of
/// template arguments.
static TemplateArgument CreatePackCopy(ASTContext &Context,
- const TemplateArgument *Args,
- unsigned NumArgs);
-
+ ArrayRef<TemplateArgument> Args);
+
/// \brief Return the kind of stored template argument.
ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
@@ -523,7 +521,7 @@ class TemplateArgumentListInfo {
// This can leak if used in an AST node, use ASTTemplateArgumentListInfo
// instead.
- void* operator new(size_t bytes, ASTContext& C);
+ void *operator new(size_t bytes, ASTContext &C) = delete;
public:
TemplateArgumentListInfo() {}
@@ -544,6 +542,10 @@ public:
return Arguments.data();
}
+ llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
+ return Arguments;
+ }
+
const TemplateArgumentLoc &operator[](unsigned I) const {
return Arguments[I];
}
@@ -561,84 +563,72 @@ public:
/// the "<int>" in "sort<int>".
/// This is safe to be used inside an AST node, in contrast with
/// TemplateArgumentListInfo.
-struct ASTTemplateArgumentListInfo {
+struct ASTTemplateArgumentListInfo final
+ : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
+ TemplateArgumentLoc> {
+private:
+ friend TrailingObjects;
+
+ ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
+
+public:
/// \brief The source location of the left angle bracket ('<').
SourceLocation LAngleLoc;
-
+
/// \brief The source location of the right angle bracket ('>').
SourceLocation RAngleLoc;
-
- union {
- /// \brief The number of template arguments in TemplateArgs.
- /// The actual template arguments (if any) are stored after the
- /// ExplicitTemplateArgumentList structure.
- unsigned NumTemplateArgs;
-
- /// Force ASTTemplateArgumentListInfo to the right alignment
- /// for the following array of TemplateArgumentLocs.
- llvm::AlignedCharArray<
- llvm::AlignOf<TemplateArgumentLoc>::Alignment, 1> Aligner;
- };
- /// \brief Retrieve the template arguments
- TemplateArgumentLoc *getTemplateArgs() {
- return reinterpret_cast<TemplateArgumentLoc *> (this + 1);
- }
-
+ /// \brief The number of template arguments in TemplateArgs.
+ unsigned NumTemplateArgs;
+
/// \brief Retrieve the template arguments
const TemplateArgumentLoc *getTemplateArgs() const {
- return reinterpret_cast<const TemplateArgumentLoc *> (this + 1);
+ return getTrailingObjects<TemplateArgumentLoc>();
}
const TemplateArgumentLoc &operator[](unsigned I) const {
return getTemplateArgs()[I];
}
- static const ASTTemplateArgumentListInfo *Create(ASTContext &C,
- const TemplateArgumentListInfo &List);
-
- void initializeFrom(const TemplateArgumentListInfo &List);
- void initializeFrom(const TemplateArgumentListInfo &List,
- bool &Dependent, bool &InstantiationDependent,
- bool &ContainsUnexpandedParameterPack);
- void copyInto(TemplateArgumentListInfo &List) const;
- static std::size_t sizeFor(unsigned NumTemplateArgs);
+ static const ASTTemplateArgumentListInfo *
+ Create(ASTContext &C, const TemplateArgumentListInfo &List);
};
-/// \brief Extends ASTTemplateArgumentListInfo with the source location
-/// information for the template keyword; this is used as part of the
-/// representation of qualified identifiers, such as S<T>::template apply<T>.
-struct ASTTemplateKWAndArgsInfo : public ASTTemplateArgumentListInfo {
- typedef ASTTemplateArgumentListInfo Base;
-
- // NOTE: the source location of the (optional) template keyword is
- // stored after all template arguments.
+/// \brief Represents an explicit template argument list in C++, e.g.,
+/// the "<int>" in "sort<int>".
+///
+/// It is intended to be used as a trailing object on AST nodes, and
+/// as such, doesn't contain the array of TemplateArgumentLoc itself,
+/// but expects the containing object to also provide storage for
+/// that.
+struct LLVM_ALIGNAS(LLVM_PTR_SIZE) ASTTemplateKWAndArgsInfo {
+ /// \brief The source location of the left angle bracket ('<').
+ SourceLocation LAngleLoc;
- /// \brief Get the source location of the template keyword.
- SourceLocation getTemplateKeywordLoc() const {
- return *reinterpret_cast<const SourceLocation*>
- (getTemplateArgs() + NumTemplateArgs);
- }
+ /// \brief The source location of the right angle bracket ('>').
+ SourceLocation RAngleLoc;
- /// \brief Sets the source location of the template keyword.
- void setTemplateKeywordLoc(SourceLocation TemplateKWLoc) {
- *reinterpret_cast<SourceLocation*>
- (getTemplateArgs() + NumTemplateArgs) = TemplateKWLoc;
- }
+ /// \brief The source location of the template keyword; this is used
+ /// as part of the representation of qualified identifiers, such as
+ /// S<T>::template apply<T>. Will be empty if this expression does
+ /// not have a template keyword.
+ SourceLocation TemplateKWLoc;
- static const ASTTemplateKWAndArgsInfo*
- Create(ASTContext &C, SourceLocation TemplateKWLoc,
- const TemplateArgumentListInfo &List);
+ /// \brief The number of template arguments in TemplateArgs.
+ unsigned NumTemplateArgs;
void initializeFrom(SourceLocation TemplateKWLoc,
- const TemplateArgumentListInfo &List);
+ const TemplateArgumentListInfo &List,
+ TemplateArgumentLoc *OutArgArray);
void initializeFrom(SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo &List,
- bool &Dependent, bool &InstantiationDependent,
+ TemplateArgumentLoc *OutArgArray, bool &Dependent,
+ bool &InstantiationDependent,
bool &ContainsUnexpandedParameterPack);
void initializeFrom(SourceLocation TemplateKWLoc);
- static std::size_t sizeFor(unsigned NumTemplateArgs);
+ void copyInto(const TemplateArgumentLoc *ArgArray,
+ TemplateArgumentListInfo &List) const;
};
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h
index f3d23b9..3e10d2f 100644
--- a/include/clang/AST/TemplateName.h
+++ b/include/clang/AST/TemplateName.h
@@ -180,9 +180,7 @@ class TemplateName {
StorageType Storage;
- explicit TemplateName(void *Ptr) {
- Storage = StorageType::getFromOpaqueValue(Ptr);
- }
+ explicit TemplateName(void *Ptr);
public:
// \brief Kind of name that is actually stored.
@@ -207,17 +205,15 @@ public:
};
TemplateName() : Storage() { }
- explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
- explicit TemplateName(OverloadedTemplateStorage *Storage)
- : Storage(Storage) { }
+ explicit TemplateName(TemplateDecl *Template);
+ explicit TemplateName(OverloadedTemplateStorage *Storage);
explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);
- explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
- : Storage(Storage) { }
- explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { }
- explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { }
+ explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage);
+ explicit TemplateName(QualifiedTemplateName *Qual);
+ explicit TemplateName(DependentTemplateName *Dep);
/// \brief Determine whether this template name is NULL.
- bool isNull() const { return Storage.isNull(); }
+ bool isNull() const;
// \brief Get the kind of name that is actually stored.
NameKind getKind() const;
@@ -238,26 +234,14 @@ public:
/// name refers to, if known. If the template name does not refer to a
/// specific set of function templates because it is a dependent name or
/// refers to a single template, returns NULL.
- OverloadedTemplateStorage *getAsOverloadedTemplate() const {
- if (UncommonTemplateNameStorage *Uncommon =
- Storage.dyn_cast<UncommonTemplateNameStorage *>())
- return Uncommon->getAsOverloadedStorage();
-
- return nullptr;
- }
+ OverloadedTemplateStorage *getAsOverloadedTemplate() const;
/// \brief Retrieve the substituted template template parameter, if
/// known.
///
/// \returns The storage for the substituted template template parameter,
/// if known. Otherwise, returns NULL.
- SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const {
- if (UncommonTemplateNameStorage *uncommon =
- Storage.dyn_cast<UncommonTemplateNameStorage *>())
- return uncommon->getAsSubstTemplateTemplateParm();
-
- return nullptr;
- }
+ SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const;
/// \brief Retrieve the substituted template template parameter pack, if
/// known.
@@ -265,25 +249,15 @@ public:
/// \returns The storage for the substituted template template parameter pack,
/// if known. Otherwise, returns NULL.
SubstTemplateTemplateParmPackStorage *
- getAsSubstTemplateTemplateParmPack() const {
- if (UncommonTemplateNameStorage *Uncommon =
- Storage.dyn_cast<UncommonTemplateNameStorage *>())
- return Uncommon->getAsSubstTemplateTemplateParmPack();
-
- return nullptr;
- }
+ getAsSubstTemplateTemplateParmPack() const;
/// \brief Retrieve the underlying qualified template name
/// structure, if any.
- QualifiedTemplateName *getAsQualifiedTemplateName() const {
- return Storage.dyn_cast<QualifiedTemplateName *>();
- }
+ QualifiedTemplateName *getAsQualifiedTemplateName() const;
/// \brief Retrieve the underlying dependent template name
/// structure, if any.
- DependentTemplateName *getAsDependentTemplateName() const {
- return Storage.dyn_cast<DependentTemplateName *>();
- }
+ DependentTemplateName *getAsDependentTemplateName() const;
TemplateName getUnderlying() const;
@@ -359,9 +333,6 @@ public:
TemplateName replacement);
};
-inline TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
- : Storage(Storage) { }
-
inline TemplateName TemplateName::getUnderlying() const {
if (SubstTemplateTemplateParmStorage *subst
= getAsSubstTemplateTemplateParm())
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 632d4b9..0c08130 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -6,9 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file defines the Type interface and subclasses.
-//
+/// \file
+/// \brief C Language Family Type Representation
+///
+/// This file defines the clang::Type interface and subclasses, used to
+/// represent types for languages in the C family.
+///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TYPE_H
@@ -105,7 +108,7 @@ namespace clang {
#define TYPE(Class, Base) class Class##Type;
#include "clang/AST/TypeNodes.def"
-/// Qualifiers - The collection of all-type qualifiers we support.
+/// The collection of all-type qualifiers we support.
/// Clang supports five independent qualifiers:
/// * C99: const, volatile, and restrict
/// * Embedded C (TR18037): address spaces
@@ -161,7 +164,7 @@ public:
Qualifiers() : Mask(0) {}
- /// \brief Returns the common set of qualifiers while removing them from
+ /// Returns the common set of qualifiers while removing them from
/// the given sets.
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
// If both are only CVR-qualified, bit operations are sufficient.
@@ -342,8 +345,8 @@ public:
Mask |= mask;
}
- /// hasNonFastQualifiers - Return true if the set contains any
- /// qualifiers which require an ExtQuals node to be allocated.
+ /// Return true if the set contains any qualifiers which require an ExtQuals
+ /// node to be allocated.
bool hasNonFastQualifiers() const { return Mask & ~FastMask; }
Qualifiers getNonFastQualifiers() const {
Qualifiers Quals = *this;
@@ -351,11 +354,11 @@ public:
return Quals;
}
- /// hasQualifiers - Return true if the set contains any qualifiers.
+ /// Return true if the set contains any qualifiers.
bool hasQualifiers() const { return Mask; }
bool empty() const { return !Mask; }
- /// \brief Add the qualifiers from the given set to this set.
+ /// Add the qualifiers from the given set to this set.
void addQualifiers(Qualifiers Q) {
// If the other set doesn't have any non-boolean qualifiers, just
// bit-or it in.
@@ -389,7 +392,7 @@ public:
}
}
- /// \brief Add the qualifiers from the given set to this set, given that
+ /// Add the qualifiers from the given set to this set, given that
/// they don't conflict.
void addConsistentQualifiers(Qualifiers qs) {
assert(getAddressSpace() == qs.getAddressSpace() ||
@@ -401,7 +404,7 @@ public:
Mask |= qs.Mask;
}
- /// \brief Returns true if this address space is a superset of the other one.
+ /// Returns true if this address space is a superset of the other one.
/// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of
/// overlapping address spaces.
/// CL1.1 or CL1.2:
@@ -418,7 +421,7 @@ public:
other.getAddressSpace() != LangAS::opencl_constant);
}
- /// \brief Determines if these qualifiers compatibly include another set.
+ /// Determines if these qualifiers compatibly include another set.
/// Generally this answers the question of whether an object with the other
/// qualifiers can be safely used as an object with these qualifiers.
bool compatiblyIncludes(Qualifiers other) const {
@@ -438,7 +441,8 @@ public:
///
/// One set of Objective-C lifetime qualifiers compatibly includes the other
/// if the lifetime qualifiers match, or if both are non-__weak and the
- /// including set also contains the 'const' qualifier.
+ /// including set also contains the 'const' qualifier, or both are non-__weak
+ /// and one is None (which can only happen in non-ARC modes).
bool compatiblyIncludesObjCLifetime(Qualifiers other) const {
if (getObjCLifetime() == other.getObjCLifetime())
return true;
@@ -446,6 +450,9 @@ public:
if (getObjCLifetime() == OCL_Weak || other.getObjCLifetime() == OCL_Weak)
return false;
+ if (getObjCLifetime() == OCL_None || other.getObjCLifetime() == OCL_None)
+ return true;
+
return hasConst();
}
@@ -551,8 +558,10 @@ enum class ObjCSubstitutionContext {
Superclass,
};
-/// QualType - For efficiency, we don't store CV-qualified types as nodes on
-/// their own: instead each reference to a type stores the qualifiers. This
+/// A (possibly-)qualified type.
+///
+/// For efficiency, we don't store CV-qualified types as nodes on their
+/// own: instead each reference to a type stores the qualifiers. This
/// greatly reduces the number of nodes we need to allocate for types (for
/// example we only need one for 'int', 'const int', 'volatile int',
/// 'const volatile int', etc).
@@ -629,7 +638,7 @@ public:
bool isCanonical() const;
bool isCanonicalAsParam() const;
- /// isNull - Return true if this QualType doesn't point to a type yet.
+ /// Return true if this QualType doesn't point to a type yet.
bool isNull() const {
return Value.getPointer().isNull();
}
@@ -707,29 +716,25 @@ public:
/// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
bool isPODType(ASTContext &Context) const;
- /// isCXX98PODType() - Return true if this is a POD type according to the
- /// rules of the C++98 standard, regardless of the current compilation's
- /// language.
+ /// Return true if this is a POD type according to the rules of the C++98
+ /// standard, regardless of the current compilation's language.
bool isCXX98PODType(ASTContext &Context) const;
- /// isCXX11PODType() - Return true if this is a POD type according to the
- /// more relaxed rules of the C++11 standard, regardless of the current
- /// compilation's language.
+ /// Return true if this is a POD type according to the more relaxed rules
+ /// of the C++11 standard, regardless of the current compilation's language.
/// (C++0x [basic.types]p9)
bool isCXX11PODType(ASTContext &Context) const;
- /// isTrivialType - Return true if this is a trivial type
- /// (C++0x [basic.types]p9)
+ /// Return true if this is a trivial type per (C++0x [basic.types]p9)
bool isTrivialType(ASTContext &Context) const;
- /// isTriviallyCopyableType - Return true if this is a trivially
- /// copyable type (C++0x [basic.types]p9)
+ /// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool isTriviallyCopyableType(ASTContext &Context) const;
// Don't promise in the API that anything besides 'const' can be
// easily added.
- /// addConst - add the specified type qualifier to this QualType.
+ /// Add the `const` type qualifier to this QualType.
void addConst() {
addFastQualifiers(Qualifiers::Const);
}
@@ -737,15 +742,15 @@ public:
return withFastQualifiers(Qualifiers::Const);
}
- /// addVolatile - add the specified type qualifier to this QualType.
+ /// Add the `volatile` type qualifier to this QualType.
void addVolatile() {
addFastQualifiers(Qualifiers::Volatile);
}
QualType withVolatile() const {
return withFastQualifiers(Qualifiers::Volatile);
}
-
- /// Add the restrict qualifier to this QualType.
+
+ /// Add the `restrict` qualifier to this QualType.
void addRestrict() {
addFastQualifiers(Qualifiers::Restrict);
}
@@ -822,8 +827,8 @@ public:
/// ASTContext::getUnqualifiedArrayType.
inline QualType getUnqualifiedType() const;
- /// getSplitUnqualifiedType - Retrieve the unqualified variant of the
- /// given type, removing as little sugar as possible.
+ /// Retrieve the unqualified variant of the given type, removing as little
+ /// sugar as possible.
///
/// Like getUnqualifiedType(), but also returns the set of
/// qualifiers that were built up.
@@ -853,7 +858,7 @@ public:
/// from non-class types (in C++) or all types (in C).
QualType getNonLValueExprType(const ASTContext &Context) const;
- /// getDesugaredType - Return the specified type with any "sugar" removed from
+ /// Return the specified type with any "sugar" removed from
/// the type. This takes off typedefs, typeof's etc. If the outer level of
/// the type is already concrete, it returns it unmodified. This is similar
/// to getting the canonical type, but it doesn't remove *all* typedefs. For
@@ -878,7 +883,7 @@ public:
return getSingleStepDesugaredTypeImpl(*this, Context);
}
- /// IgnoreParens - Returns the specified type after dropping any
+ /// Returns the specified type after dropping any
/// outer-level parentheses.
QualType IgnoreParens() const {
if (isa<ParenType>(*this))
@@ -886,8 +891,7 @@ public:
return *this;
}
- /// operator==/!= - Indicate whether the specified types and qualifiers are
- /// identical.
+ /// Indicate whether the specified types and qualifiers are identical.
friend bool operator==(const QualType &LHS, const QualType &RHS) {
return LHS.Value == RHS.Value;
}
@@ -956,23 +960,23 @@ public:
ID.AddPointer(getAsOpaquePtr());
}
- /// getAddressSpace - Return the address space of this type.
+ /// Return the address space of this type.
inline unsigned getAddressSpace() const;
- /// getObjCGCAttr - Returns gc attribute of this type.
+ /// Returns gc attribute of this type.
inline Qualifiers::GC getObjCGCAttr() const;
- /// isObjCGCWeak true when Type is objc's weak.
+ /// true when Type is objc's weak.
bool isObjCGCWeak() const {
return getObjCGCAttr() == Qualifiers::Weak;
}
- /// isObjCGCStrong true when Type is objc's strong.
+ /// true when Type is objc's strong.
bool isObjCGCStrong() const {
return getObjCGCAttr() == Qualifiers::Strong;
}
- /// getObjCLifetime - Returns lifetime attribute of this type.
+ /// Returns lifetime attribute of this type.
Qualifiers::ObjCLifetime getObjCLifetime() const {
return getQualifiers().getObjCLifetime();
}
@@ -992,7 +996,7 @@ public:
DK_objc_weak_lifetime
};
- /// isDestructedType - nonzero if objects of this type require
+ /// Returns a nonzero value if objects of this type require
/// non-trivial work to clean up after. Non-zero because it's
/// conceivable that qualifiers (objc_gc(weak)?) could make
/// something require destruction.
@@ -1000,7 +1004,7 @@ public:
return isDestructedTypeImpl(*this);
}
- /// \brief Determine whether expressions of the given type are forbidden
+ /// Determine whether expressions of the given type are forbidden
/// from being lvalues in C.
///
/// The expression types that are forbidden to be lvalues are:
@@ -1124,7 +1128,7 @@ class ExtQualsTypeCommonBase {
friend class ExtQuals;
};
-/// ExtQuals - We can encode up to four bits in the low bits of a
+/// We can encode up to four bits in the low bits of a
/// type pointer, but there are many more type qualifiers that we want
/// to be able to apply to an arbitrary type. Therefore we have this
/// struct, intended to be heap-allocated and used by QualType to
@@ -1148,8 +1152,8 @@ class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode {
// 3. ASTContext:
// a) Update get{Volatile,Restrict}Type.
- /// Quals - the immutable set of qualifiers applied by this
- /// node; always contains extended qualifiers.
+ /// The immutable set of qualifiers applied by this node. Always contains
+ /// extended qualifiers.
Qualifiers Quals;
ExtQuals *this_() { return this; }
@@ -1194,8 +1198,8 @@ public:
}
};
-/// \brief The kind of C++0x ref-qualifier associated with a function type,
-/// which determines whether a member function's "this" object can be an
+/// The kind of C++11 ref-qualifier associated with a function type.
+/// This determines whether a member function's "this" object can be an
/// lvalue, rvalue, or neither.
enum RefQualifierKind {
/// \brief No ref-qualifier was provided.
@@ -1206,17 +1210,28 @@ enum RefQualifierKind {
RQ_RValue
};
-/// Type - This is the base class of the type hierarchy. A central concept
-/// with types is that each type always has a canonical type. A canonical type
-/// is the type with any typedef names stripped out of it or the types it
-/// references. For example, consider:
+/// Which keyword(s) were used to create an AutoType.
+enum class AutoTypeKeyword {
+ /// \brief auto
+ Auto,
+ /// \brief decltype(auto)
+ DecltypeAuto,
+ /// \brief __auto_type (GNU extension)
+ GNUAutoType
+};
+
+/// The base class of the type hierarchy.
+///
+/// A central concept with types is that each type always has a canonical
+/// type. A canonical type is the type with any typedef names stripped out
+/// of it or the types it references. For example, consider:
///
/// typedef int foo;
/// typedef foo* bar;
/// 'int *' 'foo *' 'bar'
///
/// There will be a Type object created for 'int'. Since int is canonical, its
-/// canonicaltype pointer points to itself. There is also a Type for 'foo' (a
+/// CanonicalType pointer points to itself. There is also a Type for 'foo' (a
/// TypedefType). Its CanonicalType pointer points to the 'int' Type. Next
/// there is a PointerType that represents 'int*', which, like 'int', is
/// canonical. Finally, there is a PointerType type for 'foo*' whose canonical
@@ -1253,18 +1268,18 @@ private:
/// TypeClass bitfield - Enum that specifies what subclass this belongs to.
unsigned TC : 8;
- /// Dependent - Whether this type is a dependent type (C++ [temp.dep.type]).
+ /// Whether this type is a dependent type (C++ [temp.dep.type]).
unsigned Dependent : 1;
- /// \brief Whether this type somehow involves a template parameter, even
+ /// Whether this type somehow involves a template parameter, even
/// if the resolution of the type does not depend on a template parameter.
unsigned InstantiationDependent : 1;
- /// \brief Whether this type is a variably-modified type (C99 6.7.5).
+ /// Whether this type is a variably-modified type (C99 6.7.5).
unsigned VariablyModified : 1;
/// \brief Whether this type contains an unexpanded parameter pack
- /// (for C++0x variadic templates).
+ /// (for C++11 variadic templates).
unsigned ContainsUnexpandedParameterPack : 1;
/// \brief True if the cache (i.e. the bitfields here starting with
@@ -1277,7 +1292,7 @@ private:
/// \brief Whether this type involves and local or unnamed types.
mutable unsigned CachedLocalOrUnnamed : 1;
- /// \brief FromAST - Whether this type comes from an AST file.
+ /// \brief Whether this type comes from an AST file.
mutable unsigned FromAST : 1;
bool isCacheValid() const {
@@ -1303,11 +1318,11 @@ protected:
unsigned : NumTypeBits;
- /// IndexTypeQuals - CVR qualifiers from declarations like
+ /// CVR qualifiers from declarations like
/// 'int X[static restrict 4]'. For function parameters only.
unsigned IndexTypeQuals : 3;
- /// SizeModifier - storage class qualifiers from declarations like
+ /// Storage class qualifiers from declarations like
/// 'int X[static restrict 4]'. For function parameters only.
/// Actually an ArrayType::ArraySizeModifier.
unsigned SizeModifier : 3;
@@ -1332,7 +1347,7 @@ protected:
/// regparm and the calling convention.
unsigned ExtInfo : 9;
- /// TypeQuals - Used only by FunctionProtoType, put here to pack with the
+ /// Used only by FunctionProtoType, put here to pack with the
/// other bitfields.
/// The qualifiers are part of FunctionProtoType because...
///
@@ -1354,8 +1369,7 @@ protected:
/// The number of type arguments stored directly on this object type.
unsigned NumTypeArgs : 7;
- /// NumProtocols - The number of protocols stored directly on this
- /// object type.
+ /// The number of protocols stored directly on this object type.
unsigned NumProtocols : 6;
/// Whether this is a "kindof" type.
@@ -1400,11 +1414,11 @@ protected:
unsigned : NumTypeBits;
- /// VecKind - The kind of vector, either a generic vector type or some
+ /// The kind of vector, either a generic vector type or some
/// target-specific vector type such as for AltiVec or Neon.
unsigned VecKind : 3;
- /// NumElements - The number of elements in the vector.
+ /// The number of elements in the vector.
unsigned NumElements : 29 - NumTypeBits;
enum { MaxNumElements = (1 << (29 - NumTypeBits)) - 1 };
@@ -1415,7 +1429,7 @@ protected:
unsigned : NumTypeBits;
- /// AttrKind - an AttributedType::Kind
+ /// An AttributedType::Kind
unsigned AttrKind : 32 - NumTypeBits;
};
@@ -1424,8 +1438,9 @@ protected:
unsigned : NumTypeBits;
- /// Was this placeholder type spelled as 'decltype(auto)'?
- unsigned IsDecltypeAuto : 1;
+ /// Was this placeholder type spelled as 'auto', 'decltype(auto)',
+ /// or '__auto_type'? AutoTypeKeyword value.
+ unsigned Keyword : 2;
};
union {
@@ -1521,17 +1536,17 @@ public:
/// Types are partitioned into 3 broad categories (C99 6.2.5p1):
/// object types, function types, and incomplete types.
- /// isIncompleteType - Return true if this is an incomplete type.
+ /// Return true if this is an incomplete type.
/// A type that can describe objects, but which lacks information needed to
/// determine its size (e.g. void, or a fwd declared struct). Clients of this
/// routine will need to determine if the size is actually required.
///
- /// \brief Def If non-NULL, and the type refers to some kind of declaration
+ /// \brief Def If non-null, and the type refers to some kind of declaration
/// that can be completed (such as a C struct, C++ class, or Objective-C
/// class), will be set to the declaration.
bool isIncompleteType(NamedDecl **Def = nullptr) const;
- /// isIncompleteOrObjectType - Return true if this is an incomplete or object
+ /// Return true if this is an incomplete or object
/// type, in other words, not a function type.
bool isIncompleteOrObjectType() const {
return !isFunctionType();
@@ -1545,35 +1560,34 @@ public:
return !isReferenceType() && !isFunctionType() && !isVoidType();
}
- /// isLiteralType - Return true if this is a literal type
+ /// Return true if this is a literal type
/// (C++11 [basic.types]p10)
bool isLiteralType(const ASTContext &Ctx) const;
- /// \brief Test if this type is a standard-layout type.
+ /// Test if this type is a standard-layout type.
/// (C++0x [basic.type]p9)
bool isStandardLayoutType() const;
/// Helper methods to distinguish type categories. All type predicates
/// operate on the canonical type, ignoring typedefs and qualifiers.
- /// isBuiltinType - returns true if the type is a builtin type.
+ /// Returns true if the type is a builtin type.
bool isBuiltinType() const;
- /// isSpecificBuiltinType - Test for a particular builtin type.
+ /// Test for a particular builtin type.
bool isSpecificBuiltinType(unsigned K) const;
- /// isPlaceholderType - Test for a type which does not represent an
- /// actual type-system type but is instead used as a placeholder for
- /// various convenient purposes within Clang. All such types are
- /// BuiltinTypes.
+ /// Test for a type which does not represent an actual type-system type but
+ /// is instead used as a placeholder for various convenient purposes within
+ /// Clang. All such types are BuiltinTypes.
bool isPlaceholderType() const;
const BuiltinType *getAsPlaceholderType() const;
- /// isSpecificPlaceholderType - Test for a specific placeholder type.
+ /// Test for a specific placeholder type.
bool isSpecificPlaceholderType(unsigned K) const;
- /// isNonOverloadPlaceholderType - Test for a placeholder type
- /// other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
+ /// Test for a placeholder type other than Overload; see
+ /// BuiltinType::isNonOverloadPlaceholderType.
bool isNonOverloadPlaceholderType() const;
/// isIntegerType() does *not* include complex integers (a GCC extension).
@@ -1588,10 +1602,9 @@ public:
bool isAnyCharacterType() const;
bool isIntegralType(ASTContext &Ctx) const;
- /// \brief Determine whether this type is an integral or enumeration type.
+ /// Determine whether this type is an integral or enumeration type.
bool isIntegralOrEnumerationType() const;
- /// \brief Determine whether this type is an integral or unscoped enumeration
- /// type.
+ /// Determine whether this type is an integral or unscoped enumeration type.
bool isIntegralOrUnscopedEnumerationType() const;
/// Floating point categories.
@@ -1655,6 +1668,7 @@ public:
bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id
+ bool isObjCInertUnsafeUnretainedType() const;
/// Whether the type is Objective-C 'id' or a __kindof type of an
/// object type, e.g., __kindof NSView * or __kindof id
@@ -1685,17 +1699,27 @@ public:
bool isNullPtrType() const; // C++0x nullptr_t
bool isAtomicType() const; // C11 _Atomic()
- bool isImage1dT() const; // OpenCL image1d_t
- bool isImage1dArrayT() const; // OpenCL image1d_array_t
- bool isImage1dBufferT() const; // OpenCL image1d_buffer_t
- bool isImage2dT() const; // OpenCL image2d_t
- bool isImage2dArrayT() const; // OpenCL image2d_array_t
- bool isImage3dT() const; // OpenCL image3d_t
+ bool isImage1dT() const; // OpenCL image1d_t
+ bool isImage1dArrayT() const; // OpenCL image1d_array_t
+ bool isImage1dBufferT() const; // OpenCL image1d_buffer_t
+ bool isImage2dT() const; // OpenCL image2d_t
+ bool isImage2dArrayT() const; // OpenCL image2d_array_t
+ bool isImage2dDepthT() const; // OpenCL image_2d_depth_t
+ bool isImage2dArrayDepthT() const; // OpenCL image_2d_array_depth_t
+ bool isImage2dMSAAT() const; // OpenCL image_2d_msaa_t
+ bool isImage2dArrayMSAAT() const; // OpenCL image_2d_array_msaa_t
+ bool isImage2dMSAATDepth() const; // OpenCL image_2d_msaa_depth_t
+ bool isImage2dArrayMSAATDepth() const; // OpenCL image_2d_array_msaa_depth_t
+ bool isImage3dT() const; // OpenCL image3d_t
bool isImageType() const; // Any OpenCL image type
bool isSamplerT() const; // OpenCL sampler_t
bool isEventT() const; // OpenCL event_t
+ bool isClkEventT() const; // OpenCL clk_event_t
+ bool isQueueT() const; // OpenCL queue_t
+ bool isNDRangeT() const; // OpenCL ndrange_t
+ bool isReserveIDT() const; // OpenCL reserve_id_t
bool isOpenCLSpecificType() const; // Any OpenCL specific type
@@ -1718,12 +1742,11 @@ public:
STK_IntegralComplex,
STK_FloatingComplex
};
- /// getScalarTypeKind - Given that this is a scalar type, classify it.
+ /// Given that this is a scalar type, classify it.
ScalarTypeKind getScalarTypeKind() const;
- /// isDependentType - Whether this type is a dependent type, meaning
- /// that its definition somehow depends on a template parameter
- /// (C++ [temp.dep.type]).
+ /// Whether this type is a dependent type, meaning that its definition
+ /// somehow depends on a template parameter (C++ [temp.dep.type]).
bool isDependentType() const { return TypeBits.Dependent; }
/// \brief Determine whether this type is an instantiation-dependent type,
@@ -1755,14 +1778,13 @@ public:
bool canDecayToPointerType() const;
- /// hasPointerRepresentation - Whether this type is represented
- /// natively as a pointer; this includes pointers, references, block
- /// pointers, and Objective-C interface, qualified id, and qualified
- /// interface types, as well as nullptr_t.
+ /// Whether this type is represented natively as a pointer. This includes
+ /// pointers, references, block pointers, and Objective-C interface,
+ /// qualified id, and qualified interface types, as well as nullptr_t.
bool hasPointerRepresentation() const;
- /// hasObjCPointerRepresentation - Whether this type can represent
- /// an objective pointer type for the purpose of GC'ability
+ /// Whether this type can represent an objective pointer type for the
+ /// purpose of GC'ability
bool hasObjCPointerRepresentation() const;
/// \brief Determine whether this type has an integer representation
@@ -1813,7 +1835,7 @@ public:
/// not refer to a CXXRecordDecl, returns NULL.
const CXXRecordDecl *getPointeeCXXRecordDecl() const;
- /// \brief Get the AutoType whose type will be deduced for a variable with
+ /// Get the AutoType whose type will be deduced for a variable with
/// an initializer of this type. This looks through declarators like pointer
/// types, but not through decltype or typedefs.
AutoType *getContainedAutoType() const;
@@ -1842,34 +1864,33 @@ public:
/// qualifiers from the outermost type.
const ArrayType *castAsArrayTypeUnsafe() const;
- /// getBaseElementTypeUnsafe - Get the base element type of this
- /// type, potentially discarding type qualifiers. This method
- /// should never be used when type qualifiers are meaningful.
+ /// Get the base element type of this type, potentially discarding type
+ /// qualifiers. This should never be used when type qualifiers
+ /// are meaningful.
const Type *getBaseElementTypeUnsafe() const;
- /// getArrayElementTypeNoTypeQual - If this is an array type, return the
- /// element type of the array, potentially with type qualifiers missing.
- /// This method should never be used when type qualifiers are meaningful.
+ /// If this is an array type, return the element type of the array,
+ /// potentially with type qualifiers missing.
+ /// This should never be used when type qualifiers are meaningful.
const Type *getArrayElementTypeNoTypeQual() const;
- /// getPointeeType - If this is a pointer, ObjC object pointer, or block
+ /// If this is a pointer, ObjC object pointer, or block
/// pointer, this returns the respective pointee.
QualType getPointeeType() const;
- /// getUnqualifiedDesugaredType() - Return the specified type with
- /// any "sugar" removed from the type, removing any typedefs,
- /// typeofs, etc., as well as any qualifiers.
+ /// Return the specified type with any "sugar" removed from the type,
+ /// removing any typedefs, typeofs, etc., as well as any qualifiers.
const Type *getUnqualifiedDesugaredType() const;
/// More type predicates useful for type checking/promotion
bool isPromotableIntegerType() const; // C99 6.3.1.1p2
- /// isSignedIntegerType - Return true if this is an integer type that is
+ /// Return true if this is an integer type that is
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
/// or an enum decl which has a signed representation.
bool isSignedIntegerType() const;
- /// isUnsignedIntegerType - Return true if this is an integer type that is
+ /// Return true if this is an integer type that is
/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool],
/// or an enum decl which has an unsigned representation.
bool isUnsignedIntegerType() const;
@@ -1882,32 +1903,32 @@ public:
/// enumeration types whose underlying type is a unsigned integer type.
bool isUnsignedIntegerOrEnumerationType() const;
- /// isConstantSizeType - Return true if this is not a variable sized type,
+ /// Return true if this is not a variable sized type,
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
/// incomplete types.
bool isConstantSizeType() const;
- /// isSpecifierType - Returns true if this type can be represented by some
+ /// Returns true if this type can be represented by some
/// set of type specifiers.
bool isSpecifierType() const;
- /// \brief Determine the linkage of this type.
+ /// Determine the linkage of this type.
Linkage getLinkage() const;
- /// \brief Determine the visibility of this type.
+ /// Determine the visibility of this type.
Visibility getVisibility() const {
return getLinkageAndVisibility().getVisibility();
}
- /// \brief Return true if the visibility was explicitly set is the code.
+ /// Return true if the visibility was explicitly set is the code.
bool isVisibilityExplicit() const {
return getLinkageAndVisibility().isVisibilityExplicit();
}
- /// \brief Determine the linkage and visibility of this type.
+ /// Determine the linkage and visibility of this type.
LinkageInfo getLinkageAndVisibility() const;
- /// \brief True if the computed linkage is valid. Used for consistency
+ /// True if the computed linkage is valid. Used for consistency
/// checking. Should always return true.
bool isLinkageValid() const;
@@ -1984,7 +2005,7 @@ template <> inline const Class##Type *Type::castAs() const { \
#include "clang/AST/TypeNodes.def"
-/// BuiltinType - This class is used for builtin types like 'int'. Builtin
+/// This class is used for builtin types like 'int'. Builtin
/// types are always canonical and have a literal name field.
class BuiltinType : public Type {
public:
@@ -2059,7 +2080,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Builtin; }
};
-/// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex
+/// Complex values, per C99 6.2.5p11. This supports the C99 complex
/// types (_Complex float etc) as well as the GCC integer complex extensions.
///
class ComplexType : public Type, public llvm::FoldingSetNode {
@@ -2089,7 +2110,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Complex; }
};
-/// ParenType - Sugar for parentheses used when specifying types.
+/// Sugar for parentheses used when specifying types.
///
class ParenType : public Type, public llvm::FoldingSetNode {
QualType Inner;
@@ -2138,7 +2159,7 @@ public:
QualType getPointeeType() const { return PointeeType; }
- /// \brief Returns true if address spaces of pointers overlap.
+ /// Returns true if address spaces of pointers overlap.
/// OpenCL v2.0 defines conversion rules for pointers to different
/// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping
/// address spaces.
@@ -2167,7 +2188,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Pointer; }
};
-/// \brief Represents a type which was implicitly adjusted by the semantic
+/// Represents a type which was implicitly adjusted by the semantic
/// engine for arbitrary reasons. For example, array and function types can
/// decay, and function types can have their calling conventions adjusted.
class AdjustedType : public Type, public llvm::FoldingSetNode {
@@ -2205,7 +2226,7 @@ public:
}
};
-/// \brief Represents a pointer type decayed from an array or function type.
+/// Represents a pointer type decayed from an array or function type.
class DecayedType : public AdjustedType {
DecayedType(QualType OriginalType, QualType DecayedPtr, QualType CanonicalPtr)
@@ -2225,7 +2246,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Decayed; }
};
-/// BlockPointerType - pointer to a block type.
+/// Pointer to a block type.
/// This type is to represent types syntactically represented as
/// "void (^)(int)", etc. Pointee is required to always be a function type.
///
@@ -2260,7 +2281,7 @@ public:
}
};
-/// ReferenceType - Base for LValueReferenceType and RValueReferenceType
+/// Base for LValueReferenceType and RValueReferenceType
///
class ReferenceType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
@@ -2307,7 +2328,7 @@ public:
}
};
-/// LValueReferenceType - C++ [dcl.ref] - Lvalue reference
+/// An lvalue reference type, per C++11 [dcl.ref].
///
class LValueReferenceType : public ReferenceType {
LValueReferenceType(QualType Referencee, QualType CanonicalRef,
@@ -2324,7 +2345,7 @@ public:
}
};
-/// RValueReferenceType - C++0x [dcl.ref] - Rvalue reference
+/// An rvalue reference type, per C++11 [dcl.ref].
///
class RValueReferenceType : public ReferenceType {
RValueReferenceType(QualType Referencee, QualType CanonicalRef) :
@@ -2340,7 +2361,9 @@ public:
}
};
-/// MemberPointerType - C++ 8.3.3 - Pointers to members
+/// A pointer to member type per C++ 8.3.3 - Pointers to members.
+///
+/// This includes both pointers to data members and pointer to member functions.
///
class MemberPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
@@ -2395,11 +2418,11 @@ public:
}
};
-/// ArrayType - C99 6.7.5.2 - Array Declarators.
+/// Represents an array type, per C99 6.7.5.2 - Array Declarators.
///
class ArrayType : public Type, public llvm::FoldingSetNode {
public:
- /// ArraySizeModifier - Capture whether this is a normal array (e.g. int X[4])
+ /// Capture whether this is a normal array (e.g. int X[4])
/// an array with a static size (e.g. int X[static 4]), or an array
/// with a star size (e.g. int X[*]).
/// 'static' is only allowed on function parameters.
@@ -2407,7 +2430,7 @@ public:
Normal, Static, Star
};
private:
- /// ElementType - The element type of the array.
+ /// The element type of the array.
QualType ElementType;
protected:
@@ -2450,10 +2473,9 @@ public:
}
};
-/// ConstantArrayType - This class represents the canonical version of
-/// C arrays with a specified constant size. For example, the canonical
-/// type for 'int A[4 + 4*100]' is a ConstantArrayType where the element
-/// type is 'int' and the size is 404.
+/// Represents the canonical version of C arrays with a specified constant size.
+/// For example, the canonical type for 'int A[4 + 4*100]' is a
+/// ConstantArrayType where the element type is 'int' and the size is 404.
class ConstantArrayType : public ArrayType {
llvm::APInt Size; // Allows us to unique the type.
@@ -2501,9 +2523,9 @@ public:
}
};
-/// IncompleteArrayType - This class represents C arrays with an unspecified
-/// size. For example 'int A[]' has an IncompleteArrayType where the element
-/// type is 'int' and the size is unspecified.
+/// Represents a C array with an unspecified size. For example 'int A[]' has
+/// an IncompleteArrayType where the element type is 'int' and the size is
+/// unspecified.
class IncompleteArrayType : public ArrayType {
IncompleteArrayType(QualType et, QualType can,
@@ -2534,8 +2556,8 @@ public:
}
};
-/// VariableArrayType - This class represents C arrays with a specified size
-/// which is not an integer-constant-expression. For example, 'int s[x+foo()]'.
+/// Represents a C array with a specified size that is not an
+/// integer-constant-expression. For example, 'int s[x+foo()]'.
/// Since the size expression is an arbitrary expression, we store it as such.
///
/// Note: VariableArrayType's aren't uniqued (since the expressions aren't) and
@@ -2550,10 +2572,10 @@ public:
/// }
///
class VariableArrayType : public ArrayType {
- /// SizeExpr - An assignment expression. VLA's are only permitted within
+ /// An assignment-expression. VLA's are only permitted within
/// a function block.
Stmt *SizeExpr;
- /// Brackets - The left and right array brackets.
+ /// The range spanned by the left and right array brackets.
SourceRange Brackets;
VariableArrayType(QualType et, QualType can, Expr *e,
@@ -2588,9 +2610,9 @@ public:
}
};
-/// DependentSizedArrayType - This type represents an array type in
-/// C++ whose size is a value-dependent expression. For example:
+/// Represents an array type in C++ whose size is a value-dependent expression.
///
+/// For example:
/// \code
/// template<typename T, int Size>
/// class array {
@@ -2607,11 +2629,11 @@ class DependentSizedArrayType : public ArrayType {
/// \brief An assignment expression that will instantiate to the
/// size of the array.
///
- /// The expression itself might be NULL, in which case the array
+ /// The expression itself might be null, in which case the array
/// type will have its size deduced from an initializer.
Stmt *SizeExpr;
- /// Brackets - The left and right array brackets.
+ /// The range spanned by the left and right array brackets.
SourceRange Brackets;
DependentSizedArrayType(const ASTContext &Context, QualType et, QualType can,
@@ -2650,18 +2672,20 @@ public:
unsigned TypeQuals, Expr *E);
};
-/// DependentSizedExtVectorType - This type represent an extended vector type
-/// where either the type or size is dependent. For example:
-/// @code
+/// Represents an extended vector type where either the type or size is
+/// dependent.
+///
+/// For example:
+/// \code
/// template<typename T, int Size>
/// class vector {
/// typedef T __attribute__((ext_vector_type(Size))) type;
/// }
-/// @endcode
+/// \endcode
class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
const ASTContext &Context;
Expr *SizeExpr;
- /// ElementType - The element type of the array.
+ /// The element type of the array.
QualType ElementType;
SourceLocation loc;
@@ -2691,7 +2715,7 @@ public:
};
-/// VectorType - GCC generic vector type. This type is created using
+/// Represents a GCC generic vector type. This type is created using
/// __attribute__((vector_size(n)), where "n" specifies the vector size in
/// bytes; or from an Altivec __vector or vector declaration.
/// Since the constructor takes the number of vector elements, the
@@ -2699,15 +2723,15 @@ public:
class VectorType : public Type, public llvm::FoldingSetNode {
public:
enum VectorKind {
- GenericVector, // not a target-specific vector type
- AltiVecVector, // is AltiVec vector
- AltiVecPixel, // is AltiVec 'vector Pixel'
- AltiVecBool, // is AltiVec 'vector bool ...'
- NeonVector, // is ARM Neon vector
- NeonPolyVector // is ARM Neon polynomial vector
+ GenericVector, ///< not a target-specific vector type
+ AltiVecVector, ///< is AltiVec vector
+ AltiVecPixel, ///< is AltiVec 'vector Pixel'
+ AltiVecBool, ///< is AltiVec 'vector bool ...'
+ NeonVector, ///< is ARM Neon vector
+ NeonPolyVector ///< is ARM Neon polynomial vector
};
protected:
- /// ElementType - The element type of the vector.
+ /// The element type of the vector.
QualType ElementType;
VectorType(QualType vecType, unsigned nElements, QualType canonType,
@@ -2824,7 +2848,7 @@ class FunctionType : public Type {
QualType ResultType;
public:
- /// ExtInfo - A class which abstracts out some details necessary for
+ /// A class which abstracts out some details necessary for
/// making a call.
///
/// It is not actually used directly for storing this information in
@@ -2878,7 +2902,7 @@ class FunctionType : public Type {
}
// Constructor with all defaults. Use when for example creating a
- // function know to use defaults.
+ // function known to use defaults.
ExtInfo() : Bits(CC_C) { }
// Constructor with just the calling convention, which is an important part
@@ -2953,7 +2977,7 @@ public:
bool getHasRegParm() const { return getExtInfo().getHasRegParm(); }
unsigned getRegParmType() const { return getExtInfo().getRegParm(); }
- /// \brief Determine whether this function type includes the GNU noreturn
+ /// Determine whether this function type includes the GNU noreturn
/// attribute. The C++11 [[noreturn]] attribute does not affect the function
/// type.
bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); }
@@ -2977,7 +3001,7 @@ public:
}
};
-/// FunctionNoProtoType - Represents a K&R-style 'int foo()' function, which has
+/// Represents a K&R-style 'int foo()' function, which has
/// no information available about its arguments.
class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
@@ -3008,7 +3032,7 @@ public:
}
};
-/// FunctionProtoType - Represents a prototype with parameter type info, e.g.
+/// Represents a prototype with parameter type info, e.g.
/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no
/// parameters, not as having a single void parameter. Such a type can have an
/// exception specification, but this specification is not part of the canonical
@@ -3038,7 +3062,7 @@ public:
FunctionDecl *SourceTemplate;
};
- /// ExtProtoInfo - Extra information about a function prototype.
+ /// Extra information about a function prototype.
struct ExtProtoInfo {
ExtProtoInfo()
: Variadic(false), HasTrailingReturn(false), TypeQuals(0),
@@ -3081,19 +3105,19 @@ private:
/// The number of parameters this function has, not counting '...'.
unsigned NumParams : 15;
- /// NumExceptions - The number of types in the exception spec, if any.
+ /// The number of types in the exception spec, if any.
unsigned NumExceptions : 9;
- /// ExceptionSpecType - The type of exception specification this function has.
+ /// The type of exception specification this function has.
unsigned ExceptionSpecType : 4;
- /// HasAnyConsumedParams - Whether this function has any consumed parameters.
+ /// Whether this function has any consumed parameters.
unsigned HasAnyConsumedParams : 1;
- /// Variadic - Whether the function is variadic.
+ /// Whether the function is variadic.
unsigned Variadic : 1;
- /// HasTrailingReturn - Whether this function has a trailing return type.
+ /// Whether this function has a trailing return type.
unsigned HasTrailingReturn : 1;
// ParamInfo - There is an variable size array after the class in memory that
@@ -3120,11 +3144,13 @@ private:
assert(hasAnyConsumedParams());
// Find the end of the exceptions.
- Expr *const *eh_end = reinterpret_cast<Expr *const *>(param_type_end());
- if (getExceptionSpecType() != EST_ComputedNoexcept)
- eh_end += NumExceptions;
- else
+ Expr *const *eh_end = reinterpret_cast<Expr *const *>(exception_end());
+ if (getExceptionSpecType() == EST_ComputedNoexcept)
eh_end += 1; // NoexceptExpr
+ // The memory layout of these types isn't handled here, so
+ // hopefully this is never called for them?
+ assert(getExceptionSpecType() != EST_Uninstantiated &&
+ getExceptionSpecType() != EST_Unevaluated);
return reinterpret_cast<const bool*>(eh_end);
}
@@ -3162,25 +3188,25 @@ public:
return EPI;
}
- /// \brief Get the kind of exception specification on this function.
+ /// Get the kind of exception specification on this function.
ExceptionSpecificationType getExceptionSpecType() const {
return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
}
- /// \brief Return whether this function has any kind of exception spec.
+ /// Return whether this function has any kind of exception spec.
bool hasExceptionSpec() const {
return getExceptionSpecType() != EST_None;
}
- /// \brief Return whether this function has a dynamic (throw) exception spec.
+ /// Return whether this function has a dynamic (throw) exception spec.
bool hasDynamicExceptionSpec() const {
return isDynamicExceptionSpec(getExceptionSpecType());
}
- /// \brief Return whether this function has a noexcept exception spec.
+ /// Return whether this function has a noexcept exception spec.
bool hasNoexceptExceptionSpec() const {
return isNoexceptExceptionSpec(getExceptionSpecType());
}
- /// \brief Return whether this function has a dependent exception spec.
+ /// Return whether this function has a dependent exception spec.
bool hasDependentExceptionSpec() const;
- /// \brief Result type of getNoexceptSpec().
+ /// Result type of getNoexceptSpec().
enum NoexceptResult {
NR_NoNoexcept, ///< There is no noexcept specifier.
NR_BadNoexcept, ///< The noexcept specifier has a bad expression.
@@ -3188,7 +3214,7 @@ public:
NR_Throw, ///< The noexcept specifier evaluates to false.
NR_Nothrow ///< The noexcept specifier evaluates to true.
};
- /// \brief Get the meaning of the noexcept spec on this function, if any.
+ /// Get the meaning of the noexcept spec on this function, if any.
NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const;
unsigned getNumExceptions() const { return NumExceptions; }
QualType getExceptionType(unsigned i) const {
@@ -3220,14 +3246,14 @@ public:
return nullptr;
return reinterpret_cast<FunctionDecl *const *>(param_type_end())[1];
}
- /// \brief Determine whether this function type has a non-throwing exception
+ /// Determine whether this function type has a non-throwing exception
/// specification. If this depends on template arguments, returns
/// \c ResultIfDependent.
bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const;
bool isVariadic() const { return Variadic; }
- /// \brief Determines whether this function prototype contains a
+ /// Determines whether this function prototype contains a
/// parameter pack at the end.
///
/// A function template whose last parameter is a parameter pack can be
@@ -3240,7 +3266,7 @@ public:
unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
- /// \brief Retrieve the ref-qualifier associated with this function type.
+ /// Retrieve the ref-qualifier associated with this function type.
RefQualifierKind getRefQualifier() const {
return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier);
}
@@ -3284,7 +3310,7 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
- void printExceptionSpecification(raw_ostream &OS,
+ void printExceptionSpecification(raw_ostream &OS,
const PrintingPolicy &Policy) const;
static bool classof(const Type *T) {
@@ -3297,10 +3323,10 @@ public:
const ExtProtoInfo &EPI, const ASTContext &Context);
};
-
/// \brief Represents the dependent type named by a dependently-scoped
/// typename using declaration, e.g.
/// using typename Base<T>::foo;
+///
/// Template instantiation turns these into the underlying type.
class UnresolvedUsingType : public Type {
UnresolvedUsingTypenameDecl *Decl;
@@ -3353,7 +3379,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Typedef; }
};
-/// TypeOfExprType (GCC extension).
+/// Represents a `typeof` (or __typeof__) expression (a GCC extension).
class TypeOfExprType : public Type {
Expr *TOExpr;
@@ -3373,7 +3399,7 @@ public:
};
/// \brief Internal representation of canonical, dependent
-/// typeof(expr) types.
+/// `typeof(expr)` types.
///
/// This class is used internally by the ASTContext to manage
/// canonical, dependent types, only. Clients will only see instances
@@ -3394,7 +3420,7 @@ public:
Expr *E);
};
-/// TypeOfType (GCC extension).
+/// Represents `typeof(type)`, a GCC extension.
class TypeOfType : public Type {
QualType TOType;
TypeOfType(QualType T, QualType can)
@@ -3418,7 +3444,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; }
};
-/// DecltypeType (C++0x)
+/// Represents the type `decltype(expr)` (C++11).
class DecltypeType : public Type {
Expr *E;
QualType UnderlyingType;
@@ -3459,7 +3485,7 @@ public:
Expr *E);
};
-/// \brief A unary type transform, which is a type constructed from another
+/// A unary type transform, which is a type constructed from another.
class UnaryTransformType : public Type {
public:
enum UTTKind {
@@ -3497,15 +3523,14 @@ class TagType : public Type {
TagDecl * decl;
friend class ASTReader;
-
+
protected:
TagType(TypeClass TC, const TagDecl *D, QualType can);
public:
TagDecl *getDecl() const;
- /// @brief Determines whether this type is in the process of being
- /// defined.
+ /// Determines whether this type is in the process of being defined.
bool isBeingDefined() const;
static bool classof(const Type *T) {
@@ -3513,7 +3538,7 @@ public:
}
};
-/// RecordType - This is a helper class that allows the use of isa/cast/dyncast
+/// A helper class that allows the use of isa/cast/dyncast
/// to detect TagType objects of structs/unions/classes.
class RecordType : public TagType {
protected:
@@ -3539,7 +3564,7 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Record; }
};
-/// EnumType - This is a helper class that allows the use of isa/cast/dyncast
+/// A helper class that allows the use of isa/cast/dyncast
/// to detect TagType objects of enums.
class EnumType : public TagType {
explicit EnumType(const EnumDecl *D)
@@ -3557,12 +3582,12 @@ public:
static bool classof(const Type *T) { return T->getTypeClass() == Enum; }
};
-/// AttributedType - An attributed type is a type to which a type
-/// attribute has been applied. The "modified type" is the
-/// fully-sugared type to which the attributed type was applied;
-/// generally it is not canonically equivalent to the attributed type.
-/// The "equivalent type" is the minimally-desugared type which the
-/// type is canonically equivalent to.
+/// An attributed type is a type to which a type attribute has been applied.
+///
+/// The "modified type" is the fully-sugared type to which the attributed
+/// type was applied; generally it is not canonically equivalent to the
+/// attributed type. The "equivalent type" is the minimally-desugared type
+/// which the type is canonically equivalent to.
///
/// For example, in the following attributed type:
/// int32_t __attribute__((vector_size(16)))
@@ -3612,6 +3637,7 @@ public:
attr_nullable,
attr_null_unspecified,
attr_objc_kindof,
+ attr_objc_inert_unsafe_unretained,
};
private:
@@ -3641,6 +3667,23 @@ public:
bool isSugared() const { return true; }
QualType desugar() const { return getEquivalentType(); }
+ /// Does this attribute behave like a type qualifier?
+ ///
+ /// A type qualifier adjusts a type to provide specialized rules for
+ /// a specific object, like the standard const and volatile qualifiers.
+ /// This includes attributes controlling things like nullability,
+ /// address spaces, and ARC ownership. The value of the object is still
+ /// largely described by the modified type.
+ ///
+ /// In contrast, many type attributes "rewrite" their modified type to
+ /// produce a fundamentally different type, not necessarily related in any
+ /// formalizable way to the original type. For example, calling convention
+ /// and vector attributes are not simple type qualifiers.
+ ///
+ /// Type qualifiers are often, but not always, reflected in the canonical
+ /// type.
+ bool isQualifier() const;
+
bool isMSTypeSpec() const;
bool isCallingConv() const;
@@ -3653,7 +3696,7 @@ public:
switch (kind) {
case NullabilityKind::NonNull:
return attr_nonnull;
-
+
case NullabilityKind::Nullable:
return attr_nullable;
@@ -3865,29 +3908,33 @@ public:
}
};
-/// \brief Represents a C++11 auto or C++1y decltype(auto) type.
+/// \brief Represents a C++11 auto or C++14 decltype(auto) type.
///
/// These types are usually a placeholder for a deduced type. However, before
/// the initializer is attached, or if the initializer is type-dependent, there
/// is no deduced type and an auto type is canonical. In the latter case, it is
/// also a dependent type.
class AutoType : public Type, public llvm::FoldingSetNode {
- AutoType(QualType DeducedType, bool IsDecltypeAuto,
- bool IsDependent)
+ AutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent)
: Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
/*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
- /*VariablyModified=*/false,
- /*ContainsParameterPack=*/DeducedType.isNull()
+ /*VariablyModified=*/false,
+ /*ContainsParameterPack=*/DeducedType.isNull()
? false : DeducedType->containsUnexpandedParameterPack()) {
assert((DeducedType.isNull() || !IsDependent) &&
"auto deduced to dependent type");
- AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto;
+ AutoTypeBits.Keyword = (unsigned)Keyword;
}
friend class ASTContext; // ASTContext creates these
public:
- bool isDecltypeAuto() const { return AutoTypeBits.IsDecltypeAuto; }
+ bool isDecltypeAuto() const {
+ return getKeyword() == AutoTypeKeyword::DecltypeAuto;
+ }
+ AutoTypeKeyword getKeyword() const {
+ return (AutoTypeKeyword)AutoTypeBits.Keyword;
+ }
bool isSugared() const { return !isCanonicalUnqualified(); }
QualType desugar() const { return getCanonicalTypeInternal(); }
@@ -3902,14 +3949,13 @@ public:
}
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getDeducedType(), isDecltypeAuto(),
- isDependentType());
+ Profile(ID, getDeducedType(), getKeyword(), isDependentType());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,
- bool IsDecltypeAuto, bool IsDependent) {
+ AutoTypeKeyword Keyword, bool IsDependent) {
ID.AddPointer(Deduced.getAsOpaquePtr());
- ID.AddBoolean(IsDecltypeAuto);
+ ID.AddInteger((unsigned)Keyword);
ID.AddBoolean(IsDependent);
}
@@ -3926,9 +3972,9 @@ public:
/// @c DependentTemplateSpecializationType.
///
/// A non-dependent template specialization type is always "sugar",
-/// typically for a @c RecordType. For example, a class template
-/// specialization type of @c vector<int> will refer to a tag type for
-/// the instantiation @c std::vector<int, std::allocator<int>>
+/// typically for a \c RecordType. For example, a class template
+/// specialization type of \c vector<int> will refer to a tag type for
+/// the instantiation \c std::vector<int, std::allocator<int>>
///
/// Template specializations are dependent if either the template or
/// any of the template arguments are dependent, in which case the
@@ -3938,9 +3984,10 @@ public:
/// TemplateArguments, followed by a QualType representing the
/// non-canonical aliased type when the template is a type alias
/// template.
-class TemplateSpecializationType
- : public Type, public llvm::FoldingSetNode {
- /// \brief The name of the template being specialized. This is
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType
+ : public Type,
+ public llvm::FoldingSetNode {
+ /// The name of the template being specialized. This is
/// either a TemplateName::Template (in which case it is a
/// ClassTemplateDecl*, a TemplateTemplateParmDecl*, or a
/// TypeAliasTemplateDecl*), a
@@ -3949,14 +3996,13 @@ class TemplateSpecializationType
/// replacement must, recursively, be one of these).
TemplateName Template;
- /// \brief - The number of template arguments named in this class
- /// template specialization.
+ /// The number of template arguments named in this class template
+ /// specialization.
unsigned NumArgs : 31;
- /// \brief Whether this template specialization type is a substituted
- /// type alias.
+ /// Whether this template specialization type is a substituted type alias.
bool TypeAlias : 1;
-
+
TemplateSpecializationType(TemplateName T,
const TemplateArgument *Args,
unsigned NumArgs, QualType Canon,
@@ -3965,8 +4011,7 @@ class TemplateSpecializationType
friend class ASTContext; // ASTContext creates these
public:
- /// \brief Determine whether any of the given template arguments are
- /// dependent.
+ /// Determine whether any of the given template arguments are dependent.
static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args,
unsigned NumArgs,
bool &InstantiationDependent);
@@ -4013,7 +4058,7 @@ public:
/// };
/// \endcode
bool isTypeAlias() const { return TypeAlias; }
-
+
/// Get the aliased type, if this is a specialization of a type alias
/// template.
QualType getAliasedType() const {
@@ -4026,19 +4071,19 @@ public:
iterator begin() const { return getArgs(); }
iterator end() const; // defined inline in TemplateBase.h
- /// \brief Retrieve the name of the template that we are specializing.
+ /// Retrieve the name of the template that we are specializing.
TemplateName getTemplateName() const { return Template; }
- /// \brief Retrieve the template arguments.
+ /// Retrieve the template arguments.
const TemplateArgument *getArgs() const {
return reinterpret_cast<const TemplateArgument *>(this + 1);
}
- /// \brief Retrieve the number of template arguments.
+ /// Retrieve the number of template arguments.
unsigned getNumArgs() const { return NumArgs; }
- /// \brief Retrieve a specific template argument as a type.
- /// \pre @c isArgType(Arg)
+ /// Retrieve a specific template argument as a type.
+ /// \pre \c isArgType(Arg)
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
bool isSugared() const {
@@ -4062,7 +4107,7 @@ public:
}
};
-/// \brief The injected class name of a C++ class template or class
+/// The injected class name of a C++ class template or class
/// template partial specialization. Used to record that a type was
/// spelled with a bare identifier rather than as a template-id; the
/// equivalent for non-templated classes is just RecordType.
@@ -4178,21 +4223,18 @@ public:
return static_cast<ElaboratedTypeKeyword>(TypeWithKeywordBits.Keyword);
}
- /// getKeywordForTypeSpec - Converts a type specifier (DeclSpec::TST)
- /// into an elaborated type keyword.
+ /// Converts a type specifier (DeclSpec::TST) into an elaborated type keyword.
static ElaboratedTypeKeyword getKeywordForTypeSpec(unsigned TypeSpec);
- /// getTagTypeKindForTypeSpec - Converts a type specifier (DeclSpec::TST)
- /// into a tag type kind. It is an error to provide a type specifier
- /// which *isn't* a tag kind here.
+ /// Converts a type specifier (DeclSpec::TST) into a tag type kind.
+ /// It is an error to provide a type specifier which *isn't* a tag kind here.
static TagTypeKind getTagTypeKindForTypeSpec(unsigned TypeSpec);
- /// getKeywordForTagDeclKind - Converts a TagTypeKind into an
- /// elaborated type keyword.
+ /// Converts a TagTypeKind into an elaborated type keyword.
static ElaboratedTypeKeyword getKeywordForTagTypeKind(TagTypeKind Tag);
- /// getTagTypeKindForKeyword - Converts an elaborated type keyword into
- // a TagTypeKind. It is an error to provide an elaborated type keyword
+ /// Converts an elaborated type keyword into a TagTypeKind.
+ /// It is an error to provide an elaborated type keyword
/// which *isn't* a tag kind here.
static TagTypeKind getTagTypeKindForKeyword(ElaboratedTypeKeyword Keyword);
@@ -4218,10 +4260,10 @@ public:
/// in the source code but containing no additional semantic information.
class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
- /// \brief The nested name specifier containing the qualifier.
+ /// The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
- /// \brief The type that this qualified name refers to.
+ /// The type that this qualified name refers to.
QualType NamedType;
ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
@@ -4242,16 +4284,16 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode {
public:
~ElaboratedType();
- /// \brief Retrieve the qualification on this type.
+ /// Retrieve the qualification on this type.
NestedNameSpecifier *getQualifier() const { return NNS; }
- /// \brief Retrieve the type named by the qualified-id.
+ /// Retrieve the type named by the qualified-id.
QualType getNamedType() const { return NamedType; }
- /// \brief Remove a single level of sugar.
+ /// Remove a single level of sugar.
QualType desugar() const { return getNamedType(); }
- /// \brief Returns whether this type directly provides sugar.
+ /// Returns whether this type directly provides sugar.
bool isSugared() const { return true; }
void Profile(llvm::FoldingSetNodeID &ID) {
@@ -4301,11 +4343,10 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
public:
- /// \brief Retrieve the qualification on this type.
+ /// Retrieve the qualification on this type.
NestedNameSpecifier *getQualifier() const { return NNS; }
- /// \brief Retrieve the type named by the typename specifier as an
- /// identifier.
+ /// Retrieve the type named by the typename specifier as an identifier.
///
/// This routine will return a non-NULL identifier pointer when the
/// form of the original typename was terminated by an identifier,
@@ -4333,20 +4374,21 @@ public:
}
};
-/// DependentTemplateSpecializationType - Represents a template
-/// specialization type whose template cannot be resolved, e.g.
+/// Represents a template specialization type whose template cannot be
+/// resolved, e.g.
/// A<T>::template B<T>
-class DependentTemplateSpecializationType :
- public TypeWithKeyword, public llvm::FoldingSetNode {
+class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType
+ : public TypeWithKeyword,
+ public llvm::FoldingSetNode {
- /// \brief The nested name specifier containing the qualifier.
+ /// The nested name specifier containing the qualifier.
NestedNameSpecifier *NNS;
- /// \brief The identifier of the template.
+ /// The identifier of the template.
const IdentifierInfo *Name;
- /// \brief - The number of template arguments named in this class
- /// template specialization.
+ /// \brief The number of template arguments named in this class template
+ /// specialization.
unsigned NumArgs;
const TemplateArgument *getArgBuffer() const {
@@ -4405,7 +4447,7 @@ public:
/// \brief Represents a pack expansion of types.
///
-/// Pack expansions are part of C++0x variadic templates. A pack
+/// Pack expansions are part of C++11 variadic templates. A pack
/// expansion contains a pattern, which itself contains one or more
/// "unexpanded" parameter packs. When instantiated, a pack expansion
/// produces a series of types, each instantiated from the pattern of
@@ -4483,7 +4525,7 @@ public:
}
};
-/// ObjCObjectType - Represents a class type in Objective C.
+/// Represents a class type in Objective C.
///
/// Every Objective C type is a combination of a base type, a set of
/// type arguments (optional, for parameterized classes) and a list of
@@ -4560,8 +4602,8 @@ protected:
void computeSuperClassTypeSlow() const;
public:
- /// getBaseType - Gets the base type of this object type. This is
- /// always (possibly sugar for) one of:
+ /// Gets the base type of this object type. This is always (possibly
+ /// sugar for) one of:
/// - the 'id' builtin type (as opposed to the 'id' type visible to the
/// user, which is a typedef for an ObjCObjectPointerType)
/// - the 'Class' builtin type (same caveat)
@@ -4595,8 +4637,8 @@ public:
bool isSpecialized() const;
/// Determine whether this object type was written with type arguments.
- bool isSpecializedAsWritten() const {
- return ObjCObjectTypeBits.NumTypeArgs > 0;
+ bool isSpecializedAsWritten() const {
+ return ObjCObjectTypeBits.NumTypeArgs > 0;
}
/// Determine whether this object type is "unspecialized", meaning
@@ -4612,8 +4654,8 @@ public:
/// Retrieve the type arguments of this object type as they were
/// written.
- ArrayRef<QualType> getTypeArgsAsWritten() const {
- return ArrayRef<QualType>(getTypeArgStorage(),
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return llvm::makeArrayRef(getTypeArgStorage(),
ObjCObjectTypeBits.NumTypeArgs);
}
@@ -4626,11 +4668,11 @@ public:
bool qual_empty() const { return getNumProtocols() == 0; }
- /// getNumProtocols - Return the number of qualifying protocols in this
- /// interface type, or 0 if there are none.
+ /// Return the number of qualifying protocols in this interface type,
+ /// or 0 if there are none.
unsigned getNumProtocols() const { return ObjCObjectTypeBits.NumProtocols; }
- /// \brief Fetch a protocol by index.
+ /// Fetch a protocol by index.
ObjCProtocolDecl *getProtocol(unsigned I) const {
assert(I < getNumProtocols() && "Out-of-range protocol access");
return qual_begin()[I];
@@ -4674,7 +4716,7 @@ public:
}
};
-/// ObjCObjectTypeImpl - A class providing a concrete implementation
+/// A class providing a concrete implementation
/// of ObjCObjectType, so as to not increase the footprint of
/// ObjCInterfaceType. Code outside of ASTContext and the core type
/// system should not reference this type.
@@ -4708,11 +4750,10 @@ inline ObjCProtocolDecl **ObjCObjectType::getProtocolStorage() {
getTypeArgStorage() + ObjCObjectTypeBits.NumTypeArgs);
}
-/// ObjCInterfaceType - Interfaces are the core concept in Objective-C for
-/// object oriented design. They basically correspond to C++ classes. There
-/// are two kinds of interface types, normal interfaces like "NSString" and
-/// qualified interfaces, which are qualified with a protocol list like
-/// "NSString<NSCopyable, NSAmazing>".
+/// Interfaces are the core concept in Objective-C for object oriented design.
+/// They basically correspond to C++ classes. There are two kinds of interface
+/// types: normal interfaces like `NSString`, and qualified interfaces, which
+/// are qualified with a protocol list like `NSString<NSCopyable, NSAmazing>`.
///
/// ObjCInterfaceType guarantees the following properties when considered
/// as a subtype of its superclass, ObjCObjectType:
@@ -4732,7 +4773,7 @@ class ObjCInterfaceType : public ObjCObjectType {
friend class ObjCInterfaceDecl;
public:
- /// getDecl - Get the declaration of this interface.
+ /// Get the declaration of this interface.
ObjCInterfaceDecl *getDecl() const { return Decl; }
bool isSugared() const { return false; }
@@ -4767,12 +4808,12 @@ inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const {
return nullptr;
}
-/// ObjCObjectPointerType - Used to represent a pointer to an
-/// Objective C object. These are constructed from pointer
-/// declarators when the pointee type is an ObjCObjectType (or sugar
-/// for one). In addition, the 'id' and 'Class' types are typedefs
-/// for these, and the protocol-qualified types 'id<P>' and 'Class<P>'
-/// are translated into these.
+/// Represents a pointer to an Objective C object.
+///
+/// These are constructed from pointer declarators when the pointee type is
+/// an ObjCObjectType (or sugar for one). In addition, the 'id' and 'Class'
+/// types are typedefs for these, and the protocol-qualified types 'id<P>'
+/// and 'Class<P>' are translated into these.
///
/// Pointers to pointers to Objective C objects are still PointerTypes;
/// only the first level of pointer gets it own type implementation.
@@ -4789,12 +4830,11 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
public:
- /// getPointeeType - Gets the type pointed to by this ObjC pointer.
+ /// Gets the type pointed to by this ObjC pointer.
/// The result will always be an ObjCObjectType or sugar thereof.
QualType getPointeeType() const { return PointeeType; }
- /// getObjCObjectType - Gets the type pointed to by this ObjC
- /// pointer. This method always returns non-null.
+ /// Gets the type pointed to by this ObjC pointer. Always returns non-null.
///
/// This method is equivalent to getPointeeType() except that
/// it discards any typedefs (or other sugar) between this
@@ -4821,14 +4861,14 @@ public:
return PointeeType->castAs<ObjCObjectType>();
}
- /// getInterfaceType - If this pointer points to an Objective C
+ /// If this pointer points to an Objective C
/// \@interface type, gets the type for that interface. Any protocol
/// qualifiers on the interface are ignored.
///
/// \return null if the base type for this pointer is 'id' or 'Class'
const ObjCInterfaceType *getInterfaceType() const;
- /// getInterfaceDecl - If this pointer points to an Objective \@interface
+ /// If this pointer points to an Objective \@interface
/// type, gets the declaration for that interface.
///
/// \return null if the base type for this pointer is 'id' or 'Class'
@@ -4836,32 +4876,31 @@ public:
return getObjectType()->getInterface();
}
- /// isObjCIdType - True if this is equivalent to the 'id' type, i.e. if
+ /// True if this is equivalent to the 'id' type, i.e. if
/// its object type is the primitive 'id' type with no protocols.
bool isObjCIdType() const {
return getObjectType()->isObjCUnqualifiedId();
}
- /// isObjCClassType - True if this is equivalent to the 'Class' type,
+ /// True if this is equivalent to the 'Class' type,
/// i.e. if its object tive is the primitive 'Class' type with no protocols.
bool isObjCClassType() const {
return getObjectType()->isObjCUnqualifiedClass();
}
- /// isObjCIdOrClassType - True if this is equivalent to the 'id' or
- /// 'Class' type,
+ /// True if this is equivalent to the 'id' or 'Class' type,
bool isObjCIdOrClassType() const {
return getObjectType()->isObjCUnqualifiedIdOrClass();
}
- /// isObjCQualifiedIdType - True if this is equivalent to 'id<P>' for some
- /// non-empty set of protocols.
+ /// True if this is equivalent to 'id<P>' for some non-empty set of
+ /// protocols.
bool isObjCQualifiedIdType() const {
return getObjectType()->isObjCQualifiedId();
}
- /// isObjCQualifiedClassType - True if this is equivalent to 'Class<P>' for
- /// some non-empty set of protocols.
+ /// True if this is equivalent to 'Class<P>' for some non-empty set of
+ /// protocols.
bool isObjCQualifiedClassType() const {
return getObjectType()->isObjCQualifiedClass();
}
@@ -4873,10 +4912,10 @@ public:
bool isSpecialized() const { return getObjectType()->isSpecialized(); }
/// Whether this type is specialized, meaning that it has type arguments.
- bool isSpecializedAsWritten() const {
- return getObjectType()->isSpecializedAsWritten();
+ bool isSpecializedAsWritten() const {
+ return getObjectType()->isSpecializedAsWritten();
}
-
+
/// Whether this type is unspecialized, meaning that is has no type arguments.
bool isUnspecialized() const { return getObjectType()->isUnspecialized(); }
@@ -4885,13 +4924,13 @@ public:
bool isUnspecializedAsWritten() const { return !isSpecializedAsWritten(); }
/// Retrieve the type arguments for this type.
- ArrayRef<QualType> getTypeArgs() const {
- return getObjectType()->getTypeArgs();
+ ArrayRef<QualType> getTypeArgs() const {
+ return getObjectType()->getTypeArgs();
}
/// Retrieve the type arguments for this type.
- ArrayRef<QualType> getTypeArgsAsWritten() const {
- return getObjectType()->getTypeArgsAsWritten();
+ ArrayRef<QualType> getTypeArgsAsWritten() const {
+ return getObjectType()->getTypeArgsAsWritten();
}
/// An iterator over the qualifiers on the object type. Provided
@@ -4909,14 +4948,12 @@ public:
}
bool qual_empty() const { return getObjectType()->qual_empty(); }
- /// getNumProtocols - Return the number of qualifying protocols on
- /// the object type.
+ /// Return the number of qualifying protocols on the object type.
unsigned getNumProtocols() const {
return getObjectType()->getNumProtocols();
}
- /// \brief Retrieve a qualifying protocol by index on the object
- /// type.
+ /// Retrieve a qualifying protocol by index on the object type.
ObjCProtocolDecl *getProtocol(unsigned I) const {
return getObjectType()->getProtocol(I);
}
@@ -4960,7 +4997,7 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
public:
- /// getValueType - Gets the type contained by this atomic type, i.e.
+ /// Gets the type contained by this atomic type, i.e.
/// the type returned by performing an atomic load of this atomic type.
QualType getValueType() const { return ValueType; }
@@ -5127,12 +5164,12 @@ inline void QualType::removeLocalCVRQualifiers(unsigned Mask) {
removeLocalFastQualifiers(Mask);
}
-/// getAddressSpace - Return the address space of this type.
+/// Return the address space of this type.
inline unsigned QualType::getAddressSpace() const {
return getQualifiers().getAddressSpace();
}
-
-/// getObjCGCAttr - Return the gc attribute of this type.
+
+/// Return the gc attribute of this type.
inline Qualifiers::GC QualType::getObjCGCAttr() const {
return getQualifiers().getObjCGCAttr();
}
@@ -5151,7 +5188,7 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) {
return getFunctionExtInfo(*t);
}
-/// isMoreQualifiedThan - Determine whether this type is more
+/// Determine whether this type is more
/// qualified than the Other type. For example, "const volatile int"
/// is more qualified than "const int", "volatile int", and
/// "int". However, it is not more qualified than "const volatile
@@ -5162,7 +5199,7 @@ inline bool QualType::isMoreQualifiedThan(QualType other) const {
return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals));
}
-/// isAtLeastAsQualifiedAs - Determine whether this type is at last
+/// Determine whether this type is at last
/// as qualified as the Other type. For example, "const volatile
/// int" is at least as qualified as "const int", "volatile int",
/// "int", and "const volatile int".
@@ -5170,7 +5207,7 @@ inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const {
return getQualifiers().compatiblyIncludes(other.getQualifiers());
}
-/// getNonReferenceType - If Type is a reference type (e.g., const
+/// If Type is a reference type (e.g., const
/// int&), returns the type that the reference refers to ("const
/// int"). Otherwise, returns the type itself. This routine is used
/// throughout Sema to implement C++ 5p6:
@@ -5191,7 +5228,7 @@ inline bool QualType::isCForbiddenLValueType() const {
getTypePtr()->isFunctionType());
}
-/// \brief Tests whether the type is categorized as a fundamental type.
+/// Tests whether the type is categorized as a fundamental type.
///
/// \returns True for types specified in C++0x [basic.fundamental].
inline bool Type::isFundamentalType() const {
@@ -5201,7 +5238,7 @@ inline bool Type::isFundamentalType() const {
(isArithmeticType() && !isEnumeralType());
}
-/// \brief Tests whether the type is categorized as a compound type.
+/// Tests whether the type is categorized as a compound type.
///
/// \returns True for types specified in C++0x [basic.compound].
inline bool Type::isCompoundType() const {
@@ -5364,6 +5401,30 @@ inline bool Type::isImage2dArrayT() const {
return isSpecificBuiltinType(BuiltinType::OCLImage2dArray);
}
+inline bool Type::isImage2dDepthT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dDepth);
+}
+
+inline bool Type::isImage2dArrayDepthT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayDepth);
+}
+
+inline bool Type::isImage2dMSAAT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAA);
+}
+
+inline bool Type::isImage2dArrayMSAAT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAA);
+}
+
+inline bool Type::isImage2dMSAATDepth() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAADepth);
+}
+
+inline bool Type::isImage2dArrayMSAATDepth() const {
+ return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAADepth);
+}
+
inline bool Type::isImage3dT() const {
return isSpecificBuiltinType(BuiltinType::OCLImage3d);
}
@@ -5376,14 +5437,33 @@ inline bool Type::isEventT() const {
return isSpecificBuiltinType(BuiltinType::OCLEvent);
}
+inline bool Type::isClkEventT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLClkEvent);
+}
+
+inline bool Type::isQueueT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLQueue);
+}
+
+inline bool Type::isNDRangeT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLNDRange);
+}
+
+inline bool Type::isReserveIDT() const {
+ return isSpecificBuiltinType(BuiltinType::OCLReserveID);
+}
+
inline bool Type::isImageType() const {
- return isImage3dT() ||
- isImage2dT() || isImage2dArrayT() ||
- isImage1dT() || isImage1dArrayT() || isImage1dBufferT();
+ return isImage3dT() || isImage2dT() || isImage2dArrayT() ||
+ isImage2dDepthT() || isImage2dArrayDepthT() || isImage2dMSAAT() ||
+ isImage2dArrayMSAAT() || isImage2dMSAATDepth() ||
+ isImage2dArrayMSAATDepth() || isImage1dT() || isImage1dArrayT() ||
+ isImage1dBufferT();
}
inline bool Type::isOpenCLSpecificType() const {
- return isSamplerT() || isEventT() || isImageType();
+ return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
+ isQueueT() || isNDRangeT() || isReserveIDT();
}
inline bool Type::isTemplateTypeParmType() const {
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index f4d20b8..26feda5 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -151,6 +151,14 @@ public:
TypeLoc IgnoreParens() const;
+ /// \brief Find a type with the location of an explicit type qualifier.
+ ///
+ /// The result, if non-null, will be one of:
+ /// QualifiedTypeLoc
+ /// AtomicTypeLoc
+ /// AttributedTypeLoc, for those type attributes that behave as qualifiers
+ TypeLoc findExplicitQualifierLoc() const;
+
/// \brief Initializes this to state that every location in this
/// type is the given location.
///
@@ -162,19 +170,18 @@ public:
/// \brief Initializes this by copying its information from another
/// TypeLoc of the same type.
- void initializeFullCopy(TypeLoc Other) const {
+ void initializeFullCopy(TypeLoc Other) {
assert(getType() == Other.getType());
- size_t Size = getFullDataSize();
- memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
+ copy(Other);
}
/// \brief Initializes this by copying its information from another
/// TypeLoc of the same type. The given size must be the full data
/// size.
- void initializeFullCopy(TypeLoc Other, unsigned Size) const {
+ void initializeFullCopy(TypeLoc Other, unsigned Size) {
assert(getType() == Other.getType());
assert(getFullDataSize() == Size);
- memcpy(getOpaqueData(), Other.getOpaqueData(), Size);
+ copy(Other);
}
/// Copies the other type loc into this one.
@@ -206,6 +213,7 @@ private:
/// \brief Return the TypeLoc for a type source info.
inline TypeLoc TypeSourceInfo::getTypeLoc() const {
+ // TODO: is this alignment already sufficient?
return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1)));
}
@@ -736,6 +744,10 @@ public:
return hasAttrExprOperand() || hasAttrEnumOperand();
}
+ bool isQualifier() const {
+ return getTypePtr()->isQualifier();
+ }
+
/// The modified type, which is generally canonically different from
/// the attribute type.
/// int main(int, char**) __attribute__((noreturn))
diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h
index ebfbb8a..481fd11 100644
--- a/include/clang/AST/VTableBuilder.h
+++ b/include/clang/AST/VTableBuilder.h
@@ -51,7 +51,7 @@ public:
CK_UnusedFunctionPointer
};
- VTableComponent() { }
+ VTableComponent() = default;
static VTableComponent MakeVCallOffset(CharUnits Offset) {
return VTableComponent(CK_VCallOffset, Offset);
@@ -122,31 +122,56 @@ public:
}
const CXXRecordDecl *getRTTIDecl() const {
- assert(getKind() == CK_RTTI && "Invalid component kind!");
-
+ assert(isRTTIKind() && "Invalid component kind!");
return reinterpret_cast<CXXRecordDecl *>(getPointer());
}
const CXXMethodDecl *getFunctionDecl() const {
- assert(getKind() == CK_FunctionPointer);
-
+ assert(isFunctionPointerKind() && "Invalid component kind!");
+ if (isDestructorKind())
+ return getDestructorDecl();
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
const CXXDestructorDecl *getDestructorDecl() const {
- assert((getKind() == CK_CompleteDtorPointer ||
- getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
-
+ assert(isDestructorKind() && "Invalid component kind!");
return reinterpret_cast<CXXDestructorDecl *>(getPointer());
}
const CXXMethodDecl *getUnusedFunctionDecl() const {
- assert(getKind() == CK_UnusedFunctionPointer);
-
+ assert(getKind() == CK_UnusedFunctionPointer && "Invalid component kind!");
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
+ bool isDestructorKind() const { return isDestructorKind(getKind()); }
+
+ bool isUsedFunctionPointerKind() const {
+ return isUsedFunctionPointerKind(getKind());
+ }
+
+ bool isFunctionPointerKind() const {
+ return isFunctionPointerKind(getKind());
+ }
+
+ bool isRTTIKind() const { return isRTTIKind(getKind()); }
+
private:
+ static bool isFunctionPointerKind(Kind ComponentKind) {
+ return isUsedFunctionPointerKind(ComponentKind) ||
+ ComponentKind == CK_UnusedFunctionPointer;
+ }
+ static bool isUsedFunctionPointerKind(Kind ComponentKind) {
+ return ComponentKind == CK_FunctionPointer ||
+ isDestructorKind(ComponentKind);
+ }
+ static bool isDestructorKind(Kind ComponentKind) {
+ return ComponentKind == CK_CompleteDtorPointer ||
+ ComponentKind == CK_DeletingDtorPointer;
+ }
+ static bool isRTTIKind(Kind ComponentKind) {
+ return ComponentKind == CK_RTTI;
+ }
+
VTableComponent(Kind ComponentKind, CharUnits Offset) {
assert((ComponentKind == CK_VCallOffset ||
ComponentKind == CK_VBaseOffset ||
@@ -158,12 +183,8 @@ private:
}
VTableComponent(Kind ComponentKind, uintptr_t Ptr) {
- assert((ComponentKind == CK_RTTI ||
- ComponentKind == CK_FunctionPointer ||
- ComponentKind == CK_CompleteDtorPointer ||
- ComponentKind == CK_DeletingDtorPointer ||
- ComponentKind == CK_UnusedFunctionPointer) &&
- "Invalid component kind!");
+ assert((isRTTIKind(ComponentKind) || isFunctionPointerKind(ComponentKind)) &&
+ "Invalid component kind!");
assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
@@ -178,11 +199,7 @@ private:
}
uintptr_t getPointer() const {
- assert((getKind() == CK_RTTI ||
- getKind() == CK_FunctionPointer ||
- getKind() == CK_CompleteDtorPointer ||
- getKind() == CK_DeletingDtorPointer ||
- getKind() == CK_UnusedFunctionPointer) &&
+ assert((getKind() == CK_RTTI || isFunctionPointerKind()) &&
"Invalid component kind!");
return static_cast<uintptr_t>(Value & ~7ULL);
@@ -205,8 +222,11 @@ public:
typedef const VTableComponent *vtable_component_iterator;
typedef const VTableThunkTy *vtable_thunk_iterator;
+ typedef llvm::iterator_range<vtable_component_iterator>
+ vtable_component_range;
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
+
private:
uint64_t NumVTableComponents;
std::unique_ptr<VTableComponent[]> VTableComponents;
@@ -233,6 +253,11 @@ public:
return NumVTableComponents;
}
+ vtable_component_range vtable_components() const {
+ return vtable_component_range(vtable_component_begin(),
+ vtable_component_end());
+ }
+
vtable_component_iterator vtable_component_begin() const {
return VTableComponents.get();
}
@@ -376,10 +401,6 @@ struct VPtrInfo {
VPtrInfo(const CXXRecordDecl *RD)
: ReusingBase(RD), BaseWithVPtr(RD), NextBaseToMangle(RD) {}
- // Copy constructor.
- // FIXME: Uncomment when we've moved to C++11.
- // VPtrInfo(const VPtrInfo &) = default;
-
/// The vtable will hold all of the virtual bases or virtual methods of
/// ReusingBase. This may or may not be the same class as VPtrSubobject.Base.
/// A derived class will reuse the vptr of the first non-virtual base
OpenPOWER on IntegriCloud