r260077 - [OPENMP 4.5] Ccapture/codegen of private non-static data members.
NAKAMURA Takumi via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 8 04:43:56 PST 2016
The test is incompatible to i686-pc-win32. See also
http://bb.pgr.jp/builders/ninja-clang-i686-msc18-R/builds/5498
On Mon, Feb 8, 2016 at 6:33 PM Alexey Bataev via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: abataev
> Date: Mon Feb 8 03:29:13 2016
> New Revision: 260077
>
> URL: http://llvm.org/viewvc/llvm-project?rev=260077&view=rev
> Log:
> [OPENMP 4.5] Ccapture/codegen of private non-static data members.
> OpenMP 4.5 introduces privatization of non-static data members of current
> class in non-static member functions.
> To correctly handle such kind of privatization a new (pseudo)declaration
> VarDecl-based node is added. It allows to reuse an existing code for
> capturing variables in Lambdas/Block/Captured blocks of code for correct
> privatization and codegen.
>
> Modified:
> cfe/trunk/include/clang/AST/DeclOpenMP.h
> cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> cfe/trunk/include/clang/Basic/DeclNodes.td
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> cfe/trunk/lib/AST/DeclBase.cpp
> cfe/trunk/lib/AST/DeclOpenMP.cpp
> cfe/trunk/lib/AST/DeclPrinter.cpp
> cfe/trunk/lib/AST/StmtPrinter.cpp
> cfe/trunk/lib/CodeGen/CGDecl.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/lib/Sema/SemaExprMember.cpp
> cfe/trunk/lib/Sema/SemaOpenMP.cpp
> cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> cfe/trunk/lib/Serialization/ASTCommon.cpp
> cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
> cfe/trunk/test/OpenMP/parallel_private_codegen.cpp
> cfe/trunk/tools/libclang/CIndex.cpp
>
> Modified: cfe/trunk/include/clang/AST/DeclOpenMP.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclOpenMP.h?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclOpenMP.h (original)
> +++ cfe/trunk/include/clang/AST/DeclOpenMP.h Mon Feb 8 03:29:13 2016
> @@ -87,6 +87,35 @@ public:
> static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
> };
>
> -} // end namespace clang
> +/// Pseudo declaration for capturing of non-static data members in
> non-static
> +/// member functions.
> +///
> +/// Clang supports capturing of variables only, but OpenMP 4.5 allows to
> +/// privatize non-static members of current class in non-static member
> +/// functions. This pseudo-declaration allows properly handle this kind of
> +/// capture by wrapping captured expression into a variable-like
> declaration.
> +class OMPCapturedFieldDecl final : public VarDecl {
> + friend class ASTDeclReader;
> + void anchor() override;
> +
> + OMPCapturedFieldDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
> + QualType Type)
> + : VarDecl(OMPCapturedField, C, DC, SourceLocation(),
> SourceLocation(), Id,
> + Type, nullptr, SC_None) {
> + setImplicit();
> + }
> +
> +public:
> + static OMPCapturedFieldDecl *Create(ASTContext &C, DeclContext *DC,
> + IdentifierInfo *Id, QualType T);
> +
> + static OMPCapturedFieldDecl *CreateDeserialized(ASTContext &C, unsigned
> ID);
> +
> + // Implement isa/cast/dyncast/etc.
> + static bool classof(const Decl *D) { return classofKind(D->getKind()); }
> + static bool classofKind(Kind K) { return K == OMPCapturedField; }
> +};
> +
> +} // end namespace clang
>
> #endif
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Mon Feb 8 03:29:13
> 2016
> @@ -1434,6 +1434,8 @@ DEF_TRAVERSE_DECL(OMPThreadPrivateDecl,
> }
> })
>
> +DEF_TRAVERSE_DECL(OMPCapturedFieldDecl, { TRY_TO(TraverseVarHelper(D)); })
> +
> // A helper method for TemplateDecl's children.
> template <typename Derived>
> bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
>
> Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
> +++ cfe/trunk/include/clang/Basic/DeclNodes.td Mon Feb 8 03:29:13 2016
> @@ -51,6 +51,7 @@ def Named : Decl<1>;
> : DDecl<VarTemplateSpecialization>;
> def ImplicitParam : DDecl<Var>;
> def ParmVar : DDecl<Var>;
> + def OMPCapturedField : DDecl<Var>;
> def NonTypeTemplateParm : DDecl<Declarator>;
> def Template : DDecl<Named, 1>;
> def RedeclarableTemplate : DDecl<Template, 1>;
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Feb 8 03:29:13 2016
> @@ -7789,7 +7789,9 @@ public:
> /// \brief Check if the specified variable is used in one of the private
> /// clauses (private, firstprivate, lastprivate, reduction etc.) in
> OpenMP
> /// constructs.
> - bool IsOpenMPCapturedDecl(ValueDecl *D);
> + VarDecl *IsOpenMPCapturedDecl(ValueDecl *D);
> + ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
> + ExprObjectKind OK);
>
> /// \brief Check if the specified variable is used in 'private' clause.
> /// \param Level Relative level of nested OpenMP construct for that the
> check
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Mon Feb 8
> 03:29:13 2016
> @@ -1163,6 +1163,8 @@ namespace clang {
> DECL_EMPTY,
> /// \brief An ObjCTypeParamDecl record.
> DECL_OBJC_TYPE_PARAM,
> + /// \brief An OMPCapturedFieldDecl record.
> + DECL_OMP_CAPTUREDFIELD,
> };
>
> /// \brief Record codes for each kind of statement or expression.
>
> Modified: cfe/trunk/lib/AST/DeclBase.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclBase.cpp (original)
> +++ cfe/trunk/lib/AST/DeclBase.cpp Mon Feb 8 03:29:13 2016
> @@ -655,6 +655,7 @@ unsigned Decl::getIdentifierNamespaceFor
> case ObjCCategoryImpl:
> case Import:
> case OMPThreadPrivate:
> + case OMPCapturedField:
> case Empty:
> // Never looked up by name.
> return 0;
>
> Modified: cfe/trunk/lib/AST/DeclOpenMP.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclOpenMP.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclOpenMP.cpp (original)
> +++ cfe/trunk/lib/AST/DeclOpenMP.cpp Mon Feb 8 03:29:13 2016
> @@ -7,7 +7,8 @@
> //
>
> //===----------------------------------------------------------------------===//
> /// \file
> -/// \brief This file implements OMPThreadPrivateDecl class.
> +/// \brief This file implements OMPThreadPrivateDecl, OMPCapturedFieldDecl
> +/// classes.
> ///
>
> //===----------------------------------------------------------------------===//
>
> @@ -52,3 +53,21 @@ void OMPThreadPrivateDecl::setVars(Array
> std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr
> *>());
> }
>
>
> +//===----------------------------------------------------------------------===//
> +// OMPCapturedFieldDecl Implementation.
>
> +//===----------------------------------------------------------------------===//
> +
> +void OMPCapturedFieldDecl::anchor() {}
> +
> +OMPCapturedFieldDecl *OMPCapturedFieldDecl::Create(ASTContext &C,
> + DeclContext *DC,
> + IdentifierInfo *Id,
> + QualType T) {
> + return new (C, DC) OMPCapturedFieldDecl(C, DC, Id, T);
> +}
> +
> +OMPCapturedFieldDecl *OMPCapturedFieldDecl::CreateDeserialized(ASTContext
> &C,
> + unsigned
> ID) {
> + return new (C, ID) OMPCapturedFieldDecl(C, nullptr, nullptr,
> QualType());
> +}
> +
>
> Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
> +++ cfe/trunk/lib/AST/DeclPrinter.cpp Mon Feb 8 03:29:13 2016
> @@ -92,6 +92,7 @@ namespace {
> void VisitUsingDecl(UsingDecl *D);
> void VisitUsingShadowDecl(UsingShadowDecl *D);
> void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
> + void VisitOMPCapturedFieldDecl(OMPCapturedFieldDecl *D);
>
> void PrintTemplateParameters(const TemplateParameterList *Params,
> const TemplateArgumentList *Args =
> nullptr);
> @@ -1366,3 +1367,7 @@ void DeclPrinter::VisitOMPThreadPrivateD
> }
> }
>
> +void DeclPrinter::VisitOMPCapturedFieldDecl(OMPCapturedFieldDecl *D) {
> + D->getInit()->printPretty(Out, nullptr, Policy, Indentation);
> +}
> +
>
> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Feb 8 03:29:13 2016
> @@ -16,6 +16,7 @@
> #include "clang/AST/Attr.h"
> #include "clang/AST/DeclCXX.h"
> #include "clang/AST/DeclObjC.h"
> +#include "clang/AST/DeclOpenMP.h"
> #include "clang/AST/DeclTemplate.h"
> #include "clang/AST/Expr.h"
> #include "clang/AST/ExprCXX.h"
> @@ -763,15 +764,16 @@ template<typename T>
> void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
> for (typename T::varlist_iterator I = Node->varlist_begin(),
> E = Node->varlist_end();
> - I != E; ++I) {
> + I != E; ++I) {
> assert(*I && "Expected non-null Stmt");
> + OS << (I == Node->varlist_begin() ? StartSym : ',');
> if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*I)) {
> - OS << (I == Node->varlist_begin() ? StartSym : ',');
> - cast<NamedDecl>(DRE->getDecl())->printQualifiedName(OS);
> - } else {
> - OS << (I == Node->varlist_begin() ? StartSym : ',');
> + if (auto *CFD = dyn_cast<OMPCapturedFieldDecl>(DRE->getDecl()))
> + CFD->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr,
> Policy, 0);
> + else
> + DRE->getDecl()->printQualifiedName(OS);
> + } else
> (*I)->printPretty(OS, nullptr, Policy, 0);
> - }
> }
> }
>
>
> Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Mon Feb 8 03:29:13 2016
> @@ -92,6 +92,7 @@ void CodeGenFunction::EmitDecl(const Dec
> case Decl::Label: // __label__ x;
> case Decl::Import:
> case Decl::OMPThreadPrivate:
> + case Decl::OMPCapturedField:
> case Decl::Empty:
> // None of these decls require codegen support.
> return;
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Feb 8 03:29:13 2016
> @@ -2874,6 +2874,7 @@ ExprResult Sema::BuildDeclarationNameExp
> case Decl::Var:
> case Decl::VarTemplateSpecialization:
> case Decl::VarTemplatePartialSpecialization:
> + case Decl::OMPCapturedField:
> // In C, "extern void blah;" is valid and is an r-value.
> if (!getLangOpts().CPlusPlus &&
> !type.hasQualifiers() &&
>
> Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprMember.cpp Mon Feb 8 03:29:13 2016
> @@ -1735,9 +1735,19 @@ BuildFieldReferenceExpr(Sema &S, Expr *B
> FoundDecl, Field);
> if (Base.isInvalid())
> return ExprError();
> - return BuildMemberExpr(S, S.Context, Base.get(), IsArrow, OpLoc, SS,
> - /*TemplateKWLoc=*/SourceLocation(), Field,
> FoundDecl,
> - MemberNameInfo, MemberType, VK, OK);
> + MemberExpr *ME =
> + BuildMemberExpr(S, S.Context, Base.get(), IsArrow, OpLoc, SS,
> + /*TemplateKWLoc=*/SourceLocation(), Field,
> FoundDecl,
> + MemberNameInfo, MemberType, VK, OK);
> +
> + // Build a reference to a private copy for non-static data members in
> + // non-static member functions, privatized by OpenMP constructs.
> + if (S.getLangOpts().OpenMP && IsArrow &&
> + isa<CXXThisExpr>(Base.get()->IgnoreParenImpCasts())) {
> + if (auto *PrivateCopy = S.IsOpenMPCapturedDecl(Field))
> + return S.getOpenMPCapturedExpr(PrivateCopy, VK, OK);
> + }
> + return ME;
> }
>
> /// Builds an implicit member access expression. The current context
>
> Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Mon Feb 8 03:29:13 2016
> @@ -71,10 +71,11 @@ public:
> OpenMPDirectiveKind DKind;
> OpenMPClauseKind CKind;
> Expr *RefExpr;
> + DeclRefExpr *PrivateCopy;
> SourceLocation ImplicitDSALoc;
> DSAVarData()
> : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr),
> - ImplicitDSALoc() {}
> + PrivateCopy(nullptr), ImplicitDSALoc() {}
> };
>
> private:
> @@ -83,11 +84,12 @@ private:
> struct DSAInfo {
> OpenMPClauseKind Attributes;
> Expr *RefExpr;
> + DeclRefExpr *PrivateCopy;
> };
> - typedef llvm::SmallDenseMap<ValueDecl *, DSAInfo, 64> DeclSAMapTy;
> - typedef llvm::SmallDenseMap<ValueDecl *, Expr *, 64> AlignedMapTy;
> + typedef llvm::DenseMap<ValueDecl *, DSAInfo> DeclSAMapTy;
> + typedef llvm::DenseMap<ValueDecl *, Expr *> AlignedMapTy;
> typedef llvm::DenseMap<ValueDecl *, unsigned> LoopControlVariablesMapTy;
> - typedef llvm::SmallDenseMap<ValueDecl *, MapInfo, 64> MappedDeclsTy;
> + typedef llvm::DenseMap<ValueDecl *, MapInfo> MappedDeclsTy;
> typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>>
> CriticalsWithHintsTy;
>
> @@ -195,7 +197,8 @@ public:
> ValueDecl *getParentLoopControlVariable(unsigned I);
>
> /// \brief Adds explicit data sharing attribute to the specified
> declaration.
> - void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A);
> + void addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
> + DeclRefExpr *PrivateCopy = nullptr);
>
> /// \brief Returns data sharing attributes from top of the stack for the
> /// specified declaration.
> @@ -434,6 +437,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
> // attributes.
> if (Iter->SharingMap.count(D)) {
> DVar.RefExpr = Iter->SharingMap[D].RefExpr;
> + DVar.PrivateCopy = Iter->SharingMap[D].PrivateCopy;
> DVar.CKind = Iter->SharingMap[D].Attributes;
> DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
> return DVar;
> @@ -547,15 +551,20 @@ ValueDecl *DSAStackTy::getParentLoopCont
> return nullptr;
> }
>
> -void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A) {
> +void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
> + DeclRefExpr *PrivateCopy) {
> D = getCanonicalDecl(D);
> if (A == OMPC_threadprivate) {
> Stack[0].SharingMap[D].Attributes = A;
> Stack[0].SharingMap[D].RefExpr = E;
> + Stack[0].SharingMap[D].PrivateCopy = nullptr;
> } else {
> assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
> Stack.back().SharingMap[D].Attributes = A;
> Stack.back().SharingMap[D].RefExpr = E;
> + Stack.back().SharingMap[D].PrivateCopy = PrivateCopy;
> + if (PrivateCopy)
> + addDSA(PrivateCopy->getDecl(), PrivateCopy, A);
> }
> }
>
> @@ -682,6 +691,7 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
> auto I = std::prev(StartI);
> if (I->SharingMap.count(D)) {
> DVar.RefExpr = I->SharingMap[D].RefExpr;
> + DVar.PrivateCopy = I->SharingMap[D].PrivateCopy;
> DVar.CKind = I->SharingMap[D].Attributes;
> DVar.ImplicitDSALoc = I->DefaultAttrLoc;
> }
> @@ -886,7 +896,7 @@ bool Sema::IsOpenMPCapturedByRef(ValueDe
> return IsByRef;
> }
>
> -bool Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
> +VarDecl *Sema::IsOpenMPCapturedDecl(ValueDecl *D) {
> assert(LangOpts.OpenMP && "OpenMP is not allowed");
> D = getCanonicalDecl(D);
>
> @@ -900,18 +910,16 @@ bool Sema::IsOpenMPCapturedDecl(ValueDec
> auto *VD = dyn_cast<VarDecl>(D);
> if (VD && !VD->hasLocalStorage()) {
> if (DSAStack->getCurrentDirective() == OMPD_target &&
> - !DSAStack->isClauseParsingMode()) {
> - return true;
> - }
> + !DSAStack->isClauseParsingMode())
> + return VD;
> if (DSAStack->getCurScope() &&
> DSAStack->hasDirective(
> [](OpenMPDirectiveKind K, const DeclarationNameInfo &DNI,
> SourceLocation Loc) -> bool {
> return isOpenMPTargetExecutionDirective(K);
> },
> - false)) {
> - return true;
> - }
> + false))
> + return VD;
> }
>
> if (DSAStack->getCurrentDirective() != OMPD_unknown &&
> @@ -921,15 +929,16 @@ bool Sema::IsOpenMPCapturedDecl(ValueDec
> (VD && VD->hasLocalStorage() &&
> isParallelOrTaskRegion(DSAStack->getCurrentDirective())) ||
> (VD && DSAStack->isForceVarCapturing()))
> - return true;
> + return VD;
> auto DVarPrivate = DSAStack->getTopDSA(D,
> DSAStack->isClauseParsingMode());
> if (DVarPrivate.CKind != OMPC_unknown &&
> isOpenMPPrivate(DVarPrivate.CKind))
> - return true;
> + return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
> DVarPrivate = DSAStack->hasDSA(D, isOpenMPPrivate, MatchesAlways(),
> DSAStack->isClauseParsingMode());
> - return DVarPrivate.CKind != OMPC_unknown;
> + if (DVarPrivate.CKind != OMPC_unknown)
> + return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
> }
> - return false;
> + return nullptr;
> }
>
> bool Sema::isOpenMPPrivateDecl(ValueDecl *D, unsigned Level) {
> @@ -6958,6 +6967,50 @@ OMPClause *Sema::ActOnOpenMPVarListClaus
> return Res;
> }
>
> +static DeclRefExpr *buildCapture(Sema &S, IdentifierInfo *Id,
> + Expr *CaptureExpr) {
> + ASTContext &C = S.getASTContext();
> + Expr *Init = CaptureExpr->IgnoreImpCasts();
> + QualType Ty = Init->getType();
> + if (CaptureExpr->getObjectKind() == OK_Ordinary) {
> + if (S.getLangOpts().CPlusPlus)
> + Ty = C.getLValueReferenceType(Ty);
> + else {
> + Ty = C.getPointerType(Ty);
> + ExprResult Res =
> + S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf,
> Init);
> + if (!Res.isUsable())
> + return nullptr;
> + Init = Res.get();
> + }
> + }
> + auto *CFD = OMPCapturedFieldDecl::Create(C, S.CurContext, Id, Ty);
> + S.CurContext->addHiddenDecl(CFD);
> + S.AddInitializerToDecl(CFD, Init, /*DirectInit=*/false,
> + /*TypeMayContainAuto=*/true);
> + return buildDeclRefExpr(S, CFD, Ty.getNonReferenceType(),
> SourceLocation());
> +}
> +
> +ExprResult Sema::getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
> + ExprObjectKind OK) {
> + SourceLocation Loc = Capture->getInit()->getExprLoc();
> + ExprResult Res = BuildDeclRefExpr(
> + Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
> + if (!Res.isUsable())
> + return ExprError();
> + if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
> + Res = CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
> + if (!Res.isUsable())
> + return ExprError();
> + }
> + if (VK != VK_LValue && Res.get()->isGLValue()) {
> + Res = DefaultLvalueConversion(Res.get());
> + if (!Res.isUsable())
> + return ExprError();
> + }
> + return Res;
> +}
> +
> OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
> SourceLocation StartLoc,
> SourceLocation LParenLoc,
> @@ -7050,8 +7103,11 @@ OMPClause *Sema::ActOnOpenMPPrivateClaus
> auto VDPrivateRefExpr = buildDeclRefExpr(
> *this, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
>
> - DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private);
> - Vars.push_back(RefExpr->IgnoreParens());
> + DeclRefExpr *Ref = nullptr;
> + if (!VD)
> + Ref = buildCapture(*this, D->getIdentifier(), RefExpr);
> + DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
> + Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref);
> PrivateCopies.push_back(VDPrivateRefExpr);
> }
>
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Feb 8 03:29:13
> 2016
> @@ -2483,6 +2483,11 @@ Decl *TemplateDeclInstantiator::VisitOMP
> return TD;
> }
>
> +Decl *TemplateDeclInstantiator::VisitOMPCapturedFieldDecl(
> + OMPCapturedFieldDecl * /*D*/) {
> + llvm_unreachable("Should not be met in templates");
> +}
> +
> Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
> return VisitFunctionDecl(D, nullptr);
> }
>
> Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTCommon.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTCommon.cpp Mon Feb 8 03:29:13 2016
> @@ -329,6 +329,7 @@ bool serialization::isRedeclarableDeclKi
> case Decl::ClassScopeFunctionSpecialization:
> case Decl::Import:
> case Decl::OMPThreadPrivate:
> + case Decl::OMPCapturedField:
> case Decl::BuiltinTemplate:
> return false;
>
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Feb 8 03:29:13 2016
> @@ -350,6 +350,7 @@ namespace clang {
> void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
> void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
> void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
> + void VisitOMPCapturedFieldDecl(OMPCapturedFieldDecl *D);
>
> /// We've merged the definition \p MergedDef into the existing
> definition
> /// \p Def. Ensure that \p Def is made visible whenever \p MergedDef
> is made
> @@ -2360,6 +2361,10 @@ void ASTDeclReader::VisitOMPThreadPrivat
> D->setVars(Vars);
> }
>
> +void ASTDeclReader::VisitOMPCapturedFieldDecl(OMPCapturedFieldDecl *D) {
> + VisitVarDecl(D);
> +}
> +
>
> //===----------------------------------------------------------------------===//
> // Attribute Reading
>
> //===----------------------------------------------------------------------===//
> @@ -3323,6 +3328,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID I
> case DECL_OMP_THREADPRIVATE:
> D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID,
> Record[Idx++]);
> break;
> + case DECL_OMP_CAPTUREDFIELD:
> + D = OMPCapturedFieldDecl::CreateDeserialized(Context, ID);
> + break;
> case DECL_EMPTY:
> D = EmptyDecl::CreateDeserialized(Context, ID);
> break;
>
> Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Mon Feb 8 03:29:13 2016
> @@ -131,6 +131,7 @@ namespace clang {
> void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
> void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
> void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
> + void VisitOMPCapturedFieldDecl(OMPCapturedFieldDecl *D);
>
> /// Add an Objective-C type parameter list to the given record.
> void AddObjCTypeParamList(ObjCTypeParamList *typeParams) {
> @@ -1628,6 +1629,11 @@ void ASTDeclWriter::VisitOMPThreadPrivat
> Code = serialization::DECL_OMP_THREADPRIVATE;
> }
>
> +void ASTDeclWriter::VisitOMPCapturedFieldDecl(OMPCapturedFieldDecl *D) {
> + VisitVarDecl(D);
> + Code = serialization::DECL_OMP_CAPTUREDFIELD;
> +}
> +
>
> //===----------------------------------------------------------------------===//
> // ASTWriter Implementation
>
> //===----------------------------------------------------------------------===//
>
> Modified: cfe/trunk/test/OpenMP/parallel_private_codegen.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_private_codegen.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/OpenMP/parallel_private_codegen.cpp (original)
> +++ cfe/trunk/test/OpenMP/parallel_private_codegen.cpp Mon Feb 8 03:29:13
> 2016
> @@ -18,11 +18,69 @@ struct S {
>
> volatile int g __attribute__((aligned(128))) = 1212;
>
> +struct SS {
> + int a;
> + int b : 4;
> + int &c;
> + SS(int &d) : a(0), b(0), c(d) {
> +#pragma omp parallel private(a, b, c)
> +#ifdef LAMBDA
> + [&]() {
> + ++this->a, --b, (this)->c /= 1;
> +#pragma omp parallel private(a, b, c)
> + ++(this)->a, --b, this->c /= 1;
> + }();
> +#elif defined(BLOCKS)
> + ^{
> + ++a;
> + --this->b;
> + (this)->c /= 1;
> +#pragma omp parallel private(a, b, c)
> + ++(this)->a, --b, this->c /= 1;
> + }();
> +#else
> + ++this->a, --b, c /= 1;
> +#endif
> + }
> +};
> +
> +template<typename T>
> +struct SST {
> + T a;
> + SST() : a(T()) {
> +#pragma omp parallel private(a)
> +#ifdef LAMBDA
> + [&]() {
> + [&]() {
> + ++this->a;
> +#pragma omp parallel private(a)
> + ++(this)->a;
> + }();
> + }();
> +#elif defined(BLOCKS)
> + ^{
> + ^{
> + ++a;
> +#pragma omp parallel private(a)
> + ++(this)->a;
> + }();
> + }();
> +#else
> + ++(this)->a;
> +#endif
> + }
> +};
> +
> +// CHECK: [[SS_TY:%.+]] = type { i{{[0-9]+}}, i8
> +// LAMBDA: [[SS_TY:%.+]] = type { i{{[0-9]+}}, i8
> +// BLOCKS: [[SS_TY:%.+]] = type { i{{[0-9]+}}, i8
> // CHECK: [[S_FLOAT_TY:%.+]] = type { float }
> // CHECK: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
> +// CHECK: [[SST_TY:%.+]] = type { i{{[0-9]+}} }
> template <typename T>
> T tmain() {
> S<T> test;
> + SST<T> sst;
> T t_var __attribute__((aligned(128))) = T();
> T vec[] __attribute__((aligned(128))) = {1, 2};
> S<T> s_arr[] __attribute__((aligned(128))) = {1, 2};
> @@ -37,9 +95,11 @@ T tmain() {
>
> int main() {
> static int sivar;
> + SS ss(sivar);
> #ifdef LAMBDA
> // LAMBDA: [[G:@.+]] = global i{{[0-9]+}} 1212,
> // LAMBDA-LABEL: @main
> + // LAMBDA: call
> // LAMBDA: call{{.*}} void [[OUTER_LAMBDA:@.+]](
> [&]() {
> // LAMBDA: define{{.*}} internal{{.*}} void [[OUTER_LAMBDA]](
> @@ -47,6 +107,36 @@ int main() {
> // LAMBDA: call{{.*}} void {{.+}} @__kmpc_fork_call({{.+}}, i32 0,
> {{.+}}* [[OMP_REGION:@.+]] to {{.+}})
> #pragma omp parallel private(g, sivar)
> {
> + // LAMBDA: define {{.+}} @{{.+}}([[SS_TY]]* %
> + // LAMBDA: store i{{[0-9]+}} 0, i{{[0-9]+}}* %
> + // LAMBDA: store i8
> + // LAMBDA: 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]+}}*, [[SS_TY]]*)* [[SS_MICROTASK:@.+]] to void
> + // LAMBDA: ret
> +
> + // LAMBDA: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias
> [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})
> + // LAMBDA-NOT: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %
> + // LAMBDA: call{{.*}} void
> + // LAMBDA: ret void
> +
> + // LAMBDA: define internal void @{{.+}}(i{{[0-9]+}}* noalias
> [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})
> + // LAMBDA: [[A_PRIV:%.+]] = alloca i{{[0-9]+}},
> + // LAMBDA: [[B_PRIV:%.+]] = alloca i{{[0-9]+}},
> + // LAMBDA: [[C_PRIV:%.+]] = alloca i{{[0-9]+}},
> + // LAMBDA: store i{{[0-9]+}}* [[A_PRIV]], i{{[0-9]+}}** [[REFA:%.+]],
> + // LAMBDA: store i{{[0-9]+}}* [[C_PRIV]], i{{[0-9]+}}** [[REFC:%.+]],
> + // LAMBDA-NEXT: [[A_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}**
> [[REFA]],
> + // LAMBDA-NEXT: [[A_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}*
> [[A_PRIV]],
> + // LAMBDA-NEXT: [[INC:%.+]] = add nsw i{{[0-9]+}} [[A_VAL]], 1
> + // LAMBDA-NEXT: store i{{[0-9]+}} [[INC]], i{{[0-9]+}}* [[A_PRIV]],
> + // LAMBDA-NEXT: [[B_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}*
> [[B_PRIV]],
> + // LAMBDA-NEXT: [[DEC:%.+]] = add nsw i{{[0-9]+}} [[B_VAL]], -1
> + // LAMBDA-NEXT: store i{{[0-9]+}} [[DEC]], i{{[0-9]+}}* [[B_PRIV]],
> + // LAMBDA-NEXT: [[C_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}**
> [[REFC]],
> + // LAMBDA-NEXT: [[C_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}*
> [[C_PRIV]],
> + // LAMBDA-NEXT: [[DIV:%.+]] = sdiv i{{[0-9]+}} [[C_VAL]], 1
> + // LAMBDA-NEXT: store i{{[0-9]+}} [[DIV]], i{{[0-9]+}}* [[C_PRIV]],
> + // LAMBDA-NEXT: ret void
> +
> // LAMBDA: define{{.*}} internal{{.*}} void [[OMP_REGION]](i32*
> noalias %{{.+}}, i32* noalias %{{.+}})
> // LAMBDA: [[G_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
> // LAMBDA: [[SIVAR_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}},
> @@ -80,6 +170,7 @@ int main() {
> #elif defined(BLOCKS)
> // BLOCKS: [[G:@.+]] = global i{{[0-9]+}} 1212,
> // BLOCKS-LABEL: @main
> + // BLOCKS: call
> // BLOCKS: call{{.*}} void {{%.+}}(i8
> ^{
> // BLOCKS: define{{.*}} internal{{.*}} void {{.+}}(i8*
> @@ -116,6 +207,35 @@ int main() {
> }
> }();
> return 0;
> +// BLOCKS: define {{.+}} @{{.+}}([[SS_TY]]* %
> +// BLOCKS: store i{{[0-9]+}} 0, i{{[0-9]+}}* %
> +// BLOCKS: store i8
> +// BLOCKS: 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]+}}*, [[SS_TY]]*)* [[SS_MICROTASK:@.+]] to void
> +// BLOCKS: ret
> +
> +// BLOCKS: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias
> [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})
> +// BLOCKS-NOT: getelementptr {{.*}}[[SS_TY]], [[SS_TY]]* %
> +// BLOCKS: call{{.*}} void
> +// BLOCKS: ret void
> +
> +// BLOCKS: define internal void @{{.+}}(i{{[0-9]+}}* noalias
> [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})
> +// BLOCKS: [[A_PRIV:%.+]] = alloca i{{[0-9]+}},
> +// BLOCKS: [[B_PRIV:%.+]] = alloca i{{[0-9]+}},
> +// BLOCKS: [[C_PRIV:%.+]] = alloca i{{[0-9]+}},
> +// BLOCKS: store i{{[0-9]+}}* [[A_PRIV]], i{{[0-9]+}}** [[REFA:%.+]],
> +// BLOCKS: store i{{[0-9]+}}* [[C_PRIV]], i{{[0-9]+}}** [[REFC:%.+]],
> +// BLOCKS-NEXT: [[A_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}**
> [[REFA]],
> +// BLOCKS-NEXT: [[A_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[A_PRIV]],
> +// BLOCKS-NEXT: [[INC:%.+]] = add nsw i{{[0-9]+}} [[A_VAL]], 1
> +// BLOCKS-NEXT: store i{{[0-9]+}} [[INC]], i{{[0-9]+}}* [[A_PRIV]],
> +// BLOCKS-NEXT: [[B_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[B_PRIV]],
> +// BLOCKS-NEXT: [[DEC:%.+]] = add nsw i{{[0-9]+}} [[B_VAL]], -1
> +// BLOCKS-NEXT: store i{{[0-9]+}} [[DEC]], i{{[0-9]+}}* [[B_PRIV]],
> +// BLOCKS-NEXT: [[C_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}**
> [[REFC]],
> +// BLOCKS-NEXT: [[C_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[C_PRIV]],
> +// BLOCKS-NEXT: [[DIV:%.+]] = sdiv i{{[0-9]+}} [[C_VAL]], 1
> +// BLOCKS-NEXT: store i{{[0-9]+}} [[DIV]], i{{[0-9]+}}* [[C_PRIV]],
> +// BLOCKS-NEXT: ret void
> #else
> S<float> test;
> int t_var = 0;
> @@ -166,6 +286,31 @@ int main() {
> // CHECK: call void [[S_INT_TY_DESTR:@.+]]([[S_INT_TY]]*
> // CHECK: ret
> //
> +// CHECK: define {{.+}} @{{.+}}([[SS_TY]]* %
> +// CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* %
> +// CHECK: store i8
> +// 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]+}}*, [[SS_TY]]*)* [[SS_MICROTASK:@.+]] to void
> +// CHECK: ret
> +
> +// CHECK: define internal void [[SS_MICROTASK]](i{{[0-9]+}}* noalias
> [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SS_TY]]* %{{.+}})
> +// CHECK: [[A_PRIV:%.+]] = alloca i{{[0-9]+}},
> +// CHECK: [[B_PRIV:%.+]] = alloca i{{[0-9]+}},
> +// CHECK: [[C_PRIV:%.+]] = alloca i{{[0-9]+}},
> +// CHECK: store i{{[0-9]+}}* [[A_PRIV]], i{{[0-9]+}}** [[REFA:%.+]],
> +// CHECK: store i{{[0-9]+}}* [[C_PRIV]], i{{[0-9]+}}** [[REFC:%.+]],
> +// CHECK-NEXT: [[A_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFA]],
> +// CHECK-NEXT: [[A_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[A_PRIV]],
> +// CHECK-NEXT: [[INC:%.+]] = add nsw i{{[0-9]+}} [[A_VAL]], 1
> +// CHECK-NEXT: store i{{[0-9]+}} [[INC]], i{{[0-9]+}}* [[A_PRIV]],
> +// CHECK-NEXT: [[B_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[B_PRIV]],
> +// CHECK-NEXT: [[DEC:%.+]] = add nsw i{{[0-9]+}} [[B_VAL]], -1
> +// CHECK-NEXT: store i{{[0-9]+}} [[DEC]], i{{[0-9]+}}* [[B_PRIV]],
> +// CHECK-NEXT: [[C_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFC]],
> +// CHECK-NEXT: [[C_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[C_PRIV]],
> +// CHECK-NEXT: [[DIV:%.+]] = sdiv i{{[0-9]+}} [[C_VAL]], 1
> +// CHECK-NEXT: store i{{[0-9]+}} [[DIV]], i{{[0-9]+}}* [[C_PRIV]],
> +// CHECK-NEXT: ret void
> +
> // CHECK: define internal void [[TMAIN_MICROTASK]](i{{[0-9]+}}* noalias
> [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}})
> // CHECK: [[T_VAR_PRIV:%.+]] = alloca i{{[0-9]+}}, align 128
> // CHECK: [[VEC_PRIV:%.+]] = alloca [2 x i{{[0-9]+}}], align 128
> @@ -184,5 +329,20 @@ int main() {
> // 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
> +
> +// CHECK: define {{.+}} @{{.+}}([[SST_TY]]* %
> +// CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* %
> +// 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]+}}*, [[SST_TY]]*)* [[SST_MICROTASK:@.+]] to void
> +// CHECK: ret
> +
> +// CHECK: define internal void [[SST_MICROTASK]](i{{[0-9]+}}* noalias
> [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[SST_TY]]* %{{.+}})
> +// CHECK: [[A_PRIV:%.+]] = alloca i{{[0-9]+}},
> +// CHECK: store i{{[0-9]+}}* [[A_PRIV]], i{{[0-9]+}}** [[REF:%.+]],
> +// CHECK-NEXT: [[A_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REF]],
> +// CHECK-NEXT: [[A_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[A_PRIV]],
> +// CHECK-NEXT: [[INC:%.+]] = add nsw i{{[0-9]+}} [[A_VAL]], 1
> +// CHECK-NEXT: store i{{[0-9]+}} [[INC]], i{{[0-9]+}}* [[A_PRIV]],
> +// CHECK-NEXT: ret void
> +
> #endif
>
>
> Modified: cfe/trunk/tools/libclang/CIndex.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=260077&r1=260076&r2=260077&view=diff
>
> ==============================================================================
> --- cfe/trunk/tools/libclang/CIndex.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndex.cpp Mon Feb 8 03:29:13 2016
> @@ -5669,6 +5669,7 @@ CXCursor clang_getCursorDefinition(CXCur
> case Decl::StaticAssert:
> case Decl::Block:
> case Decl::Captured:
> + case Decl::OMPCapturedField:
> case Decl::Label: // FIXME: Is this right??
> case Decl::ClassScopeFunctionSpecialization:
> case Decl::Import:
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160208/790b2269/attachment-0001.html>
More information about the cfe-commits
mailing list