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@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@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits