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