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 | 5808ce43f8d7e71f5acacc9ca320268c4f37565a (patch) | |
tree | 50a9b47a2ac607cfe51b3498125d8d4b07667e17 /lib/Sema/SemaExprCXX.cpp | |
parent | 553304523bcce281aa3b1afe0f84ae34a90a3c86 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124785 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 73e9778a74..81031a54ee 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/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)); } |