1//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===//
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// This file implements the Stmt class and statement subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/ASTDiagnostic.h"
16#include "clang/AST/ExprCXX.h"
17#include "clang/AST/ExprObjC.h"
18#include "clang/AST/Stmt.h"
19#include "clang/AST/StmtCXX.h"
20#include "clang/AST/StmtObjC.h"
21#include "clang/AST/StmtOpenMP.h"
22#include "clang/AST/Type.h"
23#include "clang/Basic/CharInfo.h"
24#include "clang/Basic/TargetInfo.h"
25#include "clang/Lex/Token.h"
26#include "llvm/ADT/StringExtras.h"
27#include "llvm/Support/raw_ostream.h"
28using namespace clang;
29
30static struct StmtClassNameTable {
31  const char *Name;
32  unsigned Counter;
33  unsigned Size;
34} StmtClassInfo[Stmt::lastStmtConstant+1];
35
36static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
37  static bool Initialized = false;
38  if (Initialized)
39    return StmtClassInfo[E];
40
41  // Intialize the table on the first use.
42  Initialized = true;
43#define ABSTRACT_STMT(STMT)
44#define STMT(CLASS, PARENT) \
45  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS;    \
46  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
47#include "clang/AST/StmtNodes.inc"
48
49  return StmtClassInfo[E];
50}
51
52void *Stmt::operator new(size_t bytes, ASTContext& C,
53                         unsigned alignment) throw() {
54  return ::operator new(bytes, C, alignment);
55}
56
57void *Stmt::operator new(size_t bytes, ASTContext* C,
58                         unsigned alignment) throw() {
59  return ::operator new(bytes, *C, alignment);
60}
61
62const char *Stmt::getStmtClassName() const {
63  return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
64}
65
66void Stmt::PrintStats() {
67  // Ensure the table is primed.
68  getStmtInfoTableEntry(Stmt::NullStmtClass);
69
70  unsigned sum = 0;
71  llvm::errs() << "\n*** Stmt/Expr Stats:\n";
72  for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
73    if (StmtClassInfo[i].Name == 0) continue;
74    sum += StmtClassInfo[i].Counter;
75  }
76  llvm::errs() << "  " << sum << " stmts/exprs total.\n";
77  sum = 0;
78  for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
79    if (StmtClassInfo[i].Name == 0) continue;
80    if (StmtClassInfo[i].Counter == 0) continue;
81    llvm::errs() << "    " << StmtClassInfo[i].Counter << " "
82                 << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size
83                 << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size
84                 << " bytes)\n";
85    sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
86  }
87
88  llvm::errs() << "Total bytes = " << sum << "\n";
89}
90
91void Stmt::addStmtClass(StmtClass s) {
92  ++getStmtInfoTableEntry(s).Counter;
93}
94
95bool Stmt::StatisticsEnabled = false;
96void Stmt::EnableStatistics() {
97  StatisticsEnabled = true;
98}
99
100Stmt *Stmt::IgnoreImplicit() {
101  Stmt *s = this;
102
103  if (ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(s))
104    s = ewc->getSubExpr();
105
106  while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(s))
107    s = ice->getSubExpr();
108
109  return s;
110}
111
112/// \brief Strip off all label-like statements.
113///
114/// This will strip off label statements, case statements, attributed
115/// statements and default statements recursively.
116const Stmt *Stmt::stripLabelLikeStatements() const {
117  const Stmt *S = this;
118  while (true) {
119    if (const LabelStmt *LS = dyn_cast<LabelStmt>(S))
120      S = LS->getSubStmt();
121    else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S))
122      S = SC->getSubStmt();
123    else if (const AttributedStmt *AS = dyn_cast<AttributedStmt>(S))
124      S = AS->getSubStmt();
125    else
126      return S;
127  }
128}
129
130namespace {
131  struct good {};
132  struct bad {};
133
134  // These silly little functions have to be static inline to suppress
135  // unused warnings, and they have to be defined to suppress other
136  // warnings.
137  static inline good is_good(good) { return good(); }
138
139  typedef Stmt::child_range children_t();
140  template <class T> good implements_children(children_t T::*) {
141    return good();
142  }
143  static inline bad implements_children(children_t Stmt::*) {
144    return bad();
145  }
146
147  typedef SourceLocation getLocStart_t() const;
148  template <class T> good implements_getLocStart(getLocStart_t T::*) {
149    return good();
150  }
151  static inline bad implements_getLocStart(getLocStart_t Stmt::*) {
152    return bad();
153  }
154
155  typedef SourceLocation getLocEnd_t() const;
156  template <class T> good implements_getLocEnd(getLocEnd_t T::*) {
157    return good();
158  }
159  static inline bad implements_getLocEnd(getLocEnd_t Stmt::*) {
160    return bad();
161  }
162
163#define ASSERT_IMPLEMENTS_children(type) \
164  (void) sizeof(is_good(implements_children(&type::children)))
165#define ASSERT_IMPLEMENTS_getLocStart(type) \
166  (void) sizeof(is_good(implements_getLocStart(&type::getLocStart)))
167#define ASSERT_IMPLEMENTS_getLocEnd(type) \
168  (void) sizeof(is_good(implements_getLocEnd(&type::getLocEnd)))
169}
170
171/// Check whether the various Stmt classes implement their member
172/// functions.
173static inline void check_implementations() {
174#define ABSTRACT_STMT(type)
175#define STMT(type, base) \
176  ASSERT_IMPLEMENTS_children(type); \
177  ASSERT_IMPLEMENTS_getLocStart(type); \
178  ASSERT_IMPLEMENTS_getLocEnd(type);
179#include "clang/AST/StmtNodes.inc"
180}
181
182Stmt::child_range Stmt::children() {
183  switch (getStmtClass()) {
184  case Stmt::NoStmtClass: llvm_unreachable("statement without class");
185#define ABSTRACT_STMT(type)
186#define STMT(type, base) \
187  case Stmt::type##Class: \
188    return static_cast<type*>(this)->children();
189#include "clang/AST/StmtNodes.inc"
190  }
191  llvm_unreachable("unknown statement kind!");
192}
193
194// Amusing macro metaprogramming hack: check whether a class provides
195// a more specific implementation of getSourceRange.
196//
197// See also Expr.cpp:getExprLoc().
198namespace {
199  /// This implementation is used when a class provides a custom
200  /// implementation of getSourceRange.
201  template <class S, class T>
202  SourceRange getSourceRangeImpl(const Stmt *stmt,
203                                 SourceRange (T::*v)() const) {
204    return static_cast<const S*>(stmt)->getSourceRange();
205  }
206
207  /// This implementation is used when a class doesn't provide a custom
208  /// implementation of getSourceRange.  Overload resolution should pick it over
209  /// the implementation above because it's more specialized according to
210  /// function template partial ordering.
211  template <class S>
212  SourceRange getSourceRangeImpl(const Stmt *stmt,
213                                 SourceRange (Stmt::*v)() const) {
214    return SourceRange(static_cast<const S*>(stmt)->getLocStart(),
215                       static_cast<const S*>(stmt)->getLocEnd());
216  }
217}
218
219SourceRange Stmt::getSourceRange() const {
220  switch (getStmtClass()) {
221  case Stmt::NoStmtClass: llvm_unreachable("statement without class");
222#define ABSTRACT_STMT(type)
223#define STMT(type, base) \
224  case Stmt::type##Class: \
225    return getSourceRangeImpl<type>(this, &type::getSourceRange);
226#include "clang/AST/StmtNodes.inc"
227  }
228  llvm_unreachable("unknown statement kind!");
229}
230
231SourceLocation Stmt::getLocStart() const {
232//  llvm::errs() << "getLocStart() for " << getStmtClassName() << "\n";
233  switch (getStmtClass()) {
234  case Stmt::NoStmtClass: llvm_unreachable("statement without class");
235#define ABSTRACT_STMT(type)
236#define STMT(type, base) \
237  case Stmt::type##Class: \
238    return static_cast<const type*>(this)->getLocStart();
239#include "clang/AST/StmtNodes.inc"
240  }
241  llvm_unreachable("unknown statement kind");
242}
243
244SourceLocation Stmt::getLocEnd() const {
245  switch (getStmtClass()) {
246  case Stmt::NoStmtClass: llvm_unreachable("statement without class");
247#define ABSTRACT_STMT(type)
248#define STMT(type, base) \
249  case Stmt::type##Class: \
250    return static_cast<const type*>(this)->getLocEnd();
251#include "clang/AST/StmtNodes.inc"
252  }
253  llvm_unreachable("unknown statement kind");
254}
255
256CompoundStmt::CompoundStmt(ASTContext &C, ArrayRef<Stmt*> Stmts,
257                           SourceLocation LB, SourceLocation RB)
258  : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) {
259  CompoundStmtBits.NumStmts = Stmts.size();
260  assert(CompoundStmtBits.NumStmts == Stmts.size() &&
261         "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
262
263  if (Stmts.size() == 0) {
264    Body = 0;
265    return;
266  }
267
268  Body = new (C) Stmt*[Stmts.size()];
269  std::copy(Stmts.begin(), Stmts.end(), Body);
270}
271
272void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
273  if (this->Body)
274    C.Deallocate(Body);
275  this->CompoundStmtBits.NumStmts = NumStmts;
276
277  Body = new (C) Stmt*[NumStmts];
278  memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
279}
280
281const char *LabelStmt::getName() const {
282  return getDecl()->getIdentifier()->getNameStart();
283}
284
285AttributedStmt *AttributedStmt::Create(ASTContext &C, SourceLocation Loc,
286                                       ArrayRef<const Attr*> Attrs,
287                                       Stmt *SubStmt) {
288  void *Mem = C.Allocate(sizeof(AttributedStmt) +
289                         sizeof(Attr*) * (Attrs.size() - 1),
290                         llvm::alignOf<AttributedStmt>());
291  return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
292}
293
294AttributedStmt *AttributedStmt::CreateEmpty(ASTContext &C, unsigned NumAttrs) {
295  assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
296  void *Mem = C.Allocate(sizeof(AttributedStmt) +
297                         sizeof(Attr*) * (NumAttrs - 1),
298                         llvm::alignOf<AttributedStmt>());
299  return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
300}
301
302std::string AsmStmt::generateAsmString(ASTContext &C) const {
303  if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
304    return gccAsmStmt->generateAsmString(C);
305  if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
306    return msAsmStmt->generateAsmString(C);
307  llvm_unreachable("unknown asm statement kind!");
308}
309
310StringRef AsmStmt::getOutputConstraint(unsigned i) const {
311  if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
312    return gccAsmStmt->getOutputConstraint(i);
313  if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
314    return msAsmStmt->getOutputConstraint(i);
315  llvm_unreachable("unknown asm statement kind!");
316}
317
318const Expr *AsmStmt::getOutputExpr(unsigned i) const {
319  if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
320    return gccAsmStmt->getOutputExpr(i);
321  if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
322    return msAsmStmt->getOutputExpr(i);
323  llvm_unreachable("unknown asm statement kind!");
324}
325
326StringRef AsmStmt::getInputConstraint(unsigned i) const {
327  if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
328    return gccAsmStmt->getInputConstraint(i);
329  if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
330    return msAsmStmt->getInputConstraint(i);
331  llvm_unreachable("unknown asm statement kind!");
332}
333
334const Expr *AsmStmt::getInputExpr(unsigned i) const {
335  if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
336    return gccAsmStmt->getInputExpr(i);
337  if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
338    return msAsmStmt->getInputExpr(i);
339  llvm_unreachable("unknown asm statement kind!");
340}
341
342StringRef AsmStmt::getClobber(unsigned i) const {
343  if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
344    return gccAsmStmt->getClobber(i);
345  if (const MSAsmStmt *msAsmStmt = dyn_cast<MSAsmStmt>(this))
346    return msAsmStmt->getClobber(i);
347  llvm_unreachable("unknown asm statement kind!");
348}
349
350/// getNumPlusOperands - Return the number of output operands that have a "+"
351/// constraint.
352unsigned AsmStmt::getNumPlusOperands() const {
353  unsigned Res = 0;
354  for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
355    if (isOutputPlusConstraint(i))
356      ++Res;
357  return Res;
358}
359
360StringRef GCCAsmStmt::getClobber(unsigned i) const {
361  return getClobberStringLiteral(i)->getString();
362}
363
364Expr *GCCAsmStmt::getOutputExpr(unsigned i) {
365  return cast<Expr>(Exprs[i]);
366}
367
368/// getOutputConstraint - Return the constraint string for the specified
369/// output operand.  All output constraints are known to be non-empty (either
370/// '=' or '+').
371StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const {
372  return getOutputConstraintLiteral(i)->getString();
373}
374
375Expr *GCCAsmStmt::getInputExpr(unsigned i) {
376  return cast<Expr>(Exprs[i + NumOutputs]);
377}
378void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) {
379  Exprs[i + NumOutputs] = E;
380}
381
382/// getInputConstraint - Return the specified input constraint.  Unlike output
383/// constraints, these can be empty.
384StringRef GCCAsmStmt::getInputConstraint(unsigned i) const {
385  return getInputConstraintLiteral(i)->getString();
386}
387
388void GCCAsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C,
389                                             IdentifierInfo **Names,
390                                             StringLiteral **Constraints,
391                                             Stmt **Exprs,
392                                             unsigned NumOutputs,
393                                             unsigned NumInputs,
394                                             StringLiteral **Clobbers,
395                                             unsigned NumClobbers) {
396  this->NumOutputs = NumOutputs;
397  this->NumInputs = NumInputs;
398  this->NumClobbers = NumClobbers;
399
400  unsigned NumExprs = NumOutputs + NumInputs;
401
402  C.Deallocate(this->Names);
403  this->Names = new (C) IdentifierInfo*[NumExprs];
404  std::copy(Names, Names + NumExprs, this->Names);
405
406  C.Deallocate(this->Exprs);
407  this->Exprs = new (C) Stmt*[NumExprs];
408  std::copy(Exprs, Exprs + NumExprs, this->Exprs);
409
410  C.Deallocate(this->Constraints);
411  this->Constraints = new (C) StringLiteral*[NumExprs];
412  std::copy(Constraints, Constraints + NumExprs, this->Constraints);
413
414  C.Deallocate(this->Clobbers);
415  this->Clobbers = new (C) StringLiteral*[NumClobbers];
416  std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);
417}
418
419/// getNamedOperand - Given a symbolic operand reference like %[foo],
420/// translate this into a numeric value needed to reference the same operand.
421/// This returns -1 if the operand name is invalid.
422int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const {
423  unsigned NumPlusOperands = 0;
424
425  // Check if this is an output operand.
426  for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
427    if (getOutputName(i) == SymbolicName)
428      return i;
429  }
430
431  for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
432    if (getInputName(i) == SymbolicName)
433      return getNumOutputs() + NumPlusOperands + i;
434
435  // Not found.
436  return -1;
437}
438
439/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
440/// it into pieces.  If the asm string is erroneous, emit errors and return
441/// true, otherwise return false.
442unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
443                                   ASTContext &C, unsigned &DiagOffs) const {
444  StringRef Str = getAsmString()->getString();
445  const char *StrStart = Str.begin();
446  const char *StrEnd = Str.end();
447  const char *CurPtr = StrStart;
448
449  // "Simple" inline asms have no constraints or operands, just convert the asm
450  // string to escape $'s.
451  if (isSimple()) {
452    std::string Result;
453    for (; CurPtr != StrEnd; ++CurPtr) {
454      switch (*CurPtr) {
455      case '$':
456        Result += "$$";
457        break;
458      default:
459        Result += *CurPtr;
460        break;
461      }
462    }
463    Pieces.push_back(AsmStringPiece(Result));
464    return 0;
465  }
466
467  // CurStringPiece - The current string that we are building up as we scan the
468  // asm string.
469  std::string CurStringPiece;
470
471  bool HasVariants = !C.getTargetInfo().hasNoAsmVariants();
472
473  while (1) {
474    // Done with the string?
475    if (CurPtr == StrEnd) {
476      if (!CurStringPiece.empty())
477        Pieces.push_back(AsmStringPiece(CurStringPiece));
478      return 0;
479    }
480
481    char CurChar = *CurPtr++;
482    switch (CurChar) {
483    case '$': CurStringPiece += "$$"; continue;
484    case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue;
485    case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue;
486    case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue;
487    case '%':
488      break;
489    default:
490      CurStringPiece += CurChar;
491      continue;
492    }
493
494    // Escaped "%" character in asm string.
495    if (CurPtr == StrEnd) {
496      // % at end of string is invalid (no escape).
497      DiagOffs = CurPtr-StrStart-1;
498      return diag::err_asm_invalid_escape;
499    }
500
501    char EscapedChar = *CurPtr++;
502    if (EscapedChar == '%') {  // %% -> %
503      // Escaped percentage sign.
504      CurStringPiece += '%';
505      continue;
506    }
507
508    if (EscapedChar == '=') {  // %= -> Generate an unique ID.
509      CurStringPiece += "${:uid}";
510      continue;
511    }
512
513    // Otherwise, we have an operand.  If we have accumulated a string so far,
514    // add it to the Pieces list.
515    if (!CurStringPiece.empty()) {
516      Pieces.push_back(AsmStringPiece(CurStringPiece));
517      CurStringPiece.clear();
518    }
519
520    // Handle %x4 and %x[foo] by capturing x as the modifier character.
521    char Modifier = '\0';
522    if (isLetter(EscapedChar)) {
523      if (CurPtr == StrEnd) { // Premature end.
524        DiagOffs = CurPtr-StrStart-1;
525        return diag::err_asm_invalid_escape;
526      }
527      Modifier = EscapedChar;
528      EscapedChar = *CurPtr++;
529    }
530
531    if (isDigit(EscapedChar)) {
532      // %n - Assembler operand n
533      unsigned N = 0;
534
535      --CurPtr;
536      while (CurPtr != StrEnd && isDigit(*CurPtr))
537        N = N*10 + ((*CurPtr++)-'0');
538
539      unsigned NumOperands =
540        getNumOutputs() + getNumPlusOperands() + getNumInputs();
541      if (N >= NumOperands) {
542        DiagOffs = CurPtr-StrStart-1;
543        return diag::err_asm_invalid_operand_number;
544      }
545
546      Pieces.push_back(AsmStringPiece(N, Modifier));
547      continue;
548    }
549
550    // Handle %[foo], a symbolic operand reference.
551    if (EscapedChar == '[') {
552      DiagOffs = CurPtr-StrStart-1;
553
554      // Find the ']'.
555      const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
556      if (NameEnd == 0)
557        return diag::err_asm_unterminated_symbolic_operand_name;
558      if (NameEnd == CurPtr)
559        return diag::err_asm_empty_symbolic_operand_name;
560
561      StringRef SymbolicName(CurPtr, NameEnd - CurPtr);
562
563      int N = getNamedOperand(SymbolicName);
564      if (N == -1) {
565        // Verify that an operand with that name exists.
566        DiagOffs = CurPtr-StrStart;
567        return diag::err_asm_unknown_symbolic_operand_name;
568      }
569      Pieces.push_back(AsmStringPiece(N, Modifier));
570
571      CurPtr = NameEnd+1;
572      continue;
573    }
574
575    DiagOffs = CurPtr-StrStart-1;
576    return diag::err_asm_invalid_escape;
577  }
578}
579
580/// Assemble final IR asm string (GCC-style).
581std::string GCCAsmStmt::generateAsmString(ASTContext &C) const {
582  // Analyze the asm string to decompose it into its pieces.  We know that Sema
583  // has already done this, so it is guaranteed to be successful.
584  SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces;
585  unsigned DiagOffs;
586  AnalyzeAsmString(Pieces, C, DiagOffs);
587
588  std::string AsmString;
589  for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
590    if (Pieces[i].isString())
591      AsmString += Pieces[i].getString();
592    else if (Pieces[i].getModifier() == '\0')
593      AsmString += '$' + llvm::utostr(Pieces[i].getOperandNo());
594    else
595      AsmString += "${" + llvm::utostr(Pieces[i].getOperandNo()) + ':' +
596                   Pieces[i].getModifier() + '}';
597  }
598  return AsmString;
599}
600
601/// Assemble final IR asm string (MS-style).
602std::string MSAsmStmt::generateAsmString(ASTContext &C) const {
603  // FIXME: This needs to be translated into the IR string representation.
604  return AsmStr;
605}
606
607Expr *MSAsmStmt::getOutputExpr(unsigned i) {
608  return cast<Expr>(Exprs[i]);
609}
610
611Expr *MSAsmStmt::getInputExpr(unsigned i) {
612  return cast<Expr>(Exprs[i + NumOutputs]);
613}
614void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
615  Exprs[i + NumOutputs] = E;
616}
617
618QualType CXXCatchStmt::getCaughtType() const {
619  if (ExceptionDecl)
620    return ExceptionDecl->getType();
621  return QualType();
622}
623
624//===----------------------------------------------------------------------===//
625// Constructors
626//===----------------------------------------------------------------------===//
627
628GCCAsmStmt::GCCAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
629                       bool isvolatile, unsigned numoutputs, unsigned numinputs,
630                       IdentifierInfo **names, StringLiteral **constraints,
631                       Expr **exprs, StringLiteral *asmstr,
632                       unsigned numclobbers, StringLiteral **clobbers,
633                       SourceLocation rparenloc)
634  : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
635            numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) {
636
637  unsigned NumExprs = NumOutputs + NumInputs;
638
639  Names = new (C) IdentifierInfo*[NumExprs];
640  std::copy(names, names + NumExprs, Names);
641
642  Exprs = new (C) Stmt*[NumExprs];
643  std::copy(exprs, exprs + NumExprs, Exprs);
644
645  Constraints = new (C) StringLiteral*[NumExprs];
646  std::copy(constraints, constraints + NumExprs, Constraints);
647
648  Clobbers = new (C) StringLiteral*[NumClobbers];
649  std::copy(clobbers, clobbers + NumClobbers, Clobbers);
650}
651
652MSAsmStmt::MSAsmStmt(ASTContext &C, SourceLocation asmloc,
653                     SourceLocation lbraceloc, bool issimple, bool isvolatile,
654                     ArrayRef<Token> asmtoks, unsigned numoutputs,
655                     unsigned numinputs,
656                     ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs,
657                     StringRef asmstr, ArrayRef<StringRef> clobbers,
658                     SourceLocation endloc)
659  : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
660            numinputs, clobbers.size()), LBraceLoc(lbraceloc),
661            EndLoc(endloc), NumAsmToks(asmtoks.size()) {
662
663  initialize(C, asmstr, asmtoks, constraints, exprs, clobbers);
664}
665
666static StringRef copyIntoContext(ASTContext &C, StringRef str) {
667  size_t size = str.size();
668  char *buffer = new (C) char[size];
669  memcpy(buffer, str.data(), size);
670  return StringRef(buffer, size);
671}
672
673void MSAsmStmt::initialize(ASTContext &C,
674                           StringRef asmstr,
675                           ArrayRef<Token> asmtoks,
676                           ArrayRef<StringRef> constraints,
677                           ArrayRef<Expr*> exprs,
678                           ArrayRef<StringRef> clobbers) {
679  assert(NumAsmToks == asmtoks.size());
680  assert(NumClobbers == clobbers.size());
681
682  unsigned NumExprs = exprs.size();
683  assert(NumExprs == NumOutputs + NumInputs);
684  assert(NumExprs == constraints.size());
685
686  AsmStr = copyIntoContext(C, asmstr);
687
688  Exprs = new (C) Stmt*[NumExprs];
689  for (unsigned i = 0, e = NumExprs; i != e; ++i)
690    Exprs[i] = exprs[i];
691
692  AsmToks = new (C) Token[NumAsmToks];
693  for (unsigned i = 0, e = NumAsmToks; i != e; ++i)
694    AsmToks[i] = asmtoks[i];
695
696  Constraints = new (C) StringRef[NumExprs];
697  for (unsigned i = 0, e = NumExprs; i != e; ++i) {
698    Constraints[i] = copyIntoContext(C, constraints[i]);
699  }
700
701  Clobbers = new (C) StringRef[NumClobbers];
702  for (unsigned i = 0, e = NumClobbers; i != e; ++i) {
703    // FIXME: Avoid the allocation/copy if at all possible.
704    Clobbers[i] = copyIntoContext(C, clobbers[i]);
705  }
706}
707
708ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
709                                             Stmt *Body,  SourceLocation FCL,
710                                             SourceLocation RPL)
711: Stmt(ObjCForCollectionStmtClass) {
712  SubExprs[ELEM] = Elem;
713  SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect);
714  SubExprs[BODY] = Body;
715  ForLoc = FCL;
716  RParenLoc = RPL;
717}
718
719ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
720                             Stmt **CatchStmts, unsigned NumCatchStmts,
721                             Stmt *atFinallyStmt)
722  : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc),
723    NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != 0)
724{
725  Stmt **Stmts = getStmts();
726  Stmts[0] = atTryStmt;
727  for (unsigned I = 0; I != NumCatchStmts; ++I)
728    Stmts[I + 1] = CatchStmts[I];
729
730  if (HasFinally)
731    Stmts[NumCatchStmts + 1] = atFinallyStmt;
732}
733
734ObjCAtTryStmt *ObjCAtTryStmt::Create(ASTContext &Context,
735                                     SourceLocation atTryLoc,
736                                     Stmt *atTryStmt,
737                                     Stmt **CatchStmts,
738                                     unsigned NumCatchStmts,
739                                     Stmt *atFinallyStmt) {
740  unsigned Size = sizeof(ObjCAtTryStmt) +
741    (1 + NumCatchStmts + (atFinallyStmt != 0)) * sizeof(Stmt *);
742  void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
743  return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts,
744                                 atFinallyStmt);
745}
746
747ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(ASTContext &Context,
748                                                 unsigned NumCatchStmts,
749                                                 bool HasFinally) {
750  unsigned Size = sizeof(ObjCAtTryStmt) +
751    (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *);
752  void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
753  return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally);
754}
755
756SourceLocation ObjCAtTryStmt::getLocEnd() const {
757  if (HasFinally)
758    return getFinallyStmt()->getLocEnd();
759  if (NumCatchStmts)
760    return getCatchStmt(NumCatchStmts - 1)->getLocEnd();
761  return getTryBody()->getLocEnd();
762}
763
764CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc,
765                               Stmt *tryBlock, ArrayRef<Stmt*> handlers) {
766  std::size_t Size = sizeof(CXXTryStmt);
767  Size += ((handlers.size() + 1) * sizeof(Stmt));
768
769  void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
770  return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers);
771}
772
773CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty,
774                               unsigned numHandlers) {
775  std::size_t Size = sizeof(CXXTryStmt);
776  Size += ((numHandlers + 1) * sizeof(Stmt));
777
778  void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
779  return new (Mem) CXXTryStmt(Empty, numHandlers);
780}
781
782CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
783                       ArrayRef<Stmt*> handlers)
784  : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(handlers.size()) {
785  Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
786  Stmts[0] = tryBlock;
787  std::copy(handlers.begin(), handlers.end(), Stmts + 1);
788}
789
790CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt,
791                                 Expr *Cond, Expr *Inc, DeclStmt *LoopVar,
792                                 Stmt *Body, SourceLocation FL,
793                                 SourceLocation CL, SourceLocation RPL)
794  : Stmt(CXXForRangeStmtClass), ForLoc(FL), ColonLoc(CL), RParenLoc(RPL) {
795  SubExprs[RANGE] = Range;
796  SubExprs[BEGINEND] = BeginEndStmt;
797  SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
798  SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
799  SubExprs[LOOPVAR] = LoopVar;
800  SubExprs[BODY] = Body;
801}
802
803Expr *CXXForRangeStmt::getRangeInit() {
804  DeclStmt *RangeStmt = getRangeStmt();
805  VarDecl *RangeDecl = dyn_cast_or_null<VarDecl>(RangeStmt->getSingleDecl());
806  assert(RangeDecl &&& "for-range should have a single var decl");
807  return RangeDecl->getInit();
808}
809
810const Expr *CXXForRangeStmt::getRangeInit() const {
811  return const_cast<CXXForRangeStmt*>(this)->getRangeInit();
812}
813
814VarDecl *CXXForRangeStmt::getLoopVariable() {
815  Decl *LV = cast<DeclStmt>(getLoopVarStmt())->getSingleDecl();
816  assert(LV && "No loop variable in CXXForRangeStmt");
817  return cast<VarDecl>(LV);
818}
819
820const VarDecl *CXXForRangeStmt::getLoopVariable() const {
821  return const_cast<CXXForRangeStmt*>(this)->getLoopVariable();
822}
823
824IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
825               Stmt *then, SourceLocation EL, Stmt *elsev)
826  : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL)
827{
828  setConditionVariable(C, var);
829  SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
830  SubExprs[THEN] = then;
831  SubExprs[ELSE] = elsev;
832}
833
834VarDecl *IfStmt::getConditionVariable() const {
835  if (!SubExprs[VAR])
836    return 0;
837
838  DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
839  return cast<VarDecl>(DS->getSingleDecl());
840}
841
842void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
843  if (!V) {
844    SubExprs[VAR] = 0;
845    return;
846  }
847
848  SourceRange VarRange = V->getSourceRange();
849  SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
850                                   VarRange.getEnd());
851}
852
853ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
854                 Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
855                 SourceLocation RP)
856  : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP)
857{
858  SubExprs[INIT] = Init;
859  setConditionVariable(C, condVar);
860  SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
861  SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
862  SubExprs[BODY] = Body;
863}
864
865VarDecl *ForStmt::getConditionVariable() const {
866  if (!SubExprs[CONDVAR])
867    return 0;
868
869  DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
870  return cast<VarDecl>(DS->getSingleDecl());
871}
872
873void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
874  if (!V) {
875    SubExprs[CONDVAR] = 0;
876    return;
877  }
878
879  SourceRange VarRange = V->getSourceRange();
880  SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
881                                       VarRange.getEnd());
882}
883
884SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond)
885  : Stmt(SwitchStmtClass), FirstCase(0), AllEnumCasesCovered(0)
886{
887  setConditionVariable(C, Var);
888  SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
889  SubExprs[BODY] = NULL;
890}
891
892VarDecl *SwitchStmt::getConditionVariable() const {
893  if (!SubExprs[VAR])
894    return 0;
895
896  DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
897  return cast<VarDecl>(DS->getSingleDecl());
898}
899
900void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
901  if (!V) {
902    SubExprs[VAR] = 0;
903    return;
904  }
905
906  SourceRange VarRange = V->getSourceRange();
907  SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
908                                   VarRange.getEnd());
909}
910
911Stmt *SwitchCase::getSubStmt() {
912  if (isa<CaseStmt>(this))
913    return cast<CaseStmt>(this)->getSubStmt();
914  return cast<DefaultStmt>(this)->getSubStmt();
915}
916
917WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
918                     SourceLocation WL)
919  : Stmt(WhileStmtClass) {
920  setConditionVariable(C, Var);
921  SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
922  SubExprs[BODY] = body;
923  WhileLoc = WL;
924}
925
926VarDecl *WhileStmt::getConditionVariable() const {
927  if (!SubExprs[VAR])
928    return 0;
929
930  DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
931  return cast<VarDecl>(DS->getSingleDecl());
932}
933
934void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
935  if (!V) {
936    SubExprs[VAR] = 0;
937    return;
938  }
939
940  SourceRange VarRange = V->getSourceRange();
941  SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
942                                   VarRange.getEnd());
943}
944
945// IndirectGotoStmt
946LabelDecl *IndirectGotoStmt::getConstantTarget() {
947  if (AddrLabelExpr *E =
948        dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
949    return E->getLabel();
950  return 0;
951}
952
953// ReturnStmt
954const Expr* ReturnStmt::getRetValue() const {
955  return cast_or_null<Expr>(RetExpr);
956}
957Expr* ReturnStmt::getRetValue() {
958  return cast_or_null<Expr>(RetExpr);
959}
960
961SEHTryStmt::SEHTryStmt(bool IsCXXTry,
962                       SourceLocation TryLoc,
963                       Stmt *TryBlock,
964                       Stmt *Handler)
965  : Stmt(SEHTryStmtClass),
966    IsCXXTry(IsCXXTry),
967    TryLoc(TryLoc)
968{
969  Children[TRY]     = TryBlock;
970  Children[HANDLER] = Handler;
971}
972
973SEHTryStmt* SEHTryStmt::Create(ASTContext &C,
974                               bool IsCXXTry,
975                               SourceLocation TryLoc,
976                               Stmt *TryBlock,
977                               Stmt *Handler) {
978  return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler);
979}
980
981SEHExceptStmt* SEHTryStmt::getExceptHandler() const {
982  return dyn_cast<SEHExceptStmt>(getHandler());
983}
984
985SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const {
986  return dyn_cast<SEHFinallyStmt>(getHandler());
987}
988
989SEHExceptStmt::SEHExceptStmt(SourceLocation Loc,
990                             Expr *FilterExpr,
991                             Stmt *Block)
992  : Stmt(SEHExceptStmtClass),
993    Loc(Loc)
994{
995  Children[FILTER_EXPR] = reinterpret_cast<Stmt*>(FilterExpr);
996  Children[BLOCK]       = Block;
997}
998
999SEHExceptStmt* SEHExceptStmt::Create(ASTContext &C,
1000                                     SourceLocation Loc,
1001                                     Expr *FilterExpr,
1002                                     Stmt *Block) {
1003  return new(C) SEHExceptStmt(Loc,FilterExpr,Block);
1004}
1005
1006SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc,
1007                               Stmt *Block)
1008  : Stmt(SEHFinallyStmtClass),
1009    Loc(Loc),
1010    Block(Block)
1011{}
1012
1013SEHFinallyStmt* SEHFinallyStmt::Create(ASTContext &C,
1014                                       SourceLocation Loc,
1015                                       Stmt *Block) {
1016  return new(C)SEHFinallyStmt(Loc,Block);
1017}
1018
1019CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const {
1020  unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
1021
1022  // Offset of the first Capture object.
1023  unsigned FirstCaptureOffset =
1024    llvm::RoundUpToAlignment(Size, llvm::alignOf<Capture>());
1025
1026  return reinterpret_cast<Capture *>(
1027      reinterpret_cast<char *>(const_cast<CapturedStmt *>(this))
1028      + FirstCaptureOffset);
1029}
1030
1031CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind,
1032                           ArrayRef<Capture> Captures,
1033                           ArrayRef<Expr *> CaptureInits,
1034                           CapturedDecl *CD,
1035                           RecordDecl *RD)
1036  : Stmt(CapturedStmtClass), NumCaptures(Captures.size()),
1037    CapDeclAndKind(CD, Kind), TheRecordDecl(RD) {
1038  assert( S && "null captured statement");
1039  assert(CD && "null captured declaration for captured statement");
1040  assert(RD && "null record declaration for captured statement");
1041
1042  // Copy initialization expressions.
1043  Stmt **Stored = getStoredStmts();
1044  for (unsigned I = 0, N = NumCaptures; I != N; ++I)
1045    *Stored++ = CaptureInits[I];
1046
1047  // Copy the statement being captured.
1048  *Stored = S;
1049
1050  // Copy all Capture objects.
1051  Capture *Buffer = getStoredCaptures();
1052  std::copy(Captures.begin(), Captures.end(), Buffer);
1053}
1054
1055CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures)
1056  : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures),
1057    CapDeclAndKind(0, CR_Default), TheRecordDecl(0) {
1058  getStoredStmts()[NumCaptures] = 0;
1059}
1060
1061CapturedStmt *CapturedStmt::Create(ASTContext &Context, Stmt *S,
1062                                   CapturedRegionKind Kind,
1063                                   ArrayRef<Capture> Captures,
1064                                   ArrayRef<Expr *> CaptureInits,
1065                                   CapturedDecl *CD,
1066                                   RecordDecl *RD) {
1067  // The layout is
1068  //
1069  // -----------------------------------------------------------
1070  // | CapturedStmt, Init, ..., Init, S, Capture, ..., Capture |
1071  // ----------------^-------------------^----------------------
1072  //                 getStoredStmts()    getStoredCaptures()
1073  //
1074  // where S is the statement being captured.
1075  //
1076  assert(CaptureInits.size() == Captures.size() && "wrong number of arguments");
1077
1078  unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1);
1079  if (!Captures.empty()) {
1080    // Realign for the following Capture array.
1081    Size = llvm::RoundUpToAlignment(Size, llvm::alignOf<Capture>());
1082    Size += sizeof(Capture) * Captures.size();
1083  }
1084
1085  void *Mem = Context.Allocate(Size);
1086  return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD);
1087}
1088
1089CapturedStmt *CapturedStmt::CreateDeserialized(ASTContext &Context,
1090                                               unsigned NumCaptures) {
1091  unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
1092  if (NumCaptures > 0) {
1093    // Realign for the following Capture array.
1094    Size = llvm::RoundUpToAlignment(Size, llvm::alignOf<Capture>());
1095    Size += sizeof(Capture) * NumCaptures;
1096  }
1097
1098  void *Mem = Context.Allocate(Size);
1099  return new (Mem) CapturedStmt(EmptyShell(), NumCaptures);
1100}
1101
1102Stmt::child_range CapturedStmt::children() {
1103  // Children are captured field initilizers.
1104  return child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
1105}
1106
1107bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
1108  for (const_capture_iterator I = capture_begin(),
1109                              E = capture_end(); I != E; ++I) {
1110    if (!I->capturesVariable())
1111      continue;
1112
1113    // This does not handle variable redeclarations. This should be
1114    // extended to capture variables with redeclarations, for example
1115    // a thread-private variable in OpenMP.
1116    if (I->getCapturedVar() == Var)
1117      return true;
1118  }
1119
1120  return false;
1121}
1122
1123OMPPrivateClause *OMPPrivateClause::Create(ASTContext &C,
1124                                           SourceLocation StartLoc,
1125                                           SourceLocation LParenLoc,
1126                                           SourceLocation EndLoc,
1127                                           ArrayRef<Expr *> VL) {
1128  void *Mem = C.Allocate(sizeof(OMPPrivateClause) + sizeof(Expr *) * VL.size(),
1129                         llvm::alignOf<OMPPrivateClause>());
1130  OMPPrivateClause *Clause = new (Mem) OMPPrivateClause(StartLoc, LParenLoc,
1131                                                        EndLoc, VL.size());
1132  Clause->setVarRefs(VL);
1133  return Clause;
1134}
1135
1136OMPPrivateClause *OMPPrivateClause::CreateEmpty(ASTContext &C,
1137                                                unsigned N) {
1138  void *Mem = C.Allocate(sizeof(OMPPrivateClause) + sizeof(Expr *) * N,
1139                         llvm::alignOf<OMPPrivateClause>());
1140  return new (Mem) OMPPrivateClause(N);
1141}
1142
1143void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
1144  assert(Clauses.size() == this->Clauses.size() &&
1145         "Number of clauses is not the same as the preallocated buffer");
1146  std::copy(Clauses.begin(), Clauses.end(), this->Clauses.begin());
1147}
1148
1149OMPParallelDirective *OMPParallelDirective::Create(
1150                                              ASTContext &C,
1151                                              SourceLocation StartLoc,
1152                                              SourceLocation EndLoc,
1153                                              ArrayRef<OMPClause *> Clauses,
1154                                              Stmt *AssociatedStmt) {
1155  void *Mem = C.Allocate(sizeof(OMPParallelDirective) +
1156                         sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *),
1157                         llvm::alignOf<OMPParallelDirective>());
1158  OMPParallelDirective *Dir = new (Mem) OMPParallelDirective(StartLoc, EndLoc,
1159                                                             Clauses.size());
1160  Dir->setClauses(Clauses);
1161  Dir->setAssociatedStmt(AssociatedStmt);
1162  return Dir;
1163}
1164
1165OMPParallelDirective *OMPParallelDirective::CreateEmpty(ASTContext &C,
1166                                                        unsigned N,
1167                                                        EmptyShell) {
1168  void *Mem = C.Allocate(sizeof(OMPParallelDirective) +
1169                         sizeof(OMPClause *) * N + sizeof(Stmt *),
1170                         llvm::alignOf<OMPParallelDirective>());
1171  return new (Mem) OMPParallelDirective(N);
1172}
1173