summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/Attr.td7
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp12
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp115
-rw-r--r--clang/test/OpenMP/for_ast_print.cpp24
-rw-r--r--clang/test/OpenMP/for_linear_messages.cpp2
-rw-r--r--clang/test/OpenMP/for_simd_linear_messages.cpp2
-rw-r--r--clang/test/OpenMP/parallel_for_linear_messages.cpp2
-rw-r--r--clang/test/OpenMP/parallel_for_simd_linear_messages.cpp2
-rw-r--r--clang/test/OpenMP/target_parallel_for_linear_messages.cpp2
9 files changed, 92 insertions, 76 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index b77a5337192..983f5346797 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2185,6 +2185,13 @@ def OMPThreadPrivateDecl : InheritableAttr {
let Documentation = [Undocumented];
}
+def OMPCaptureNoInit : InheritableAttr {
+ // This attribute has no spellings as it is only ever created implicitly.
+ let Spellings = [];
+ let SemaHandler = 0;
+ let Documentation = [Undocumented];
+}
+
def InternalLinkage : InheritableAttr {
let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">];
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 90d6a829e14..ddceb1b559c 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -18,6 +18,7 @@
#include "TargetInfo.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/AST/DeclOpenMP.h"
using namespace clang;
using namespace CodeGen;
@@ -30,8 +31,15 @@ class OMPLexicalScope {
for (const auto *C : S.clauses()) {
if (auto *CPI = OMPClauseWithPreInit::get(C)) {
if (auto *PreInit = cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
- for (const auto *I : PreInit->decls())
- CGF.EmitVarDecl(cast<VarDecl>(*I));
+ for (const auto *I : PreInit->decls()) {
+ if (!I->hasAttr<OMPCaptureNoInitAttr>())
+ CGF.EmitVarDecl(cast<VarDecl>(*I));
+ else {
+ CodeGenFunction::AutoVarEmission Emission =
+ CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
+ CGF.EmitAutoVarCleanups(Emission);
+ }
+ }
}
}
}
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 86ad66f4a62..50148b5187c 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -1706,6 +1706,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
Expr *CaptureExpr, bool WithInit) {
+ assert(CaptureExpr);
ASTContext &C = S.getASTContext();
Expr *Init = CaptureExpr->IgnoreImpCasts();
QualType Ty = Init->getType();
@@ -1723,12 +1724,11 @@ static OMPCapturedExprDecl *buildCaptureDecl(Sema &S, IdentifierInfo *Id,
WithInit = true;
}
auto *CED = OMPCapturedExprDecl::Create(C, S.CurContext, Id, Ty);
+ if (!WithInit)
+ CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C, SourceRange()));
S.CurContext->addHiddenDecl(CED);
- if (WithInit)
- S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
- /*TypeMayContainAuto=*/true);
- else
- S.ActOnUninitializedDecl(CED, /*TypeMayContainAuto=*/true);
+ S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false,
+ /*TypeMayContainAuto=*/true);
return CED;
}
@@ -7676,7 +7676,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList,
}
if (TopDVar.CKind == OMPC_firstprivate ||
(!IsOpenMPCapturedDecl(D) &&
- !cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit())) {
+ Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
ExprResult RefRes = DefaultLvalueConversion(Ref);
if (!RefRes.isUsable())
continue;
@@ -8277,7 +8277,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/false);
if (!IsOpenMPCapturedDecl(D)) {
ExprCaptures.push_back(Ref->getDecl());
- if (!cast<OMPCapturedExprDecl>(Ref->getDecl())->getInit()) {
+ if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
ExprResult RefRes = DefaultLvalueConversion(Ref);
if (!RefRes.isUsable())
continue;
@@ -8340,115 +8340,96 @@ OMPClause *Sema::ActOnOpenMPLinearClause(
}
for (auto &RefExpr : VarList) {
assert(RefExpr && "NULL expr in OpenMP linear clause.");
- if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ SourceLocation ELoc;
+ SourceRange ERange;
+ Expr *SimpleRefExpr = RefExpr;
+ auto Res = getPrivateItem(*this, SimpleRefExpr, ELoc, ERange,
+ /*AllowArraySection=*/false);
+ if (Res.second) {
// It will be analyzed later.
Vars.push_back(RefExpr);
Privates.push_back(nullptr);
Inits.push_back(nullptr);
- continue;
}
-
- // OpenMP [2.14.3.7, linear clause]
- // A list item that appears in a linear clause is subject to the private
- // clause semantics described in Section 2.14.3.3 on page 159 except as
- // noted. In addition, the value of the new list item on each iteration
- // of the associated loop(s) corresponds to the value of the original
- // list item before entering the construct plus the logical number of
- // the iteration times linear-step.
-
- SourceLocation ELoc = RefExpr->getExprLoc();
- // OpenMP [2.1, C/C++]
- // A list item is a variable name.
- // OpenMP [2.14.3.3, Restrictions, p.1]
- // A variable that is part of another variable (as an array or
- // structure element) cannot appear in a private clause.
- DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
- if (!DE || !isa<VarDecl>(DE->getDecl())) {
- Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
- << 0 << RefExpr->getSourceRange();
+ ValueDecl *D = Res.first;
+ if (!D)
continue;
- }
- VarDecl *VD = cast<VarDecl>(DE->getDecl());
+ QualType Type = D->getType();
+ auto *VD = dyn_cast<VarDecl>(D);
// OpenMP [2.14.3.7, linear clause]
// A list-item cannot appear in more than one linear clause.
// A list-item that appears in a linear clause cannot appear in any
// other data-sharing attribute clause.
- DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false);
+ DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, false);
if (DVar.RefExpr) {
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
<< getOpenMPClauseName(OMPC_linear);
- ReportOriginalDSA(*this, DSAStack, VD, DVar);
- continue;
- }
-
- QualType QType = VD->getType();
- if (QType->isDependentType() || QType->isInstantiationDependentType()) {
- // It will be analyzed later.
- Vars.push_back(DE);
- Privates.push_back(nullptr);
- Inits.push_back(nullptr);
+ ReportOriginalDSA(*this, DSAStack, D, DVar);
continue;
}
// A variable must not have an incomplete type or a reference type.
- if (RequireCompleteType(ELoc, QType,
- diag::err_omp_linear_incomplete_type)) {
+ if (RequireCompleteType(ELoc, Type,
+ diag::err_omp_linear_incomplete_type))
continue;
- }
if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
- !QType->isReferenceType()) {
+ !Type->isReferenceType()) {
Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
- << QType << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
+ << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
continue;
}
- QType = QType.getNonReferenceType();
+ Type = Type.getNonReferenceType();
// A list item must not be const-qualified.
- if (QType.isConstant(Context)) {
+ if (Type.isConstant(Context)) {
Diag(ELoc, diag::err_omp_const_variable)
<< getOpenMPClauseName(OMPC_linear);
bool IsDecl =
+ !VD ||
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
+ Diag(D->getLocation(),
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ << D;
continue;
}
// A list item must be of integral or pointer type.
- QType = QType.getUnqualifiedType().getCanonicalType();
- const Type *Ty = QType.getTypePtrOrNull();
+ Type = Type.getUnqualifiedType().getCanonicalType();
+ const auto *Ty = Type.getTypePtrOrNull();
if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) &&
!Ty->isPointerType())) {
- Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << QType;
+ Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
bool IsDecl =
+ !VD ||
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
- Diag(VD->getLocation(),
+ Diag(D->getLocation(),
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
- << VD;
+ << D;
continue;
}
// Build private copy of original var.
- auto *Private = buildVarDecl(*this, ELoc, QType, VD->getName(),
- VD->hasAttrs() ? &VD->getAttrs() : nullptr);
- auto *PrivateRef = buildDeclRefExpr(
- *this, Private, DE->getType().getUnqualifiedType(), DE->getExprLoc());
+ auto *Private = buildVarDecl(*this, ELoc, Type, D->getName(),
+ D->hasAttrs() ? &D->getAttrs() : nullptr);
+ auto *PrivateRef = buildDeclRefExpr(*this, Private, Type, ELoc);
// Build var to save initial value.
- VarDecl *Init = buildVarDecl(*this, ELoc, QType, ".linear.start");
+ VarDecl *Init = buildVarDecl(*this, ELoc, Type, ".linear.start");
Expr *InitExpr;
+ DeclRefExpr *Ref = nullptr;
+ if (!VD)
+ Ref = buildCapture(*this, D, SimpleRefExpr, /*WithInit=*/true);
if (LinKind == OMPC_LINEAR_uval)
- InitExpr = VD->getInit();
+ InitExpr = VD ? VD->getInit() : SimpleRefExpr;
else
- InitExpr = DE;
+ InitExpr = VD ? SimpleRefExpr : Ref;
AddInitializerToDecl(Init, DefaultLvalueConversion(InitExpr).get(),
- /*DirectInit*/ false, /*TypeMayContainAuto*/ false);
- auto InitRef = buildDeclRefExpr(
- *this, Init, DE->getType().getUnqualifiedType(), DE->getExprLoc());
- DSAStack->addDSA(VD, DE, OMPC_linear);
- Vars.push_back(DE);
+ /*DirectInit=*/false, /*TypeMayContainAuto=*/false);
+ auto InitRef = buildDeclRefExpr(*this, Init, Type, ELoc);
+
+ DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
+ Vars.push_back(VD ? RefExpr->IgnoreParens() : Ref);
Privates.push_back(PrivateRef);
Inits.push_back(InitRef);
}
diff --git a/clang/test/OpenMP/for_ast_print.cpp b/clang/test/OpenMP/for_ast_print.cpp
index 38dafc0125d..182b395c13c 100644
--- a/clang/test/OpenMP/for_ast_print.cpp
+++ b/clang/test/OpenMP/for_ast_print.cpp
@@ -19,16 +19,22 @@ template <typename T>
class S7 : public T {
protected:
T a;
- S7() : a(0) {}
+ T &b;
+ typename T::type c:12;
+ typename T::type &d;
+ S7() : a(0), b(a), c(0), d(a.a) {}
public:
- S7(typename T::type v) : a(v) {
+ S7(typename T::type v) : a(v), b(a), c(v), d(a.a) {
#pragma omp for private(a) private(this->a) private(T::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
#pragma omp for lastprivate(a) lastprivate(this->a) lastprivate(T::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
+#pragma omp for linear(val(c))
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
}
S7 &operator=(S7 &s) {
#pragma omp for private(a) private(this->a)
@@ -37,16 +43,22 @@ public:
#pragma omp for lastprivate(a) lastprivate(this->a)
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
+#pragma omp for linear(uval(this->b))
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
return *this;
}
};
// CHECK: #pragma omp for private(this->a) private(this->a) private(this->S::a)
// CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(this->S::a)
+// CHECK: #pragma omp for linear(val(this->c))
// CHECK: #pragma omp for private(this->a) private(this->a) private(T::a)
// CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(T::a)
+// CHECK: #pragma omp for linear(val(this->c))
// CHECK: #pragma omp for private(this->a) private(this->a)
// CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a)
+// CHECK: #pragma omp for linear(uval(this->b))
class S8 : public S7<S> {
S8() {}
@@ -59,6 +71,9 @@ public:
#pragma omp for lastprivate(a) lastprivate(this->a) lastprivate(S7<S>::a)
for (int k = 0; k < a.a; ++k)
++this->a.a;
+#pragma omp for linear(ref(S7<S>::d))
+ for (int k = 0; k < a.a; ++k)
+ ++this->a.a;
}
S8 &operator=(S8 &s) {
#pragma omp for private(a) private(this->a)
@@ -67,14 +82,19 @@ public:
#pragma omp for lastprivate(a) lastprivate(this->a)
for (int k = 0; k < s.a.a; ++k)
++s.a.a;
+#pragma omp for linear(this->c)
+ for (int k = 0; k < s.a.a; ++k)
+ ++s.a.a;
return *this;
}
};
// CHECK: #pragma omp for private(this->a) private(this->a) private(this->S7<S>::a)
// CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a) lastprivate(this->S7<S>::a)
+// CHECK: #pragma omp for linear(ref(this->S7<S>::d))
// CHECK: #pragma omp for private(this->a) private(this->a)
// CHECK: #pragma omp for lastprivate(this->a) lastprivate(this->a)
+// CHECK: #pragma omp for linear(this->c)
template <class T, int N>
T tmain(T argc) {
diff --git a/clang/test/OpenMP/for_linear_messages.cpp b/clang/test/OpenMP/for_linear_messages.cpp
index 39fb21ef7be..ab8934979ac 100644
--- a/clang/test/OpenMP/for_linear_messages.cpp
+++ b/clang/test/OpenMP/for_linear_messages.cpp
@@ -212,7 +212,7 @@ int main(int argc, char **argv) {
#pragma omp for linear(i) ordered(1) // expected-error {{'linear' clause cannot be specified along with 'ordered' clause with a parameter}}
for (int k = 0; k < argc; ++k) ++k;
- foomain<int,char>(argc,argv);
+ foomain<int,char>(argc,argv); // expected-note {{n instantiation of function template specialization 'foomain<int, char>' requested here}}
return 0;
}
diff --git a/clang/test/OpenMP/for_simd_linear_messages.cpp b/clang/test/OpenMP/for_simd_linear_messages.cpp
index 44370a15664..3f93125a38a 100644
--- a/clang/test/OpenMP/for_simd_linear_messages.cpp
+++ b/clang/test/OpenMP/for_simd_linear_messages.cpp
@@ -208,7 +208,7 @@ int main(int argc, char **argv) {
#pragma omp for simd linear(i)
for (int k = 0; k < argc; ++k) ++k;
- foomain<int,char>(argc,argv);
+ foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
return 0;
}
diff --git a/clang/test/OpenMP/parallel_for_linear_messages.cpp b/clang/test/OpenMP/parallel_for_linear_messages.cpp
index 7272aada92a..e5f5b61873c 100644
--- a/clang/test/OpenMP/parallel_for_linear_messages.cpp
+++ b/clang/test/OpenMP/parallel_for_linear_messages.cpp
@@ -263,7 +263,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k)
++k;
- foomain<int, char>(argc, argv);
+ foomain<int, char>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
return 0;
}
diff --git a/clang/test/OpenMP/parallel_for_simd_linear_messages.cpp b/clang/test/OpenMP/parallel_for_simd_linear_messages.cpp
index 858f53f4674..fc1895a3685 100644
--- a/clang/test/OpenMP/parallel_for_simd_linear_messages.cpp
+++ b/clang/test/OpenMP/parallel_for_simd_linear_messages.cpp
@@ -208,7 +208,7 @@ int main(int argc, char **argv) {
#pragma omp parallel for simd linear(i)
for (int k = 0; k < argc; ++k) ++k;
- foomain<int,char>(argc,argv);
+ foomain<int,char>(argc,argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
return 0;
}
diff --git a/clang/test/OpenMP/target_parallel_for_linear_messages.cpp b/clang/test/OpenMP/target_parallel_for_linear_messages.cpp
index c1694c0c499..36e897d5946 100644
--- a/clang/test/OpenMP/target_parallel_for_linear_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_linear_messages.cpp
@@ -263,7 +263,7 @@ int main(int argc, char **argv) {
for (int k = 0; k < argc; ++k)
++k;
- foomain<int, char>(argc, argv);
+ foomain<int, char>(argc, argv); // expected-note {{in instantiation of function template specialization 'foomain<int, char>' requested here}}
return 0;
}
OpenPOWER on IntegriCloud