diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-18 05:51:20 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-18 05:51:20 +0000 |
commit | 68932845a432d2a1dbbc57a84fd85bbb37c90487 (patch) | |
tree | 135bedbb565cfe47f8fc84749b471eae7821f674 /lib | |
parent | b78ae9716576399145786b93f687943f8b197170 (diff) |
Unify our computation of the type of a captured reference to a
variable; it was previously duplicated, and one of the copies failed
to account for outer non-mutable lambda captures.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150872 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 81 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 39 |
2 files changed, 43 insertions, 77 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c15102c4da..38783eb865 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2094,42 +2094,6 @@ static bool shouldBuildBlockDeclRef(ValueDecl *D, Sema &S) { return S.getCurBlock() != 0; } -/// \brief Determine whether the given lambda would capture the given -/// variable by copy. -static bool willCaptureByCopy(LambdaScopeInfo *LSI, VarDecl *Var) { - if (LSI->isCaptured(Var)) - return LSI->getCapture(Var).isCopyCapture(); - - return LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval; -} - -static bool shouldAddConstQualToVarRef(ValueDecl *D, Sema &S) { - VarDecl *var = dyn_cast<VarDecl>(D); - if (!var) - return false; - if (var->getDeclContext() == S.CurContext) - return false; - if (!var->hasLocalStorage()) - return false; - - LambdaScopeInfo *LSI = S.getCurLambda(); - if (!LSI) - return false; - - // We don't actually allow capturing a __block variable in a lambda, but - // this way gives better diagnostics. - if (var->hasAttr<BlocksAttr>()) - return false; - - // FIXME: Does the addition of const really only apply in - // potentially-evaluated contexts? The text in the lambda spec - // about decltype hints that it might apply in unevaluated contexts - // as well... and there's precent in our blocks implementation. - return !LSI->Mutable && - S.ExprEvalContexts.back().Context != Sema::Unevaluated && - willCaptureByCopy(LSI, var); -} - static ExprResult BuildBlockDeclRefExpr(Sema &S, ValueDecl *VD, const DeclarationNameInfo &NameInfo) { VarDecl *var = cast<VarDecl>(VD); @@ -2269,7 +2233,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // fallthrough case Decl::ImplicitParam: - case Decl::ParmVar: + case Decl::ParmVar: { // These are always l-values. valueKind = VK_LValue; type = type.getNonReferenceType(); @@ -2277,11 +2241,18 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, if (shouldBuildBlockDeclRef(VD, *this)) return BuildBlockDeclRefExpr(*this, VD, NameInfo); - if (shouldAddConstQualToVarRef(VD, *this)) - type.addConst(); - + // FIXME: Does the addition of const really only apply in + // potentially-evaluated contexts? Since the variable isn't actually + // captured in an unevaluated context, it seems that the answer is no. + if (ExprEvalContexts.back().Context != Sema::Unevaluated) { + QualType CapturedType = getCapturedDeclRefType(cast<VarDecl>(VD), Loc); + if (!CapturedType.isNull()) + type = CapturedType; + } + break; - + } + case Decl::Function: { const FunctionType *fty = type->castAs<FunctionType>(); @@ -9850,6 +9821,34 @@ bool Sema::canCaptureVariable(VarDecl *Var, SourceLocation Loc, bool Explicit, return !Type->isVariablyModifiedType(); } +QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) { + QualType T = Var->getType().getNonReferenceType(); + unsigned FunctionScopesIndex; + bool Nested; + // Determine whether we can capture this variable. + if (!canCaptureVariable(Var, Loc, /*Explicit=*/false, /*Diagnose=*/false, + T, FunctionScopesIndex, Nested)) + return QualType(); + + // Outer lambda scopes may have an effect on the type of a + // capture. Walk the captures outside-in to determine + // whether they can add 'const' to a capture by copy. + T = Var->getType().getNonReferenceType(); + if (FunctionScopesIndex == FunctionScopes.size()) + --FunctionScopesIndex; + for (unsigned I = FunctionScopesIndex, E = FunctionScopes.size(); + I != E; ++I) { + CapturingScopeInfo *CSI = dyn_cast<LambdaScopeInfo>(FunctionScopes[I]); + if (!CSI) + break; + + if (shouldAddConstForScope(CSI, Var)) + T.addConst(); + } + + return T; +} + // Check if the variable needs to be captured; if so, try to perform // the capture. void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc, diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index a4b3d86d10..9c8a68b3da 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -4382,42 +4382,9 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { if (isa<ParenExpr>(E)) { if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) { if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - QualType T = Var->getType(); - unsigned FunctionScopesIndex; - bool Nested; - // Determine whether we can capture this variable. - if (S.canCaptureVariable(Var, DRE->getLocation(), - /*Explicit=*/false, /*Diagnose=*/false, - T, FunctionScopesIndex, Nested)) { - // Outer lambda scopes may have an effect on the type of a - // capture. Walk the captures outside-in to determine - // whether they can add 'const' to a capture by copy. - if (FunctionScopesIndex == S.FunctionScopes.size()) - --FunctionScopesIndex; - for (unsigned I = FunctionScopesIndex, - E = S.FunctionScopes.size(); - I != E; ++I) { - LambdaScopeInfo *LSI - = dyn_cast<LambdaScopeInfo>(S.FunctionScopes[I]); - if (!LSI) - continue; - - bool ByRef = false; - if (LSI->isCaptured(Var)) - ByRef = LSI->getCapture(Var).isReferenceCapture(); - else - ByRef = (LSI->ImpCaptureStyle - == CapturingScopeInfo::ImpCap_LambdaByref); - - T = S.getLambdaCaptureFieldType(T, ByRef); - if (!ByRef && !LSI->Mutable) - T.addConst(); - } - - if (!T->isReferenceType()) - T = S.Context.getLValueReferenceType(T); - return T; - } + QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation()); + if (!T.isNull()) + return S.Context.getLValueReferenceType(T); } } } |