diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-04-16 18:27:27 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-04-16 18:27:27 +0000 |
commit | 74e2fc332e07c76d4e69ccbd0e9e47a0bafd3908 (patch) | |
tree | e13935dca7e6eaa9e934215f7517e99dd591fcb4 /lib/Parse/ParseCXXInlineMethods.cpp | |
parent | 0f90590c96375052c67116f620fafa2b1eadb41e (diff) |
Implement the last part of C++ [class.mem]p2, delaying the parsing of
exception specifications on member functions until after the closing
'}' for the containing class. This allows, for example, a member
function to throw an instance of its own class. Fixes PR12564 and a
fairly embarassing oversight in our C++98/03 support.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154844 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index d2a85355b6..f04d76723b 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -59,7 +59,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, } } - HandleMemberFunctionDefaultArgs(D, FnD); + HandleMemberFunctionDeclDelays(D, FnD); D.complete(FnD); @@ -348,6 +348,77 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { LM.DefaultArgs[I].Toks = 0; } } + + // Parse a delayed exception-specification, if there is one. + if (CachedTokens *Toks = LM.ExceptionSpecTokens) { + // Save the current token position. + SourceLocation origLoc = Tok.getLocation(); + + // Parse the default argument from its saved token stream. + Toks->push_back(Tok); // So that the current token doesn't get lost + PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); + + // Consume the previously-pushed token. + ConsumeAnyToken(); + + // 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. + CXXMethodDecl *Method; + if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(LM.Method)) + Method = cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + else + Method = cast<CXXMethodDecl>(LM.Method); + + Sema::CXXThisScopeRAII ThisScope(Actions, Method->getParent(), + Method->getTypeQualifiers(), + getLangOpts().CPlusPlus0x); + + // Parse the exception-specification. + SourceRange SpecificationRange; + SmallVector<ParsedType, 4> DynamicExceptions; + SmallVector<SourceRange, 4> DynamicExceptionRanges; + ExprResult NoexceptExpr; + CachedTokens *ExceptionSpecTokens; + + ExceptionSpecificationType EST + = tryParseExceptionSpecification(/*Delayed=*/false, SpecificationRange, + DynamicExceptions, + DynamicExceptionRanges, NoexceptExpr, + ExceptionSpecTokens); + + // Clean up the remaining tokens. + if (Tok.is(tok::cxx_exceptspec_end)) + ConsumeToken(); + else if (EST != EST_None) + Diag(Tok.getLocation(), diag::err_except_spec_unparsed); + + // Attach the exception-specification to the method. + if (EST != EST_None) + Actions.actOnDelayedExceptionSpecification(LM.Method, EST, + SpecificationRange, + DynamicExceptions, + DynamicExceptionRanges, + NoexceptExpr.isUsable()? + NoexceptExpr.get() : 0); + + assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, + Tok.getLocation()) && + "tryParseExceptionSpecification went over the exception tokens!"); + + // There could be leftover tokens (e.g. because of an error). + // Skip through until we reach the original token position. + while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + delete LM.ExceptionSpecTokens; + LM.ExceptionSpecTokens = 0; + } + PrototypeScope.Exit(); // Finish the delayed C++ method declaration. |