| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 1 | //===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | //  This file implements semantic analysis for C++ lambda expressions. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 | #include "clang/Sema/DeclSpec.h" | 
|  | 14 | #include "clang/Sema/Initialization.h" | 
|  | 15 | #include "clang/Sema/Lookup.h" | 
|  | 16 | #include "clang/Sema/ScopeInfo.h" | 
|  | 17 | #include "clang/Sema/SemaInternal.h" | 
|  | 18 | #include "clang/AST/ExprCXX.h" | 
|  | 19 | using namespace clang; | 
|  | 20 | using namespace sema; | 
|  | 21 |  | 
|  | 22 | void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, | 
|  | 23 | Declarator &ParamInfo, | 
|  | 24 | Scope *CurScope) { | 
|  | 25 | DeclContext *DC = CurContext; | 
|  | 26 | while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) | 
|  | 27 | DC = DC->getParent(); | 
|  | 28 |  | 
|  | 29 | // Start constructing the lambda class. | 
|  | 30 | CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC, | 
|  | 31 | Intro.Range.getBegin(), | 
| Douglas Gregor | 5e058eb | 2012-02-09 02:20:38 +0000 | [diff] [blame] | 32 | /*IdLoc=*/Intro.Range.getBegin(), | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 33 | /*Id=*/0); | 
|  | 34 | Class->startDefinition(); | 
|  | 35 | Class->setLambda(true); | 
|  | 36 | CurContext->addDecl(Class); | 
|  | 37 |  | 
|  | 38 | // Build the call operator; we don't really have all the relevant information | 
|  | 39 | // at this point, but we need something to attach child declarations to. | 
|  | 40 | QualType MethodTy; | 
|  | 41 | TypeSourceInfo *MethodTyInfo; | 
|  | 42 | bool ExplicitParams = true; | 
|  | 43 | SourceLocation EndLoc; | 
|  | 44 | if (ParamInfo.getNumTypeObjects() == 0) { | 
|  | 45 | // C++11 [expr.prim.lambda]p4: | 
|  | 46 | //   If a lambda-expression does not include a lambda-declarator, it is as | 
|  | 47 | //   if the lambda-declarator were (). | 
|  | 48 | FunctionProtoType::ExtProtoInfo EPI; | 
|  | 49 | EPI.TypeQuals |= DeclSpec::TQ_const; | 
|  | 50 | MethodTy = Context.getFunctionType(Context.DependentTy, | 
|  | 51 | /*Args=*/0, /*NumArgs=*/0, EPI); | 
|  | 52 | MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); | 
|  | 53 | ExplicitParams = false; | 
|  | 54 | EndLoc = Intro.Range.getEnd(); | 
|  | 55 | } else { | 
|  | 56 | assert(ParamInfo.isFunctionDeclarator() && | 
|  | 57 | "lambda-declarator is a function"); | 
|  | 58 | DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo(); | 
|  | 59 |  | 
|  | 60 | // C++11 [expr.prim.lambda]p5: | 
|  | 61 | //   This function call operator is declared const (9.3.1) if and only if | 
|  | 62 | //   the lambda-expression's parameter-declaration-clause is not followed | 
|  | 63 | //   by mutable. It is neither virtual nor declared volatile. [...] | 
|  | 64 | if (!FTI.hasMutableQualifier()) | 
|  | 65 | FTI.TypeQuals |= DeclSpec::TQ_const; | 
|  | 66 |  | 
|  | 67 | // C++11 [expr.prim.lambda]p5: | 
|  | 68 | //   [...] Default arguments (8.3.6) shall not be specified in the | 
|  | 69 | //   parameter-declaration-clause of a lambda-declarator. | 
|  | 70 | CheckExtraCXXDefaultArguments(ParamInfo); | 
|  | 71 |  | 
|  | 72 | MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); | 
|  | 73 | // FIXME: Can these asserts actually fail? | 
|  | 74 | assert(MethodTyInfo && "no type from lambda-declarator"); | 
|  | 75 | MethodTy = MethodTyInfo->getType(); | 
|  | 76 | assert(!MethodTy.isNull() && "no type from lambda declarator"); | 
|  | 77 | EndLoc = ParamInfo.getSourceRange().getEnd(); | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | // C++11 [expr.prim.lambda]p5: | 
|  | 81 | //   The closure type for a lambda-expression has a public inline function | 
|  | 82 | //   call operator (13.5.4) whose parameters and return type are described by | 
|  | 83 | //   the lambda-expression's parameter-declaration-clause and | 
|  | 84 | //   trailing-return-type respectively. | 
|  | 85 | DeclarationName MethodName | 
|  | 86 | = Context.DeclarationNames.getCXXOperatorName(OO_Call); | 
|  | 87 | DeclarationNameLoc MethodNameLoc; | 
|  | 88 | MethodNameLoc.CXXOperatorName.BeginOpNameLoc | 
|  | 89 | = Intro.Range.getBegin().getRawEncoding(); | 
|  | 90 | MethodNameLoc.CXXOperatorName.EndOpNameLoc | 
|  | 91 | = Intro.Range.getEnd().getRawEncoding(); | 
|  | 92 | CXXMethodDecl *Method | 
|  | 93 | = CXXMethodDecl::Create(Context, Class, EndLoc, | 
|  | 94 | DeclarationNameInfo(MethodName, | 
|  | 95 | Intro.Range.getBegin(), | 
|  | 96 | MethodNameLoc), | 
|  | 97 | MethodTy, MethodTyInfo, | 
|  | 98 | /*isStatic=*/false, | 
|  | 99 | SC_None, | 
|  | 100 | /*isInline=*/true, | 
|  | 101 | /*isConstExpr=*/false, | 
|  | 102 | EndLoc); | 
|  | 103 | Method->setAccess(AS_public); | 
|  | 104 | Class->addDecl(Method); | 
|  | 105 | Method->setLexicalDeclContext(DC); // FIXME: Minor hack. | 
| Douglas Gregor | 503384f | 2012-02-09 00:47:04 +0000 | [diff] [blame] | 106 |  | 
|  | 107 | // Attributes on the lambda apply to the method. | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 108 | ProcessDeclAttributes(CurScope, Method, ParamInfo); | 
|  | 109 |  | 
| Douglas Gregor | 503384f | 2012-02-09 00:47:04 +0000 | [diff] [blame] | 110 | // Introduce the function call operator as the current declaration context. | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 111 | PushDeclContext(CurScope, Method); | 
|  | 112 |  | 
|  | 113 | // Introduce the lambda scope. | 
|  | 114 | PushLambdaScope(Class, Method); | 
|  | 115 | LambdaScopeInfo *LSI = getCurLambda(); | 
|  | 116 | if (Intro.Default == LCD_ByCopy) | 
|  | 117 | LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; | 
|  | 118 | else if (Intro.Default == LCD_ByRef) | 
|  | 119 | LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref; | 
|  | 120 | LSI->IntroducerRange = Intro.Range; | 
|  | 121 | LSI->ExplicitParams = ExplicitParams; | 
|  | 122 | LSI->Mutable = (Method->getTypeQualifiers() & Qualifiers::Const) == 0; | 
|  | 123 |  | 
|  | 124 | // Handle explicit captures. | 
|  | 125 | for (llvm::SmallVector<LambdaCapture, 4>::const_iterator | 
|  | 126 | C = Intro.Captures.begin(), | 
|  | 127 | E = Intro.Captures.end(); | 
|  | 128 | C != E; ++C) { | 
|  | 129 | if (C->Kind == LCK_This) { | 
|  | 130 | // C++11 [expr.prim.lambda]p8: | 
|  | 131 | //   An identifier or this shall not appear more than once in a | 
|  | 132 | //   lambda-capture. | 
|  | 133 | if (LSI->isCXXThisCaptured()) { | 
|  | 134 | Diag(C->Loc, diag::err_capture_more_than_once) | 
|  | 135 | << "'this'" | 
|  | 136 | << SourceRange(LSI->getCXXThisCapture().getLocation()); | 
|  | 137 | continue; | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | // C++11 [expr.prim.lambda]p8: | 
|  | 141 | //   If a lambda-capture includes a capture-default that is =, the | 
|  | 142 | //   lambda-capture shall not contain this [...]. | 
|  | 143 | if (Intro.Default == LCD_ByCopy) { | 
|  | 144 | Diag(C->Loc, diag::err_this_capture_with_copy_default); | 
|  | 145 | continue; | 
|  | 146 | } | 
|  | 147 |  | 
|  | 148 | // C++11 [expr.prim.lambda]p12: | 
|  | 149 | //   If this is captured by a local lambda expression, its nearest | 
|  | 150 | //   enclosing function shall be a non-static member function. | 
|  | 151 | QualType ThisCaptureType = getCurrentThisType(); | 
|  | 152 | if (ThisCaptureType.isNull()) { | 
|  | 153 | Diag(C->Loc, diag::err_this_capture) << true; | 
|  | 154 | continue; | 
|  | 155 | } | 
|  | 156 |  | 
|  | 157 | CheckCXXThisCapture(C->Loc, /*Explicit=*/true); | 
|  | 158 | continue; | 
|  | 159 | } | 
|  | 160 |  | 
|  | 161 | assert(C->Id && "missing identifier for capture"); | 
|  | 162 |  | 
|  | 163 | // C++11 [expr.prim.lambda]p8: | 
|  | 164 | //   If a lambda-capture includes a capture-default that is &, the | 
|  | 165 | //   identifiers in the lambda-capture shall not be preceded by &. | 
|  | 166 | //   If a lambda-capture includes a capture-default that is =, [...] | 
|  | 167 | //   each identifier it contains shall be preceded by &. | 
|  | 168 | if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) { | 
|  | 169 | Diag(C->Loc, diag::err_reference_capture_with_reference_default); | 
|  | 170 | continue; | 
|  | 171 | } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) { | 
|  | 172 | Diag(C->Loc, diag::err_copy_capture_with_copy_default); | 
|  | 173 | continue; | 
|  | 174 | } | 
|  | 175 |  | 
|  | 176 | DeclarationNameInfo Name(C->Id, C->Loc); | 
|  | 177 | LookupResult R(*this, Name, LookupOrdinaryName); | 
|  | 178 | LookupName(R, CurScope); | 
|  | 179 | if (R.isAmbiguous()) | 
|  | 180 | continue; | 
|  | 181 | if (R.empty()) { | 
|  | 182 | // FIXME: Disable corrections that would add qualification? | 
|  | 183 | CXXScopeSpec ScopeSpec; | 
|  | 184 | DeclFilterCCC<VarDecl> Validator; | 
|  | 185 | if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator)) | 
|  | 186 | continue; | 
|  | 187 | } | 
|  | 188 |  | 
|  | 189 | // C++11 [expr.prim.lambda]p10: | 
|  | 190 | //   The identifiers in a capture-list are looked up using the usual rules | 
|  | 191 | //   for unqualified name lookup (3.4.1); each such lookup shall find a | 
|  | 192 | //   variable with automatic storage duration declared in the reaching | 
|  | 193 | //   scope of the local lambda expression. | 
|  | 194 | // FIXME: Check reaching scope. | 
|  | 195 | VarDecl *Var = R.getAsSingle<VarDecl>(); | 
|  | 196 | if (!Var) { | 
|  | 197 | Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id; | 
|  | 198 | continue; | 
|  | 199 | } | 
|  | 200 |  | 
|  | 201 | if (!Var->hasLocalStorage()) { | 
|  | 202 | Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id; | 
|  | 203 | Diag(Var->getLocation(), diag::note_previous_decl) << C->Id; | 
|  | 204 | continue; | 
|  | 205 | } | 
|  | 206 |  | 
|  | 207 | // C++11 [expr.prim.lambda]p8: | 
|  | 208 | //   An identifier or this shall not appear more than once in a | 
|  | 209 | //   lambda-capture. | 
|  | 210 | if (LSI->isCaptured(Var)) { | 
|  | 211 | Diag(C->Loc, diag::err_capture_more_than_once) | 
|  | 212 | << C->Id | 
|  | 213 | << SourceRange(LSI->getCapture(Var).getLocation()); | 
|  | 214 | continue; | 
|  | 215 | } | 
|  | 216 |  | 
|  | 217 | TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : | 
|  | 218 | TryCapture_ExplicitByVal; | 
|  | 219 | TryCaptureVar(Var, C->Loc, Kind); | 
|  | 220 | } | 
|  | 221 | LSI->finishedExplicitCaptures(); | 
|  | 222 |  | 
|  | 223 | // Set the parameters on the decl, if specified. | 
|  | 224 | if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) { | 
|  | 225 | FunctionProtoTypeLoc Proto = | 
|  | 226 | cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc()); | 
|  | 227 | Method->setParams(Proto.getParams()); | 
|  | 228 | CheckParmsForFunctionDef(Method->param_begin(), | 
|  | 229 | Method->param_end(), | 
|  | 230 | /*CheckParameterNames=*/false); | 
|  | 231 |  | 
|  | 232 | // Introduce our parameters into the function scope | 
|  | 233 | for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) { | 
|  | 234 | ParmVarDecl *Param = Method->getParamDecl(p); | 
|  | 235 | Param->setOwningFunction(Method); | 
|  | 236 |  | 
|  | 237 | // If this has an identifier, add it to the scope stack. | 
|  | 238 | if (Param->getIdentifier()) { | 
|  | 239 | CheckShadow(CurScope, Param); | 
|  | 240 |  | 
|  | 241 | PushOnScopeChains(Param, CurScope); | 
|  | 242 | } | 
|  | 243 | } | 
|  | 244 | } | 
|  | 245 |  | 
|  | 246 | const FunctionType *Fn = MethodTy->getAs<FunctionType>(); | 
|  | 247 | QualType RetTy = Fn->getResultType(); | 
|  | 248 | if (RetTy != Context.DependentTy) { | 
|  | 249 | LSI->ReturnType = RetTy; | 
|  | 250 | } else { | 
|  | 251 | LSI->HasImplicitReturnType = true; | 
|  | 252 | } | 
|  | 253 |  | 
|  | 254 | // FIXME: Check return type is complete, !isObjCObjectType | 
|  | 255 |  | 
| Douglas Gregor | 503384f | 2012-02-09 00:47:04 +0000 | [diff] [blame] | 256 | // Enter a new evaluation context to insulate the block from any | 
|  | 257 | // cleanups from the enclosing full-expression. | 
|  | 258 | PushExpressionEvaluationContext(PotentiallyEvaluated); | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 259 | } | 
|  | 260 |  | 
|  | 261 | void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) { | 
|  | 262 | // Leave the expression-evaluation context. | 
|  | 263 | DiscardCleanupsInEvaluationContext(); | 
|  | 264 | PopExpressionEvaluationContext(); | 
|  | 265 |  | 
|  | 266 | // Leave the context of the lambda. | 
|  | 267 | PopDeclContext(); | 
| Douglas Gregor | 630d5ff | 2012-02-09 01:28:42 +0000 | [diff] [blame] | 268 |  | 
|  | 269 | // Finalize the lambda. | 
|  | 270 | LambdaScopeInfo *LSI = getCurLambda(); | 
|  | 271 | CXXRecordDecl *Class = LSI->Lambda; | 
|  | 272 | Class->setInvalidDecl(); | 
|  | 273 | SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end()); | 
|  | 274 | ActOnFields(0, Class->getLocation(), Class, Fields, | 
|  | 275 | SourceLocation(), SourceLocation(), 0); | 
|  | 276 | CheckCompletedCXXClass(Class); | 
|  | 277 |  | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 278 | PopFunctionScopeInfo(); | 
|  | 279 | } | 
|  | 280 |  | 
|  | 281 | ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, | 
|  | 282 | Stmt *Body, Scope *CurScope) { | 
|  | 283 | // Leave the expression-evaluation context. | 
|  | 284 | DiscardCleanupsInEvaluationContext(); | 
|  | 285 | PopExpressionEvaluationContext(); | 
|  | 286 |  | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 287 | // Collect information from the lambda scope. | 
|  | 288 | llvm::SmallVector<LambdaExpr::Capture, 4> Captures; | 
|  | 289 | llvm::SmallVector<Expr *, 4> CaptureInits; | 
|  | 290 | LambdaCaptureDefault CaptureDefault; | 
|  | 291 | CXXRecordDecl *Class; | 
|  | 292 | SourceRange IntroducerRange; | 
|  | 293 | bool ExplicitParams; | 
| Douglas Gregor | 503384f | 2012-02-09 00:47:04 +0000 | [diff] [blame] | 294 | bool LambdaExprNeedsCleanups; | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 295 | { | 
|  | 296 | LambdaScopeInfo *LSI = getCurLambda(); | 
|  | 297 | Class = LSI->Lambda; | 
|  | 298 | IntroducerRange = LSI->IntroducerRange; | 
|  | 299 | ExplicitParams = LSI->ExplicitParams; | 
| Douglas Gregor | 503384f | 2012-02-09 00:47:04 +0000 | [diff] [blame] | 300 | LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 301 |  | 
|  | 302 | // Translate captures. | 
|  | 303 | for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { | 
|  | 304 | LambdaScopeInfo::Capture From = LSI->Captures[I]; | 
|  | 305 | assert(!From.isBlockCapture() && "Cannot capture __block variables"); | 
|  | 306 | bool IsImplicit = I >= LSI->NumExplicitCaptures; | 
|  | 307 |  | 
|  | 308 | // Handle 'this' capture. | 
|  | 309 | if (From.isThisCapture()) { | 
|  | 310 | Captures.push_back(LambdaExpr::Capture(From.getLocation(), | 
|  | 311 | IsImplicit, | 
|  | 312 | LCK_This)); | 
|  | 313 | CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(), | 
|  | 314 | getCurrentThisType(), | 
|  | 315 | /*isImplicit=*/true)); | 
|  | 316 | continue; | 
|  | 317 | } | 
|  | 318 |  | 
|  | 319 | VarDecl *Var = From.getVariable(); | 
|  | 320 | // FIXME: Handle pack expansions. | 
|  | 321 | LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; | 
|  | 322 | Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, | 
|  | 323 | Kind, Var)); | 
|  | 324 | CaptureInits.push_back(From.getCopyExpr()); | 
|  | 325 | } | 
|  | 326 |  | 
|  | 327 | switch (LSI->ImpCaptureStyle) { | 
|  | 328 | case CapturingScopeInfo::ImpCap_None: | 
|  | 329 | CaptureDefault = LCD_None; | 
|  | 330 | break; | 
|  | 331 |  | 
|  | 332 | case CapturingScopeInfo::ImpCap_LambdaByval: | 
|  | 333 | CaptureDefault = LCD_ByCopy; | 
|  | 334 | break; | 
|  | 335 |  | 
|  | 336 | case CapturingScopeInfo::ImpCap_LambdaByref: | 
|  | 337 | CaptureDefault = LCD_ByRef; | 
|  | 338 | break; | 
|  | 339 |  | 
|  | 340 | case CapturingScopeInfo::ImpCap_Block: | 
|  | 341 | llvm_unreachable("block capture in lambda"); | 
|  | 342 | break; | 
|  | 343 | } | 
|  | 344 |  | 
| Douglas Gregor | 503384f | 2012-02-09 00:47:04 +0000 | [diff] [blame] | 345 | // Finalize the lambda class. | 
|  | 346 | SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end()); | 
|  | 347 | ActOnFields(0, Class->getLocation(), Class, Fields, | 
|  | 348 | SourceLocation(), SourceLocation(), 0); | 
|  | 349 | CheckCompletedCXXClass(Class); | 
|  | 350 |  | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 351 | // C++ [expr.prim.lambda]p7: | 
|  | 352 | //   The lambda-expression's compound-statement yields the | 
|  | 353 | //   function-body (8.4) of the function call operator [...]. | 
|  | 354 | ActOnFinishFunctionBody(LSI->CallOperator, Body, /*IsInstantation=*/false); | 
|  | 355 | } | 
|  | 356 |  | 
| Douglas Gregor | 503384f | 2012-02-09 00:47:04 +0000 | [diff] [blame] | 357 | if (LambdaExprNeedsCleanups) | 
|  | 358 | ExprNeedsCleanups = true; | 
|  | 359 |  | 
| Douglas Gregor | e2c5913 | 2012-02-09 08:14:43 +0000 | [diff] [blame^] | 360 | LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, | 
|  | 361 | CaptureDefault, Captures, | 
|  | 362 | ExplicitParams, CaptureInits, | 
|  | 363 | Body->getLocEnd()); | 
|  | 364 |  | 
|  | 365 | // C++11 [expr.prim.lambda]p2: | 
|  | 366 | //   A lambda-expression shall not appear in an unevaluated operand | 
|  | 367 | //   (Clause 5). | 
|  | 368 | switch (ExprEvalContexts.back().Context) { | 
|  | 369 | case Unevaluated: | 
|  | 370 | // We don't actually diagnose this case immediately, because we | 
|  | 371 | // could be within a context where we might find out later that | 
|  | 372 | // the expression is potentially evaluated (e.g., for typeid). | 
|  | 373 | ExprEvalContexts.back().Lambdas.push_back(Lambda); | 
|  | 374 | break; | 
|  | 375 |  | 
|  | 376 | case ConstantEvaluated: | 
|  | 377 | case PotentiallyEvaluated: | 
|  | 378 | case PotentiallyEvaluatedIfUsed: | 
|  | 379 | break; | 
|  | 380 | } | 
|  | 381 |  | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 382 | Diag(StartLoc, diag::err_lambda_unsupported); | 
| Douglas Gregor | 503384f | 2012-02-09 00:47:04 +0000 | [diff] [blame] | 383 |  | 
|  | 384 | return MaybeBindToTemporary(Lambda); | 
| Douglas Gregor | e2a7ad0 | 2012-02-08 21:18:48 +0000 | [diff] [blame] | 385 | } |