SemaOpenMP.cpp revision 38afbc7361d861968232defaeaf8e302af75b5ee
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" 21using namespace clang; 22 23namespace { 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} 41Sema::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 142OMPThreadPrivateDecl *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} 182