diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-04-16 07:05:22 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-04-16 07:05:22 +0000 |
commit | cefc3afac14d29de5aba7810cc8fe6c858949e9d (patch) | |
tree | 1ebfb2a0c67f5e253edc1a2900cdda348163f4f5 /lib/Parse/ParseDecl.cpp | |
parent | 275a8505420733a9e4c662289f36522a1dabaa51 (diff) |
Implement C++11 [expr.prim.general]p3, which permits the use of 'this'
in the declaration of a non-static member function after the
(optional) cv-qualifier-seq, which in practice means in the exception
specification and late-specified return type.
The new scheme here used to manage 'this' outside of a member function
scope is more general than the Scope-based mechanism previously used
for non-static data member initializers and late-parsesd attributes,
because it can also handle the cv-qualifiers on the member
function. Note, however, that a separate pass is required for static
member functions to determine whether 'this' was used, because we
might not know that we have a static function until after declaration
matching.
Finally, this introduces name mangling for 'this' and for the implicit
'this', which is intended to match GCC's mangling. Independent
verification for the new mangling test case would be appreciated.
Fixes PR10036 and PR12450.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154799 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 884820e023..16c90e9b71 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -729,9 +729,9 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) { if (HasTemplateScope) Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); - // Set or update the scope flags to include Scope::ThisScope. + // Set or update the scope flags. bool AlreadyHasClassScope = Class.TopLevelClass; - unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope|Scope::ThisScope; + unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope; ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope); ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope); @@ -739,11 +739,16 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) { if (!AlreadyHasClassScope) Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); - - for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i) { - Class.LateParsedDeclarations[i]->ParseLexedAttributes(); + { + // Allow 'this' within late-parsed attributes. + Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate, + /*TypeQuals=*/0); + + for (unsigned i = 0, ni = Class.LateParsedDeclarations.size(); i < ni; ++i){ + Class.LateParsedDeclarations[i]->ParseLexedAttributes(); + } } - + if (!AlreadyHasClassScope) Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), Class.TagOrTemplate); @@ -4242,6 +4247,23 @@ void Parser::ParseFunctionDeclarator(Declarator &D, EndLoc = RefQualifierLoc; } + // C++11 [expr.prim.general]p3: + // If a declaration declares a member function or member function + // template of a class X, the expression this is a prvalue of type + // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq + // and the end of the function-definition, member-declarator, or + // declarator. + bool IsCXX11MemberFunction = + getLangOpts().CPlusPlus0x && + (D.getContext() == Declarator::MemberContext || + (D.getContext() == Declarator::FileContext && + D.getCXXScopeSpec().isValid() && + Actions.CurContext->isRecord())); + Sema::CXXThisScopeRAII ThisScope(Actions, + dyn_cast<CXXRecordDecl>(Actions.CurContext), + DS.getTypeQualifiers(), + IsCXX11MemberFunction); + // Parse exception-specification[opt]. ESpecType = MaybeParseExceptionSpecification(ESpecRange, DynamicExceptions, |