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 
42 ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
43                                          CXXScopeSpec &ScopeSpec,
44                                          const DeclarationNameInfo &Id) {
45   LookupResult Lookup(*this, Id, LookupOrdinaryName);
46   LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
47 
48   if (Lookup.isAmbiguous())
49     return ExprError();
50 
51   VarDecl *VD;
52   if (!Lookup.isSingleResult()) {
53     VarDeclFilterCCC Validator(*this);
54     TypoCorrection Corrected = CorrectTypo(Id, LookupOrdinaryName, CurScope,
55                                            0, Validator);
56     std::string CorrectedStr = Corrected.getAsString(getLangOpts());
57     std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
58     if (Lookup.empty()) {
59       if (Corrected.isResolved()) {
60         Diag(Id.getLoc(), diag::err_undeclared_var_use_suggest)
61           << Id.getName() << CorrectedQuotedStr
62           << FixItHint::CreateReplacement(Id.getLoc(), CorrectedStr);
63       } else {
64         Diag(Id.getLoc(), diag::err_undeclared_var_use)
65           << Id.getName();
66       }
67     } else {
68       Diag(Id.getLoc(), diag::err_omp_expected_var_arg_suggest)
69         << Id.getName() << Corrected.isResolved() << CorrectedQuotedStr
70         << FixItHint::CreateReplacement(Id.getLoc(), CorrectedStr);
71     }
72     if (!Corrected.isResolved()) return ExprError();
73     VD = Corrected.getCorrectionDeclAs<VarDecl>();
74   } else {
75     if (!(VD = Lookup.getAsSingle<VarDecl>())) {
76       Diag(Id.getLoc(), diag::err_omp_expected_var_arg_suggest)
77         << Id.getName() << 0;
78       Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
79       return ExprError();
80     }
81   }
82   Lookup.suppressDiagnostics();
83 
84   // OpenMP [2.9.2, Syntax, C/C++]
85   //   Variables must be file-scope, namespace-scope, or static block-scope.
86   if (!VD->hasGlobalStorage()) {
87     Diag(Id.getLoc(), diag::err_omp_global_var_arg)
88       << getOpenMPDirectiveName(OMPD_threadprivate)
89       << !VD->isStaticLocal();
90     bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
91                   VarDecl::DeclarationOnly;
92     Diag(VD->getLocation(),
93          IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD;
94     return ExprError();
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(Id.getLoc(), diag::err_omp_var_scope)
114       << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
115     bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
116                   VarDecl::DeclarationOnly;
117     Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
118                                      diag::note_defined_here) << VD;
119     return ExprError();
120   }
121 
122   // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
123   //   A threadprivate directive must lexically precede all references to any
124   //   of the variables in its list.
125   if (VD->isUsed()) {
126     Diag(Id.getLoc(), diag::err_omp_var_used)
127       << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
128     return ExprError();
129   }
130 
131   QualType ExprType = VD->getType().getNonReferenceType();
132   ExprResult DE = BuildDeclRefExpr(VD, ExprType, VK_RValue, Id.getLoc());
133   return DE;
134 }
135 
136 Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
137                                 SourceLocation Loc,
138                                 ArrayRef<Expr *> VarList) {
139   if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
140     CurContext->addDecl(D);
141     return DeclGroupPtrTy::make(DeclGroupRef(D));
142   }
143   return DeclGroupPtrTy();
144 }
145 
146 OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
147                                  SourceLocation Loc,
148                                  ArrayRef<Expr *> VarList) {
149   SmallVector<Expr *, 8> Vars;
150   for (ArrayRef<Expr *>::iterator I = VarList.begin(),
151                                          E = VarList.end();
152        I != E; ++I) {
153     DeclRefExpr *DE = cast<DeclRefExpr>(*I);
154     VarDecl *VD = cast<VarDecl>(DE->getDecl());
155     SourceLocation ILoc = DE->getExprLoc();
156 
157     // OpenMP [2.9.2, Restrictions, C/C++, p.10]
158     //   A threadprivate variable must not have an incomplete type.
159     if (RequireCompleteType(ILoc, VD->getType(),
160                             diag::err_omp_threadprivate_incomplete_type)) {
161       continue;
162     }
163 
164     // OpenMP [2.9.2, Restrictions, C/C++, p.10]
165     //   A threadprivate variable must not have a reference type.
166     if (VD->getType()->isReferenceType()) {
167       Diag(ILoc, diag::err_omp_ref_type_arg)
168         << getOpenMPDirectiveName(OMPD_threadprivate);
169       bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
170                     VarDecl::DeclarationOnly;
171       Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
172                                        diag::note_defined_here) << VD;
173       continue;
174     }
175 
176     // Check if this is a TLS variable.
177     if (VD->getTLSKind()) {
178       Diag(ILoc, diag::err_omp_var_thread_local) << VD;
179       bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
180                     VarDecl::DeclarationOnly;
181       Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
182                                        diag::note_defined_here) << VD;
183       continue;
184     }
185 
186     Vars.push_back(*I);
187   }
188   return Vars.empty() ?
189               0 : OMPThreadPrivateDecl::Create(Context,
190                                                getCurLexicalContext(),
191                                                Loc, Vars);
192 }
193 
194