]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/clang/lib/Sema/SemaOpenMP.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / clang / lib / Sema / SemaOpenMP.cpp
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"
21 using namespace clang;
22
23 namespace {
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 }
41 Sema::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
142 OMPThreadPrivateDecl *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 }