[cfe-commits] r150872 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaType.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
Douglas Gregor
dgregor at apple.com
Fri Feb 17 21:51:20 PST 2012
Author: dgregor
Date: Fri Feb 17 23:51:20 2012
New Revision: 150872
URL: http://llvm.org/viewvc/llvm-project?rev=150872&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=150872&r1=150871&r2=150872&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Feb 17 23:51:20 2012
@@ -2327,6 +2327,10 @@
bool Diagnose, QualType &Type,
unsigned &FunctionScopesIndex, bool &Nested);
+ /// \brief Given a variable, determine the type that a reference to that
+ /// variable will have in the given scope.
+ QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc);
+
/// \brief Determine the type of the field that will capture the
/// given variable in a lambda expression.
///
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=150872&r1=150871&r2=150872&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Feb 17 23:51:20 2012
@@ -2094,42 +2094,6 @@
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 @@
// 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 @@
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 @@
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,
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=150872&r1=150871&r2=150872&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Feb 17 23:51:20 2012
@@ -4382,42 +4382,9 @@
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);
}
}
}
Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp?rev=150872&r1=150871&r2=150872&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp Fri Feb 17 23:51:20 2012
@@ -13,4 +13,7 @@
[x] { // expected-error{{call to deleted constructor of 'const X'}}
}();
}();
+
+ int a;
+ [=]{ [&] { int&x = a; }(); }(); // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
}
Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp?rev=150872&r1=150871&r2=150872&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp Fri Feb 17 23:51:20 2012
@@ -17,12 +17,12 @@
const int &irc = i;
[=,&irc,&ir] {
+ static_assert(is_same<decltype(((r))), float const&>::value,
+ "should be const float&");
static_assert(is_same<decltype(x), float>::value, "should be float");
static_assert(is_same<decltype((x)), const float&>::value,
"should be const float&");
static_assert(is_same<decltype(r), float&>::value, "should be float&");
- static_assert(is_same<decltype(((r))), float const&>::value,
- "should be const float&");
static_assert(is_same<decltype(ir), int&>::value, "should be int&");
static_assert(is_same<decltype((ir)), int&>::value, "should be int&");
static_assert(is_same<decltype(irc), const int&>::value,
More information about the cfe-commits
mailing list