1249261Sdim//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ----------===//
2249261Sdim//
3249261Sdim//                     The LLVM Compiler Infrastructure
4249261Sdim//
5249261Sdim// This file is distributed under the University of Illinois Open Source
6249261Sdim// License. See LICENSE.TXT for details.
7249261Sdim//
8249261Sdim//===----------------------------------------------------------------------===//
9249261Sdim/// \file
10249261Sdim/// \brief This file implements semantic analysis for OpenMP directives and
11263508Sdim/// clauses.
12249261Sdim///
13249261Sdim//===----------------------------------------------------------------------===//
14249261Sdim
15249261Sdim#include "clang/Basic/OpenMPKinds.h"
16249261Sdim#include "clang/AST/Decl.h"
17263508Sdim#include "clang/AST/DeclCXX.h"
18249261Sdim#include "clang/AST/DeclOpenMP.h"
19263508Sdim#include "clang/AST/StmtCXX.h"
20263508Sdim#include "clang/AST/StmtOpenMP.h"
21263508Sdim#include "clang/AST/StmtVisitor.h"
22249261Sdim#include "clang/Lex/Preprocessor.h"
23263508Sdim#include "clang/Sema/Initialization.h"
24249261Sdim#include "clang/Sema/SemaInternal.h"
25249261Sdim#include "clang/Sema/Lookup.h"
26263508Sdim#include "clang/Sema/Scope.h"
27263508Sdim#include "clang/Sema/ScopeInfo.h"
28249261Sdimusing namespace clang;
29249261Sdim
30263508Sdim//===----------------------------------------------------------------------===//
31263508Sdim// Stack of data-sharing attributes for variables
32263508Sdim//===----------------------------------------------------------------------===//
33263508Sdim
34249261Sdimnamespace {
35263508Sdim/// \brief Default data sharing attributes, which can be applied to directive.
36263508Sdimenum DefaultDataSharingAttributes {
37263508Sdim  DSA_unspecified = 0,   /// \brief Data sharing attribute not specified.
38263508Sdim  DSA_none = 1 << 0,     /// \brief Default data sharing attribute 'none'.
39263508Sdim  DSA_shared = 1 << 1    /// \brief Default data sharing attribute 'shared'.
40263508Sdim};
41249261Sdim
42263508Sdim/// \brief Stack for tracking declarations used in OpenMP directives and
43263508Sdim/// clauses and their data-sharing attributes.
44263508Sdimclass DSAStackTy {
45263508Sdimpublic:
46263508Sdim  struct DSAVarData {
47263508Sdim    OpenMPDirectiveKind DKind;
48263508Sdim    OpenMPClauseKind CKind;
49263508Sdim    DeclRefExpr *RefExpr;
50263508Sdim    DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(0) { }
51263508Sdim  };
52263508Sdimprivate:
53263508Sdim  struct DSAInfo {
54263508Sdim    OpenMPClauseKind Attributes;
55263508Sdim    DeclRefExpr *RefExpr;
56263508Sdim  };
57263508Sdim  typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy;
58263508Sdim
59263508Sdim  struct SharingMapTy {
60263508Sdim    DeclSAMapTy SharingMap;
61263508Sdim    DefaultDataSharingAttributes DefaultAttr;
62263508Sdim    OpenMPDirectiveKind Directive;
63263508Sdim    DeclarationNameInfo DirectiveName;
64263508Sdim    Scope *CurScope;
65263508Sdim    SharingMapTy(OpenMPDirectiveKind DKind,
66263508Sdim                 const DeclarationNameInfo &Name,
67263508Sdim                 Scope *CurScope)
68263508Sdim      : SharingMap(), DefaultAttr(DSA_unspecified), Directive(DKind),
69263508Sdim        DirectiveName(Name), CurScope(CurScope) { }
70263508Sdim    SharingMapTy()
71263508Sdim      : SharingMap(), DefaultAttr(DSA_unspecified),
72263508Sdim        Directive(OMPD_unknown), DirectiveName(),
73263508Sdim        CurScope(0) { }
74263508Sdim  };
75263508Sdim
76263508Sdim  typedef SmallVector<SharingMapTy, 64> StackTy;
77263508Sdim
78263508Sdim  /// \brief Stack of used declaration and their data-sharing attributes.
79263508Sdim  StackTy Stack;
80263508Sdim  Sema &Actions;
81263508Sdim
82263508Sdim  typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
83263508Sdim
84263508Sdim  DSAVarData getDSA(StackTy::reverse_iterator Iter, VarDecl *D);
85263508Sdimpublic:
86263508Sdim  explicit DSAStackTy(Sema &S) : Stack(1), Actions(S) { }
87263508Sdim
88263508Sdim  void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
89263508Sdim            Scope *CurScope) {
90263508Sdim    Stack.push_back(SharingMapTy(DKind, DirName, CurScope));
91263508Sdim  }
92263508Sdim
93263508Sdim  void pop() {
94263508Sdim    assert(Stack.size() > 1 && "Data-sharing attributes stack is empty!");
95263508Sdim    Stack.pop_back();
96263508Sdim  }
97263508Sdim
98263508Sdim  /// \brief Adds explicit data sharing attribute to the specified declaration.
99263508Sdim  void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A);
100263508Sdim
101263508Sdim  /// \brief Checks if the variable is a local for OpenMP region.
102263508Sdim  bool isOpenMPLocal(VarDecl *D);
103263508Sdim
104263508Sdim  /// \brief Returns data sharing attributes from top of the stack for the
105263508Sdim  /// specified declaration.
106263508Sdim  DSAVarData getTopDSA(VarDecl *D);
107263508Sdim  /// \brief Returns data-sharing attributes for the specified declaration.
108263508Sdim  DSAVarData getImplicitDSA(VarDecl *D);
109263508Sdim  /// \brief Checks if the specified variables has \a CKind data-sharing
110263508Sdim  /// attribute in \a DKind directive.
111263508Sdim  DSAVarData hasDSA(VarDecl *D, OpenMPClauseKind CKind,
112263508Sdim                    OpenMPDirectiveKind DKind = OMPD_unknown);
113263508Sdim
114263508Sdim
115263508Sdim  /// \brief Returns currently analyzed directive.
116263508Sdim  OpenMPDirectiveKind getCurrentDirective() const {
117263508Sdim    return Stack.back().Directive;
118263508Sdim  }
119263508Sdim
120263508Sdim  /// \brief Set default data sharing attribute to none.
121263508Sdim  void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; }
122263508Sdim  /// \brief Set default data sharing attribute to shared.
123263508Sdim  void setDefaultDSAShared() { Stack.back().DefaultAttr = DSA_shared; }
124263508Sdim
125263508Sdim  DefaultDataSharingAttributes getDefaultDSA() const {
126263508Sdim    return Stack.back().DefaultAttr;
127263508Sdim  }
128263508Sdim
129263508Sdim  Scope *getCurScope() { return Stack.back().CurScope; }
130263508Sdim};
131263508Sdim} // end anonymous namespace.
132263508Sdim
133263508SdimDSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
134263508Sdim                                          VarDecl *D) {
135263508Sdim  DSAVarData DVar;
136263508Sdim  if (Iter == Stack.rend() - 1) {
137263508Sdim    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
138263508Sdim    // in a region but not in construct]
139263508Sdim    //  File-scope or namespace-scope variables referenced in called routines
140263508Sdim    //  in the region are shared unless they appear in a threadprivate
141263508Sdim    //  directive.
142263508Sdim    // TODO
143263508Sdim    if (!D->isFunctionOrMethodVarDecl())
144263508Sdim      DVar.CKind = OMPC_shared;
145263508Sdim
146263508Sdim    // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
147263508Sdim    // in a region but not in construct]
148263508Sdim    //  Variables with static storage duration that are declared in called
149263508Sdim    //  routines in the region are shared.
150263508Sdim    if (D->hasGlobalStorage())
151263508Sdim      DVar.CKind = OMPC_shared;
152263508Sdim
153263508Sdim    return DVar;
154263508Sdim  }
155263508Sdim  DVar.DKind = Iter->Directive;
156263508Sdim  // Explicitly specified attributes and local variables with predetermined
157263508Sdim  // attributes.
158263508Sdim  if (Iter->SharingMap.count(D)) {
159263508Sdim    DVar.RefExpr = Iter->SharingMap[D].RefExpr;
160263508Sdim    DVar.CKind = Iter->SharingMap[D].Attributes;
161263508Sdim    return DVar;
162263508Sdim  }
163263508Sdim
164263508Sdim  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
165263508Sdim  // in a Construct, C/C++, implicitly determined, p.1]
166263508Sdim  //  In a parallel or task construct, the data-sharing attributes of these
167263508Sdim  //  variables are determined by the default clause, if present.
168263508Sdim  switch (Iter->DefaultAttr) {
169263508Sdim  case DSA_shared:
170263508Sdim    DVar.CKind = OMPC_shared;
171263508Sdim    return DVar;
172263508Sdim  case DSA_none:
173263508Sdim    return DVar;
174263508Sdim  case DSA_unspecified:
175263508Sdim    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
176263508Sdim    // in a Construct, implicitly determined, p.2]
177263508Sdim    //  In a parallel construct, if no default clause is present, these
178263508Sdim    //  variables are shared.
179263508Sdim    if (DVar.DKind == OMPD_parallel) {
180263508Sdim      DVar.CKind = OMPC_shared;
181263508Sdim      return DVar;
182263508Sdim    }
183263508Sdim
184263508Sdim    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
185263508Sdim    // in a Construct, implicitly determined, p.4]
186263508Sdim    //  In a task construct, if no default clause is present, a variable that in
187263508Sdim    //  the enclosing context is determined to be shared by all implicit tasks
188263508Sdim    //  bound to the current team is shared.
189263508Sdim    // TODO
190263508Sdim    if (DVar.DKind == OMPD_task) {
191263508Sdim      DSAVarData DVarTemp;
192263508Sdim      for (StackTy::reverse_iterator I = Iter + 1,
193263508Sdim                                     EE = Stack.rend() - 1;
194263508Sdim           I != EE; ++I) {
195263508Sdim        // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
196263508Sdim        // in a Construct, implicitly determined, p.6]
197263508Sdim        //  In a task construct, if no default clause is present, a variable
198263508Sdim        //  whose data-sharing attribute is not determined by the rules above is
199263508Sdim        //  firstprivate.
200263508Sdim        DVarTemp = getDSA(I, D);
201263508Sdim        if (DVarTemp.CKind != OMPC_shared) {
202263508Sdim          DVar.RefExpr = 0;
203263508Sdim          DVar.DKind = OMPD_task;
204263508Sdim          DVar.CKind = OMPC_firstprivate;
205263508Sdim          return DVar;
206249261Sdim        }
207263508Sdim        if (I->Directive == OMPD_parallel) break;
208249261Sdim      }
209263508Sdim      DVar.DKind = OMPD_task;
210263508Sdim      DVar.CKind =
211263508Sdim        (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
212263508Sdim      return DVar;
213263508Sdim    }
214263508Sdim  }
215263508Sdim  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
216263508Sdim  // in a Construct, implicitly determined, p.3]
217263508Sdim  //  For constructs other than task, if no default clause is present, these
218263508Sdim  //  variables inherit their data-sharing attributes from the enclosing
219263508Sdim  //  context.
220263508Sdim  return getDSA(Iter + 1, D);
221249261Sdim}
222263508Sdim
223263508Sdimvoid DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
224263508Sdim  if (A == OMPC_threadprivate) {
225263508Sdim    Stack[0].SharingMap[D].Attributes = A;
226263508Sdim    Stack[0].SharingMap[D].RefExpr = E;
227263508Sdim  } else {
228263508Sdim    assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
229263508Sdim    Stack.back().SharingMap[D].Attributes = A;
230263508Sdim    Stack.back().SharingMap[D].RefExpr = E;
231263508Sdim  }
232263508Sdim}
233263508Sdim
234263508Sdimbool DSAStackTy::isOpenMPLocal(VarDecl *D) {
235263508Sdim  Scope *CurScope = getCurScope();
236263508Sdim  while (CurScope && !CurScope->isDeclScope(D))
237263508Sdim    CurScope = CurScope->getParent();
238263508Sdim  while (CurScope && !CurScope->isOpenMPDirectiveScope())
239263508Sdim    CurScope = CurScope->getParent();
240263508Sdim  bool isOpenMPLocal = !!CurScope;
241263508Sdim  if (!isOpenMPLocal) {
242263508Sdim    CurScope = getCurScope();
243263508Sdim    while (CurScope && !CurScope->isOpenMPDirectiveScope())
244263508Sdim      CurScope = CurScope->getParent();
245263508Sdim    isOpenMPLocal =
246263508Sdim      CurScope &&
247263508Sdim      isa<CapturedDecl>(D->getDeclContext()) &&
248263508Sdim      CurScope->getFnParent()->getEntity()->Encloses(D->getDeclContext());
249263508Sdim  }
250263508Sdim  return isOpenMPLocal;
251263508Sdim}
252263508Sdim
253263508SdimDSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
254263508Sdim  DSAVarData DVar;
255263508Sdim
256263508Sdim  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
257263508Sdim  // in a Construct, C/C++, predetermined, p.1]
258263508Sdim  //  Variables appearing in threadprivate directives are threadprivate.
259263508Sdim  if (D->getTLSKind() != VarDecl::TLS_None) {
260263508Sdim    DVar.CKind = OMPC_threadprivate;
261263508Sdim    return DVar;
262263508Sdim  }
263263508Sdim  if (Stack[0].SharingMap.count(D)) {
264263508Sdim    DVar.RefExpr = Stack[0].SharingMap[D].RefExpr;
265263508Sdim    DVar.CKind = OMPC_threadprivate;
266263508Sdim    return DVar;
267263508Sdim  }
268263508Sdim
269263508Sdim  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
270263508Sdim  // in a Construct, C/C++, predetermined, p.1]
271263508Sdim  // Variables with automatic storage duration that are declared in a scope
272263508Sdim  // inside the construct are private.
273263508Sdim  if (isOpenMPLocal(D) && D->isLocalVarDecl() &&
274263508Sdim      (D->getStorageClass() == SC_Auto ||
275263508Sdim       D->getStorageClass() == SC_None)) {
276263508Sdim    DVar.CKind = OMPC_private;
277263508Sdim    return DVar;
278263508Sdim  }
279263508Sdim
280263508Sdim  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
281263508Sdim  // in a Construct, C/C++, predetermined, p.4]
282263508Sdim  //  Static data memebers are shared.
283263508Sdim  if (D->isStaticDataMember()) {
284263508Sdim    // Variables with const-qualified type having no mutable member may be listed
285263508Sdim    // in a firstprivate clause, even if they are static data members.
286263508Sdim    DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate);
287263508Sdim    if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
288263508Sdim      return DVar;
289263508Sdim
290263508Sdim    DVar.CKind = OMPC_shared;
291263508Sdim    return DVar;
292263508Sdim  }
293263508Sdim
294263508Sdim  QualType Type = D->getType().getNonReferenceType().getCanonicalType();
295263508Sdim  bool IsConstant = Type.isConstant(Actions.getASTContext());
296263508Sdim  while (Type->isArrayType()) {
297263508Sdim    QualType ElemType = cast<ArrayType>(Type.getTypePtr())->getElementType();
298263508Sdim    Type = ElemType.getNonReferenceType().getCanonicalType();
299263508Sdim  }
300263508Sdim  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
301263508Sdim  // in a Construct, C/C++, predetermined, p.6]
302263508Sdim  //  Variables with const qualified type having no mutable member are
303263508Sdim  //  shared.
304263508Sdim  CXXRecordDecl *RD = Actions.getLangOpts().CPlusPlus ?
305263508Sdim                                Type->getAsCXXRecordDecl() : 0;
306263508Sdim  if (IsConstant &&
307263508Sdim      !(Actions.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) {
308263508Sdim    // Variables with const-qualified type having no mutable member may be
309263508Sdim    // listed in a firstprivate clause, even if they are static data members.
310263508Sdim    DSAVarData DVarTemp = hasDSA(D, OMPC_firstprivate);
311263508Sdim    if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr)
312263508Sdim      return DVar;
313263508Sdim
314263508Sdim    DVar.CKind = OMPC_shared;
315263508Sdim    return DVar;
316263508Sdim  }
317263508Sdim
318263508Sdim  // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
319263508Sdim  // in a Construct, C/C++, predetermined, p.7]
320263508Sdim  //  Variables with static storage duration that are declared in a scope
321263508Sdim  //  inside the construct are shared.
322263508Sdim  if (isOpenMPLocal(D) && D->isStaticLocal()) {
323263508Sdim    DVar.CKind = OMPC_shared;
324263508Sdim    return DVar;
325263508Sdim  }
326263508Sdim
327263508Sdim  // Explicitly specified attributes and local variables with predetermined
328263508Sdim  // attributes.
329263508Sdim  if (Stack.back().SharingMap.count(D)) {
330263508Sdim    DVar.RefExpr = Stack.back().SharingMap[D].RefExpr;
331263508Sdim    DVar.CKind = Stack.back().SharingMap[D].Attributes;
332263508Sdim  }
333263508Sdim
334263508Sdim  return DVar;
335263508Sdim}
336263508Sdim
337263508SdimDSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D) {
338263508Sdim  return getDSA(Stack.rbegin() + 1, D);
339263508Sdim}
340263508Sdim
341263508SdimDSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, OpenMPClauseKind CKind,
342263508Sdim                                          OpenMPDirectiveKind DKind) {
343263508Sdim  for (StackTy::reverse_iterator I = Stack.rbegin() + 1,
344263508Sdim                                 E = Stack.rend() - 1;
345249261Sdim       I != E; ++I) {
346263508Sdim    if (DKind != OMPD_unknown && DKind != I->Directive) continue;
347263508Sdim    DSAVarData DVar = getDSA(I, D);
348263508Sdim    if (DVar.CKind == CKind)
349263508Sdim      return DVar;
350263508Sdim  }
351263508Sdim  return DSAVarData();
352263508Sdim}
353249261Sdim
354263508Sdimvoid Sema::InitDataSharingAttributesStack() {
355263508Sdim  VarDataSharingAttributesStack = new DSAStackTy(*this);
356263508Sdim}
357249261Sdim
358263508Sdim#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
359263508Sdim
360263508Sdimvoid Sema::DestroyDataSharingAttributesStack() {
361263508Sdim  delete DSAStack;
362263508Sdim}
363263508Sdim
364263508Sdimvoid Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
365263508Sdim                               const DeclarationNameInfo &DirName,
366263508Sdim                               Scope *CurScope) {
367263508Sdim  DSAStack->push(DKind, DirName, CurScope);
368263508Sdim  PushExpressionEvaluationContext(PotentiallyEvaluated);
369263508Sdim}
370263508Sdim
371263508Sdimvoid Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
372263508Sdim  DSAStack->pop();
373263508Sdim  DiscardCleanupsInEvaluationContext();
374263508Sdim  PopExpressionEvaluationContext();
375263508Sdim}
376263508Sdim
377263508Sdimnamespace {
378263508Sdim
379263508Sdimclass VarDeclFilterCCC : public CorrectionCandidateCallback {
380263508Sdimprivate:
381263508Sdim  Sema &Actions;
382263508Sdimpublic:
383263508Sdim  VarDeclFilterCCC(Sema &S) : Actions(S) { }
384263508Sdim  virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
385263508Sdim    NamedDecl *ND = Candidate.getCorrectionDecl();
386263508Sdim    if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
387263508Sdim      return VD->hasGlobalStorage() &&
388263508Sdim             Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
389263508Sdim                                   Actions.getCurScope());
390263508Sdim    }
391263508Sdim    return false;
392263508Sdim  }
393263508Sdim};
394263508Sdim}
395263508Sdim
396263508SdimExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
397263508Sdim                                         CXXScopeSpec &ScopeSpec,
398263508Sdim                                         const DeclarationNameInfo &Id) {
399263508Sdim  LookupResult Lookup(*this, Id, LookupOrdinaryName);
400263508Sdim  LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
401263508Sdim
402263508Sdim  if (Lookup.isAmbiguous())
403263508Sdim    return ExprError();
404263508Sdim
405263508Sdim  VarDecl *VD;
406263508Sdim  if (!Lookup.isSingleResult()) {
407263508Sdim    VarDeclFilterCCC Validator(*this);
408263508Sdim    if (TypoCorrection Corrected = CorrectTypo(Id, LookupOrdinaryName, CurScope,
409263508Sdim                                               0, Validator)) {
410263508Sdim      diagnoseTypo(Corrected,
411263508Sdim                   PDiag(Lookup.empty()? diag::err_undeclared_var_use_suggest
412263508Sdim                                       : diag::err_omp_expected_var_arg_suggest)
413263508Sdim                     << Id.getName());
414249261Sdim      VD = Corrected.getCorrectionDeclAs<VarDecl>();
415249261Sdim    } else {
416263508Sdim      Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
417263508Sdim                                       : diag::err_omp_expected_var_arg)
418263508Sdim          << Id.getName();
419263508Sdim      return ExprError();
420249261Sdim    }
421263508Sdim  } else {
422263508Sdim    if (!(VD = Lookup.getAsSingle<VarDecl>())) {
423263508Sdim      Diag(Id.getLoc(), diag::err_omp_expected_var_arg)
424263508Sdim        << Id.getName();
425263508Sdim      Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
426263508Sdim      return ExprError();
427249261Sdim    }
428263508Sdim  }
429263508Sdim  Lookup.suppressDiagnostics();
430249261Sdim
431263508Sdim  // OpenMP [2.9.2, Syntax, C/C++]
432263508Sdim  //   Variables must be file-scope, namespace-scope, or static block-scope.
433263508Sdim  if (!VD->hasGlobalStorage()) {
434263508Sdim    Diag(Id.getLoc(), diag::err_omp_global_var_arg)
435263508Sdim      << getOpenMPDirectiveName(OMPD_threadprivate)
436263508Sdim      << !VD->isStaticLocal();
437263508Sdim    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
438263508Sdim                  VarDecl::DeclarationOnly;
439263508Sdim    Diag(VD->getLocation(),
440263508Sdim         IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD;
441263508Sdim    return ExprError();
442263508Sdim  }
443249261Sdim
444263508Sdim  VarDecl *CanonicalVD = VD->getCanonicalDecl();
445263508Sdim  NamedDecl *ND = cast<NamedDecl>(CanonicalVD);
446263508Sdim  // OpenMP [2.9.2, Restrictions, C/C++, p.2]
447263508Sdim  //   A threadprivate directive for file-scope variables must appear outside
448263508Sdim  //   any definition or declaration.
449263508Sdim  if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
450263508Sdim      !getCurLexicalContext()->isTranslationUnit()) {
451263508Sdim    Diag(Id.getLoc(), diag::err_omp_var_scope)
452263508Sdim      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
453263508Sdim    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
454263508Sdim                  VarDecl::DeclarationOnly;
455263508Sdim    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
456263508Sdim                                     diag::note_defined_here) << VD;
457263508Sdim    return ExprError();
458263508Sdim  }
459263508Sdim  // OpenMP [2.9.2, Restrictions, C/C++, p.3]
460263508Sdim  //   A threadprivate directive for static class member variables must appear
461263508Sdim  //   in the class definition, in the same scope in which the member
462263508Sdim  //   variables are declared.
463263508Sdim  if (CanonicalVD->isStaticDataMember() &&
464263508Sdim      !CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
465263508Sdim    Diag(Id.getLoc(), diag::err_omp_var_scope)
466263508Sdim      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
467263508Sdim    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
468263508Sdim                  VarDecl::DeclarationOnly;
469263508Sdim    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
470263508Sdim                                     diag::note_defined_here) << VD;
471263508Sdim    return ExprError();
472263508Sdim  }
473263508Sdim  // OpenMP [2.9.2, Restrictions, C/C++, p.4]
474263508Sdim  //   A threadprivate directive for namespace-scope variables must appear
475263508Sdim  //   outside any definition or declaration other than the namespace
476263508Sdim  //   definition itself.
477263508Sdim  if (CanonicalVD->getDeclContext()->isNamespace() &&
478263508Sdim      (!getCurLexicalContext()->isFileContext() ||
479263508Sdim       !getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
480263508Sdim    Diag(Id.getLoc(), diag::err_omp_var_scope)
481263508Sdim      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
482263508Sdim    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
483263508Sdim                  VarDecl::DeclarationOnly;
484263508Sdim    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
485263508Sdim                                     diag::note_defined_here) << VD;
486263508Sdim    return ExprError();
487263508Sdim  }
488263508Sdim  // OpenMP [2.9.2, Restrictions, C/C++, p.6]
489263508Sdim  //   A threadprivate directive for static block-scope variables must appear
490263508Sdim  //   in the scope of the variable and not in a nested scope.
491263508Sdim  if (CanonicalVD->isStaticLocal() && CurScope &&
492263508Sdim      !isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
493263508Sdim    Diag(Id.getLoc(), diag::err_omp_var_scope)
494263508Sdim      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
495263508Sdim    bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
496263508Sdim                  VarDecl::DeclarationOnly;
497263508Sdim    Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
498263508Sdim                                     diag::note_defined_here) << VD;
499263508Sdim    return ExprError();
500263508Sdim  }
501249261Sdim
502263508Sdim  // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
503263508Sdim  //   A threadprivate directive must lexically precede all references to any
504263508Sdim  //   of the variables in its list.
505263508Sdim  if (VD->isUsed()) {
506263508Sdim    Diag(Id.getLoc(), diag::err_omp_var_used)
507263508Sdim      << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
508263508Sdim    return ExprError();
509249261Sdim  }
510263508Sdim
511263508Sdim  QualType ExprType = VD->getType().getNonReferenceType();
512263508Sdim  ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_RValue, Id.getLoc());
513263508Sdim  DSAStack->addDSA(VD, cast<DeclRefExpr>(DE.get()), OMPC_threadprivate);
514263508Sdim  return DE;
515263508Sdim}
516263508Sdim
517263508SdimSema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
518263508Sdim                                SourceLocation Loc,
519263508Sdim                                ArrayRef<Expr *> VarList) {
520263508Sdim  if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
521249261Sdim    CurContext->addDecl(D);
522249261Sdim    return DeclGroupPtrTy::make(DeclGroupRef(D));
523249261Sdim  }
524249261Sdim  return DeclGroupPtrTy();
525249261Sdim}
526249261Sdim
527249261SdimOMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
528249261Sdim                                 SourceLocation Loc,
529263508Sdim                                 ArrayRef<Expr *> VarList) {
530263508Sdim  SmallVector<Expr *, 8> Vars;
531263508Sdim  for (ArrayRef<Expr *>::iterator I = VarList.begin(),
532249261Sdim                                         E = VarList.end();
533249261Sdim       I != E; ++I) {
534263508Sdim    DeclRefExpr *DE = cast<DeclRefExpr>(*I);
535263508Sdim    VarDecl *VD = cast<VarDecl>(DE->getDecl());
536263508Sdim    SourceLocation ILoc = DE->getExprLoc();
537249261Sdim
538249261Sdim    // OpenMP [2.9.2, Restrictions, C/C++, p.10]
539249261Sdim    //   A threadprivate variable must not have an incomplete type.
540249261Sdim    if (RequireCompleteType(ILoc, VD->getType(),
541263508Sdim                            diag::err_omp_threadprivate_incomplete_type)) {
542249261Sdim      continue;
543249261Sdim    }
544249261Sdim
545249261Sdim    // OpenMP [2.9.2, Restrictions, C/C++, p.10]
546249261Sdim    //   A threadprivate variable must not have a reference type.
547249261Sdim    if (VD->getType()->isReferenceType()) {
548249261Sdim      Diag(ILoc, diag::err_omp_ref_type_arg)
549263508Sdim        << getOpenMPDirectiveName(OMPD_threadprivate)
550263508Sdim        << VD->getType();
551263508Sdim      bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
552263508Sdim                    VarDecl::DeclarationOnly;
553263508Sdim      Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
554263508Sdim                                       diag::note_defined_here) << VD;
555249261Sdim      continue;
556249261Sdim    }
557249261Sdim
558251662Sdim    // Check if this is a TLS variable.
559251662Sdim    if (VD->getTLSKind()) {
560249261Sdim      Diag(ILoc, diag::err_omp_var_thread_local) << VD;
561263508Sdim      bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
562263508Sdim                    VarDecl::DeclarationOnly;
563263508Sdim      Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
564263508Sdim                                       diag::note_defined_here) << VD;
565249261Sdim      continue;
566249261Sdim    }
567249261Sdim
568249261Sdim    Vars.push_back(*I);
569249261Sdim  }
570249261Sdim  return Vars.empty() ?
571249261Sdim              0 : OMPThreadPrivateDecl::Create(Context,
572249261Sdim                                               getCurLexicalContext(),
573249261Sdim                                               Loc, Vars);
574249261Sdim}
575263508Sdim
576263508Sdimnamespace {
577263508Sdimclass DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> {
578263508Sdim  DSAStackTy *Stack;
579263508Sdim  Sema &Actions;
580263508Sdim  bool ErrorFound;
581263508Sdim  CapturedStmt *CS;
582263508Sdim  llvm::SmallVector<Expr *, 8> ImplicitFirstprivate;
583263508Sdimpublic:
584263508Sdim  void VisitDeclRefExpr(DeclRefExpr *E) {
585263508Sdim    if(VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
586263508Sdim      // Skip internally declared variables.
587263508Sdim      if (VD->isLocalVarDecl() && !CS->capturesVariable(VD)) return;
588263508Sdim
589263508Sdim      SourceLocation ELoc = E->getExprLoc();
590263508Sdim
591263508Sdim      OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
592263508Sdim      DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
593263508Sdim      if (DVar.CKind != OMPC_unknown) {
594263508Sdim        if (DKind == OMPD_task && DVar.CKind != OMPC_shared &&
595263508Sdim            DVar.CKind != OMPC_threadprivate && !DVar.RefExpr)
596263508Sdim          ImplicitFirstprivate.push_back(DVar.RefExpr);
597263508Sdim        return;
598263508Sdim      }
599263508Sdim      // The default(none) clause requires that each variable that is referenced
600263508Sdim      // in the construct, and does not have a predetermined data-sharing
601263508Sdim      // attribute, must have its data-sharing attribute explicitly determined
602263508Sdim      // by being listed in a data-sharing attribute clause.
603263508Sdim      if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none &&
604263508Sdim          (DKind == OMPD_parallel || DKind == OMPD_task)) {
605263508Sdim        ErrorFound = true;
606263508Sdim        Actions.Diag(ELoc, diag::err_omp_no_dsa_for_variable) << VD;
607263508Sdim        return;
608263508Sdim      }
609263508Sdim
610263508Sdim      // OpenMP [2.9.3.6, Restrictions, p.2]
611263508Sdim      //  A list item that appears in a reduction clause of the innermost
612263508Sdim      //  enclosing worksharing or parallel construct may not be accessed in an
613263508Sdim      //  explicit task.
614263508Sdim      // TODO:
615263508Sdim
616263508Sdim      // Define implicit data-sharing attributes for task.
617263508Sdim      DVar = Stack->getImplicitDSA(VD);
618263508Sdim      if (DKind == OMPD_task && DVar.CKind != OMPC_shared)
619263508Sdim        ImplicitFirstprivate.push_back(DVar.RefExpr);
620263508Sdim    }
621263508Sdim  }
622263508Sdim  void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
623263508Sdim    for (ArrayRef<OMPClause *>::iterator I = S->clauses().begin(),
624263508Sdim                                         E = S->clauses().end();
625263508Sdim         I != E; ++I)
626263508Sdim      if (OMPClause *C = *I)
627263508Sdim        for (StmtRange R = C->children(); R; ++R)
628263508Sdim          if (Stmt *Child = *R)
629263508Sdim            Visit(Child);
630263508Sdim  }
631263508Sdim  void VisitStmt(Stmt *S) {
632263508Sdim    for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();
633263508Sdim         I != E; ++I)
634263508Sdim      if (Stmt *Child = *I)
635263508Sdim        if (!isa<OMPExecutableDirective>(Child))
636263508Sdim          Visit(Child);
637263508Sdim    }
638263508Sdim
639263508Sdim  bool isErrorFound() { return ErrorFound; }
640263508Sdim  ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; }
641263508Sdim
642263508Sdim  DSAAttrChecker(DSAStackTy *S, Sema &Actions, CapturedStmt *CS)
643263508Sdim    : Stack(S), Actions(Actions), ErrorFound(false), CS(CS) { }
644263508Sdim};
645263508Sdim}
646263508Sdim
647263508SdimStmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
648263508Sdim                                                ArrayRef<OMPClause *> Clauses,
649263508Sdim                                                Stmt *AStmt,
650263508Sdim                                                SourceLocation StartLoc,
651263508Sdim                                                SourceLocation EndLoc) {
652263508Sdim  assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected");
653263508Sdim
654263508Sdim  StmtResult Res = StmtError();
655263508Sdim
656263508Sdim  // Check default data sharing attributes for referenced variables.
657263508Sdim  DSAAttrChecker DSAChecker(DSAStack, *this, cast<CapturedStmt>(AStmt));
658263508Sdim  DSAChecker.Visit(cast<CapturedStmt>(AStmt)->getCapturedStmt());
659263508Sdim  if (DSAChecker.isErrorFound())
660263508Sdim    return StmtError();
661263508Sdim  // Generate list of implicitly defined firstprivate variables.
662263508Sdim  llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
663263508Sdim  ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
664263508Sdim
665263508Sdim  bool ErrorFound = false;
666263508Sdim  if (!DSAChecker.getImplicitFirstprivate().empty()) {
667263508Sdim    if (OMPClause *Implicit =
668263508Sdim         ActOnOpenMPFirstprivateClause(DSAChecker.getImplicitFirstprivate(),
669263508Sdim                                       SourceLocation(), SourceLocation(),
670263508Sdim                                       SourceLocation())) {
671263508Sdim      ClausesWithImplicit.push_back(Implicit);
672263508Sdim      ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
673263508Sdim                                    DSAChecker.getImplicitFirstprivate().size();
674263508Sdim    } else
675263508Sdim      ErrorFound = true;
676263508Sdim  }
677263508Sdim
678263508Sdim  switch (Kind) {
679263508Sdim  case OMPD_parallel:
680263508Sdim    Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt,
681263508Sdim                                       StartLoc, EndLoc);
682263508Sdim    break;
683263508Sdim  case OMPD_threadprivate:
684263508Sdim  case OMPD_task:
685263508Sdim    llvm_unreachable("OpenMP Directive is not allowed");
686263508Sdim  case OMPD_unknown:
687263508Sdim  case NUM_OPENMP_DIRECTIVES:
688263508Sdim    llvm_unreachable("Unknown OpenMP directive");
689263508Sdim  }
690263508Sdim
691263508Sdim  if (ErrorFound) return StmtError();
692263508Sdim  return Res;
693263508Sdim}
694263508Sdim
695263508SdimStmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
696263508Sdim                                              Stmt *AStmt,
697263508Sdim                                              SourceLocation StartLoc,
698263508Sdim                                              SourceLocation EndLoc) {
699263508Sdim  getCurFunction()->setHasBranchProtectedScope();
700263508Sdim
701263508Sdim  return Owned(OMPParallelDirective::Create(Context, StartLoc, EndLoc,
702263508Sdim                                            Clauses, AStmt));
703263508Sdim}
704263508Sdim
705263508SdimOMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
706263508Sdim                                         unsigned Argument,
707263508Sdim                                         SourceLocation ArgumentLoc,
708263508Sdim                                         SourceLocation StartLoc,
709263508Sdim                                         SourceLocation LParenLoc,
710263508Sdim                                         SourceLocation EndLoc) {
711263508Sdim  OMPClause *Res = 0;
712263508Sdim  switch (Kind) {
713263508Sdim  case OMPC_default:
714263508Sdim    Res =
715263508Sdim      ActOnOpenMPDefaultClause(static_cast<OpenMPDefaultClauseKind>(Argument),
716263508Sdim                               ArgumentLoc, StartLoc, LParenLoc, EndLoc);
717263508Sdim    break;
718263508Sdim  case OMPC_private:
719263508Sdim  case OMPC_firstprivate:
720263508Sdim  case OMPC_shared:
721263508Sdim  case OMPC_threadprivate:
722263508Sdim  case OMPC_unknown:
723263508Sdim  case NUM_OPENMP_CLAUSES:
724263508Sdim    llvm_unreachable("Clause is not allowed.");
725263508Sdim  }
726263508Sdim  return Res;
727263508Sdim}
728263508Sdim
729263508SdimOMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
730263508Sdim                                          SourceLocation KindKwLoc,
731263508Sdim                                          SourceLocation StartLoc,
732263508Sdim                                          SourceLocation LParenLoc,
733263508Sdim                                          SourceLocation EndLoc) {
734263508Sdim  if (Kind == OMPC_DEFAULT_unknown) {
735263508Sdim    std::string Values;
736263508Sdim    std::string Sep(NUM_OPENMP_DEFAULT_KINDS > 1 ? ", " : "");
737263508Sdim    for (unsigned i = OMPC_DEFAULT_unknown + 1;
738263508Sdim         i < NUM_OPENMP_DEFAULT_KINDS; ++i) {
739263508Sdim      Values += "'";
740263508Sdim      Values += getOpenMPSimpleClauseTypeName(OMPC_default, i);
741263508Sdim      Values += "'";
742263508Sdim      switch (i) {
743263508Sdim      case NUM_OPENMP_DEFAULT_KINDS - 2:
744263508Sdim        Values += " or ";
745263508Sdim        break;
746263508Sdim      case NUM_OPENMP_DEFAULT_KINDS - 1:
747263508Sdim        break;
748263508Sdim      default:
749263508Sdim        Values += Sep;
750263508Sdim        break;
751263508Sdim      }
752263508Sdim    }
753263508Sdim    Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
754263508Sdim      << Values << getOpenMPClauseName(OMPC_default);
755263508Sdim    return 0;
756263508Sdim  }
757263508Sdim  switch (Kind) {
758263508Sdim  case OMPC_DEFAULT_none:
759263508Sdim    DSAStack->setDefaultDSANone();
760263508Sdim    break;
761263508Sdim  case OMPC_DEFAULT_shared:
762263508Sdim    DSAStack->setDefaultDSAShared();
763263508Sdim    break;
764263508Sdim  default:
765263508Sdim    break;
766263508Sdim  }
767263508Sdim  return new (Context) OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc,
768263508Sdim                                        EndLoc);
769263508Sdim}
770263508Sdim
771263508SdimOMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
772263508Sdim                                          ArrayRef<Expr *> VarList,
773263508Sdim                                          SourceLocation StartLoc,
774263508Sdim                                          SourceLocation LParenLoc,
775263508Sdim                                          SourceLocation EndLoc) {
776263508Sdim  OMPClause *Res = 0;
777263508Sdim  switch (Kind) {
778263508Sdim  case OMPC_private:
779263508Sdim    Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
780263508Sdim    break;
781263508Sdim  case OMPC_firstprivate:
782263508Sdim    Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
783263508Sdim    break;
784263508Sdim  case OMPC_shared:
785263508Sdim    Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
786263508Sdim    break;
787263508Sdim  case OMPC_default:
788263508Sdim  case OMPC_threadprivate:
789263508Sdim  case OMPC_unknown:
790263508Sdim  case NUM_OPENMP_CLAUSES:
791263508Sdim    llvm_unreachable("Clause is not allowed.");
792263508Sdim  }
793263508Sdim  return Res;
794263508Sdim}
795263508Sdim
796263508SdimOMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
797263508Sdim                                          SourceLocation StartLoc,
798263508Sdim                                          SourceLocation LParenLoc,
799263508Sdim                                          SourceLocation EndLoc) {
800263508Sdim  SmallVector<Expr *, 8> Vars;
801263508Sdim  for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
802263508Sdim       I != E; ++I) {
803263508Sdim    assert(*I && "NULL expr in OpenMP private clause.");
804263508Sdim    if (isa<DependentScopeDeclRefExpr>(*I)) {
805263508Sdim      // It will be analyzed later.
806263508Sdim      Vars.push_back(*I);
807263508Sdim      continue;
808263508Sdim    }
809263508Sdim
810263508Sdim    SourceLocation ELoc = (*I)->getExprLoc();
811263508Sdim    // OpenMP [2.1, C/C++]
812263508Sdim    //  A list item is a variable name.
813263508Sdim    // OpenMP  [2.9.3.3, Restrictions, p.1]
814263508Sdim    //  A variable that is part of another variable (as an array or
815263508Sdim    //  structure element) cannot appear in a private clause.
816263508Sdim    DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
817263508Sdim    if (!DE || !isa<VarDecl>(DE->getDecl())) {
818263508Sdim      Diag(ELoc, diag::err_omp_expected_var_name)
819263508Sdim        << (*I)->getSourceRange();
820263508Sdim      continue;
821263508Sdim    }
822263508Sdim    Decl *D = DE->getDecl();
823263508Sdim    VarDecl *VD = cast<VarDecl>(D);
824263508Sdim
825263508Sdim    QualType Type = VD->getType();
826263508Sdim    if (Type->isDependentType() || Type->isInstantiationDependentType()) {
827263508Sdim      // It will be analyzed later.
828263508Sdim      Vars.push_back(DE);
829263508Sdim      continue;
830263508Sdim    }
831263508Sdim
832263508Sdim    // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
833263508Sdim    //  A variable that appears in a private clause must not have an incomplete
834263508Sdim    //  type or a reference type.
835263508Sdim    if (RequireCompleteType(ELoc, Type,
836263508Sdim                            diag::err_omp_private_incomplete_type)) {
837263508Sdim      continue;
838263508Sdim    }
839263508Sdim    if (Type->isReferenceType()) {
840263508Sdim      Diag(ELoc, diag::err_omp_clause_ref_type_arg)
841263508Sdim        << getOpenMPClauseName(OMPC_private) << Type;
842263508Sdim      bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
843263508Sdim                    VarDecl::DeclarationOnly;
844263508Sdim      Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
845263508Sdim                                       diag::note_defined_here) << VD;
846263508Sdim      continue;
847263508Sdim    }
848263508Sdim
849263508Sdim    // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
850263508Sdim    //  A variable of class type (or array thereof) that appears in a private
851263508Sdim    //  clause requires an accesible, unambiguous default constructor for the
852263508Sdim    //  class type.
853263508Sdim    while (Type.getNonReferenceType()->isArrayType()) {
854263508Sdim      Type = cast<ArrayType>(
855263508Sdim                 Type.getNonReferenceType().getTypePtr())->getElementType();
856263508Sdim    }
857263508Sdim    CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
858263508Sdim                          Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
859263508Sdim    if (RD) {
860263508Sdim      CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
861263508Sdim      PartialDiagnostic PD =
862263508Sdim        PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
863263508Sdim      if (!CD ||
864263508Sdim          CheckConstructorAccess(ELoc, CD,
865263508Sdim                                 InitializedEntity::InitializeTemporary(Type),
866263508Sdim                                 CD->getAccess(), PD) == AR_inaccessible ||
867263508Sdim          CD->isDeleted()) {
868263508Sdim        Diag(ELoc, diag::err_omp_required_method)
869263508Sdim             << getOpenMPClauseName(OMPC_private) << 0;
870263508Sdim        bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
871263508Sdim                      VarDecl::DeclarationOnly;
872263508Sdim        Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
873263508Sdim                                         diag::note_defined_here) << VD;
874263508Sdim        Diag(RD->getLocation(), diag::note_previous_decl) << RD;
875263508Sdim        continue;
876263508Sdim      }
877263508Sdim      MarkFunctionReferenced(ELoc, CD);
878263508Sdim      DiagnoseUseOfDecl(CD, ELoc);
879263508Sdim
880263508Sdim      CXXDestructorDecl *DD = RD->getDestructor();
881263508Sdim      if (DD) {
882263508Sdim        if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
883263508Sdim            DD->isDeleted()) {
884263508Sdim          Diag(ELoc, diag::err_omp_required_method)
885263508Sdim               << getOpenMPClauseName(OMPC_private) << 4;
886263508Sdim          bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
887263508Sdim                        VarDecl::DeclarationOnly;
888263508Sdim          Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
889263508Sdim                                           diag::note_defined_here) << VD;
890263508Sdim          Diag(RD->getLocation(), diag::note_previous_decl) << RD;
891263508Sdim          continue;
892263508Sdim        }
893263508Sdim        MarkFunctionReferenced(ELoc, DD);
894263508Sdim        DiagnoseUseOfDecl(DD, ELoc);
895263508Sdim      }
896263508Sdim    }
897263508Sdim
898263508Sdim    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
899263508Sdim    // in a Construct]
900263508Sdim    //  Variables with the predetermined data-sharing attributes may not be
901263508Sdim    //  listed in data-sharing attributes clauses, except for the cases
902263508Sdim    //  listed below. For these exceptions only, listing a predetermined
903263508Sdim    //  variable in a data-sharing attribute clause is allowed and overrides
904263508Sdim    //  the variable's predetermined data-sharing attributes.
905263508Sdim    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
906263508Sdim    if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
907263508Sdim      Diag(ELoc, diag::err_omp_wrong_dsa)
908263508Sdim         << getOpenMPClauseName(DVar.CKind)
909263508Sdim         << getOpenMPClauseName(OMPC_private);
910263508Sdim      if (DVar.RefExpr) {
911263508Sdim        Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
912263508Sdim             << getOpenMPClauseName(DVar.CKind);
913263508Sdim      } else {
914263508Sdim        Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
915263508Sdim             << getOpenMPClauseName(DVar.CKind);
916263508Sdim      }
917263508Sdim      continue;
918263508Sdim    }
919263508Sdim
920263508Sdim    DSAStack->addDSA(VD, DE, OMPC_private);
921263508Sdim    Vars.push_back(DE);
922263508Sdim  }
923263508Sdim
924263508Sdim  if (Vars.empty()) return 0;
925263508Sdim
926263508Sdim  return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
927263508Sdim}
928263508Sdim
929263508SdimOMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
930263508Sdim                                               SourceLocation StartLoc,
931263508Sdim                                               SourceLocation LParenLoc,
932263508Sdim                                               SourceLocation EndLoc) {
933263508Sdim  SmallVector<Expr *, 8> Vars;
934263508Sdim  for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
935263508Sdim       I != E; ++I) {
936263508Sdim    assert(*I && "NULL expr in OpenMP firstprivate clause.");
937263508Sdim    if (isa<DependentScopeDeclRefExpr>(*I)) {
938263508Sdim      // It will be analyzed later.
939263508Sdim      Vars.push_back(*I);
940263508Sdim      continue;
941263508Sdim    }
942263508Sdim
943263508Sdim    SourceLocation ELoc = (*I)->getExprLoc();
944263508Sdim    // OpenMP [2.1, C/C++]
945263508Sdim    //  A list item is a variable name.
946263508Sdim    // OpenMP  [2.9.3.3, Restrictions, p.1]
947263508Sdim    //  A variable that is part of another variable (as an array or
948263508Sdim    //  structure element) cannot appear in a private clause.
949263508Sdim    DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I);
950263508Sdim    if (!DE || !isa<VarDecl>(DE->getDecl())) {
951263508Sdim      Diag(ELoc, diag::err_omp_expected_var_name)
952263508Sdim        << (*I)->getSourceRange();
953263508Sdim      continue;
954263508Sdim    }
955263508Sdim    Decl *D = DE->getDecl();
956263508Sdim    VarDecl *VD = cast<VarDecl>(D);
957263508Sdim
958263508Sdim    QualType Type = VD->getType();
959263508Sdim    if (Type->isDependentType() || Type->isInstantiationDependentType()) {
960263508Sdim      // It will be analyzed later.
961263508Sdim      Vars.push_back(DE);
962263508Sdim      continue;
963263508Sdim    }
964263508Sdim
965263508Sdim    // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
966263508Sdim    //  A variable that appears in a private clause must not have an incomplete
967263508Sdim    //  type or a reference type.
968263508Sdim    if (RequireCompleteType(ELoc, Type,
969263508Sdim                            diag::err_omp_firstprivate_incomplete_type)) {
970263508Sdim      continue;
971263508Sdim    }
972263508Sdim    if (Type->isReferenceType()) {
973263508Sdim      Diag(ELoc, diag::err_omp_clause_ref_type_arg)
974263508Sdim        << getOpenMPClauseName(OMPC_firstprivate) << Type;
975263508Sdim      bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
976263508Sdim                    VarDecl::DeclarationOnly;
977263508Sdim      Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
978263508Sdim                                       diag::note_defined_here) << VD;
979263508Sdim      continue;
980263508Sdim    }
981263508Sdim
982263508Sdim    // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
983263508Sdim    //  A variable of class type (or array thereof) that appears in a private
984263508Sdim    //  clause requires an accesible, unambiguous copy constructor for the
985263508Sdim    //  class type.
986263508Sdim    Type = Context.getBaseElementType(Type);
987263508Sdim    CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
988263508Sdim                          Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
989263508Sdim    if (RD) {
990263508Sdim      CXXConstructorDecl *CD = LookupCopyingConstructor(RD, 0);
991263508Sdim      PartialDiagnostic PD =
992263508Sdim        PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
993263508Sdim      if (!CD ||
994263508Sdim          CheckConstructorAccess(ELoc, CD,
995263508Sdim                                 InitializedEntity::InitializeTemporary(Type),
996263508Sdim                                 CD->getAccess(), PD) == AR_inaccessible ||
997263508Sdim          CD->isDeleted()) {
998263508Sdim        Diag(ELoc, diag::err_omp_required_method)
999263508Sdim             << getOpenMPClauseName(OMPC_firstprivate) << 1;
1000263508Sdim        bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
1001263508Sdim                      VarDecl::DeclarationOnly;
1002263508Sdim        Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
1003263508Sdim                                         diag::note_defined_here) << VD;
1004263508Sdim        Diag(RD->getLocation(), diag::note_previous_decl) << RD;
1005263508Sdim        continue;
1006263508Sdim      }
1007263508Sdim      MarkFunctionReferenced(ELoc, CD);
1008263508Sdim      DiagnoseUseOfDecl(CD, ELoc);
1009263508Sdim
1010263508Sdim      CXXDestructorDecl *DD = RD->getDestructor();
1011263508Sdim      if (DD) {
1012263508Sdim        if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
1013263508Sdim            DD->isDeleted()) {
1014263508Sdim          Diag(ELoc, diag::err_omp_required_method)
1015263508Sdim               << getOpenMPClauseName(OMPC_firstprivate) << 4;
1016263508Sdim          bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
1017263508Sdim                        VarDecl::DeclarationOnly;
1018263508Sdim          Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
1019263508Sdim                                           diag::note_defined_here) << VD;
1020263508Sdim          Diag(RD->getLocation(), diag::note_previous_decl) << RD;
1021263508Sdim          continue;
1022263508Sdim        }
1023263508Sdim        MarkFunctionReferenced(ELoc, DD);
1024263508Sdim        DiagnoseUseOfDecl(DD, ELoc);
1025263508Sdim      }
1026263508Sdim    }
1027263508Sdim
1028263508Sdim    // If StartLoc and EndLoc are invalid - this is an implicit firstprivate
1029263508Sdim    // variable and it was checked already.
1030263508Sdim    if (StartLoc.isValid() && EndLoc.isValid()) {
1031263508Sdim      DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
1032263508Sdim      Type = Type.getNonReferenceType().getCanonicalType();
1033263508Sdim      bool IsConstant = Type.isConstant(Context);
1034263508Sdim      Type = Context.getBaseElementType(Type);
1035263508Sdim      // OpenMP [2.4.13, Data-sharing Attribute Clauses]
1036263508Sdim      //  A list item that specifies a given variable may not appear in more
1037263508Sdim      // than one clause on the same directive, except that a variable may be
1038263508Sdim      //  specified in both firstprivate and lastprivate clauses.
1039263508Sdim      //  TODO: add processing for lastprivate.
1040263508Sdim      if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
1041263508Sdim          DVar.RefExpr) {
1042263508Sdim        Diag(ELoc, diag::err_omp_wrong_dsa)
1043263508Sdim           << getOpenMPClauseName(DVar.CKind)
1044263508Sdim           << getOpenMPClauseName(OMPC_firstprivate);
1045263508Sdim        Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
1046263508Sdim           << getOpenMPClauseName(DVar.CKind);
1047263508Sdim        continue;
1048263508Sdim      }
1049263508Sdim
1050263508Sdim      // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1051263508Sdim      // in a Construct]
1052263508Sdim      //  Variables with the predetermined data-sharing attributes may not be
1053263508Sdim      //  listed in data-sharing attributes clauses, except for the cases
1054263508Sdim      //  listed below. For these exceptions only, listing a predetermined
1055263508Sdim      //  variable in a data-sharing attribute clause is allowed and overrides
1056263508Sdim      //  the variable's predetermined data-sharing attributes.
1057263508Sdim      // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1058263508Sdim      // in a Construct, C/C++, p.2]
1059263508Sdim      //  Variables with const-qualified type having no mutable member may be
1060263508Sdim      //  listed in a firstprivate clause, even if they are static data members.
1061263508Sdim      if (!(IsConstant || VD->isStaticDataMember()) && !DVar.RefExpr &&
1062263508Sdim          DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
1063263508Sdim        Diag(ELoc, diag::err_omp_wrong_dsa)
1064263508Sdim           << getOpenMPClauseName(DVar.CKind)
1065263508Sdim           << getOpenMPClauseName(OMPC_firstprivate);
1066263508Sdim        Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
1067263508Sdim           << getOpenMPClauseName(DVar.CKind);
1068263508Sdim        continue;
1069263508Sdim      }
1070263508Sdim
1071263508Sdim      // OpenMP [2.9.3.4, Restrictions, p.2]
1072263508Sdim      //  A list item that is private within a parallel region must not appear
1073263508Sdim      //  in a firstprivate clause on a worksharing construct if any of the
1074263508Sdim      //  worksharing regions arising from the worksharing construct ever bind
1075263508Sdim      //  to any of the parallel regions arising from the parallel construct.
1076263508Sdim      // OpenMP [2.9.3.4, Restrictions, p.3]
1077263508Sdim      //  A list item that appears in a reduction clause of a parallel construct
1078263508Sdim      //  must not appear in a firstprivate clause on a worksharing or task
1079263508Sdim      //  construct if any of the worksharing or task regions arising from the
1080263508Sdim      //  worksharing or task construct ever bind to any of the parallel regions
1081263508Sdim      //  arising from the parallel construct.
1082263508Sdim      // OpenMP [2.9.3.4, Restrictions, p.4]
1083263508Sdim      //  A list item that appears in a reduction clause in worksharing
1084263508Sdim      //  construct must not appear in a firstprivate clause in a task construct
1085263508Sdim      //  encountered during execution of any of the worksharing regions arising
1086263508Sdim      //  from the worksharing construct.
1087263508Sdim      // TODO:
1088263508Sdim    }
1089263508Sdim
1090263508Sdim    DSAStack->addDSA(VD, DE, OMPC_firstprivate);
1091263508Sdim    Vars.push_back(DE);
1092263508Sdim  }
1093263508Sdim
1094263508Sdim  if (Vars.empty()) return 0;
1095263508Sdim
1096263508Sdim  return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc,
1097263508Sdim                                       Vars);
1098263508Sdim}
1099263508Sdim
1100263508SdimOMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
1101263508Sdim                                         SourceLocation StartLoc,
1102263508Sdim                                         SourceLocation LParenLoc,
1103263508Sdim                                         SourceLocation EndLoc) {
1104263508Sdim  SmallVector<Expr *, 8> Vars;
1105263508Sdim  for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
1106263508Sdim       I != E; ++I) {
1107263508Sdim    assert(*I && "NULL expr in OpenMP shared clause.");
1108263508Sdim    if (isa<DependentScopeDeclRefExpr>(*I)) {
1109263508Sdim      // It will be analyzed later.
1110263508Sdim      Vars.push_back(*I);
1111263508Sdim      continue;
1112263508Sdim    }
1113263508Sdim
1114263508Sdim    SourceLocation ELoc = (*I)->getExprLoc();
1115263508Sdim    // OpenMP [2.1, C/C++]
1116263508Sdim    //  A list item is a variable name.
1117263508Sdim    // OpenMP  [2.9.3.4, Restrictions, p.1]
1118263508Sdim    //  A variable that is part of another variable (as an array or
1119263508Sdim    //  structure element) cannot appear in a private clause.
1120263508Sdim    DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I);
1121263508Sdim    if (!DE || !isa<VarDecl>(DE->getDecl())) {
1122263508Sdim      Diag(ELoc, diag::err_omp_expected_var_name)
1123263508Sdim        << (*I)->getSourceRange();
1124263508Sdim      continue;
1125263508Sdim    }
1126263508Sdim    Decl *D = DE->getDecl();
1127263508Sdim    VarDecl *VD = cast<VarDecl>(D);
1128263508Sdim
1129263508Sdim    QualType Type = VD->getType();
1130263508Sdim    if (Type->isDependentType() || Type->isInstantiationDependentType()) {
1131263508Sdim      // It will be analyzed later.
1132263508Sdim      Vars.push_back(DE);
1133263508Sdim      continue;
1134263508Sdim    }
1135263508Sdim
1136263508Sdim    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1137263508Sdim    // in a Construct]
1138263508Sdim    //  Variables with the predetermined data-sharing attributes may not be
1139263508Sdim    //  listed in data-sharing attributes clauses, except for the cases
1140263508Sdim    //  listed below. For these exceptions only, listing a predetermined
1141263508Sdim    //  variable in a data-sharing attribute clause is allowed and overrides
1142263508Sdim    //  the variable's predetermined data-sharing attributes.
1143263508Sdim    DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
1144263508Sdim    if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && DVar.RefExpr) {
1145263508Sdim      Diag(ELoc, diag::err_omp_wrong_dsa)
1146263508Sdim         << getOpenMPClauseName(DVar.CKind)
1147263508Sdim         << getOpenMPClauseName(OMPC_shared);
1148263508Sdim      Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
1149263508Sdim           << getOpenMPClauseName(DVar.CKind);
1150263508Sdim      continue;
1151263508Sdim    }
1152263508Sdim
1153263508Sdim    DSAStack->addDSA(VD, DE, OMPC_shared);
1154263508Sdim    Vars.push_back(DE);
1155263508Sdim  }
1156263508Sdim
1157263508Sdim  if (Vars.empty()) return 0;
1158263508Sdim
1159263508Sdim  return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
1160263508Sdim}
1161263508Sdim
1162263508Sdim#undef DSAStack
1163