| Alexey Bataev | a769e07 | 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 | 
|  | 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 threadspecified is set. | 
|  | 169 | if (VD->isThreadSpecified()) { | 
|  | 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 | } |