1 //===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// \brief This file implements semantic analysis for OpenMP directives and
13 //===----------------------------------------------------------------------===//
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;
25 class VarDeclFilterCCC : public CorrectionCandidateCallback {
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());
41 Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective(
44 ArrayRef<DeclarationNameInfo> IdList) {
45 SmallVector<DeclRefExpr *, 5> Vars;
46 for (ArrayRef<DeclarationNameInfo>::iterator I = IdList.begin(),
49 LookupResult Lookup(*this, *I, LookupOrdinaryName);
50 LookupParsedName(Lookup, CurScope, NULL, true);
52 if (Lookup.isAmbiguous())
56 if (!Lookup.isSingleResult()) {
57 VarDeclFilterCCC Validator(*this);
58 TypoCorrection Corrected = CorrectTypo(*I, LookupOrdinaryName, CurScope,
60 std::string CorrectedStr = Corrected.getAsString(getLangOpts());
61 std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts());
63 if (Corrected.isResolved()) {
64 Diag(I->getLoc(), diag::err_undeclared_var_use_suggest)
65 << I->getName() << CorrectedQuotedStr
66 << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
68 Diag(I->getLoc(), diag::err_undeclared_var_use)
72 Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
73 << I->getName() << Corrected.isResolved() << CorrectedQuotedStr
74 << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr);
76 if (!Corrected.isResolved()) continue;
77 VD = Corrected.getCorrectionDeclAs<VarDecl>();
79 if (!(VD = Lookup.getAsSingle<VarDecl>())) {
80 Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest)
82 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
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;
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;
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.
123 Diag(I->getLoc(), diag::err_omp_var_used)
124 << getOpenMPDirectiveName(OMPD_threadprivate) << VD;
128 QualType ExprType = VD->getType().getNonReferenceType();
129 DeclRefExpr *Var = cast<DeclRefExpr>(BuildDeclRefExpr(VD,
132 I->getLoc()).take());
135 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, Vars)) {
136 CurContext->addDecl(D);
137 return DeclGroupPtrTy::make(DeclGroupRef(D));
139 return DeclGroupPtrTy();
142 OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
144 ArrayRef<DeclRefExpr *> VarList) {
145 SmallVector<DeclRefExpr *, 5> Vars;
146 for (ArrayRef<DeclRefExpr *>::iterator I = VarList.begin(),
149 VarDecl *VD = cast<VarDecl>((*I)->getDecl());
150 SourceLocation ILoc = (*I)->getLocation();
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)) {
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;
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;
177 return Vars.empty() ?
178 0 : OMPThreadPrivateDecl::Create(Context,
179 getCurLexicalContext(),