1 //===- OpenMPClause.cpp - Classes for OpenMP clauses ----------------------===//
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 // This file implements the subclesses of Stmt class declared in OpenMPClause.h
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/AST/OpenMPClause.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/DeclOpenMP.h"
17 #include "clang/Basic/LLVM.h"
18 #include "llvm/ADT/SmallPtrSet.h"
19 #include "llvm/Support/Casting.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include <algorithm>
22 #include <cassert>
23 
24 using namespace clang;
25 
26 OMPClause::child_range OMPClause::children() {
27   switch (getClauseKind()) {
28   default:
29     break;
30 #define OPENMP_CLAUSE(Name, Class)                                             \
31   case OMPC_##Name:                                                            \
32     return static_cast<Class *>(this)->children();
33 #include "clang/Basic/OpenMPKinds.def"
34   }
35   llvm_unreachable("unknown OMPClause");
36 }
37 
38 OMPClauseWithPreInit *OMPClauseWithPreInit::get(OMPClause *C) {
39   auto *Res = OMPClauseWithPreInit::get(const_cast<const OMPClause *>(C));
40   return Res ? const_cast<OMPClauseWithPreInit *>(Res) : nullptr;
41 }
42 
43 const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
44   switch (C->getClauseKind()) {
45   case OMPC_schedule:
46     return static_cast<const OMPScheduleClause *>(C);
47   case OMPC_dist_schedule:
48     return static_cast<const OMPDistScheduleClause *>(C);
49   case OMPC_firstprivate:
50     return static_cast<const OMPFirstprivateClause *>(C);
51   case OMPC_lastprivate:
52     return static_cast<const OMPLastprivateClause *>(C);
53   case OMPC_reduction:
54     return static_cast<const OMPReductionClause *>(C);
55   case OMPC_task_reduction:
56     return static_cast<const OMPTaskReductionClause *>(C);
57   case OMPC_in_reduction:
58     return static_cast<const OMPInReductionClause *>(C);
59   case OMPC_linear:
60     return static_cast<const OMPLinearClause *>(C);
61   case OMPC_if:
62     return static_cast<const OMPIfClause *>(C);
63   case OMPC_num_threads:
64     return static_cast<const OMPNumThreadsClause *>(C);
65   case OMPC_num_teams:
66     return static_cast<const OMPNumTeamsClause *>(C);
67   case OMPC_thread_limit:
68     return static_cast<const OMPThreadLimitClause *>(C);
69   case OMPC_device:
70     return static_cast<const OMPDeviceClause *>(C);
71   case OMPC_default:
72   case OMPC_proc_bind:
73   case OMPC_final:
74   case OMPC_safelen:
75   case OMPC_simdlen:
76   case OMPC_allocator:
77   case OMPC_allocate:
78   case OMPC_collapse:
79   case OMPC_private:
80   case OMPC_shared:
81   case OMPC_aligned:
82   case OMPC_copyin:
83   case OMPC_copyprivate:
84   case OMPC_ordered:
85   case OMPC_nowait:
86   case OMPC_untied:
87   case OMPC_mergeable:
88   case OMPC_threadprivate:
89   case OMPC_flush:
90   case OMPC_read:
91   case OMPC_write:
92   case OMPC_update:
93   case OMPC_capture:
94   case OMPC_seq_cst:
95   case OMPC_depend:
96   case OMPC_threads:
97   case OMPC_simd:
98   case OMPC_map:
99   case OMPC_priority:
100   case OMPC_grainsize:
101   case OMPC_nogroup:
102   case OMPC_num_tasks:
103   case OMPC_hint:
104   case OMPC_defaultmap:
105   case OMPC_unknown:
106   case OMPC_uniform:
107   case OMPC_to:
108   case OMPC_from:
109   case OMPC_use_device_ptr:
110   case OMPC_is_device_ptr:
111   case OMPC_unified_address:
112   case OMPC_unified_shared_memory:
113   case OMPC_reverse_offload:
114   case OMPC_dynamic_allocators:
115   case OMPC_atomic_default_mem_order:
116     break;
117   }
118 
119   return nullptr;
120 }
121 
122 OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(OMPClause *C) {
123   auto *Res = OMPClauseWithPostUpdate::get(const_cast<const OMPClause *>(C));
124   return Res ? const_cast<OMPClauseWithPostUpdate *>(Res) : nullptr;
125 }
126 
127 const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) {
128   switch (C->getClauseKind()) {
129   case OMPC_lastprivate:
130     return static_cast<const OMPLastprivateClause *>(C);
131   case OMPC_reduction:
132     return static_cast<const OMPReductionClause *>(C);
133   case OMPC_task_reduction:
134     return static_cast<const OMPTaskReductionClause *>(C);
135   case OMPC_in_reduction:
136     return static_cast<const OMPInReductionClause *>(C);
137   case OMPC_linear:
138     return static_cast<const OMPLinearClause *>(C);
139   case OMPC_schedule:
140   case OMPC_dist_schedule:
141   case OMPC_firstprivate:
142   case OMPC_default:
143   case OMPC_proc_bind:
144   case OMPC_if:
145   case OMPC_final:
146   case OMPC_num_threads:
147   case OMPC_safelen:
148   case OMPC_simdlen:
149   case OMPC_allocator:
150   case OMPC_allocate:
151   case OMPC_collapse:
152   case OMPC_private:
153   case OMPC_shared:
154   case OMPC_aligned:
155   case OMPC_copyin:
156   case OMPC_copyprivate:
157   case OMPC_ordered:
158   case OMPC_nowait:
159   case OMPC_untied:
160   case OMPC_mergeable:
161   case OMPC_threadprivate:
162   case OMPC_flush:
163   case OMPC_read:
164   case OMPC_write:
165   case OMPC_update:
166   case OMPC_capture:
167   case OMPC_seq_cst:
168   case OMPC_depend:
169   case OMPC_device:
170   case OMPC_threads:
171   case OMPC_simd:
172   case OMPC_map:
173   case OMPC_num_teams:
174   case OMPC_thread_limit:
175   case OMPC_priority:
176   case OMPC_grainsize:
177   case OMPC_nogroup:
178   case OMPC_num_tasks:
179   case OMPC_hint:
180   case OMPC_defaultmap:
181   case OMPC_unknown:
182   case OMPC_uniform:
183   case OMPC_to:
184   case OMPC_from:
185   case OMPC_use_device_ptr:
186   case OMPC_is_device_ptr:
187   case OMPC_unified_address:
188   case OMPC_unified_shared_memory:
189   case OMPC_reverse_offload:
190   case OMPC_dynamic_allocators:
191   case OMPC_atomic_default_mem_order:
192     break;
193   }
194 
195   return nullptr;
196 }
197 
198 OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num,
199                                            unsigned NumLoops,
200                                            SourceLocation StartLoc,
201                                            SourceLocation LParenLoc,
202                                            SourceLocation EndLoc) {
203   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
204   auto *Clause =
205       new (Mem) OMPOrderedClause(Num, NumLoops, StartLoc, LParenLoc, EndLoc);
206   for (unsigned I = 0; I < NumLoops; ++I) {
207     Clause->setLoopNumIterations(I, nullptr);
208     Clause->setLoopCounter(I, nullptr);
209   }
210   return Clause;
211 }
212 
213 OMPOrderedClause *OMPOrderedClause::CreateEmpty(const ASTContext &C,
214                                                 unsigned NumLoops) {
215   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * NumLoops));
216   auto *Clause = new (Mem) OMPOrderedClause(NumLoops);
217   for (unsigned I = 0; I < NumLoops; ++I) {
218     Clause->setLoopNumIterations(I, nullptr);
219     Clause->setLoopCounter(I, nullptr);
220   }
221   return Clause;
222 }
223 
224 void OMPOrderedClause::setLoopNumIterations(unsigned NumLoop,
225                                             Expr *NumIterations) {
226   assert(NumLoop < NumberOfLoops && "out of loops number.");
227   getTrailingObjects<Expr *>()[NumLoop] = NumIterations;
228 }
229 
230 ArrayRef<Expr *> OMPOrderedClause::getLoopNumIterations() const {
231   return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumberOfLoops);
232 }
233 
234 void OMPOrderedClause::setLoopCounter(unsigned NumLoop, Expr *Counter) {
235   assert(NumLoop < NumberOfLoops && "out of loops number.");
236   getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop] = Counter;
237 }
238 
239 Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) {
240   assert(NumLoop < NumberOfLoops && "out of loops number.");
241   return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop];
242 }
243 
244 const Expr *OMPOrderedClause::getLoopCounter(unsigned NumLoop) const {
245   assert(NumLoop < NumberOfLoops && "out of loops number.");
246   return getTrailingObjects<Expr *>()[NumberOfLoops + NumLoop];
247 }
248 
249 void OMPPrivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
250   assert(VL.size() == varlist_size() &&
251          "Number of private copies is not the same as the preallocated buffer");
252   std::copy(VL.begin(), VL.end(), varlist_end());
253 }
254 
255 OMPPrivateClause *
256 OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
257                          SourceLocation LParenLoc, SourceLocation EndLoc,
258                          ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL) {
259   // Allocate space for private variables and initializer expressions.
260   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * VL.size()));
261   OMPPrivateClause *Clause =
262       new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
263   Clause->setVarRefs(VL);
264   Clause->setPrivateCopies(PrivateVL);
265   return Clause;
266 }
267 
268 OMPPrivateClause *OMPPrivateClause::CreateEmpty(const ASTContext &C,
269                                                 unsigned N) {
270   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(2 * N));
271   return new (Mem) OMPPrivateClause(N);
272 }
273 
274 void OMPFirstprivateClause::setPrivateCopies(ArrayRef<Expr *> VL) {
275   assert(VL.size() == varlist_size() &&
276          "Number of private copies is not the same as the preallocated buffer");
277   std::copy(VL.begin(), VL.end(), varlist_end());
278 }
279 
280 void OMPFirstprivateClause::setInits(ArrayRef<Expr *> VL) {
281   assert(VL.size() == varlist_size() &&
282          "Number of inits is not the same as the preallocated buffer");
283   std::copy(VL.begin(), VL.end(), getPrivateCopies().end());
284 }
285 
286 OMPFirstprivateClause *
287 OMPFirstprivateClause::Create(const ASTContext &C, SourceLocation StartLoc,
288                               SourceLocation LParenLoc, SourceLocation EndLoc,
289                               ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL,
290                               ArrayRef<Expr *> InitVL, Stmt *PreInit) {
291   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(3 * VL.size()));
292   OMPFirstprivateClause *Clause =
293       new (Mem) OMPFirstprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
294   Clause->setVarRefs(VL);
295   Clause->setPrivateCopies(PrivateVL);
296   Clause->setInits(InitVL);
297   Clause->setPreInitStmt(PreInit);
298   return Clause;
299 }
300 
301 OMPFirstprivateClause *OMPFirstprivateClause::CreateEmpty(const ASTContext &C,
302                                                           unsigned N) {
303   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(3 * N));
304   return new (Mem) OMPFirstprivateClause(N);
305 }
306 
307 void OMPLastprivateClause::setPrivateCopies(ArrayRef<Expr *> PrivateCopies) {
308   assert(PrivateCopies.size() == varlist_size() &&
309          "Number of private copies is not the same as the preallocated buffer");
310   std::copy(PrivateCopies.begin(), PrivateCopies.end(), varlist_end());
311 }
312 
313 void OMPLastprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
314   assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
315                                               "not the same as the "
316                                               "preallocated buffer");
317   std::copy(SrcExprs.begin(), SrcExprs.end(), getPrivateCopies().end());
318 }
319 
320 void OMPLastprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
321   assert(DstExprs.size() == varlist_size() && "Number of destination "
322                                               "expressions is not the same as "
323                                               "the preallocated buffer");
324   std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
325 }
326 
327 void OMPLastprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
328   assert(AssignmentOps.size() == varlist_size() &&
329          "Number of assignment expressions is not the same as the preallocated "
330          "buffer");
331   std::copy(AssignmentOps.begin(), AssignmentOps.end(),
332             getDestinationExprs().end());
333 }
334 
335 OMPLastprivateClause *OMPLastprivateClause::Create(
336     const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
337     SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
338     ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps, Stmt *PreInit,
339     Expr *PostUpdate) {
340   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
341   OMPLastprivateClause *Clause =
342       new (Mem) OMPLastprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
343   Clause->setVarRefs(VL);
344   Clause->setSourceExprs(SrcExprs);
345   Clause->setDestinationExprs(DstExprs);
346   Clause->setAssignmentOps(AssignmentOps);
347   Clause->setPreInitStmt(PreInit);
348   Clause->setPostUpdateExpr(PostUpdate);
349   return Clause;
350 }
351 
352 OMPLastprivateClause *OMPLastprivateClause::CreateEmpty(const ASTContext &C,
353                                                         unsigned N) {
354   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
355   return new (Mem) OMPLastprivateClause(N);
356 }
357 
358 OMPSharedClause *OMPSharedClause::Create(const ASTContext &C,
359                                          SourceLocation StartLoc,
360                                          SourceLocation LParenLoc,
361                                          SourceLocation EndLoc,
362                                          ArrayRef<Expr *> VL) {
363   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
364   OMPSharedClause *Clause =
365       new (Mem) OMPSharedClause(StartLoc, LParenLoc, EndLoc, VL.size());
366   Clause->setVarRefs(VL);
367   return Clause;
368 }
369 
370 OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C, unsigned N) {
371   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
372   return new (Mem) OMPSharedClause(N);
373 }
374 
375 void OMPLinearClause::setPrivates(ArrayRef<Expr *> PL) {
376   assert(PL.size() == varlist_size() &&
377          "Number of privates is not the same as the preallocated buffer");
378   std::copy(PL.begin(), PL.end(), varlist_end());
379 }
380 
381 void OMPLinearClause::setInits(ArrayRef<Expr *> IL) {
382   assert(IL.size() == varlist_size() &&
383          "Number of inits is not the same as the preallocated buffer");
384   std::copy(IL.begin(), IL.end(), getPrivates().end());
385 }
386 
387 void OMPLinearClause::setUpdates(ArrayRef<Expr *> UL) {
388   assert(UL.size() == varlist_size() &&
389          "Number of updates is not the same as the preallocated buffer");
390   std::copy(UL.begin(), UL.end(), getInits().end());
391 }
392 
393 void OMPLinearClause::setFinals(ArrayRef<Expr *> FL) {
394   assert(FL.size() == varlist_size() &&
395          "Number of final updates is not the same as the preallocated buffer");
396   std::copy(FL.begin(), FL.end(), getUpdates().end());
397 }
398 
399 OMPLinearClause *OMPLinearClause::Create(
400     const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
401     OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc,
402     SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
403     ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep,
404     Stmt *PreInit, Expr *PostUpdate) {
405   // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
406   // (Step and CalcStep).
407   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size() + 2));
408   OMPLinearClause *Clause = new (Mem) OMPLinearClause(
409       StartLoc, LParenLoc, Modifier, ModifierLoc, ColonLoc, EndLoc, VL.size());
410   Clause->setVarRefs(VL);
411   Clause->setPrivates(PL);
412   Clause->setInits(IL);
413   // Fill update and final expressions with zeroes, they are provided later,
414   // after the directive construction.
415   std::fill(Clause->getInits().end(), Clause->getInits().end() + VL.size(),
416             nullptr);
417   std::fill(Clause->getUpdates().end(), Clause->getUpdates().end() + VL.size(),
418             nullptr);
419   Clause->setStep(Step);
420   Clause->setCalcStep(CalcStep);
421   Clause->setPreInitStmt(PreInit);
422   Clause->setPostUpdateExpr(PostUpdate);
423   return Clause;
424 }
425 
426 OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C,
427                                               unsigned NumVars) {
428   // Allocate space for 4 lists (Vars, Inits, Updates, Finals) and 2 expressions
429   // (Step and CalcStep).
430   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * NumVars + 2));
431   return new (Mem) OMPLinearClause(NumVars);
432 }
433 
434 OMPAlignedClause *
435 OMPAlignedClause::Create(const ASTContext &C, SourceLocation StartLoc,
436                          SourceLocation LParenLoc, SourceLocation ColonLoc,
437                          SourceLocation EndLoc, ArrayRef<Expr *> VL, Expr *A) {
438   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1));
439   OMPAlignedClause *Clause = new (Mem)
440       OMPAlignedClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
441   Clause->setVarRefs(VL);
442   Clause->setAlignment(A);
443   return Clause;
444 }
445 
446 OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C,
447                                                 unsigned NumVars) {
448   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumVars + 1));
449   return new (Mem) OMPAlignedClause(NumVars);
450 }
451 
452 void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
453   assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
454                                               "not the same as the "
455                                               "preallocated buffer");
456   std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
457 }
458 
459 void OMPCopyinClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
460   assert(DstExprs.size() == varlist_size() && "Number of destination "
461                                               "expressions is not the same as "
462                                               "the preallocated buffer");
463   std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
464 }
465 
466 void OMPCopyinClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
467   assert(AssignmentOps.size() == varlist_size() &&
468          "Number of assignment expressions is not the same as the preallocated "
469          "buffer");
470   std::copy(AssignmentOps.begin(), AssignmentOps.end(),
471             getDestinationExprs().end());
472 }
473 
474 OMPCopyinClause *OMPCopyinClause::Create(
475     const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
476     SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
477     ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
478   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * VL.size()));
479   OMPCopyinClause *Clause =
480       new (Mem) OMPCopyinClause(StartLoc, LParenLoc, EndLoc, VL.size());
481   Clause->setVarRefs(VL);
482   Clause->setSourceExprs(SrcExprs);
483   Clause->setDestinationExprs(DstExprs);
484   Clause->setAssignmentOps(AssignmentOps);
485   return Clause;
486 }
487 
488 OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C, unsigned N) {
489   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * N));
490   return new (Mem) OMPCopyinClause(N);
491 }
492 
493 void OMPCopyprivateClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
494   assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
495                                               "not the same as the "
496                                               "preallocated buffer");
497   std::copy(SrcExprs.begin(), SrcExprs.end(), varlist_end());
498 }
499 
500 void OMPCopyprivateClause::setDestinationExprs(ArrayRef<Expr *> DstExprs) {
501   assert(DstExprs.size() == varlist_size() && "Number of destination "
502                                               "expressions is not the same as "
503                                               "the preallocated buffer");
504   std::copy(DstExprs.begin(), DstExprs.end(), getSourceExprs().end());
505 }
506 
507 void OMPCopyprivateClause::setAssignmentOps(ArrayRef<Expr *> AssignmentOps) {
508   assert(AssignmentOps.size() == varlist_size() &&
509          "Number of assignment expressions is not the same as the preallocated "
510          "buffer");
511   std::copy(AssignmentOps.begin(), AssignmentOps.end(),
512             getDestinationExprs().end());
513 }
514 
515 OMPCopyprivateClause *OMPCopyprivateClause::Create(
516     const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
517     SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
518     ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps) {
519   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * VL.size()));
520   OMPCopyprivateClause *Clause =
521       new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
522   Clause->setVarRefs(VL);
523   Clause->setSourceExprs(SrcExprs);
524   Clause->setDestinationExprs(DstExprs);
525   Clause->setAssignmentOps(AssignmentOps);
526   return Clause;
527 }
528 
529 OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C,
530                                                         unsigned N) {
531   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(4 * N));
532   return new (Mem) OMPCopyprivateClause(N);
533 }
534 
535 void OMPReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
536   assert(Privates.size() == varlist_size() &&
537          "Number of private copies is not the same as the preallocated buffer");
538   std::copy(Privates.begin(), Privates.end(), varlist_end());
539 }
540 
541 void OMPReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
542   assert(
543       LHSExprs.size() == varlist_size() &&
544       "Number of LHS expressions is not the same as the preallocated buffer");
545   std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end());
546 }
547 
548 void OMPReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
549   assert(
550       RHSExprs.size() == varlist_size() &&
551       "Number of RHS expressions is not the same as the preallocated buffer");
552   std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
553 }
554 
555 void OMPReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
556   assert(ReductionOps.size() == varlist_size() && "Number of reduction "
557                                                   "expressions is not the same "
558                                                   "as the preallocated buffer");
559   std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
560 }
561 
562 OMPReductionClause *OMPReductionClause::Create(
563     const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
564     SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
565     NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
566     ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
567     ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit,
568     Expr *PostUpdate) {
569   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
570   OMPReductionClause *Clause = new (Mem) OMPReductionClause(
571       StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
572   Clause->setVarRefs(VL);
573   Clause->setPrivates(Privates);
574   Clause->setLHSExprs(LHSExprs);
575   Clause->setRHSExprs(RHSExprs);
576   Clause->setReductionOps(ReductionOps);
577   Clause->setPreInitStmt(PreInit);
578   Clause->setPostUpdateExpr(PostUpdate);
579   return Clause;
580 }
581 
582 OMPReductionClause *OMPReductionClause::CreateEmpty(const ASTContext &C,
583                                                     unsigned N) {
584   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
585   return new (Mem) OMPReductionClause(N);
586 }
587 
588 void OMPTaskReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
589   assert(Privates.size() == varlist_size() &&
590          "Number of private copies is not the same as the preallocated buffer");
591   std::copy(Privates.begin(), Privates.end(), varlist_end());
592 }
593 
594 void OMPTaskReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
595   assert(
596       LHSExprs.size() == varlist_size() &&
597       "Number of LHS expressions is not the same as the preallocated buffer");
598   std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end());
599 }
600 
601 void OMPTaskReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
602   assert(
603       RHSExprs.size() == varlist_size() &&
604       "Number of RHS expressions is not the same as the preallocated buffer");
605   std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
606 }
607 
608 void OMPTaskReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
609   assert(ReductionOps.size() == varlist_size() && "Number of task reduction "
610                                                   "expressions is not the same "
611                                                   "as the preallocated buffer");
612   std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
613 }
614 
615 OMPTaskReductionClause *OMPTaskReductionClause::Create(
616     const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
617     SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
618     NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
619     ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
620     ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit,
621     Expr *PostUpdate) {
622   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * VL.size()));
623   OMPTaskReductionClause *Clause = new (Mem) OMPTaskReductionClause(
624       StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
625   Clause->setVarRefs(VL);
626   Clause->setPrivates(Privates);
627   Clause->setLHSExprs(LHSExprs);
628   Clause->setRHSExprs(RHSExprs);
629   Clause->setReductionOps(ReductionOps);
630   Clause->setPreInitStmt(PreInit);
631   Clause->setPostUpdateExpr(PostUpdate);
632   return Clause;
633 }
634 
635 OMPTaskReductionClause *OMPTaskReductionClause::CreateEmpty(const ASTContext &C,
636                                                             unsigned N) {
637   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(5 * N));
638   return new (Mem) OMPTaskReductionClause(N);
639 }
640 
641 void OMPInReductionClause::setPrivates(ArrayRef<Expr *> Privates) {
642   assert(Privates.size() == varlist_size() &&
643          "Number of private copies is not the same as the preallocated buffer");
644   std::copy(Privates.begin(), Privates.end(), varlist_end());
645 }
646 
647 void OMPInReductionClause::setLHSExprs(ArrayRef<Expr *> LHSExprs) {
648   assert(
649       LHSExprs.size() == varlist_size() &&
650       "Number of LHS expressions is not the same as the preallocated buffer");
651   std::copy(LHSExprs.begin(), LHSExprs.end(), getPrivates().end());
652 }
653 
654 void OMPInReductionClause::setRHSExprs(ArrayRef<Expr *> RHSExprs) {
655   assert(
656       RHSExprs.size() == varlist_size() &&
657       "Number of RHS expressions is not the same as the preallocated buffer");
658   std::copy(RHSExprs.begin(), RHSExprs.end(), getLHSExprs().end());
659 }
660 
661 void OMPInReductionClause::setReductionOps(ArrayRef<Expr *> ReductionOps) {
662   assert(ReductionOps.size() == varlist_size() && "Number of in reduction "
663                                                   "expressions is not the same "
664                                                   "as the preallocated buffer");
665   std::copy(ReductionOps.begin(), ReductionOps.end(), getRHSExprs().end());
666 }
667 
668 void OMPInReductionClause::setTaskgroupDescriptors(
669     ArrayRef<Expr *> TaskgroupDescriptors) {
670   assert(TaskgroupDescriptors.size() == varlist_size() &&
671          "Number of in reduction descriptors is not the same as the "
672          "preallocated buffer");
673   std::copy(TaskgroupDescriptors.begin(), TaskgroupDescriptors.end(),
674             getReductionOps().end());
675 }
676 
677 OMPInReductionClause *OMPInReductionClause::Create(
678     const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
679     SourceLocation EndLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL,
680     NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo,
681     ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
682     ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps,
683     ArrayRef<Expr *> TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate) {
684   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(6 * VL.size()));
685   OMPInReductionClause *Clause = new (Mem) OMPInReductionClause(
686       StartLoc, LParenLoc, EndLoc, ColonLoc, VL.size(), QualifierLoc, NameInfo);
687   Clause->setVarRefs(VL);
688   Clause->setPrivates(Privates);
689   Clause->setLHSExprs(LHSExprs);
690   Clause->setRHSExprs(RHSExprs);
691   Clause->setReductionOps(ReductionOps);
692   Clause->setTaskgroupDescriptors(TaskgroupDescriptors);
693   Clause->setPreInitStmt(PreInit);
694   Clause->setPostUpdateExpr(PostUpdate);
695   return Clause;
696 }
697 
698 OMPInReductionClause *OMPInReductionClause::CreateEmpty(const ASTContext &C,
699                                                         unsigned N) {
700   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(6 * N));
701   return new (Mem) OMPInReductionClause(N);
702 }
703 
704 OMPAllocateClause *
705 OMPAllocateClause::Create(const ASTContext &C, SourceLocation StartLoc,
706                           SourceLocation LParenLoc, Expr *Allocator,
707                           SourceLocation ColonLoc, SourceLocation EndLoc,
708                           ArrayRef<Expr *> VL) {
709   // Allocate space for private variables and initializer expressions.
710   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size()));
711   auto *Clause = new (Mem) OMPAllocateClause(StartLoc, LParenLoc, Allocator,
712                                              ColonLoc, EndLoc, VL.size());
713   Clause->setVarRefs(VL);
714   return Clause;
715 }
716 
717 OMPAllocateClause *OMPAllocateClause::CreateEmpty(const ASTContext &C,
718                                                   unsigned N) {
719   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
720   return new (Mem) OMPAllocateClause(N);
721 }
722 
723 OMPFlushClause *OMPFlushClause::Create(const ASTContext &C,
724                                        SourceLocation StartLoc,
725                                        SourceLocation LParenLoc,
726                                        SourceLocation EndLoc,
727                                        ArrayRef<Expr *> VL) {
728   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + 1));
729   OMPFlushClause *Clause =
730       new (Mem) OMPFlushClause(StartLoc, LParenLoc, EndLoc, VL.size());
731   Clause->setVarRefs(VL);
732   return Clause;
733 }
734 
735 OMPFlushClause *OMPFlushClause::CreateEmpty(const ASTContext &C, unsigned N) {
736   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N));
737   return new (Mem) OMPFlushClause(N);
738 }
739 
740 OMPDependClause *
741 OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
742                         SourceLocation LParenLoc, SourceLocation EndLoc,
743                         OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
744                         SourceLocation ColonLoc, ArrayRef<Expr *> VL,
745                         unsigned NumLoops) {
746   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + NumLoops));
747   OMPDependClause *Clause = new (Mem)
748       OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops);
749   Clause->setVarRefs(VL);
750   Clause->setDependencyKind(DepKind);
751   Clause->setDependencyLoc(DepLoc);
752   Clause->setColonLoc(ColonLoc);
753   for (unsigned I = 0 ; I < NumLoops; ++I)
754     Clause->setLoopData(I, nullptr);
755   return Clause;
756 }
757 
758 OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N,
759                                               unsigned NumLoops) {
760   void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + NumLoops));
761   return new (Mem) OMPDependClause(N, NumLoops);
762 }
763 
764 void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) {
765   assert((getDependencyKind() == OMPC_DEPEND_sink ||
766           getDependencyKind() == OMPC_DEPEND_source) &&
767          NumLoop < NumLoops &&
768          "Expected sink or source depend + loop index must be less number of "
769          "loops.");
770   auto It = std::next(getVarRefs().end(), NumLoop);
771   *It = Cnt;
772 }
773 
774 Expr *OMPDependClause::getLoopData(unsigned NumLoop) {
775   assert((getDependencyKind() == OMPC_DEPEND_sink ||
776           getDependencyKind() == OMPC_DEPEND_source) &&
777          NumLoop < NumLoops &&
778          "Expected sink or source depend + loop index must be less number of "
779          "loops.");
780   auto It = std::next(getVarRefs().end(), NumLoop);
781   return *It;
782 }
783 
784 const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const {
785   assert((getDependencyKind() == OMPC_DEPEND_sink ||
786           getDependencyKind() == OMPC_DEPEND_source) &&
787          NumLoop < NumLoops &&
788          "Expected sink or source depend + loop index must be less number of "
789          "loops.");
790   auto It = std::next(getVarRefs().end(), NumLoop);
791   return *It;
792 }
793 
794 unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber(
795     MappableExprComponentListsRef ComponentLists) {
796   unsigned TotalNum = 0u;
797   for (auto &C : ComponentLists)
798     TotalNum += C.size();
799   return TotalNum;
800 }
801 
802 unsigned OMPClauseMappableExprCommon::getUniqueDeclarationsTotalNumber(
803     ArrayRef<const ValueDecl *> Declarations) {
804   unsigned TotalNum = 0u;
805   llvm::SmallPtrSet<const ValueDecl *, 8> Cache;
806   for (const ValueDecl *D : Declarations) {
807     const ValueDecl *VD = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
808     if (Cache.count(VD))
809       continue;
810     ++TotalNum;
811     Cache.insert(VD);
812   }
813   return TotalNum;
814 }
815 
816 OMPMapClause *OMPMapClause::Create(
817     const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
818     ArrayRef<ValueDecl *> Declarations,
819     MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs,
820     ArrayRef<OpenMPMapModifierKind> MapModifiers,
821     ArrayRef<SourceLocation> MapModifiersLoc,
822     NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId,
823     OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc) {
824   OMPMappableExprListSizeTy Sizes;
825   Sizes.NumVars = Vars.size();
826   Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
827   Sizes.NumComponentLists = ComponentLists.size();
828   Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
829 
830   // We need to allocate:
831   // 2 x NumVars x Expr* - we have an original list expression and an associated
832   // user-defined mapper for each clause list entry.
833   // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
834   // with each component list.
835   // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
836   // number of lists for each unique declaration and the size of each component
837   // list.
838   // NumComponents x MappableComponent - the total of all the components in all
839   // the lists.
840   void *Mem = C.Allocate(
841       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
842                        OMPClauseMappableExprCommon::MappableComponent>(
843           2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
844           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
845           Sizes.NumComponents));
846   OMPMapClause *Clause = new (Mem)
847       OMPMapClause(MapModifiers, MapModifiersLoc, UDMQualifierLoc, MapperId,
848                    Type, TypeIsImplicit, TypeLoc, Locs, Sizes);
849 
850   Clause->setVarRefs(Vars);
851   Clause->setUDMapperRefs(UDMapperRefs);
852   Clause->setClauseInfo(Declarations, ComponentLists);
853   Clause->setMapType(Type);
854   Clause->setMapLoc(TypeLoc);
855   return Clause;
856 }
857 
858 OMPMapClause *
859 OMPMapClause::CreateEmpty(const ASTContext &C,
860                           const OMPMappableExprListSizeTy &Sizes) {
861   void *Mem = C.Allocate(
862       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
863                        OMPClauseMappableExprCommon::MappableComponent>(
864           2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
865           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
866           Sizes.NumComponents));
867   return new (Mem) OMPMapClause(Sizes);
868 }
869 
870 OMPToClause *OMPToClause::Create(
871     const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
872     ArrayRef<ValueDecl *> Declarations,
873     MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs,
874     NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) {
875   OMPMappableExprListSizeTy Sizes;
876   Sizes.NumVars = Vars.size();
877   Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
878   Sizes.NumComponentLists = ComponentLists.size();
879   Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
880 
881   // We need to allocate:
882   // 2 x NumVars x Expr* - we have an original list expression and an associated
883   // user-defined mapper for each clause list entry.
884   // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
885   // with each component list.
886   // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
887   // number of lists for each unique declaration and the size of each component
888   // list.
889   // NumComponents x MappableComponent - the total of all the components in all
890   // the lists.
891   void *Mem = C.Allocate(
892       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
893                        OMPClauseMappableExprCommon::MappableComponent>(
894           2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
895           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
896           Sizes.NumComponents));
897 
898   auto *Clause = new (Mem) OMPToClause(UDMQualifierLoc, MapperId, Locs, Sizes);
899 
900   Clause->setVarRefs(Vars);
901   Clause->setUDMapperRefs(UDMapperRefs);
902   Clause->setClauseInfo(Declarations, ComponentLists);
903   return Clause;
904 }
905 
906 OMPToClause *OMPToClause::CreateEmpty(const ASTContext &C,
907                                       const OMPMappableExprListSizeTy &Sizes) {
908   void *Mem = C.Allocate(
909       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
910                        OMPClauseMappableExprCommon::MappableComponent>(
911           2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
912           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
913           Sizes.NumComponents));
914   return new (Mem) OMPToClause(Sizes);
915 }
916 
917 OMPFromClause *OMPFromClause::Create(
918     const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
919     ArrayRef<ValueDecl *> Declarations,
920     MappableExprComponentListsRef ComponentLists, ArrayRef<Expr *> UDMapperRefs,
921     NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId) {
922   OMPMappableExprListSizeTy Sizes;
923   Sizes.NumVars = Vars.size();
924   Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
925   Sizes.NumComponentLists = ComponentLists.size();
926   Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
927 
928   // We need to allocate:
929   // 2 x NumVars x Expr* - we have an original list expression and an associated
930   // user-defined mapper for each clause list entry.
931   // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
932   // with each component list.
933   // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
934   // number of lists for each unique declaration and the size of each component
935   // list.
936   // NumComponents x MappableComponent - the total of all the components in all
937   // the lists.
938   void *Mem = C.Allocate(
939       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
940                        OMPClauseMappableExprCommon::MappableComponent>(
941           2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
942           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
943           Sizes.NumComponents));
944 
945   auto *Clause =
946       new (Mem) OMPFromClause(UDMQualifierLoc, MapperId, Locs, Sizes);
947 
948   Clause->setVarRefs(Vars);
949   Clause->setUDMapperRefs(UDMapperRefs);
950   Clause->setClauseInfo(Declarations, ComponentLists);
951   return Clause;
952 }
953 
954 OMPFromClause *
955 OMPFromClause::CreateEmpty(const ASTContext &C,
956                            const OMPMappableExprListSizeTy &Sizes) {
957   void *Mem = C.Allocate(
958       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
959                        OMPClauseMappableExprCommon::MappableComponent>(
960           2 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
961           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
962           Sizes.NumComponents));
963   return new (Mem) OMPFromClause(Sizes);
964 }
965 
966 void OMPUseDevicePtrClause::setPrivateCopies(ArrayRef<Expr *> VL) {
967   assert(VL.size() == varlist_size() &&
968          "Number of private copies is not the same as the preallocated buffer");
969   std::copy(VL.begin(), VL.end(), varlist_end());
970 }
971 
972 void OMPUseDevicePtrClause::setInits(ArrayRef<Expr *> VL) {
973   assert(VL.size() == varlist_size() &&
974          "Number of inits is not the same as the preallocated buffer");
975   std::copy(VL.begin(), VL.end(), getPrivateCopies().end());
976 }
977 
978 OMPUseDevicePtrClause *OMPUseDevicePtrClause::Create(
979     const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef<Expr *> Vars,
980     ArrayRef<Expr *> PrivateVars, ArrayRef<Expr *> Inits,
981     ArrayRef<ValueDecl *> Declarations,
982     MappableExprComponentListsRef ComponentLists) {
983   OMPMappableExprListSizeTy Sizes;
984   Sizes.NumVars = Vars.size();
985   Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
986   Sizes.NumComponentLists = ComponentLists.size();
987   Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
988 
989   // We need to allocate:
990   // 3 x NumVars x Expr* - we have an original list expression for each clause
991   // list entry and an equal number of private copies and inits.
992   // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
993   // with each component list.
994   // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
995   // number of lists for each unique declaration and the size of each component
996   // list.
997   // NumComponents x MappableComponent - the total of all the components in all
998   // the lists.
999   void *Mem = C.Allocate(
1000       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
1001                        OMPClauseMappableExprCommon::MappableComponent>(
1002           3 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
1003           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
1004           Sizes.NumComponents));
1005 
1006   OMPUseDevicePtrClause *Clause = new (Mem) OMPUseDevicePtrClause(Locs, Sizes);
1007 
1008   Clause->setVarRefs(Vars);
1009   Clause->setPrivateCopies(PrivateVars);
1010   Clause->setInits(Inits);
1011   Clause->setClauseInfo(Declarations, ComponentLists);
1012   return Clause;
1013 }
1014 
1015 OMPUseDevicePtrClause *
1016 OMPUseDevicePtrClause::CreateEmpty(const ASTContext &C,
1017                                    const OMPMappableExprListSizeTy &Sizes) {
1018   void *Mem = C.Allocate(
1019       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
1020                        OMPClauseMappableExprCommon::MappableComponent>(
1021           3 * Sizes.NumVars, Sizes.NumUniqueDeclarations,
1022           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
1023           Sizes.NumComponents));
1024   return new (Mem) OMPUseDevicePtrClause(Sizes);
1025 }
1026 
1027 OMPIsDevicePtrClause *
1028 OMPIsDevicePtrClause::Create(const ASTContext &C, const OMPVarListLocTy &Locs,
1029                              ArrayRef<Expr *> Vars,
1030                              ArrayRef<ValueDecl *> Declarations,
1031                              MappableExprComponentListsRef ComponentLists) {
1032   OMPMappableExprListSizeTy Sizes;
1033   Sizes.NumVars = Vars.size();
1034   Sizes.NumUniqueDeclarations = getUniqueDeclarationsTotalNumber(Declarations);
1035   Sizes.NumComponentLists = ComponentLists.size();
1036   Sizes.NumComponents = getComponentsTotalNumber(ComponentLists);
1037 
1038   // We need to allocate:
1039   // NumVars x Expr* - we have an original list expression for each clause list
1040   // entry.
1041   // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
1042   // with each component list.
1043   // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
1044   // number of lists for each unique declaration and the size of each component
1045   // list.
1046   // NumComponents x MappableComponent - the total of all the components in all
1047   // the lists.
1048   void *Mem = C.Allocate(
1049       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
1050                        OMPClauseMappableExprCommon::MappableComponent>(
1051           Sizes.NumVars, Sizes.NumUniqueDeclarations,
1052           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
1053           Sizes.NumComponents));
1054 
1055   OMPIsDevicePtrClause *Clause = new (Mem) OMPIsDevicePtrClause(Locs, Sizes);
1056 
1057   Clause->setVarRefs(Vars);
1058   Clause->setClauseInfo(Declarations, ComponentLists);
1059   return Clause;
1060 }
1061 
1062 OMPIsDevicePtrClause *
1063 OMPIsDevicePtrClause::CreateEmpty(const ASTContext &C,
1064                                   const OMPMappableExprListSizeTy &Sizes) {
1065   void *Mem = C.Allocate(
1066       totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
1067                        OMPClauseMappableExprCommon::MappableComponent>(
1068           Sizes.NumVars, Sizes.NumUniqueDeclarations,
1069           Sizes.NumUniqueDeclarations + Sizes.NumComponentLists,
1070           Sizes.NumComponents));
1071   return new (Mem) OMPIsDevicePtrClause(Sizes);
1072 }
1073 
1074 //===----------------------------------------------------------------------===//
1075 //  OpenMP clauses printing methods
1076 //===----------------------------------------------------------------------===//
1077 
1078 void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
1079   OS << "if(";
1080   if (Node->getNameModifier() != OMPD_unknown)
1081     OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": ";
1082   Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
1083   OS << ")";
1084 }
1085 
1086 void OMPClausePrinter::VisitOMPFinalClause(OMPFinalClause *Node) {
1087   OS << "final(";
1088   Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
1089   OS << ")";
1090 }
1091 
1092 void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
1093   OS << "num_threads(";
1094   Node->getNumThreads()->printPretty(OS, nullptr, Policy, 0);
1095   OS << ")";
1096 }
1097 
1098 void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) {
1099   OS << "safelen(";
1100   Node->getSafelen()->printPretty(OS, nullptr, Policy, 0);
1101   OS << ")";
1102 }
1103 
1104 void OMPClausePrinter::VisitOMPSimdlenClause(OMPSimdlenClause *Node) {
1105   OS << "simdlen(";
1106   Node->getSimdlen()->printPretty(OS, nullptr, Policy, 0);
1107   OS << ")";
1108 }
1109 
1110 void OMPClausePrinter::VisitOMPAllocatorClause(OMPAllocatorClause *Node) {
1111   OS << "allocator(";
1112   Node->getAllocator()->printPretty(OS, nullptr, Policy, 0);
1113   OS << ")";
1114 }
1115 
1116 void OMPClausePrinter::VisitOMPCollapseClause(OMPCollapseClause *Node) {
1117   OS << "collapse(";
1118   Node->getNumForLoops()->printPretty(OS, nullptr, Policy, 0);
1119   OS << ")";
1120 }
1121 
1122 void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
1123   OS << "default("
1124      << getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind())
1125      << ")";
1126 }
1127 
1128 void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) {
1129   OS << "proc_bind("
1130      << getOpenMPSimpleClauseTypeName(OMPC_proc_bind, Node->getProcBindKind())
1131      << ")";
1132 }
1133 
1134 void OMPClausePrinter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {
1135   OS << "unified_address";
1136 }
1137 
1138 void OMPClausePrinter::VisitOMPUnifiedSharedMemoryClause(
1139     OMPUnifiedSharedMemoryClause *) {
1140   OS << "unified_shared_memory";
1141 }
1142 
1143 void OMPClausePrinter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {
1144   OS << "reverse_offload";
1145 }
1146 
1147 void OMPClausePrinter::VisitOMPDynamicAllocatorsClause(
1148     OMPDynamicAllocatorsClause *) {
1149   OS << "dynamic_allocators";
1150 }
1151 
1152 void OMPClausePrinter::VisitOMPAtomicDefaultMemOrderClause(
1153     OMPAtomicDefaultMemOrderClause *Node) {
1154   OS << "atomic_default_mem_order("
1155      << getOpenMPSimpleClauseTypeName(OMPC_atomic_default_mem_order,
1156                                       Node->getAtomicDefaultMemOrderKind())
1157      << ")";
1158 }
1159 
1160 void OMPClausePrinter::VisitOMPScheduleClause(OMPScheduleClause *Node) {
1161   OS << "schedule(";
1162   if (Node->getFirstScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
1163     OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
1164                                         Node->getFirstScheduleModifier());
1165     if (Node->getSecondScheduleModifier() != OMPC_SCHEDULE_MODIFIER_unknown) {
1166       OS << ", ";
1167       OS << getOpenMPSimpleClauseTypeName(OMPC_schedule,
1168                                           Node->getSecondScheduleModifier());
1169     }
1170     OS << ": ";
1171   }
1172   OS << getOpenMPSimpleClauseTypeName(OMPC_schedule, Node->getScheduleKind());
1173   if (auto *E = Node->getChunkSize()) {
1174     OS << ", ";
1175     E->printPretty(OS, nullptr, Policy);
1176   }
1177   OS << ")";
1178 }
1179 
1180 void OMPClausePrinter::VisitOMPOrderedClause(OMPOrderedClause *Node) {
1181   OS << "ordered";
1182   if (auto *Num = Node->getNumForLoops()) {
1183     OS << "(";
1184     Num->printPretty(OS, nullptr, Policy, 0);
1185     OS << ")";
1186   }
1187 }
1188 
1189 void OMPClausePrinter::VisitOMPNowaitClause(OMPNowaitClause *) {
1190   OS << "nowait";
1191 }
1192 
1193 void OMPClausePrinter::VisitOMPUntiedClause(OMPUntiedClause *) {
1194   OS << "untied";
1195 }
1196 
1197 void OMPClausePrinter::VisitOMPNogroupClause(OMPNogroupClause *) {
1198   OS << "nogroup";
1199 }
1200 
1201 void OMPClausePrinter::VisitOMPMergeableClause(OMPMergeableClause *) {
1202   OS << "mergeable";
1203 }
1204 
1205 void OMPClausePrinter::VisitOMPReadClause(OMPReadClause *) { OS << "read"; }
1206 
1207 void OMPClausePrinter::VisitOMPWriteClause(OMPWriteClause *) { OS << "write"; }
1208 
1209 void OMPClausePrinter::VisitOMPUpdateClause(OMPUpdateClause *) {
1210   OS << "update";
1211 }
1212 
1213 void OMPClausePrinter::VisitOMPCaptureClause(OMPCaptureClause *) {
1214   OS << "capture";
1215 }
1216 
1217 void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
1218   OS << "seq_cst";
1219 }
1220 
1221 void OMPClausePrinter::VisitOMPThreadsClause(OMPThreadsClause *) {
1222   OS << "threads";
1223 }
1224 
1225 void OMPClausePrinter::VisitOMPSIMDClause(OMPSIMDClause *) { OS << "simd"; }
1226 
1227 void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
1228   OS << "device(";
1229   Node->getDevice()->printPretty(OS, nullptr, Policy, 0);
1230   OS << ")";
1231 }
1232 
1233 void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
1234   OS << "num_teams(";
1235   Node->getNumTeams()->printPretty(OS, nullptr, Policy, 0);
1236   OS << ")";
1237 }
1238 
1239 void OMPClausePrinter::VisitOMPThreadLimitClause(OMPThreadLimitClause *Node) {
1240   OS << "thread_limit(";
1241   Node->getThreadLimit()->printPretty(OS, nullptr, Policy, 0);
1242   OS << ")";
1243 }
1244 
1245 void OMPClausePrinter::VisitOMPPriorityClause(OMPPriorityClause *Node) {
1246   OS << "priority(";
1247   Node->getPriority()->printPretty(OS, nullptr, Policy, 0);
1248   OS << ")";
1249 }
1250 
1251 void OMPClausePrinter::VisitOMPGrainsizeClause(OMPGrainsizeClause *Node) {
1252   OS << "grainsize(";
1253   Node->getGrainsize()->printPretty(OS, nullptr, Policy, 0);
1254   OS << ")";
1255 }
1256 
1257 void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) {
1258   OS << "num_tasks(";
1259   Node->getNumTasks()->printPretty(OS, nullptr, Policy, 0);
1260   OS << ")";
1261 }
1262 
1263 void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) {
1264   OS << "hint(";
1265   Node->getHint()->printPretty(OS, nullptr, Policy, 0);
1266   OS << ")";
1267 }
1268 
1269 template<typename T>
1270 void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
1271   for (typename T::varlist_iterator I = Node->varlist_begin(),
1272                                     E = Node->varlist_end();
1273        I != E; ++I) {
1274     assert(*I && "Expected non-null Stmt");
1275     OS << (I == Node->varlist_begin() ? StartSym : ',');
1276     if (auto *DRE = dyn_cast<DeclRefExpr>(*I)) {
1277       if (isa<OMPCapturedExprDecl>(DRE->getDecl()))
1278         DRE->printPretty(OS, nullptr, Policy, 0);
1279       else
1280         DRE->getDecl()->printQualifiedName(OS);
1281     } else
1282       (*I)->printPretty(OS, nullptr, Policy, 0);
1283   }
1284 }
1285 
1286 void OMPClausePrinter::VisitOMPAllocateClause(OMPAllocateClause *Node) {
1287   if (Node->varlist_empty())
1288     return;
1289   OS << "allocate";
1290   if (Expr *Allocator = Node->getAllocator()) {
1291     OS << "(";
1292     Allocator->printPretty(OS, nullptr, Policy, 0);
1293     OS << ":";
1294     VisitOMPClauseList(Node, ' ');
1295   } else {
1296     VisitOMPClauseList(Node, '(');
1297   }
1298   OS << ")";
1299 }
1300 
1301 void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) {
1302   if (!Node->varlist_empty()) {
1303     OS << "private";
1304     VisitOMPClauseList(Node, '(');
1305     OS << ")";
1306   }
1307 }
1308 
1309 void OMPClausePrinter::VisitOMPFirstprivateClause(OMPFirstprivateClause *Node) {
1310   if (!Node->varlist_empty()) {
1311     OS << "firstprivate";
1312     VisitOMPClauseList(Node, '(');
1313     OS << ")";
1314   }
1315 }
1316 
1317 void OMPClausePrinter::VisitOMPLastprivateClause(OMPLastprivateClause *Node) {
1318   if (!Node->varlist_empty()) {
1319     OS << "lastprivate";
1320     VisitOMPClauseList(Node, '(');
1321     OS << ")";
1322   }
1323 }
1324 
1325 void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) {
1326   if (!Node->varlist_empty()) {
1327     OS << "shared";
1328     VisitOMPClauseList(Node, '(');
1329     OS << ")";
1330   }
1331 }
1332 
1333 void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) {
1334   if (!Node->varlist_empty()) {
1335     OS << "reduction(";
1336     NestedNameSpecifier *QualifierLoc =
1337         Node->getQualifierLoc().getNestedNameSpecifier();
1338     OverloadedOperatorKind OOK =
1339         Node->getNameInfo().getName().getCXXOverloadedOperator();
1340     if (QualifierLoc == nullptr && OOK != OO_None) {
1341       // Print reduction identifier in C format
1342       OS << getOperatorSpelling(OOK);
1343     } else {
1344       // Use C++ format
1345       if (QualifierLoc != nullptr)
1346         QualifierLoc->print(OS, Policy);
1347       OS << Node->getNameInfo();
1348     }
1349     OS << ":";
1350     VisitOMPClauseList(Node, ' ');
1351     OS << ")";
1352   }
1353 }
1354 
1355 void OMPClausePrinter::VisitOMPTaskReductionClause(
1356     OMPTaskReductionClause *Node) {
1357   if (!Node->varlist_empty()) {
1358     OS << "task_reduction(";
1359     NestedNameSpecifier *QualifierLoc =
1360         Node->getQualifierLoc().getNestedNameSpecifier();
1361     OverloadedOperatorKind OOK =
1362         Node->getNameInfo().getName().getCXXOverloadedOperator();
1363     if (QualifierLoc == nullptr && OOK != OO_None) {
1364       // Print reduction identifier in C format
1365       OS << getOperatorSpelling(OOK);
1366     } else {
1367       // Use C++ format
1368       if (QualifierLoc != nullptr)
1369         QualifierLoc->print(OS, Policy);
1370       OS << Node->getNameInfo();
1371     }
1372     OS << ":";
1373     VisitOMPClauseList(Node, ' ');
1374     OS << ")";
1375   }
1376 }
1377 
1378 void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) {
1379   if (!Node->varlist_empty()) {
1380     OS << "in_reduction(";
1381     NestedNameSpecifier *QualifierLoc =
1382         Node->getQualifierLoc().getNestedNameSpecifier();
1383     OverloadedOperatorKind OOK =
1384         Node->getNameInfo().getName().getCXXOverloadedOperator();
1385     if (QualifierLoc == nullptr && OOK != OO_None) {
1386       // Print reduction identifier in C format
1387       OS << getOperatorSpelling(OOK);
1388     } else {
1389       // Use C++ format
1390       if (QualifierLoc != nullptr)
1391         QualifierLoc->print(OS, Policy);
1392       OS << Node->getNameInfo();
1393     }
1394     OS << ":";
1395     VisitOMPClauseList(Node, ' ');
1396     OS << ")";
1397   }
1398 }
1399 
1400 void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
1401   if (!Node->varlist_empty()) {
1402     OS << "linear";
1403     if (Node->getModifierLoc().isValid()) {
1404       OS << '('
1405          << getOpenMPSimpleClauseTypeName(OMPC_linear, Node->getModifier());
1406     }
1407     VisitOMPClauseList(Node, '(');
1408     if (Node->getModifierLoc().isValid())
1409       OS << ')';
1410     if (Node->getStep() != nullptr) {
1411       OS << ": ";
1412       Node->getStep()->printPretty(OS, nullptr, Policy, 0);
1413     }
1414     OS << ")";
1415   }
1416 }
1417 
1418 void OMPClausePrinter::VisitOMPAlignedClause(OMPAlignedClause *Node) {
1419   if (!Node->varlist_empty()) {
1420     OS << "aligned";
1421     VisitOMPClauseList(Node, '(');
1422     if (Node->getAlignment() != nullptr) {
1423       OS << ": ";
1424       Node->getAlignment()->printPretty(OS, nullptr, Policy, 0);
1425     }
1426     OS << ")";
1427   }
1428 }
1429 
1430 void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
1431   if (!Node->varlist_empty()) {
1432     OS << "copyin";
1433     VisitOMPClauseList(Node, '(');
1434     OS << ")";
1435   }
1436 }
1437 
1438 void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) {
1439   if (!Node->varlist_empty()) {
1440     OS << "copyprivate";
1441     VisitOMPClauseList(Node, '(');
1442     OS << ")";
1443   }
1444 }
1445 
1446 void OMPClausePrinter::VisitOMPFlushClause(OMPFlushClause *Node) {
1447   if (!Node->varlist_empty()) {
1448     VisitOMPClauseList(Node, '(');
1449     OS << ")";
1450   }
1451 }
1452 
1453 void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
1454   OS << "depend(";
1455   OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
1456                                       Node->getDependencyKind());
1457   if (!Node->varlist_empty()) {
1458     OS << " :";
1459     VisitOMPClauseList(Node, ' ');
1460   }
1461   OS << ")";
1462 }
1463 
1464 void OMPClausePrinter::VisitOMPMapClause(OMPMapClause *Node) {
1465   if (!Node->varlist_empty()) {
1466     OS << "map(";
1467     if (Node->getMapType() != OMPC_MAP_unknown) {
1468       for (unsigned I = 0; I < OMPMapClause::NumberOfModifiers; ++I) {
1469         if (Node->getMapTypeModifier(I) != OMPC_MAP_MODIFIER_unknown) {
1470           OS << getOpenMPSimpleClauseTypeName(OMPC_map,
1471                                               Node->getMapTypeModifier(I));
1472           if (Node->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_mapper) {
1473             OS << '(';
1474             NestedNameSpecifier *MapperNNS =
1475                 Node->getMapperQualifierLoc().getNestedNameSpecifier();
1476             if (MapperNNS)
1477               MapperNNS->print(OS, Policy);
1478             OS << Node->getMapperIdInfo() << ')';
1479           }
1480           OS << ',';
1481         }
1482       }
1483       OS << getOpenMPSimpleClauseTypeName(OMPC_map, Node->getMapType());
1484       OS << ':';
1485     }
1486     VisitOMPClauseList(Node, ' ');
1487     OS << ")";
1488   }
1489 }
1490 
1491 void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) {
1492   if (!Node->varlist_empty()) {
1493     OS << "to";
1494     DeclarationNameInfo MapperId = Node->getMapperIdInfo();
1495     if (MapperId.getName() && !MapperId.getName().isEmpty()) {
1496       OS << '(';
1497       OS << "mapper(";
1498       NestedNameSpecifier *MapperNNS =
1499           Node->getMapperQualifierLoc().getNestedNameSpecifier();
1500       if (MapperNNS)
1501         MapperNNS->print(OS, Policy);
1502       OS << MapperId << "):";
1503       VisitOMPClauseList(Node, ' ');
1504     } else {
1505       VisitOMPClauseList(Node, '(');
1506     }
1507     OS << ")";
1508   }
1509 }
1510 
1511 void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) {
1512   if (!Node->varlist_empty()) {
1513     OS << "from";
1514     DeclarationNameInfo MapperId = Node->getMapperIdInfo();
1515     if (MapperId.getName() && !MapperId.getName().isEmpty()) {
1516       OS << '(';
1517       OS << "mapper(";
1518       NestedNameSpecifier *MapperNNS =
1519           Node->getMapperQualifierLoc().getNestedNameSpecifier();
1520       if (MapperNNS)
1521         MapperNNS->print(OS, Policy);
1522       OS << MapperId << "):";
1523       VisitOMPClauseList(Node, ' ');
1524     } else {
1525       VisitOMPClauseList(Node, '(');
1526     }
1527     OS << ")";
1528   }
1529 }
1530 
1531 void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) {
1532   OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName(
1533                            OMPC_dist_schedule, Node->getDistScheduleKind());
1534   if (auto *E = Node->getChunkSize()) {
1535     OS << ", ";
1536     E->printPretty(OS, nullptr, Policy);
1537   }
1538   OS << ")";
1539 }
1540 
1541 void OMPClausePrinter::VisitOMPDefaultmapClause(OMPDefaultmapClause *Node) {
1542   OS << "defaultmap(";
1543   OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
1544                                       Node->getDefaultmapModifier());
1545   OS << ": ";
1546   OS << getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
1547     Node->getDefaultmapKind());
1548   OS << ")";
1549 }
1550 
1551 void OMPClausePrinter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *Node) {
1552   if (!Node->varlist_empty()) {
1553     OS << "use_device_ptr";
1554     VisitOMPClauseList(Node, '(');
1555     OS << ")";
1556   }
1557 }
1558 
1559 void OMPClausePrinter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *Node) {
1560   if (!Node->varlist_empty()) {
1561     OS << "is_device_ptr";
1562     VisitOMPClauseList(Node, '(');
1563     OS << ")";
1564   }
1565 }
1566 
1567