SemaOpenMP.cpp revision 38afbc7361d861968232defaeaf8e302af75b5ee
1//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ----------===//
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/// \file
10/// \brief This file implements semantic analysis for OpenMP directives and
11/// clauses
12///
13//===----------------------------------------------------------------------===//
14
15#include "clang/Basic/OpenMPKinds.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclOpenMP.h"
18#include "clang/Lex/Preprocessor.h"
19#include "clang/Sema/SemaInternal.h"
20#include "clang/Sema/Lookup.h"
21using namespace clang;
22
23namespace {
24
25  class VarDeclFilterCCC : public CorrectionCandidateCallback {
26    private:
27      Sema &Actions;
28    public:
29      VarDeclFilterCCC(Sema &S) : Actions(S) { }
30      virtual bool ValidateCandidate(const TypoCorrection &Candidate) {
31        NamedDecl *ND = Candidate.getCorrectionDecl();
32        if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) {
33          return VD->hasGlobalStorage() &&
34                 Actions.isDeclInScope(ND, Actions.getCurLexicalContext(),
35                                       Actions.getCurScope());
36        }
37        return false;
38      }
39  };
40}
41Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
42                              SourceLocation Loc,
43                              Scope *CurScope,
44                              ArrayRef<DeclarationNameInfo> IdList) {
45  SmallVector<DeclRefExpr *, 5> Vars;
46  for (ArrayRef<DeclarationNameInfo>::iterator I = IdList.begin(),
47                                               E = IdList.end();
48       I != E; ++I) {
49    LookupResult Lookup(*this, *I, LookupOrdinaryName);
50    LookupParsedName(Lookup, CurScope, NULL, true);
51
52    if (Lookup.isAmbiguous())
53      continue;
54
55    VarDecl *VD;
56    if (!Lookup.isSingleResult()) {
57      VarDeclFilterCCC Validator(*this);
58      TypoCorrection Corrected = CorrectTypo(*I, LookupOrdinaryName, CurScope,
59                                             0, Validator);
60      std::string CorrectedStr = Corrected.getAsString(getLangOpts());
61      std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
62      if (Lookup.empty()) {
63        if (Corrected.isResolved()) {
64          Diag(I->getLoc(), diag::err_undeclared_var_use_suggest)
65            << I->getName() << CorrectedQuotedStr
66            << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
67        } else {
68          Diag(I->getLoc(), diag::err_undeclared_var_use)
69            << I->getName();
70        }
71      } else {
72        Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
73          << I->getName() << Corrected.isResolved() << CorrectedQuotedStr
74          << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
75      }
76      if (!Corrected.isResolved()) continue;
77      VD = Corrected.getCorrectionDeclAs<VarDecl>();
78    } else {
79      if (!(VD = Lookup.getAsSingle<VarDecl>())) {
80        Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
81          << I->getName() << 0;
82        Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
83        continue;
84      }
85    }
86
87    // OpenMP [2.9.2, Syntax, C/C++]
88    //   Variables must be file-scope, namespace-scope, or static block-scope.
89    if (!VD->hasGlobalStorage()) {
90      Diag(I->getLoc(), diag::err_omp_global_var_arg)
91        << getOpenMPDirectiveName(OMPD_threadprivate)
92        << !VD->isStaticLocal();
93      Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
94      continue;
95    }
96
97    // OpenMP [2.9.2, Restrictions, C/C++, p.2]
98    //   A threadprivate directive for file-scope variables must appear outside
99    //   any definition or declaration.
100    // OpenMP [2.9.2, Restrictions, C/C++, p.3]
101    //   A threadprivate directive for static class member variables must appear
102    //   in the class definition, in the same scope in which the member
103    //   variables are declared.
104    // OpenMP [2.9.2, Restrictions, C/C++, p.4]
105    //   A threadprivate directive for namespace-scope variables must appear
106    //   outside any definition or declaration other than the namespace
107    //   definition itself.
108    // OpenMP [2.9.2, Restrictions, C/C++, p.6]
109    //   A threadprivate directive for static block-scope variables must appear
110    //   in the scope of the variable and not in a nested scope.
111    NamedDecl *ND = cast<NamedDecl>(VD);
112    if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
113      Diag(I->getLoc(), diag::err_omp_var_scope)
114        << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
115      Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
116      continue;
117    }
118
119    // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
120    //   A threadprivate directive must lexically precede all references to any
121    //   of the variables in its list.
122    if (VD->isUsed()) {
123      Diag(I->getLoc(), diag::err_omp_var_used)
124        << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
125      continue;
126    }
127
128    QualType ExprType = VD->getType().getNonReferenceType();
129    DeclRefExpr *Var = cast<DeclRefExpr>(BuildDeclRefExpr(VD,
130                                                          ExprType,
131                                                          VK_RValue,
132                                                          I->getLoc()).take());
133    Vars.push_back(Var);
134  }
135  if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, Vars)) {
136    CurContext->addDecl(D);
137    return DeclGroupPtrTy::make(DeclGroupRef(D));
138  }
139  return DeclGroupPtrTy();
140}
141
142OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
143                                 SourceLocation Loc,
144                                 ArrayRef<DeclRefExpr *> VarList) {
145  SmallVector<DeclRefExpr *, 5> Vars;
146  for (ArrayRef<DeclRefExpr *>::iterator I = VarList.begin(),
147                                         E = VarList.end();
148       I != E; ++I) {
149    VarDecl *VD = cast<VarDecl>((*I)->getDecl());
150    SourceLocation ILoc = (*I)->getLocation();
151
152    // OpenMP [2.9.2, Restrictions, C/C++, p.10]
153    //   A threadprivate variable must not have an incomplete type.
154    if (RequireCompleteType(ILoc, VD->getType(),
155                            diag::err_omp_incomplete_type)) {
156      continue;
157    }
158
159    // OpenMP [2.9.2, Restrictions, C/C++, p.10]
160    //   A threadprivate variable must not have a reference type.
161    if (VD->getType()->isReferenceType()) {
162      Diag(ILoc, diag::err_omp_ref_type_arg)
163        << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
164      Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
165      continue;
166    }
167
168    // Check if this is a TLS variable.
169    if (VD->getTLSKind()) {
170      Diag(ILoc, diag::err_omp_var_thread_local) << VD;
171      Diag(VD->getLocation(), diag::note_forward_declaration) << VD;
172      continue;
173    }
174
175    Vars.push_back(*I);
176  }
177  return Vars.empty() ?
178              0 : OMPThreadPrivateDecl::Create(Context,
179                                               getCurLexicalContext(),
180                                               Loc, Vars);
181}
182