diff options
| author | John McCall <rjmccall@apple.com> | 2011-02-03 08:15:49 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2011-02-03 08:15:49 +0000 |
| commit | f3a8860ee1031a56ba05d9a33840e6a6a9dd3854 (patch) | |
| tree | d44e28d27fc630f1256ffc033d9c8221cdf97b1a /clang/lib/Sema/SemaExprCXX.cpp | |
| parent | 981ca313d7f5ffe701836ff3dc2c13e99e106e77 (diff) | |
| download | bcm5719-llvm-f3a8860ee1031a56ba05d9a33840e6a6a9dd3854.tar.gz bcm5719-llvm-f3a8860ee1031a56ba05d9a33840e6a6a9dd3854.zip | |
More capturing of 'this': implicit member expressions. Getting that
right for anonymous struct/union members led to me discovering some
seemingly broken code in that area of Sema, which I fixed, partly by
changing the representation of member pointer constants so that
IndirectFieldDecls aren't expanded. This led to assorted cleanups with
member pointers in CodeGen, and while I was doing that I saw some random
other things to clean up.
llvm-svn: 124785
Diffstat (limited to 'clang/lib/Sema/SemaExprCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 73e9778a742..81031a54eed 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -559,19 +559,22 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { return false; } -ExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) { - /// C++ 9.3.2: In the body of a non-static member function, the keyword this - /// is a non-lvalue expression whose value is the address of the object for - /// which the function is called. - - // Ignore block scopes (but nothing else). +CXXMethodDecl *Sema::tryCaptureCXXThis() { + // Ignore block scopes: we can capture through them. + // Ignore nested enum scopes: we'll diagnose non-constant expressions + // where they're invalid, and other uses are legitimate. + // Don't ignore nested class scopes: you can't use 'this' in a local class. DeclContext *DC = CurContext; - while (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext(); + while (true) { + if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext(); + else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext(); + else break; + } - // If we're not an instance method, error out. + // If we're not in an instance method, error out. CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC); if (!method || !method->isInstance()) - return ExprError(Diag(ThisLoc, diag::err_invalid_this_use)); + return 0; // Mark that we're closing on 'this' in all the block scopes, if applicable. for (unsigned idx = FunctionScopes.size() - 1; @@ -579,7 +582,18 @@ ExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) { --idx) cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true; - return Owned(new (Context) CXXThisExpr(ThisLoc, method->getThisType(Context), + return method; +} + +ExprResult Sema::ActOnCXXThis(SourceLocation loc) { + /// C++ 9.3.2: In the body of a non-static member function, the keyword this + /// is a non-lvalue expression whose value is the address of the object for + /// which the function is called. + + CXXMethodDecl *method = tryCaptureCXXThis(); + if (!method) return Diag(loc, diag::err_invalid_this_use); + + return Owned(new (Context) CXXThisExpr(loc, method->getThisType(Context), /*isImplicit=*/false)); } |

