diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 40 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 25 |
2 files changed, 52 insertions, 13 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ad4fea84d3e..f7756ba606c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1602,10 +1602,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, } bool refersToEnclosingScope = - (CurContext != D->getDeclContext() && - D->getDeclContext()->isFunctionOrMethod()) || - (isa<VarDecl>(D) && - cast<VarDecl>(D)->isInitCapture()); + isa<VarDecl>(D) && + NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc()); DeclRefExpr *E; if (isa<VarTemplateSpecializationDecl>(D)) { @@ -11799,7 +11797,7 @@ static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl * const bool Diagnose, Sema &S) { if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC)) return getLambdaAwareParentOfDeclContext(DC); - else { + else if (Var->hasLocalStorage()) { if (Diagnose) diagnoseUncapturableValueReference(S, Loc, Var, DC); } @@ -12241,7 +12239,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, QualType &CaptureType, QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt) { - bool Nested = false; + bool Nested = Var->isInitCapture(); DeclContext *DC = CurContext; const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt @@ -12259,8 +12257,13 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, // If the variable is declared in the current context (and is not an // init-capture), there is no need to capture it. - if (!Var->isInitCapture() && Var->getDeclContext() == DC) return true; - if (!Var->hasLocalStorage()) return true; + if (!Nested && Var->getDeclContext() == DC) return true; + + // Capture global variables if it is required to use private copy of this + // variable. + bool IsGlobal = !Var->hasLocalStorage(); + if (IsGlobal && !(LangOpts.OpenMP && IsOpenMPCapturedVar(Var))) + return true; // Walk up the stack to determine whether we can capture the variable, // performing the "simple" checks that don't depend on type. We stop when @@ -12281,8 +12284,17 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation ExprLoc, ExprLoc, BuildAndDiagnose, *this); - if (!ParentDC) return true; - + // We need to check for the parent *first* because, if we *have* + // private-captured a global variable, we need to recursively capture it in + // intermediate blocks, lambdas, etc. + if (!ParentDC) { + if (IsGlobal) { + FunctionScopesIndex = MaxFunctionScopesIndex - 1; + break; + } + return true; + } + FunctionScopeInfo *FSI = FunctionScopes[FunctionScopesIndex]; CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI); @@ -12508,6 +12520,14 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, DeclRefType, nullptr); } +bool Sema::NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc) { + QualType CaptureType; + QualType DeclRefType; + return !tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(), + /*BuildAndDiagnose=*/false, CaptureType, + DeclRefType, nullptr); +} + QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { QualType CaptureType; QualType DeclRefType; diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 995054321d3..a1064d68b05 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -551,6 +551,19 @@ void Sema::InitDataSharingAttributesStack() { #define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack) +bool Sema::IsOpenMPCapturedVar(VarDecl *VD) { + assert(LangOpts.OpenMP && "OpenMP is not allowed"); + if (DSAStack->getCurrentDirective() != OMPD_unknown) { + auto DVarPrivate = DSAStack->getTopDSA(VD, /*FromParent=*/false); + if (DVarPrivate.CKind != OMPC_unknown && isOpenMPPrivate(DVarPrivate.CKind)) + return true; + DVarPrivate = DSAStack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), + /*FromParent=*/false); + return DVarPrivate.CKind != OMPC_unknown; + } + return false; +} + void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; } void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind, @@ -4378,7 +4391,7 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, VDInitRefExpr = DeclRefExpr::Create( Context, /*QualifierLoc*/ NestedNameSpecifierLoc(), /*TemplateKWLoc*/ SourceLocation(), VDInit, - /*isEnclosingLocal*/ false, ELoc, Type, + /*isEnclosingLocal*/ true, ELoc, Type, /*VK*/ VK_LValue); VDInit->setIsUsed(); auto Init = DefaultLvalueConversion(VDInitRefExpr).get(); @@ -4392,8 +4405,14 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, else VDPrivate->setInit(Result.getAs<Expr>()); } else { - AddInitializerToDecl(VDPrivate, DefaultLvalueConversion(DE).get(), - /*DirectInit*/ false, /*TypeMayContainAuto*/ false); + AddInitializerToDecl( + VDPrivate, DefaultLvalueConversion( + DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), + SourceLocation(), DE->getDecl(), + /*isEnclosingLocal=*/true, + DE->getExprLoc(), DE->getType(), + /*VK=*/VK_LValue)).get(), + /*DirectInit=*/false, /*TypeMayContainAuto=*/false); } if (VDPrivate->isInvalidDecl()) { if (IsImplicitClause) { |