summaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseCXXInlineMethods.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r--clang/lib/Parse/ParseCXXInlineMethods.cpp280
1 files changed, 181 insertions, 99 deletions
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index f8b5fec438007..d05332b5ac5a7 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -133,7 +133,6 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(
LexedMethod* LM = new LexedMethod(this, FnD);
getCurrentClass().LateParsedDeclarations.push_back(LM);
- LM->TemplateScope = getCurScope()->isTemplateParamScope();
CachedTokens &Toks = LM->Toks;
tok::TokenKind kind = Tok.getKind();
@@ -223,6 +222,7 @@ Parser::LateParsedDeclaration::~LateParsedDeclaration() {}
void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {}
void Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {}
void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {}
+void Parser::LateParsedDeclaration::ParseLexedAttributes() {}
void Parser::LateParsedDeclaration::ParseLexedPragmas() {}
Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C)
@@ -244,6 +244,10 @@ void Parser::LateParsedClass::ParseLexedMethodDefs() {
Self->ParseLexedMethodDefs(*Class);
}
+void Parser::LateParsedClass::ParseLexedAttributes() {
+ Self->ParseLexedAttributes(*Class);
+}
+
void Parser::LateParsedClass::ParseLexedPragmas() {
Self->ParseLexedPragmas(*Class);
}
@@ -260,57 +264,79 @@ void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() {
Self->ParseLexedMemberInitializer(*this);
}
+void Parser::LateParsedAttribute::ParseLexedAttributes() {
+ Self->ParseLexedAttribute(*this, true, false);
+}
+
void Parser::LateParsedPragma::ParseLexedPragmas() {
Self->ParseLexedPragma(*this);
}
+/// Utility to re-enter a possibly-templated scope while parsing its
+/// late-parsed components.
+struct Parser::ReenterTemplateScopeRAII {
+ Parser &P;
+ MultiParseScope Scopes;
+ TemplateParameterDepthRAII CurTemplateDepthTracker;
+
+ ReenterTemplateScopeRAII(Parser &P, Decl *MaybeTemplated, bool Enter = true)
+ : P(P), Scopes(P), CurTemplateDepthTracker(P.TemplateParameterDepth) {
+ if (Enter) {
+ CurTemplateDepthTracker.addDepth(
+ P.ReenterTemplateScopes(Scopes, MaybeTemplated));
+ }
+ }
+};
+
+/// Utility to re-enter a class scope while parsing its late-parsed components.
+struct Parser::ReenterClassScopeRAII : ReenterTemplateScopeRAII {
+ ParsingClass &Class;
+
+ ReenterClassScopeRAII(Parser &P, ParsingClass &Class)
+ : ReenterTemplateScopeRAII(P, Class.TagOrTemplate,
+ /*Enter=*/!Class.TopLevelClass),
+ Class(Class) {
+ // If this is the top-level class, we're still within its scope.
+ if (Class.TopLevelClass)
+ return;
+
+ // Re-enter the class scope itself.
+ Scopes.Enter(Scope::ClassScope|Scope::DeclScope);
+ P.Actions.ActOnStartDelayedMemberDeclarations(P.getCurScope(),
+ Class.TagOrTemplate);
+ }
+ ~ReenterClassScopeRAII() {
+ if (Class.TopLevelClass)
+ return;
+
+ P.Actions.ActOnFinishDelayedMemberDeclarations(P.getCurScope(),
+ Class.TagOrTemplate);
+ }
+};
+
/// ParseLexedMethodDeclarations - We finished parsing the member
/// specification of a top (non-nested) C++ class. Now go over the
/// stack of method declarations with some parts for which parsing was
/// delayed (such as default arguments) and parse them.
void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
- bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
- ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
- HasTemplateScope);
- TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
- if (HasTemplateScope) {
- Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
- ++CurTemplateDepthTracker;
- }
-
- // The current scope is still active if we're the top-level class.
- // Otherwise we'll need to push and enter a new scope.
- bool HasClassScope = !Class.TopLevelClass;
- ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
- HasClassScope);
- if (HasClassScope)
- Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
- Class.TagOrTemplate);
-
- for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
- Class.LateParsedDeclarations[i]->ParseLexedMethodDeclarations();
- }
+ ReenterClassScopeRAII InClassScope(*this, Class);
- if (HasClassScope)
- Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
- Class.TagOrTemplate);
+ for (LateParsedDeclaration *LateD : Class.LateParsedDeclarations)
+ LateD->ParseLexedMethodDeclarations();
}
void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// If this is a member template, introduce the template parameter scope.
- ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
- TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
- if (LM.TemplateScope) {
- Actions.ActOnReenterTemplateScope(getCurScope(), LM.Method);
- ++CurTemplateDepthTracker;
- }
+ ReenterTemplateScopeRAII InFunctionTemplateScope(*this, LM.Method);
+
// Start the delayed C++ method declaration
Actions.ActOnStartDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
// Introduce the parameters into scope and parse their default
// arguments.
- ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
- Scope::FunctionDeclarationScope | Scope::DeclScope);
+ InFunctionTemplateScope.Scopes.Enter(Scope::FunctionPrototypeScope |
+ Scope::FunctionDeclarationScope |
+ Scope::DeclScope);
for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
auto Param = cast<ParmVarDecl>(LM.DefaultArgs[I].Param);
// Introduce the parameter into scope.
@@ -464,7 +490,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
LM.ExceptionSpecTokens = nullptr;
}
- PrototypeScope.Exit();
+ InFunctionTemplateScope.Scopes.Exit();
// Finish the delayed C++ method declaration.
Actions.ActOnFinishDelayedCXXMethodDeclaration(getCurScope(), LM.Method);
@@ -474,30 +500,15 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
/// (non-nested) C++ class. Now go over the stack of lexed methods that were
/// collected during its parsing and parse them all.
void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
- bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
- ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, HasTemplateScope);
- TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
- if (HasTemplateScope) {
- Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
- ++CurTemplateDepthTracker;
- }
- bool HasClassScope = !Class.TopLevelClass;
- ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
- HasClassScope);
+ ReenterClassScopeRAII InClassScope(*this, Class);
- for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
- Class.LateParsedDeclarations[i]->ParseLexedMethodDefs();
- }
+ for (LateParsedDeclaration *D : Class.LateParsedDeclarations)
+ D->ParseLexedMethodDefs();
}
void Parser::ParseLexedMethodDef(LexedMethod &LM) {
// If this is a member template, introduce the template parameter scope.
- ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
- TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
- if (LM.TemplateScope) {
- Actions.ActOnReenterTemplateScope(getCurScope(), LM.D);
- ++CurTemplateDepthTracker;
- }
+ ReenterTemplateScopeRAII InFunctionTemplateScope(*this, LM.D);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -578,23 +589,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
/// of a top (non-nested) C++ class. Now go over the stack of lexed data member
/// initializers that were collected during its parsing and parse them all.
void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
- bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
- ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
- HasTemplateScope);
- TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
- if (HasTemplateScope) {
- Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
- ++CurTemplateDepthTracker;
- }
- // Set or update the scope flags.
- bool AlreadyHasClassScope = Class.TopLevelClass;
- unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope;
- ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope);
- ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope);
-
- if (!AlreadyHasClassScope)
- Actions.ActOnStartDelayedMemberDeclarations(getCurScope(),
- Class.TagOrTemplate);
+ ReenterClassScopeRAII InClassScope(*this, Class);
if (!Class.LateParsedDeclarations.empty()) {
// C++11 [expr.prim.general]p4:
@@ -602,18 +597,14 @@ void Parser::ParseLexedMemberInitializers(ParsingClass &Class) {
// (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.
+ // FIXME: This should be done in ParseLexedMemberInitializer, not here.
Sema::CXXThisScopeRAII ThisScope(Actions, Class.TagOrTemplate,
Qualifiers());
- for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) {
- Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers();
- }
+ for (LateParsedDeclaration *D : Class.LateParsedDeclarations)
+ D->ParseLexedMemberInitializers();
}
- if (!AlreadyHasClassScope)
- Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(),
- Class.TagOrTemplate);
-
Actions.ActOnFinishDelayedMemberInitializers(Class.TagOrTemplate);
}
@@ -660,21 +651,115 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
ConsumeAnyToken();
}
-void Parser::ParseLexedPragmas(ParsingClass &Class) {
- bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
- ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
- HasTemplateScope);
- TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
- if (HasTemplateScope) {
- Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
- ++CurTemplateDepthTracker;
+/// Wrapper class which calls ParseLexedAttribute, after setting up the
+/// scope appropriately.
+void Parser::ParseLexedAttributes(ParsingClass &Class) {
+ ReenterClassScopeRAII InClassScope(*this, Class);
+
+ for (LateParsedDeclaration *LateD : Class.LateParsedDeclarations)
+ LateD->ParseLexedAttributes();
+}
+
+/// Parse all attributes in LAs, and attach them to Decl D.
+void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
+ bool EnterScope, bool OnDefinition) {
+ assert(LAs.parseSoon() &&
+ "Attribute list should be marked for immediate parsing.");
+ for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) {
+ if (D)
+ LAs[i]->addDecl(D);
+ ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition);
+ delete LAs[i];
+ }
+ LAs.clear();
+}
+
+/// Finish parsing an attribute for which parsing was delayed.
+/// This will be called at the end of parsing a class declaration
+/// for each LateParsedAttribute. We consume the saved tokens and
+/// create an attribute with the arguments filled in. We add this
+/// to the Attribute list for the decl.
+void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
+ bool EnterScope, bool OnDefinition) {
+ // Create a fake EOF so that attribute parsing won't go off the end of the
+ // attribute.
+ Token AttrEnd;
+ AttrEnd.startToken();
+ AttrEnd.setKind(tok::eof);
+ AttrEnd.setLocation(Tok.getLocation());
+ AttrEnd.setEofData(LA.Toks.data());
+ LA.Toks.push_back(AttrEnd);
+
+ // Append the current token at the end of the new token stream so that it
+ // doesn't get lost.
+ LA.Toks.push_back(Tok);
+ PP.EnterTokenStream(LA.Toks, true, /*IsReinject=*/true);
+ // Consume the previously pushed token.
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+
+ ParsedAttributes Attrs(AttrFactory);
+ SourceLocation endLoc;
+
+ if (LA.Decls.size() > 0) {
+ Decl *D = LA.Decls[0];
+ NamedDecl *ND = dyn_cast<NamedDecl>(D);
+ RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
+
+ // Allow 'this' within late-parsed attributes.
+ Sema::CXXThisScopeRAII ThisScope(Actions, RD, Qualifiers(),
+ ND && ND->isCXXInstanceMember());
+
+ if (LA.Decls.size() == 1) {
+ // If the Decl is templatized, add template parameters to scope.
+ ReenterTemplateScopeRAII InDeclScope(*this, D, EnterScope);
+
+ // If the Decl is on a function, add function parameters to the scope.
+ bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate();
+ if (HasFunScope) {
+ InDeclScope.Scopes.Enter(Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope);
+ Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
+ }
+
+ ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
+ nullptr, SourceLocation(), ParsedAttr::AS_GNU,
+ nullptr);
+
+ if (HasFunScope)
+ Actions.ActOnExitFunctionContext();
+ } else {
+ // If there are multiple decls, then the decl cannot be within the
+ // function scope.
+ ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
+ nullptr, SourceLocation(), ParsedAttr::AS_GNU,
+ nullptr);
+ }
+ } else {
+ Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
}
- bool HasClassScope = !Class.TopLevelClass;
- ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope,
- HasClassScope);
- for (LateParsedDeclaration *LPD : Class.LateParsedDeclarations)
- LPD->ParseLexedPragmas();
+ if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() &&
+ Attrs.begin()->isKnownToGCC())
+ Diag(Tok, diag::warn_attribute_on_function_definition)
+ << &LA.AttrName;
+
+ for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i)
+ Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs);
+
+ // Due to a parsing error, we either went over the cached tokens or
+ // there are still cached tokens left, so we skip the leftover tokens.
+ while (Tok.isNot(tok::eof))
+ ConsumeAnyToken();
+
+ if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData())
+ ConsumeAnyToken();
+}
+
+void Parser::ParseLexedPragmas(ParsingClass &Class) {
+ ReenterClassScopeRAII InClassScope(*this, Class);
+
+ for (LateParsedDeclaration *D : Class.LateParsedDeclarations)
+ D->ParseLexedPragmas();
}
void Parser::ParseLexedPragma(LateParsedPragma &LP) {
@@ -1112,17 +1197,14 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks,
break;
}
+ // Put the token stream back and undo any annotations we performed
+ // after the comma. They may reflect a different parse than the one
+ // we will actually perform at the end of the class.
+ PA.RevertAnnotations();
+
// If what follows could be a declaration, it is a declaration.
- if (Result != TPResult::False && Result != TPResult::Error) {
- PA.Revert();
+ if (Result != TPResult::False && Result != TPResult::Error)
return true;
- }
-
- // In the uncommon case that we decide the following tokens are part
- // of a template argument, revert any annotations we've performed in
- // those tokens. We're not going to look them up until we've parsed
- // the rest of the class, and that might add more declarations.
- PA.RevertAnnotations();
}
// Keep going. We know we're inside a template argument list now.