summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/DeclBase.cpp1
-rw-r--r--clang/lib/AST/DeclOpenMP.cpp21
-rw-r--r--clang/lib/AST/DeclPrinter.cpp5
-rw-r--r--clang/lib/AST/StmtPrinter.cpp14
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp1
-rw-r--r--clang/lib/Sema/SemaExpr.cpp1
-rw-r--r--clang/lib/Sema/SemaExprMember.cpp16
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp94
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp5
-rw-r--r--clang/lib/Serialization/ASTCommon.cpp1
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp8
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp6
12 files changed, 144 insertions, 29 deletions
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 72587e388e4..b699bec083c 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -655,6 +655,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCCategoryImpl:
case Import:
case OMPThreadPrivate:
+ case OMPCapturedField:
case Empty:
// Never looked up by name.
return 0;
diff --git a/clang/lib/AST/DeclOpenMP.cpp b/clang/lib/AST/DeclOpenMP.cpp
index 493e2cd4122..33677bacea7 100644
--- a/clang/lib/AST/DeclOpenMP.cpp
+++ b/clang/lib/AST/DeclOpenMP.cpp
@@ -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(ArrayRef<Expr *> VL) {
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());
+}
+
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 19c7da3074b..1a0e1488bb1 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -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::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
}
}
+void DeclPrinter::VisitOMPCapturedFieldDecl(OMPCapturedFieldDecl *D) {
+ D->getInit()->printPretty(Out, nullptr, Policy, Indentation);
+}
+
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index d9c3457f486..830eeb9efac 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -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);
- }
}
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index e8a4d552923..e18e86da029 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -92,6 +92,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
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;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 20a0e3f6a71..0c17aa1911c 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2874,6 +2874,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
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() &&
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index f62b5a58e84..415587498d4 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -1735,9 +1735,19 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow,
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
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 5b38f436fb7..d4c1f98c998 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -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::getDSA(StackTy::reverse_iterator Iter,
// 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::getParentLoopControlVariable(unsigned I) {
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::getTopDSA(ValueDecl *D, bool FromParent) {
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(ValueDecl *D,
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(ValueDecl *D) {
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(ValueDecl *D) {
(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::ActOnOpenMPVarListClause(
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::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
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);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 625760c68ca..0f011ab159a 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2483,6 +2483,11 @@ Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
return TD;
}
+Decl *TemplateDeclInstantiator::VisitOMPCapturedFieldDecl(
+ OMPCapturedFieldDecl * /*D*/) {
+ llvm_unreachable("Should not be met in templates");
+}
+
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
return VisitFunctionDecl(D, nullptr);
}
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index 2b78d745864..68621f3709f 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -329,6 +329,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::ClassScopeFunctionSpecialization:
case Decl::Import:
case Decl::OMPThreadPrivate:
+ case Decl::OMPCapturedField:
case Decl::BuiltinTemplate:
return false;
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index b249da99462..074de1a71ac 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -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::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
D->setVars(Vars);
}
+void ASTDeclReader::VisitOMPCapturedFieldDecl(OMPCapturedFieldDecl *D) {
+ VisitVarDecl(D);
+}
+
//===----------------------------------------------------------------------===//
// Attribute Reading
//===----------------------------------------------------------------------===//
@@ -3323,6 +3328,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
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;
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 54bba282ab8..4620f56055b 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -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::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
Code = serialization::DECL_OMP_THREADPRIVATE;
}
+void ASTDeclWriter::VisitOMPCapturedFieldDecl(OMPCapturedFieldDecl *D) {
+ VisitVarDecl(D);
+ Code = serialization::DECL_OMP_CAPTUREDFIELD;
+}
+
//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud