Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 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 |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 11 | /// clauses. |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 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 | |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 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()); |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 36 | } |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 37 | return false; |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 38 | } |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 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)) { |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 140 | CurContext->addDecl(D); |
| 141 | return DeclGroupPtrTy::make(DeclGroupRef(D)); |
| 142 | } |
| 143 | return DeclGroupPtrTy(); |
| 144 | } |
| 145 | |
| 146 | OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl( |
| 147 | SourceLocation Loc, |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 148 | ArrayRef<Expr *> VarList) { |
| 149 | SmallVector<Expr *, 8> Vars; |
| 150 | for (ArrayRef<Expr *>::iterator I = VarList.begin(), |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 151 | E = VarList.end(); |
| 152 | I != E; ++I) { |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 153 | DeclRefExpr *DE = cast<DeclRefExpr>(*I); |
| 154 | VarDecl *VD = cast<VarDecl>(DE->getDecl()); |
| 155 | SourceLocation ILoc = DE->getExprLoc(); |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 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(), |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 160 | diag::err_omp_threadprivate_incomplete_type)) { |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 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) |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 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; |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 173 | continue; |
| 174 | } |
| 175 | |
Richard Smith | 38afbc7 | 2013-04-13 02:43:54 +0000 | [diff] [blame] | 176 | // Check if this is a TLS variable. |
| 177 | if (VD->getTLSKind()) { |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 178 | Diag(ILoc, diag::err_omp_var_thread_local) << VD; |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 179 | bool IsDecl = VD->isThisDeclarationADefinition(Context) == |
| 180 | VarDecl::DeclarationOnly; |
| 181 | Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : |
| 182 | diag::note_defined_here) << VD; |
Alexey Bataev | c640058 | 2013-03-22 06:34:35 +0000 | [diff] [blame] | 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 | } |
Alexey Bataev | 6af701f | 2013-05-13 04:18:18 +0000 | [diff] [blame] | 193 | |