1 //===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file defines OpenMP nodes for declarative directives.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_AST_DECLOPENMP_H
15 #define LLVM_CLANG_AST_DECLOPENMP_H
16 
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExternalASTSource.h"
21 #include "clang/AST/OpenMPClause.h"
22 #include "clang/AST/Type.h"
23 #include "llvm/ADT/ArrayRef.h"
24 #include "llvm/Support/TrailingObjects.h"
25 
26 namespace clang {
27 
28 /// This is a basic class for representing single OpenMP declarative directive.
29 ///
30 template <typename U> class OMPDeclarativeDirective : public U {
31   friend class ASTDeclReader;
32   friend class ASTDeclWriter;
33 
34   /// Get the clauses storage.
getClauses()35   MutableArrayRef<OMPClause *> getClauses() {
36     if (!Data)
37       return llvm::None;
38     return Data->getClauses();
39   }
40 
41 protected:
42   /// Data, associated with the directive.
43   OMPChildren *Data = nullptr;
44 
45   /// Build instance of directive.
46   template <typename... Params>
OMPDeclarativeDirective(Params &&...P)47   OMPDeclarativeDirective(Params &&... P) : U(std::forward<Params>(P)...) {}
48 
49   template <typename T, typename... Params>
createDirective(const ASTContext & C,DeclContext * DC,ArrayRef<OMPClause * > Clauses,unsigned NumChildren,Params &&...P)50   static T *createDirective(const ASTContext &C, DeclContext *DC,
51                             ArrayRef<OMPClause *> Clauses, unsigned NumChildren,
52                             Params &&... P) {
53     auto *Inst = new (C, DC, size(Clauses.size(), NumChildren))
54         T(DC, std::forward<Params>(P)...);
55     Inst->Data = OMPChildren::Create(Inst + 1, Clauses,
56                                      /*AssociatedStmt=*/nullptr, NumChildren);
57     Inst->Data->setClauses(Clauses);
58     return Inst;
59   }
60 
61   template <typename T, typename... Params>
createEmptyDirective(const ASTContext & C,unsigned ID,unsigned NumClauses,unsigned NumChildren,Params &&...P)62   static T *createEmptyDirective(const ASTContext &C, unsigned ID,
63                                  unsigned NumClauses, unsigned NumChildren,
64                                  Params &&... P) {
65     auto *Inst = new (C, ID, size(NumClauses, NumChildren))
66         T(nullptr, std::forward<Params>(P)...);
67     Inst->Data = OMPChildren::CreateEmpty(
68         Inst + 1, NumClauses, /*HasAssociatedStmt=*/false, NumChildren);
69     return Inst;
70   }
71 
size(unsigned NumClauses,unsigned NumChildren)72   static size_t size(unsigned NumClauses, unsigned NumChildren) {
73     return OMPChildren::size(NumClauses, /*HasAssociatedStmt=*/false,
74                              NumChildren);
75   }
76 
77 public:
78   /// Get number of clauses.
getNumClauses()79   unsigned getNumClauses() const {
80     if (!Data)
81       return 0;
82     return Data->getNumClauses();
83   }
84 
85   /// Returns specified clause.
86   ///
87   /// \param I Number of clause.
88   ///
getClause(unsigned I)89   OMPClause *getClause(unsigned I) const { return clauses()[I]; }
90 
clauses()91   ArrayRef<OMPClause *> clauses() const {
92     if (!Data)
93       return llvm::None;
94     return Data->getClauses();
95   }
96 };
97 
98 /// This represents '#pragma omp threadprivate ...' directive.
99 /// For example, in the following, both 'a' and 'A::b' are threadprivate:
100 ///
101 /// \code
102 /// int a;
103 /// #pragma omp threadprivate(a)
104 /// struct A {
105 ///   static int b;
106 /// #pragma omp threadprivate(b)
107 /// };
108 /// \endcode
109 ///
110 class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> {
111   friend class OMPDeclarativeDirective<Decl>;
112 
113   virtual void anchor();
114 
115   OMPThreadPrivateDecl(DeclContext *DC = nullptr,
116                        SourceLocation L = SourceLocation())
117       : OMPDeclarativeDirective<Decl>(OMPThreadPrivate, DC, L) {}
118 
getVars()119   ArrayRef<const Expr *> getVars() const {
120     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
121     return llvm::makeArrayRef(Storage, Data->getNumChildren());
122   }
123 
getVars()124   MutableArrayRef<Expr *> getVars() {
125     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
126     return llvm::makeMutableArrayRef(Storage, Data->getNumChildren());
127   }
128 
129   void setVars(ArrayRef<Expr *> VL);
130 
131 public:
132   static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
133                                       SourceLocation L,
134                                       ArrayRef<Expr *> VL);
135   static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
136                                                   unsigned ID, unsigned N);
137 
138   typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
139   typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
140   typedef llvm::iterator_range<varlist_iterator> varlist_range;
141   typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
142 
varlist_size()143   unsigned varlist_size() const { return Data->getNumChildren(); }
varlist_empty()144   bool varlist_empty() const { return Data->getChildren().empty(); }
145 
varlists()146   varlist_range varlists() {
147     return varlist_range(varlist_begin(), varlist_end());
148   }
varlists()149   varlist_const_range varlists() const {
150     return varlist_const_range(varlist_begin(), varlist_end());
151   }
varlist_begin()152   varlist_iterator varlist_begin() { return getVars().begin(); }
varlist_end()153   varlist_iterator varlist_end() { return getVars().end(); }
varlist_begin()154   varlist_const_iterator varlist_begin() const { return getVars().begin(); }
varlist_end()155   varlist_const_iterator varlist_end() const { return getVars().end(); }
156 
classof(const Decl * D)157   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)158   static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
159 };
160 
161 /// This represents '#pragma omp declare reduction ...' directive.
162 /// For example, in the following, declared reduction 'foo' for types 'int' and
163 /// 'float':
164 ///
165 /// \code
166 /// #pragma omp declare reduction (foo : int,float : omp_out += omp_in)
167 ///                     initializer (omp_priv = 0)
168 /// \endcode
169 ///
170 /// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer.
171 class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext {
172   // This class stores some data in DeclContext::OMPDeclareReductionDeclBits
173   // to save some space. Use the provided accessors to access it.
174 public:
175   enum InitKind {
176     CallInit,   // Initialized by function call.
177     DirectInit, // omp_priv(<expr>)
178     CopyInit    // omp_priv = <expr>
179   };
180 
181 private:
182   friend class ASTDeclReader;
183   /// Combiner for declare reduction construct.
184   Expr *Combiner = nullptr;
185   /// Initializer for declare reduction construct.
186   Expr *Initializer = nullptr;
187   /// In parameter of the combiner.
188   Expr *In = nullptr;
189   /// Out parameter of the combiner.
190   Expr *Out = nullptr;
191   /// Priv parameter of the initializer.
192   Expr *Priv = nullptr;
193   /// Orig parameter of the initializer.
194   Expr *Orig = nullptr;
195 
196   /// Reference to the previous declare reduction construct in the same
197   /// scope with the same name. Required for proper templates instantiation if
198   /// the declare reduction construct is declared inside compound statement.
199   LazyDeclPtr PrevDeclInScope;
200 
201   void anchor() override;
202 
203   OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L,
204                           DeclarationName Name, QualType Ty,
205                           OMPDeclareReductionDecl *PrevDeclInScope);
206 
setPrevDeclInScope(OMPDeclareReductionDecl * Prev)207   void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) {
208     PrevDeclInScope = Prev;
209   }
210 
211 public:
212   /// Create declare reduction node.
213   static OMPDeclareReductionDecl *
214   Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name,
215          QualType T, OMPDeclareReductionDecl *PrevDeclInScope);
216   /// Create deserialized declare reduction node.
217   static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C,
218                                                      unsigned ID);
219 
220   /// Get combiner expression of the declare reduction construct.
getCombiner()221   Expr *getCombiner() { return Combiner; }
getCombiner()222   const Expr *getCombiner() const { return Combiner; }
223   /// Get In variable of the combiner.
getCombinerIn()224   Expr *getCombinerIn() { return In; }
getCombinerIn()225   const Expr *getCombinerIn() const { return In; }
226   /// Get Out variable of the combiner.
getCombinerOut()227   Expr *getCombinerOut() { return Out; }
getCombinerOut()228   const Expr *getCombinerOut() const { return Out; }
229   /// Set combiner expression for the declare reduction construct.
setCombiner(Expr * E)230   void setCombiner(Expr *E) { Combiner = E; }
231   /// Set combiner In and Out vars.
setCombinerData(Expr * InE,Expr * OutE)232   void setCombinerData(Expr *InE, Expr *OutE) {
233     In = InE;
234     Out = OutE;
235   }
236 
237   /// Get initializer expression (if specified) of the declare reduction
238   /// construct.
getInitializer()239   Expr *getInitializer() { return Initializer; }
getInitializer()240   const Expr *getInitializer() const { return Initializer; }
241   /// Get initializer kind.
getInitializerKind()242   InitKind getInitializerKind() const {
243     return static_cast<InitKind>(OMPDeclareReductionDeclBits.InitializerKind);
244   }
245   /// Get Orig variable of the initializer.
getInitOrig()246   Expr *getInitOrig() { return Orig; }
getInitOrig()247   const Expr *getInitOrig() const { return Orig; }
248   /// Get Priv variable of the initializer.
getInitPriv()249   Expr *getInitPriv() { return Priv; }
getInitPriv()250   const Expr *getInitPriv() const { return Priv; }
251   /// Set initializer expression for the declare reduction construct.
setInitializer(Expr * E,InitKind IK)252   void setInitializer(Expr *E, InitKind IK) {
253     Initializer = E;
254     OMPDeclareReductionDeclBits.InitializerKind = IK;
255   }
256   /// Set initializer Orig and Priv vars.
setInitializerData(Expr * OrigE,Expr * PrivE)257   void setInitializerData(Expr *OrigE, Expr *PrivE) {
258     Orig = OrigE;
259     Priv = PrivE;
260   }
261 
262   /// Get reference to previous declare reduction construct in the same
263   /// scope with the same name.
264   OMPDeclareReductionDecl *getPrevDeclInScope();
265   const OMPDeclareReductionDecl *getPrevDeclInScope() const;
266 
classof(const Decl * D)267   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)268   static bool classofKind(Kind K) { return K == OMPDeclareReduction; }
castToDeclContext(const OMPDeclareReductionDecl * D)269   static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) {
270     return static_cast<DeclContext *>(const_cast<OMPDeclareReductionDecl *>(D));
271   }
castFromDeclContext(const DeclContext * DC)272   static OMPDeclareReductionDecl *castFromDeclContext(const DeclContext *DC) {
273     return static_cast<OMPDeclareReductionDecl *>(
274         const_cast<DeclContext *>(DC));
275   }
276 };
277 
278 /// This represents '#pragma omp declare mapper ...' directive. Map clauses are
279 /// allowed to use with this directive. The following example declares a user
280 /// defined mapper for the type 'struct vec'. This example instructs the fields
281 /// 'len' and 'data' should be mapped when mapping instances of 'struct vec'.
282 ///
283 /// \code
284 /// #pragma omp declare mapper(mid: struct vec v) map(v.len, v.data[0:N])
285 /// \endcode
286 class OMPDeclareMapperDecl final : public OMPDeclarativeDirective<ValueDecl>,
287                                    public DeclContext {
288   friend class OMPDeclarativeDirective<ValueDecl>;
289   friend class ASTDeclReader;
290   friend class ASTDeclWriter;
291 
292   /// Mapper variable, which is 'v' in the example above
293   Expr *MapperVarRef = nullptr;
294 
295   /// Name of the mapper variable
296   DeclarationName VarName;
297 
298   LazyDeclPtr PrevDeclInScope;
299 
300   void anchor() override;
301 
OMPDeclareMapperDecl(DeclContext * DC,SourceLocation L,DeclarationName Name,QualType Ty,DeclarationName VarName,OMPDeclareMapperDecl * PrevDeclInScope)302   OMPDeclareMapperDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
303                        QualType Ty, DeclarationName VarName,
304                        OMPDeclareMapperDecl *PrevDeclInScope)
305       : OMPDeclarativeDirective<ValueDecl>(OMPDeclareMapper, DC, L, Name, Ty),
306         DeclContext(OMPDeclareMapper), VarName(VarName),
307         PrevDeclInScope(PrevDeclInScope) {}
308 
setPrevDeclInScope(OMPDeclareMapperDecl * Prev)309   void setPrevDeclInScope(OMPDeclareMapperDecl *Prev) {
310     PrevDeclInScope = Prev;
311   }
312 
313 public:
314   /// Creates declare mapper node.
315   static OMPDeclareMapperDecl *Create(ASTContext &C, DeclContext *DC,
316                                       SourceLocation L, DeclarationName Name,
317                                       QualType T, DeclarationName VarName,
318                                       ArrayRef<OMPClause *> Clauses,
319                                       OMPDeclareMapperDecl *PrevDeclInScope);
320   /// Creates deserialized declare mapper node.
321   static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C, unsigned ID,
322                                                   unsigned N);
323 
324   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
325   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
326   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
327   using clauselist_const_range =
328       llvm::iterator_range<clauselist_const_iterator>;
329 
clauselist_size()330   unsigned clauselist_size() const { return Data->getNumClauses(); }
clauselist_empty()331   bool clauselist_empty() const { return Data->getClauses().empty(); }
332 
clauselists()333   clauselist_range clauselists() {
334     return clauselist_range(clauselist_begin(), clauselist_end());
335   }
clauselists()336   clauselist_const_range clauselists() const {
337     return clauselist_const_range(clauselist_begin(), clauselist_end());
338   }
clauselist_begin()339   clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
clauselist_end()340   clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
clauselist_begin()341   clauselist_const_iterator clauselist_begin() const {
342     return Data->getClauses().begin();
343   }
clauselist_end()344   clauselist_const_iterator clauselist_end() const {
345     return Data->getClauses().end();
346   }
347 
348   /// Get the variable declared in the mapper
getMapperVarRef()349   Expr *getMapperVarRef() { return cast_or_null<Expr>(Data->getChildren()[0]); }
getMapperVarRef()350   const Expr *getMapperVarRef() const {
351     return cast_or_null<Expr>(Data->getChildren()[0]);
352   }
353   /// Set the variable declared in the mapper
setMapperVarRef(Expr * MapperVarRefE)354   void setMapperVarRef(Expr *MapperVarRefE) {
355     Data->getChildren()[0] = MapperVarRefE;
356   }
357 
358   /// Get the name of the variable declared in the mapper
getVarName()359   DeclarationName getVarName() { return VarName; }
360 
361   /// Get reference to previous declare mapper construct in the same
362   /// scope with the same name.
363   OMPDeclareMapperDecl *getPrevDeclInScope();
364   const OMPDeclareMapperDecl *getPrevDeclInScope() const;
365 
classof(const Decl * D)366   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)367   static bool classofKind(Kind K) { return K == OMPDeclareMapper; }
castToDeclContext(const OMPDeclareMapperDecl * D)368   static DeclContext *castToDeclContext(const OMPDeclareMapperDecl *D) {
369     return static_cast<DeclContext *>(const_cast<OMPDeclareMapperDecl *>(D));
370   }
castFromDeclContext(const DeclContext * DC)371   static OMPDeclareMapperDecl *castFromDeclContext(const DeclContext *DC) {
372     return static_cast<OMPDeclareMapperDecl *>(const_cast<DeclContext *>(DC));
373   }
374 };
375 
376 /// Pseudo declaration for capturing expressions. Also is used for capturing of
377 /// non-static data members in non-static member functions.
378 ///
379 /// Clang supports capturing of variables only, but OpenMP 4.5 allows to
380 /// privatize non-static members of current class in non-static member
381 /// functions. This pseudo-declaration allows properly handle this kind of
382 /// capture by wrapping captured expression into a variable-like declaration.
383 class OMPCapturedExprDecl final : public VarDecl {
384   friend class ASTDeclReader;
385   void anchor() override;
386 
OMPCapturedExprDecl(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,QualType Type,TypeSourceInfo * TInfo,SourceLocation StartLoc)387   OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
388                       QualType Type, TypeSourceInfo *TInfo,
389                       SourceLocation StartLoc)
390       : VarDecl(OMPCapturedExpr, C, DC, StartLoc, StartLoc, Id, Type, TInfo,
391                 SC_None) {
392     setImplicit();
393   }
394 
395 public:
396   static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC,
397                                      IdentifierInfo *Id, QualType T,
398                                      SourceLocation StartLoc);
399 
400   static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, unsigned ID);
401 
402   SourceRange getSourceRange() const override LLVM_READONLY;
403 
404   // Implement isa/cast/dyncast/etc.
classof(const Decl * D)405   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)406   static bool classofKind(Kind K) { return K == OMPCapturedExpr; }
407 };
408 
409 /// This represents '#pragma omp requires...' directive.
410 /// For example
411 ///
412 /// \code
413 /// #pragma omp requires unified_address
414 /// \endcode
415 ///
416 class OMPRequiresDecl final : public OMPDeclarativeDirective<Decl> {
417   friend class OMPDeclarativeDirective<Decl>;
418   friend class ASTDeclReader;
419 
420   virtual void anchor();
421 
OMPRequiresDecl(DeclContext * DC,SourceLocation L)422   OMPRequiresDecl(DeclContext *DC, SourceLocation L)
423       : OMPDeclarativeDirective<Decl>(OMPRequires, DC, L) {}
424 
425 public:
426   /// Create requires node.
427   static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC,
428                                  SourceLocation L, ArrayRef<OMPClause *> CL);
429   /// Create deserialized requires node.
430   static OMPRequiresDecl *CreateDeserialized(ASTContext &C, unsigned ID,
431                                              unsigned N);
432 
433   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
434   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
435   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
436   using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
437 
clauselist_size()438   unsigned clauselist_size() const { return Data->getNumClauses(); }
clauselist_empty()439   bool clauselist_empty() const { return Data->getClauses().empty(); }
440 
clauselists()441   clauselist_range clauselists() {
442     return clauselist_range(clauselist_begin(), clauselist_end());
443   }
clauselists()444   clauselist_const_range clauselists() const {
445     return clauselist_const_range(clauselist_begin(), clauselist_end());
446   }
clauselist_begin()447   clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
clauselist_end()448   clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
clauselist_begin()449   clauselist_const_iterator clauselist_begin() const {
450     return Data->getClauses().begin();
451   }
clauselist_end()452   clauselist_const_iterator clauselist_end() const {
453     return Data->getClauses().end();
454   }
455 
classof(const Decl * D)456   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)457   static bool classofKind(Kind K) { return K == OMPRequires; }
458 };
459 
460 /// This represents '#pragma omp allocate ...' directive.
461 /// For example, in the following, the default allocator is used for both 'a'
462 /// and 'A::b':
463 ///
464 /// \code
465 /// int a;
466 /// #pragma omp allocate(a)
467 /// struct A {
468 ///   static int b;
469 /// #pragma omp allocate(b)
470 /// };
471 /// \endcode
472 ///
473 class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> {
474   friend class OMPDeclarativeDirective<Decl>;
475   friend class ASTDeclReader;
476 
477   virtual void anchor();
478 
OMPAllocateDecl(DeclContext * DC,SourceLocation L)479   OMPAllocateDecl(DeclContext *DC, SourceLocation L)
480       : OMPDeclarativeDirective<Decl>(OMPAllocate, DC, L) {}
481 
getVars()482   ArrayRef<const Expr *> getVars() const {
483     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
484     return llvm::makeArrayRef(Storage, Data->getNumChildren());
485   }
486 
getVars()487   MutableArrayRef<Expr *> getVars() {
488     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
489     return llvm::makeMutableArrayRef(Storage, Data->getNumChildren());
490   }
491 
492   void setVars(ArrayRef<Expr *> VL);
493 
494 public:
495   static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC,
496                                  SourceLocation L, ArrayRef<Expr *> VL,
497                                  ArrayRef<OMPClause *> CL);
498   static OMPAllocateDecl *CreateDeserialized(ASTContext &C, unsigned ID,
499                                              unsigned NVars, unsigned NClauses);
500 
501   typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
502   typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
503   typedef llvm::iterator_range<varlist_iterator> varlist_range;
504   typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
505   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
506   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
507   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
508   using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
509 
varlist_size()510   unsigned varlist_size() const { return Data->getNumChildren(); }
varlist_empty()511   bool varlist_empty() const { return Data->getChildren().empty(); }
clauselist_size()512   unsigned clauselist_size() const { return Data->getNumClauses(); }
clauselist_empty()513   bool clauselist_empty() const { return Data->getClauses().empty(); }
514 
varlists()515   varlist_range varlists() {
516     return varlist_range(varlist_begin(), varlist_end());
517   }
varlists()518   varlist_const_range varlists() const {
519     return varlist_const_range(varlist_begin(), varlist_end());
520   }
varlist_begin()521   varlist_iterator varlist_begin() { return getVars().begin(); }
varlist_end()522   varlist_iterator varlist_end() { return getVars().end(); }
varlist_begin()523   varlist_const_iterator varlist_begin() const { return getVars().begin(); }
varlist_end()524   varlist_const_iterator varlist_end() const { return getVars().end(); }
525 
clauselists()526   clauselist_range clauselists() {
527     return clauselist_range(clauselist_begin(), clauselist_end());
528   }
clauselists()529   clauselist_const_range clauselists() const {
530     return clauselist_const_range(clauselist_begin(), clauselist_end());
531   }
clauselist_begin()532   clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
clauselist_end()533   clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
clauselist_begin()534   clauselist_const_iterator clauselist_begin() const {
535     return Data->getClauses().begin();
536   }
clauselist_end()537   clauselist_const_iterator clauselist_end() const {
538     return Data->getClauses().end();
539   }
540 
classof(const Decl * D)541   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)542   static bool classofKind(Kind K) { return K == OMPAllocate; }
543 };
544 
545 } // end namespace clang
546 
547 #endif
548