summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp94
1 files changed, 88 insertions, 6 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
index c000f69..f04d767 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/contrib/llvm/tools/clang/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.
@@ -447,9 +518,9 @@ void Parser::ParseLexedMemberInitializers(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);
@@ -457,10 +528,20 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
Class.TagOrTemplate);
- for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
- Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
+ {
+ // C++11 [expr.prim.general]p4:
+ // Otherwise, if a member-declarator declares a non-static data member
+ // (9.2) of a class X, the expression this is a prvalue of type "pointer
+ // to X" within the optional brace-or-equal-initializer. It shall not
+ // appear elsewhere in the member-declarator.
+ Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
+ /*TypeQuals=*/(unsigned)0);
+
+ for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
+ Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
+ }
}
-
+
if (!AlreadyHasClassScope)
Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
Class.TagOrTemplate);
@@ -481,6 +562,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
ConsumeAnyToken();
SourceLocation EqualLoc;
+
ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
EqualLoc);
OpenPOWER on IntegriCloud