diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-08-06 03:17:00 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-08-06 03:17:00 +0000 |
commit | fe85cedd58df7daed29201703cfb8806e12876d0 (patch) | |
tree | 3839a33ad270a9f4ed978e24e87a93d3ad409fdd /lib/Sema/SemaCXXScopeSpec.cpp | |
parent | 4403a5e1f956fa86d515492dbe7c7a2817d8780d (diff) |
Support nested-name-specifiers for C++ member access expressions, e.g.,
this->Base::foo
from James Porter!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78278 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaCXXScopeSpec.cpp')
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 27e0ccf7d5..e1cba36c82 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -14,6 +14,7 @@ #include "Sema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/Parse/DeclSpec.h" #include "llvm/ADT/STLExtras.h" @@ -337,6 +338,55 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, T.getTypePtr()); } +Action::OwningExprResult +Sema::ActOnCXXEnterMemberScope(Scope *S, CXXScopeSpec &SS, ExprArg Base, + tok::TokenKind OpKind) { + Expr *BaseExpr = (Expr*)Base.get(); + assert(BaseExpr && "no record expansion"); + + QualType BaseType = BaseExpr->getType(); + // FIXME: handle dependent types + if (BaseType->isDependentType()) + return move(Base); + + // C++ [over.match.oper]p8: + // [...] When operator->returns, the operator-> is applied to the value + // returned, with the original second operand. + if (OpKind == tok::arrow) { + while (BaseType->isRecordType()) { + Base = BuildOverloadedArrowExpr(S, move(Base), BaseExpr->getExprLoc()); + BaseExpr = (Expr*)Base.get(); + if (BaseExpr == NULL) + return ExprError(); + BaseType = BaseExpr->getType(); + } + } + + if (BaseType->isPointerType()) + BaseType = BaseType->getPointeeType(); + + // We could end up with various non-record types here, such as extended + // vector types or Objective-C interfaces. Just return early and let + // ActOnMemberReferenceExpr do the work. + if (!BaseType->isRecordType()) + return move(Base); + + SS.setRange(BaseExpr->getSourceRange()); + SS.setScopeRep( + NestedNameSpecifier::Create(Context, 0, false, BaseType.getTypePtr()) + ); + + if (S) + ActOnCXXEnterDeclaratorScope(S,SS); + return move(Base); +} + +void Sema::ActOnCXXExitMemberScope(Scope *S, const CXXScopeSpec &SS) { + if (S && SS.isSet()) + ActOnCXXExitDeclaratorScope(S,SS); +} + + /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global /// scope or nested-name-specifier) is parsed, part of a declarator-id. /// After this method is called, according to [C++ 3.4.3p3], names should be |