Index: cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h =================================================================== --- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h +++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h @@ -2478,6 +2478,9 @@ template bool RecursiveASTVisitor::VisitOMPPrivateClause(OMPPrivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } return true; } Index: cfe/trunk/include/clang/AST/OpenMPClause.h =================================================================== --- cfe/trunk/include/clang/AST/OpenMPClause.h +++ cfe/trunk/include/clang/AST/OpenMPClause.h @@ -138,7 +138,7 @@ return llvm::makeArrayRef( reinterpret_cast( reinterpret_cast(this) + - llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf())), + llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf())), NumVars); } }; @@ -926,6 +926,7 @@ /// with the variables 'a' and 'b'. /// class OMPPrivateClause : public OMPVarListClause { + friend class OMPClauseReader; /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. @@ -947,6 +948,20 @@ SourceLocation(), SourceLocation(), N) {} + /// \brief Sets the list of references to private copies with initializers for + /// new private variables. + /// \param InitVL List of references. + void setPrivateCopies(ArrayRef VL); + + /// \brief Gets the list of references to private copies with initializers for + /// new private variables. + MutableArrayRef getPrivateCopies() { + return MutableArrayRef(varlist_end(), varlist_size()); + } + ArrayRef getPrivateCopies() const { + return llvm::makeArrayRef(varlist_end(), varlist_size()); + } + public: /// \brief Creates clause with a list of variables \a VL. /// @@ -955,10 +970,12 @@ /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param VL List of references to the variables. + /// \param PrivateVL List of references to private copies with initializers. /// static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef VL); + SourceLocation EndLoc, ArrayRef VL, + ArrayRef PrivateVL); /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. @@ -966,6 +983,21 @@ /// static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N); + typedef MutableArrayRef::iterator private_copies_iterator; + typedef ArrayRef::iterator private_copies_const_iterator; + typedef llvm::iterator_range private_copies_range; + typedef llvm::iterator_range + private_copies_const_range; + + private_copies_range private_copies() { + return private_copies_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + private_copies_const_range private_copies() const { + return private_copies_const_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + StmtRange children() { return StmtRange(reinterpret_cast(varlist_begin()), reinterpret_cast(varlist_end())); Index: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h =================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h @@ -2500,6 +2500,9 @@ template bool RecursiveASTVisitor::VisitOMPPrivateClause(OMPPrivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } return true; } Index: cfe/trunk/lib/AST/Stmt.cpp =================================================================== --- cfe/trunk/lib/AST/Stmt.cpp +++ cfe/trunk/lib/AST/Stmt.cpp @@ -1176,17 +1176,24 @@ llvm_unreachable("unknown OMPClause"); } -OMPPrivateClause *OMPPrivateClause::Create(const ASTContext &C, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef VL) { +void OMPPrivateClause::setPrivateCopies(ArrayRef VL) { + assert(VL.size() == varlist_size() && + "Number of private copies is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), varlist_end()); +} + +OMPPrivateClause * +OMPPrivateClause::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef VL, ArrayRef PrivateVL) { + // Allocate space for private variables and initializer expressions. void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause), llvm::alignOf()) + - sizeof(Expr *) * VL.size()); - OMPPrivateClause *Clause = new (Mem) OMPPrivateClause(StartLoc, LParenLoc, - EndLoc, VL.size()); + 2 * sizeof(Expr *) * VL.size()); + OMPPrivateClause *Clause = + new (Mem) OMPPrivateClause(StartLoc, LParenLoc, EndLoc, VL.size()); Clause->setVarRefs(VL); + Clause->setPrivateCopies(PrivateVL); return Clause; } @@ -1194,7 +1201,7 @@ unsigned N) { void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPPrivateClause), llvm::alignOf()) + - sizeof(Expr *) * N); + 2 * sizeof(Expr *) * N); return new (Mem) OMPPrivateClause(N); } Index: cfe/trunk/lib/AST/StmtProfile.cpp =================================================================== --- cfe/trunk/lib/AST/StmtProfile.cpp +++ cfe/trunk/lib/AST/StmtProfile.cpp @@ -322,12 +322,16 @@ template void OMPClauseProfiler::VisitOMPClauseList(T *Node) { - for (auto *I : Node->varlists()) - Profiler->VisitStmt(I); + for (auto *E : Node->varlists()) { + Profiler->VisitStmt(E); + } } void OMPClauseProfiler::VisitOMPPrivateClause(const OMPPrivateClause *C) { VisitOMPClauseList(C); + for (auto *E : C->private_copies()) { + Profiler->VisitStmt(E); + } } void OMPClauseProfiler::VisitOMPFirstprivateClause(const OMPFirstprivateClause *C) { Index: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp @@ -71,6 +71,7 @@ void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, Stmt *S) { CodeGenFunction::OMPPrivateScope PrivateScope(CGF); + CGF.EmitOMPPrivateClause(Directive, PrivateScope); CGF.EmitOMPFirstprivateClause(Directive, PrivateScope); if (PrivateScope.Privatize()) { // Emit implicit barrier to synchronize threads and avoid data races. @@ -200,7 +201,10 @@ OpenMPLocThreadIDMapTy::iterator I = OpenMPLocThreadIDMap.find(CGF.CurFn); if (I != OpenMPLocThreadIDMap.end()) { ThreadID = I->second.ThreadID; - } else if (auto OMPRegionInfo = + if (ThreadID != nullptr) + return ThreadID; + } + if (auto OMPRegionInfo = dyn_cast_or_null(CGF.CapturedStmtInfo)) { // Check if this an outlined function with thread id passed as argument. auto ThreadIDVar = OMPRegionInfo->getThreadIDVariable(); @@ -233,7 +237,8 @@ void CGOpenMPRuntime::FunctionFinished(CodeGenFunction &CGF) { assert(CGF.CurFn && "No function in current CodeGenFunction."); - OpenMPLocThreadIDMap.erase(CGF.CurFn); + if (OpenMPLocThreadIDMap.count(CGF.CurFn)) + OpenMPLocThreadIDMap.erase(CGF.CurFn); } llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { Index: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp @@ -183,6 +183,33 @@ } } +void CodeGenFunction::EmitOMPPrivateClause( + const OMPExecutableDirective &D, + CodeGenFunction::OMPPrivateScope &PrivateScope) { + auto PrivateFilter = [](const OMPClause *C) -> bool { + return C->getClauseKind() == OMPC_private; + }; + for (OMPExecutableDirective::filtered_clause_iterator + I(D.clauses(), PrivateFilter); I; ++I) { + auto *C = cast(*I); + auto IRef = C->varlist_begin(); + for (auto IInit : C->private_copies()) { + auto *OrigVD = cast(cast(*IRef)->getDecl()); + auto VD = cast(cast(IInit)->getDecl()); + bool IsRegistered = + PrivateScope.addPrivate(OrigVD, [&]() -> llvm::Value * { + // Emit private VarDecl with copy init. + EmitDecl(*VD); + return GetAddrOfLocalVar(VD); + }); + assert(IsRegistered && "counter already registered as private"); + // Silence the warning about unused variable. + (void)IsRegistered; + ++IRef; + } + } +} + /// \brief Emits code for OpenMP parallel directive in the parallel region. static void EmitOMPParallelCall(CodeGenFunction &CGF, const OMPParallelDirective &S, Index: cfe/trunk/lib/CodeGen/CodeGenFunction.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h @@ -113,6 +113,7 @@ void operator=(const CodeGenFunction &) LLVM_DELETED_FUNCTION; friend class CGCXXABI; + friend class CGOpenMPRegionInfo; public: /// A jump destination is an abstract label, branching to which may /// require a jump out through normal cleanups. @@ -2012,6 +2013,8 @@ const VarDecl *VDInit); void EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope); + void EmitOMPPrivateClause(const OMPExecutableDirective &D, + OMPPrivateScope &PrivateScope); void EmitOMPParallelDirective(const OMPParallelDirective &S); void EmitOMPSimdDirective(const OMPSimdDirective &S); Index: cfe/trunk/lib/Sema/SemaOpenMP.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaOpenMP.cpp +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp @@ -3912,11 +3912,13 @@ SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector Vars; + SmallVector PrivateCopies; for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP private clause."); if (isa(RefExpr)) { // It will be analyzed later. Vars.push_back(RefExpr); + PrivateCopies.push_back(nullptr); continue; } @@ -3938,6 +3940,7 @@ if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); + PrivateCopies.push_back(nullptr); continue; } @@ -3963,54 +3966,8 @@ // A variable of class type (or array thereof) that appears in a private // clause requires an accessible, unambiguous default constructor for the // class type. - while (Type.getNonReferenceType()->isArrayType()) { - Type = cast(Type.getNonReferenceType().getTypePtr()) - ->getElementType(); - } - CXXRecordDecl *RD = getLangOpts().CPlusPlus - ? Type.getNonReferenceType()->getAsCXXRecordDecl() - : nullptr; - // FIXME This code must be replaced by actual constructing/destructing of - // the private variable. - if (RD) { - CXXConstructorDecl *CD = LookupDefaultConstructor(RD); - PartialDiagnostic PD = - PartialDiagnostic(PartialDiagnostic::NullDiagnostic()); - if (!CD || - CheckConstructorAccess(ELoc, CD, - InitializedEntity::InitializeTemporary(Type), - CD->getAccess(), PD) == AR_inaccessible || - CD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_private) << 0; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; - } - MarkFunctionReferenced(ELoc, CD); - DiagnoseUseOfDecl(CD, ELoc); - - CXXDestructorDecl *DD = RD->getDestructor(); - if (DD) { - if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible || - DD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_private) << 4; - bool IsDecl = VD->isThisDeclarationADefinition(Context) == - VarDecl::DeclarationOnly; - Diag(VD->getLocation(), - IsDecl ? diag::note_previous_decl : diag::note_defined_here) - << VD; - Diag(RD->getLocation(), diag::note_previous_decl) << RD; - continue; - } - MarkFunctionReferenced(ELoc, DD); - DiagnoseUseOfDecl(DD, ELoc); - } + while (Type->isArrayType()) { + Type = cast(Type.getTypePtr())->getElementType(); } // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced @@ -4028,14 +3985,35 @@ continue; } + // Generate helper private variable and initialize it with the default + // value. The address of the original variable is replaced by the address of + // the new private variable in CodeGen. This new variable is not added to + // IdResolver, so the code in the OpenMP region uses original variable for + // proper diagnostics. + auto VDPrivate = + VarDecl::Create(Context, CurContext, DE->getLocStart(), + DE->getExprLoc(), VD->getIdentifier(), VD->getType(), + VD->getTypeSourceInfo(), /*S*/ SC_Auto); + ActOnUninitializedDecl(VDPrivate, /*TypeMayContainAuto*/ false); + if (VDPrivate->isInvalidDecl()) + continue; + CurContext->addDecl(VDPrivate); + auto VDPrivateRefExpr = DeclRefExpr::Create( + Context, /*QualifierLoc*/ NestedNameSpecifierLoc(), + /*TemplateKWLoc*/ SourceLocation(), VDPrivate, + /*isEnclosingLocal*/ false, /*NameLoc*/ SourceLocation(), DE->getType(), + /*VK*/ VK_LValue); + DSAStack->addDSA(VD, DE, OMPC_private); Vars.push_back(DE); + PrivateCopies.push_back(VDPrivateRefExpr); } if (Vars.empty()) return nullptr; - return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); + return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars, + PrivateCopies); } namespace { Index: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp @@ -1845,6 +1845,10 @@ for (unsigned i = 0; i != NumVars; ++i) Vars.push_back(Reader->Reader.ReadSubExpr()); C->setVarRefs(Vars); + Vars.clear(); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setPrivateCopies(Vars); } void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { Index: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp @@ -1755,8 +1755,12 @@ void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) { Record.push_back(C->varlist_size()); Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); - for (auto *VE : C->varlists()) + for (auto *VE : C->varlists()) { + Writer->Writer.AddStmt(VE); + } + for (auto *VE : C->private_copies()) { Writer->Writer.AddStmt(VE); + } } void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { Index: cfe/trunk/test/OpenMP/for_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/for_private_messages.cpp +++ cfe/trunk/test/OpenMP/for_private_messages.cpp @@ -24,16 +24,16 @@ S3() : a(0) {} }; const S3 ca[5]; -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v) : a(v) {} }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5() : a(0) {} + S5() : a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v) : a(v) {} @@ -109,8 +109,8 @@ } int main(int argc, char **argv) { - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp for private // expected-error {{expected '(' after 'private'}} @@ -143,7 +143,7 @@ #pragma omp for private(argv[1]) // expected-error {{expected variable name}} for (int k = 0; k < argc; ++k) ++k; -#pragma omp for private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} +#pragma omp for private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} for (int k = 0; k < argc; ++k) ++k; #pragma omp for private(h) // expected-error {{threadprivate or thread local variable cannot be private}} Index: cfe/trunk/test/OpenMP/for_simd_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/for_simd_private_messages.cpp +++ cfe/trunk/test/OpenMP/for_simd_private_messages.cpp @@ -24,16 +24,16 @@ S3() : a(0) {} }; const S3 ca[5]; -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v) : a(v) {} }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5() : a(0) {} + S5() : a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v) : a(v) {} @@ -109,8 +109,8 @@ } int main(int argc, char **argv) { - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp for simd private // expected-error {{expected '(' after 'private'}} @@ -143,7 +143,7 @@ #pragma omp for simd private(argv[1]) // expected-error {{expected variable name}} for (int k = 0; k < argc; ++k) ++k; -#pragma omp for simd private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} +#pragma omp for simd private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} for (int k = 0; k < argc; ++k) ++k; #pragma omp for simd private(h) // expected-error {{threadprivate or thread local variable cannot be private}} Index: cfe/trunk/test/OpenMP/parallel_for_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/parallel_for_private_messages.cpp +++ cfe/trunk/test/OpenMP/parallel_for_private_messages.cpp @@ -24,16 +24,16 @@ S3() : a(0) {} }; const S3 ca[5]; -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v) : a(v) {} }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5() : a(0) {} + S5() : a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v) : a(v) {} @@ -109,8 +109,8 @@ } int main(int argc, char **argv) { - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp parallel for private // expected-error {{expected '(' after 'private'}} @@ -143,7 +143,7 @@ #pragma omp parallel for private(argv[1]) // expected-error {{expected variable name}} for (int k = 0; k < argc; ++k) ++k; -#pragma omp parallel for private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} +#pragma omp parallel for private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} for (int k = 0; k < argc; ++k) ++k; #pragma omp parallel for private(h) // expected-error {{threadprivate or thread local variable cannot be private}} Index: cfe/trunk/test/OpenMP/parallel_for_simd_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/parallel_for_simd_private_messages.cpp +++ cfe/trunk/test/OpenMP/parallel_for_simd_private_messages.cpp @@ -24,16 +24,16 @@ S3() : a(0) {} }; const S3 ca[5]; -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v) : a(v) {} }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5() : a(0) {} + S5() : a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v) : a(v) {} @@ -109,8 +109,8 @@ } int main(int argc, char **argv) { - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp parallel for simd private // expected-error {{expected '(' after 'private'}} @@ -143,7 +143,7 @@ #pragma omp parallel for simd private(argv[1]) // expected-error {{expected variable name}} for (int k = 0; k < argc; ++k) ++k; -#pragma omp parallel for simd private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} +#pragma omp parallel for simd private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} for (int k = 0; k < argc; ++k) ++k; #pragma omp parallel for simd private(h) // expected-error {{threadprivate or thread local variable cannot be private}} Index: cfe/trunk/test/OpenMP/parallel_private_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/parallel_private_codegen.cpp +++ cfe/trunk/test/OpenMP/parallel_private_codegen.cpp @@ -0,0 +1,109 @@ +// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -std=c++11 -triple x86_64-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp=libiomp5 -x c++ -triple x86_64-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s +// expected-no-diagnostics +#ifndef HEADER +#define HEADER + +template +struct S { + T f; + S(T a) : f(a) {} + S() : f() {} + operator T() { return T(); } + ~S() {} +}; + +// CHECK: [[S_FLOAT_TY:%.+]] = type { float } +// CHECK: [[CAP_MAIN_TY:%.+]] = type { [2 x i{{[0-9]+}}]*, i{{[0-9]+}}*, [2 x [[S_FLOAT_TY]]]*, [[S_FLOAT_TY]]* } +// CHECK: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} } +// CHECK: [[CAP_TMAIN_TY:%.+]] = type { [2 x i{{[0-9]+}}]*, i{{[0-9]+}}*, [2 x [[S_INT_TY]]]*, [[S_INT_TY]]* } +// CHECK: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8* +template +T tmain() { + S test; + T t_var; + T vec[] = {1, 2}; + S s_arr[] = {1, 2}; + S var(3); +#pragma omp parallel private(t_var, vec, s_arr, var) + { + vec[0] = t_var; + s_arr[0] = var; + } + return T(); +} + +int main() { + S test; + int t_var; + int vec[] = {1, 2}; + S s_arr[] = {1, 2}; + S var(3); +#pragma omp parallel private(t_var, vec, s_arr, var) + { + vec[0] = t_var; + s_arr[0] = var; + } + return tmain(); +} + +// CHECK: define i{{[0-9]+}} @main() +// CHECK: [[TEST:%.+]] = alloca [[S_FLOAT_TY]], +// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]]) +// CHECK: %{{.+}} = bitcast [[CAP_MAIN_TY]]* +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...)* @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_MAIN_TY]]*)* [[MAIN_MICROTASK:@.+]] to void +// CHECK: = call i{{.+}} [[TMAIN_INT:@.+]]() +// CHECK: call void [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]* +// CHECK: ret +// +// CHECK: define internal void [[MAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_MAIN_TY]]* %{{.+}}) +// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}}, +// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}], +// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]], +// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_FLOAT_TY]], +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]] +// CHECK-NOT: [[T_VAR_PRIV]] +// CHECK-NOT: [[VEC_PRIV]] +// CHECK: {{.+}}: +// CHECK: [[S_ARR_PRIV_ITEM:%.+]] = phi [[S_FLOAT_TY]]* +// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[S_ARR_PRIV_ITEM]]) +// CHECK-NOT: [[T_VAR_PRIV]] +// CHECK-NOT: [[VEC_PRIV]] +// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) +// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}** [[GTID_ADDR_REF]] +// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}* [[GTID_REF]] +// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK-DAG: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) +// CHECK-DAG: call void [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]* +// CHECK: ret void + +// CHECK: define {{.*}} i{{[0-9]+}} [[TMAIN_INT]]() +// CHECK: [[TEST:%.+]] = alloca [[S_INT_TY]], +// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR:@.+]]([[S_INT_TY]]* [[TEST]]) +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...)* @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[CAP_TMAIN_TY]]*)* [[TMAIN_MICROTASK:@.+]] to void +// CHECK: call void [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]* +// CHECK: ret +// +// CHECK: define internal void [[TMAIN_MICROTASK]](i{{[0-9]+}}* [[GTID_ADDR:%.+]], i{{[0-9]+}}* %{{.+}}, [[CAP_TMAIN_TY]]* %{{.+}}) +// CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}}, +// CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}], +// CHECK: [[S_ARR_PRIV:%.+]] = alloca [2 x [[S_INT_TY]]], +// CHECK: [[VAR_PRIV:%.+]] = alloca [[S_INT_TY]], +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_REF:%.+]] +// CHECK-NOT: [[T_VAR_PRIV]] +// CHECK-NOT: [[VEC_PRIV]] +// CHECK: {{.+}}: +// CHECK: [[S_ARR_PRIV_ITEM:%.+]] = phi [[S_INT_TY]]* +// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR]]([[S_INT_TY]]* [[S_ARR_PRIV_ITEM]]) +// CHECK-NOT: [[T_VAR_PRIV]] +// CHECK-NOT: [[VEC_PRIV]] +// CHECK: call {{.*}} [[S_INT_TY_DEF_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]]) +// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}** [[GTID_ADDR_REF]] +// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}* [[GTID_REF]] +// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]]) +// CHECK-DAG: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]]) +// CHECK-DAG: call void [[S_INT_TY_DESTR]]([[S_INT_TY]]* +// CHECK: ret void +#endif + Index: cfe/trunk/test/OpenMP/parallel_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/parallel_private_messages.cpp +++ cfe/trunk/test/OpenMP/parallel_private_messages.cpp @@ -25,15 +25,15 @@ const S3 c; // expected-note {{global variable is predetermined as shared}} const S3 ca[5]; // expected-note {{global variable is predetermined as shared}} extern const int f; // expected-note {{global variable is predetermined as shared}} -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v):a(v) { } }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5():a(0) {} + S5():a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v):a(v) { } }; @@ -44,8 +44,8 @@ int main(int argc, char **argv) { const int d = 5; // expected-note {{constant variable is predetermined as shared}} const int da[5] = { 0 }; // expected-note {{constant variable is predetermined as shared}} - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g[] = {5, 6}; int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp parallel private // expected-error {{expected '(' after 'private'}} @@ -62,7 +62,7 @@ #pragma omp parallel private(ca) // expected-error {{shared variable cannot be private}} #pragma omp parallel private(da) // expected-error {{shared variable cannot be private}} #pragma omp parallel private(S2::S2s) // expected-error {{shared variable cannot be private}} - #pragma omp parallel private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} + #pragma omp parallel private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} #pragma omp parallel private(threadvar) // expected-error {{threadprivate or thread local variable cannot be private}} #pragma omp parallel shared(i), private(i) // expected-error {{shared variable cannot be private}} expected-note {{defined as shared}} foo(); Index: cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp +++ cfe/trunk/test/OpenMP/parallel_sections_private_messages.cpp @@ -24,16 +24,16 @@ S3() : a(0) {} }; const S3 ca[5]; -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v) : a(v) {} }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5() : a(0) {} + S5() : a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v) : a(v) {} @@ -124,8 +124,8 @@ } int main(int argc, char **argv) { - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp parallel sections private // expected-error {{expected '(' after 'private'}} @@ -168,7 +168,7 @@ { foo(); } -#pragma omp parallel sections private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} +#pragma omp parallel sections private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} { foo(); } Index: cfe/trunk/test/OpenMP/sections_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/sections_private_messages.cpp +++ cfe/trunk/test/OpenMP/sections_private_messages.cpp @@ -24,16 +24,16 @@ S3() : a(0) {} }; const S3 ca[5]; -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v) : a(v) {} }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5() : a(0) {} + S5() : a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v) : a(v) {} @@ -124,8 +124,8 @@ } int main(int argc, char **argv) { - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp sections private // expected-error {{expected '(' after 'private'}} @@ -168,7 +168,7 @@ { foo(); } -#pragma omp sections private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} +#pragma omp sections private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} { foo(); } Index: cfe/trunk/test/OpenMP/simd_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/simd_private_messages.cpp +++ cfe/trunk/test/OpenMP/simd_private_messages.cpp @@ -22,15 +22,15 @@ S3():a(0) { } }; const S3 ca[5]; -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v):a(v) { } }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5():a(0) {} + S5():a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v):a(v) { } }; @@ -86,8 +86,8 @@ } int main(int argc, char **argv) { - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp simd private // expected-error {{expected '(' after 'private'}} @@ -110,7 +110,7 @@ for (int k = 0; k < argc; ++k) ++k; #pragma omp simd private (argv[1]) // expected-error {{expected variable name}} for (int k = 0; k < argc; ++k) ++k; - #pragma omp simd private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} + #pragma omp simd private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} for (int k = 0; k < argc; ++k) ++k; #pragma omp simd private(h) // expected-error {{threadprivate or thread local variable cannot be private}} for (int k = 0; k < argc; ++k) ++k; Index: cfe/trunk/test/OpenMP/single_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/single_private_messages.cpp +++ cfe/trunk/test/OpenMP/single_private_messages.cpp @@ -24,16 +24,16 @@ S3() : a(0) {} }; const S3 ca[5]; -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v) : a(v) {} }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5() : a(0) {} + S5() : a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v) : a(v) {} @@ -92,8 +92,8 @@ } int main(int argc, char **argv) { - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp single private // expected-error {{expected '(' after 'private'}} @@ -116,7 +116,7 @@ foo(); #pragma omp single private(argv[1]) // expected-error {{expected variable name}} foo(); -#pragma omp single private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} +#pragma omp single private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} foo(); #pragma omp single private(h) // expected-error {{threadprivate or thread local variable cannot be private}} foo(); Index: cfe/trunk/test/OpenMP/task_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/task_private_messages.cpp +++ cfe/trunk/test/OpenMP/task_private_messages.cpp @@ -27,16 +27,16 @@ const S3 c; // expected-note {{global variable is predetermined as shared}} const S3 ca[5]; // expected-note {{global variable is predetermined as shared}} extern const int f; // expected-note {{global variable is predetermined as shared}} -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v) : a(v) {} }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5() : a(0) {} + S5() : a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v) : a(v) {} @@ -48,8 +48,8 @@ int main(int argc, char **argv) { const int d = 5; // expected-note {{constant variable is predetermined as shared}} const int da[5] = {0}; // expected-note {{constant variable is predetermined as shared}} - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp task private // expected-error {{expected '(' after 'private'}} @@ -66,7 +66,7 @@ #pragma omp task private(ca) // expected-error {{shared variable cannot be private}} #pragma omp task private(da) // expected-error {{shared variable cannot be private}} #pragma omp task private(S2::S2s) // expected-error {{shared variable cannot be private}} -#pragma omp task private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} +#pragma omp task private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} #pragma omp task private(threadvar) // expected-error {{threadprivate or thread local variable cannot be private}} #pragma omp task shared(i), private(i) // expected-error {{shared variable cannot be private}} expected-note {{defined as shared}} foo(); Index: cfe/trunk/test/OpenMP/teams_private_messages.cpp =================================================================== --- cfe/trunk/test/OpenMP/teams_private_messages.cpp +++ cfe/trunk/test/OpenMP/teams_private_messages.cpp @@ -25,15 +25,15 @@ const S3 c; // expected-note {{global variable is predetermined as shared}} const S3 ca[5]; // expected-note {{global variable is predetermined as shared}} extern const int f; // expected-note {{global variable is predetermined as shared}} -class S4 { // expected-note {{'S4' declared here}} +class S4 { int a; - S4(); + S4(); // expected-note {{implicitly declared private here}} public: S4(int v):a(v) { } }; -class S5 { // expected-note {{'S5' declared here}} +class S5 { int a; - S5():a(0) {} + S5():a(0) {} // expected-note {{implicitly declared private here}} public: S5(int v):a(v) { } }; @@ -44,8 +44,8 @@ int main(int argc, char **argv) { const int d = 5; // expected-note {{constant variable is predetermined as shared}} const int da[5] = { 0 }; // expected-note {{constant variable is predetermined as shared}} - S4 e(4); // expected-note {{'e' defined here}} - S5 g(5); // expected-note {{'g' defined here}} + S4 e(4); + S5 g(5); int i; int &j = i; // expected-note {{'j' defined here}} #pragma omp target @@ -91,7 +91,7 @@ #pragma omp teams private(S2::S2s) // expected-error {{shared variable cannot be private}} foo(); #pragma omp target - #pragma omp teams private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}} + #pragma omp teams private(e, g) // expected-error {{calling a private constructor of class 'S4'}} expected-error {{calling a private constructor of class 'S5'}} foo(); #pragma omp target #pragma omp teams private(threadvar) // expected-error {{threadprivate or thread local variable cannot be private}} Index: cfe/trunk/tools/libclang/CIndex.cpp =================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp +++ cfe/trunk/tools/libclang/CIndex.cpp @@ -2004,12 +2004,16 @@ template void OMPClauseEnqueue::VisitOMPClauseList(T *Node) { - for (const auto *I : Node->varlists()) + for (const auto *I : Node->varlists()) { Visitor->AddStmt(I); + } } void OMPClauseEnqueue::VisitOMPPrivateClause(const OMPPrivateClause *C) { VisitOMPClauseList(C); + for (const auto *E : C->private_copies()) { + Visitor->AddStmt(E); + } } void OMPClauseEnqueue::VisitOMPFirstprivateClause( const OMPFirstprivateClause *C) {