1//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file defines OpenMP nodes for declarative directives.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_AST_DECLOPENMP_H
16#define LLVM_CLANG_AST_DECLOPENMP_H
17
18#include "clang/AST/Decl.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/ExternalASTSource.h"
21#include "clang/AST/Type.h"
22#include "llvm/ADT/ArrayRef.h"
23#include "llvm/Support/TrailingObjects.h"
24
25namespace clang {
26
27/// \brief This represents '#pragma omp threadprivate ...' directive.
28/// For example, in the following, both 'a' and 'A::b' are threadprivate:
29///
30/// \code
31/// int a;
32/// #pragma omp threadprivate(a)
33/// struct A {
34///   static int b;
35/// #pragma omp threadprivate(b)
36/// };
37/// \endcode
38///
39class OMPThreadPrivateDecl final
40    : public Decl,
41      private llvm::TrailingObjects<OMPThreadPrivateDecl, Expr *> {
42  friend class ASTDeclReader;
43  friend TrailingObjects;
44
45  unsigned NumVars;
46
47  virtual void anchor();
48
49  OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) :
50    Decl(DK, DC, L), NumVars(0) { }
51
52  ArrayRef<const Expr *> getVars() const {
53    return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
54  }
55
56  MutableArrayRef<Expr *> getVars() {
57    return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
58  }
59
60  void setVars(ArrayRef<Expr *> VL);
61
62public:
63  static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
64                                      SourceLocation L,
65                                      ArrayRef<Expr *> VL);
66  static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
67                                                  unsigned ID, unsigned N);
68
69  typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
70  typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
71  typedef llvm::iterator_range<varlist_iterator> varlist_range;
72  typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
73
74  unsigned varlist_size() const { return NumVars; }
75  bool varlist_empty() const { return NumVars == 0; }
76
77  varlist_range varlists() {
78    return varlist_range(varlist_begin(), varlist_end());
79  }
80  varlist_const_range varlists() const {
81    return varlist_const_range(varlist_begin(), varlist_end());
82  }
83  varlist_iterator varlist_begin() { return getVars().begin(); }
84  varlist_iterator varlist_end() { return getVars().end(); }
85  varlist_const_iterator varlist_begin() const { return getVars().begin(); }
86  varlist_const_iterator varlist_end() const { return getVars().end(); }
87
88  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
89  static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
90};
91
92/// \brief This represents '#pragma omp declare reduction ...' directive.
93/// For example, in the following, declared reduction 'foo' for types 'int' and
94/// 'float':
95///
96/// \code
97/// #pragma omp declare reduction (foo : int,float : omp_out += omp_in) \
98///                     initializer (omp_priv = 0)
99/// \endcode
100///
101/// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer.
102class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext {
103private:
104  friend class ASTDeclReader;
105  /// \brief Combiner for declare reduction construct.
106  Expr *Combiner;
107  /// \brief Initializer for declare reduction construct.
108  Expr *Initializer;
109  /// \brief Reference to the previous declare reduction construct in the same
110  /// scope with the same name. Required for proper templates instantiation if
111  /// the declare reduction construct is declared inside compound statement.
112  LazyDeclPtr PrevDeclInScope;
113
114  virtual void anchor();
115
116  OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L,
117                          DeclarationName Name, QualType Ty,
118                          OMPDeclareReductionDecl *PrevDeclInScope)
119      : ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr),
120        Initializer(nullptr), PrevDeclInScope(PrevDeclInScope) {}
121
122  void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) {
123    PrevDeclInScope = Prev;
124  }
125
126public:
127  /// \brief Create declare reduction node.
128  static OMPDeclareReductionDecl *
129  Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name,
130         QualType T, OMPDeclareReductionDecl *PrevDeclInScope);
131  /// \brief Create deserialized declare reduction node.
132  static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C,
133                                                     unsigned ID);
134
135  /// \brief Get combiner expression of the declare reduction construct.
136  Expr *getCombiner() { return Combiner; }
137  const Expr *getCombiner() const { return Combiner; }
138  /// \brief Set combiner expression for the declare reduction construct.
139  void setCombiner(Expr *E) { Combiner = E; }
140
141  /// \brief Get initializer expression (if specified) of the declare reduction
142  /// construct.
143  Expr *getInitializer() { return Initializer; }
144  const Expr *getInitializer() const { return Initializer; }
145  /// \brief Set initializer expression for the declare reduction construct.
146  void setInitializer(Expr *E) { Initializer = E; }
147
148  /// \brief Get reference to previous declare reduction construct in the same
149  /// scope with the same name.
150  OMPDeclareReductionDecl *getPrevDeclInScope();
151  const OMPDeclareReductionDecl *getPrevDeclInScope() const;
152
153  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
154  static bool classofKind(Kind K) { return K == OMPDeclareReduction; }
155  static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) {
156    return static_cast<DeclContext *>(const_cast<OMPDeclareReductionDecl *>(D));
157  }
158  static OMPDeclareReductionDecl *castFromDeclContext(const DeclContext *DC) {
159    return static_cast<OMPDeclareReductionDecl *>(
160        const_cast<DeclContext *>(DC));
161  }
162};
163
164/// Pseudo declaration for capturing expressions. Also is used for capturing of
165/// non-static data members in non-static member functions.
166///
167/// Clang supports capturing of variables only, but OpenMP 4.5 allows to
168/// privatize non-static members of current class in non-static member
169/// functions. This pseudo-declaration allows properly handle this kind of
170/// capture by wrapping captured expression into a variable-like declaration.
171class OMPCapturedExprDecl final : public VarDecl {
172  friend class ASTDeclReader;
173  void anchor() override;
174
175  OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
176                      QualType Type)
177      : VarDecl(OMPCapturedExpr, C, DC, SourceLocation(), SourceLocation(), Id,
178                Type, nullptr, SC_None) {
179    setImplicit();
180  }
181
182public:
183  static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC,
184                                     IdentifierInfo *Id, QualType T);
185
186  static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, unsigned ID);
187
188  // Implement isa/cast/dyncast/etc.
189  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
190  static bool classofKind(Kind K) { return K == OMPCapturedExpr; }
191};
192
193} // end namespace clang
194
195#endif
196