aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Parse/ParseDecl.cpp55
-rw-r--r--lib/Parse/ParseTemplate.cpp9
-rw-r--r--lib/Parse/Parser.cpp21
3 files changed, 69 insertions, 16 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 914a5acd09..0b98274002 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -132,14 +132,15 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
if (Tok.is(tok::l_paren)) {
// handle "parameterized" attributes
- if (LateAttrs && !ClassStack.empty() &&
- isAttributeLateParsed(*AttrName)) {
- // Delayed parsing is only available for attributes that occur
- // in certain locations within a class scope.
+ if (LateAttrs && isAttributeLateParsed(*AttrName)) {
LateParsedAttribute *LA =
new LateParsedAttribute(this, *AttrName, AttrNameLoc);
LateAttrs->push_back(LA);
- getCurrentClass().LateParsedDeclarations.push_back(LA);
+
+ // Attributes in a class are parsed at the end of the class, along
+ // with other late-parsed declarations.
+ if (!ClassStack.empty())
+ getCurrentClass().LateParsedDeclarations.push_back(LA);
// consume everything up to and including the matching right parens
ConsumeAndStoreUntil(tok::r_paren, LA->Toks, true, false);
@@ -711,7 +712,7 @@ void Parser::LateParsedClass::ParseLexedAttributes() {
}
void Parser::LateParsedAttribute::ParseLexedAttributes() {
- Self->ParseLexedAttribute(*this);
+ Self->ParseLexedAttribute(*this, true, false);
}
/// Wrapper class which calls ParseLexedAttribute, after setting up the
@@ -736,12 +737,25 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) {
}
}
+
+/// \brief Parse all attributes in LAs, and attach them to Decl D.
+void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,
+ bool EnterScope, bool OnDefinition) {
+ for (unsigned i = 0, ni = LAs.size(); i < ni; ++i) {
+ LAs[i]->setDecl(D);
+ ParseLexedAttribute(*LAs[i], EnterScope, OnDefinition);
+ }
+ LAs.clear();
+}
+
+
/// \brief 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) {
+void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
+ bool EnterScope, bool OnDefinition) {
// Save the current token position.
SourceLocation OrigLoc = Tok.getLocation();
@@ -752,17 +766,23 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA) {
// Consume the previously pushed token.
ConsumeAnyToken();
+ if (OnDefinition && !IsThreadSafetyAttribute(LA.AttrName.getName())) {
+ Diag(Tok, diag::warn_attribute_on_function_definition)
+ << LA.AttrName.getName();
+ }
+
ParsedAttributes Attrs(AttrFactory);
SourceLocation endLoc;
// If the Decl is templatized, add template parameters to scope.
- bool HasTemplateScope = LA.D && LA.D->isTemplateDecl();
+ bool HasTemplateScope = EnterScope && LA.D && LA.D->isTemplateDecl();
ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope);
if (HasTemplateScope)
Actions.ActOnReenterTemplateScope(Actions.CurScope, LA.D);
// If the Decl is on a function, add function parameters to the scope.
- bool HasFunctionScope = LA.D && LA.D->isFunctionOrFunctionTemplate();
+ bool HasFunctionScope = EnterScope && LA.D &&
+ LA.D->isFunctionOrFunctionTemplate();
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunctionScope);
if (HasFunctionScope)
Actions.ActOnReenterFunctionContext(Actions.CurScope, LA.D);
@@ -1064,6 +1084,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
return DeclGroupPtrTy();
}
+ // Save late-parsed attributes for now; they need to be parsed in the
+ // appropriate function scope after the function Decl has been constructed.
+ LateParsedAttrList LateParsedAttrs;
+ if (D.isFunctionDeclarator())
+ MaybeParseGNUAttributes(D, &LateParsedAttrs);
+
// Check to see if we have a function *definition* which must have a body.
if (AllowFunctionDefinitions && D.isFunctionDeclarator() &&
// Look at the next token to make sure that this isn't a function
@@ -1079,7 +1105,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
DS.ClearStorageClassSpecs();
}
- Decl *TheDecl = ParseFunctionDefinition(D);
+ Decl *TheDecl =
+ ParseFunctionDefinition(D, ParsedTemplateInfo(), &LateParsedAttrs);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
@@ -1096,7 +1123,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
}
}
- if (ParseAttributesAfterDeclarator(D))
+ if (ParseAsmAttributesAfterDeclarator(D))
return DeclGroupPtrTy();
// C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we
@@ -1117,6 +1144,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
SmallVector<Decl *, 8> DeclsInGroup;
Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D);
+ if (LateParsedAttrs.size() > 0)
+ ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false);
D.complete(FirstDecl);
if (FirstDecl)
DeclsInGroup.push_back(FirstDecl);
@@ -1185,7 +1214,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
/// Parse an optional simple-asm-expr and attributes, and attach them to a
/// declarator. Returns true on an error.
-bool Parser::ParseAttributesAfterDeclarator(Declarator &D) {
+bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {
// If a simple-asm-expr is present, parse it.
if (Tok.is(tok::kw_asm)) {
SourceLocation Loc;
@@ -1227,7 +1256,7 @@ bool Parser::ParseAttributesAfterDeclarator(Declarator &D) {
///
Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
const ParsedTemplateInfo &TemplateInfo) {
- if (ParseAttributesAfterDeclarator(D))
+ if (ParseAsmAttributesAfterDeclarator(D))
return 0;
return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo);
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 1222fb08f5..a30ef96d63 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -241,6 +241,10 @@ Parser::ParseSingleDeclarationAfterTemplate(
return 0;
}
+ LateParsedAttrList LateParsedAttrs;
+ if (DeclaratorInfo.isFunctionDeclarator())
+ MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);
+
// If we have a declaration or declarator list, handle it.
if (isDeclarationAfterDeclarator()) {
// Parse this declaration.
@@ -256,6 +260,8 @@ Parser::ParseSingleDeclarationAfterTemplate(
// Eat the semi colon after the declaration.
ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
+ if (LateParsedAttrs.size() > 0)
+ ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false);
DeclaratorInfo.complete(ThisDecl);
return ThisDecl;
}
@@ -270,7 +276,8 @@ Parser::ParseSingleDeclarationAfterTemplate(
<< FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
DS.ClearStorageClassSpecs();
}
- return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo);
+ return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo,
+ &LateParsedAttrs);
}
if (DeclaratorInfo.isFunctionDeclarator())
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 4d8f474514..c797436948 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -821,7 +821,8 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
/// decl-specifier-seq[opt] declarator function-try-block
///
Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
- const ParsedTemplateInfo &TemplateInfo) {
+ const ParsedTemplateInfo &TemplateInfo,
+ LateParsedAttrList *LateParsedAttrs) {
// Poison the SEH identifiers so they are flagged as illegal in function bodies
PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true);
const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
@@ -844,7 +845,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
if (FTI.isKNRPrototype())
ParseKNRParamDeclarations(D);
-
// We should have either an opening brace or, in a C++ constructor,
// we may have a colon.
if (Tok.isNot(tok::l_brace) &&
@@ -861,6 +861,19 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
return 0;
}
+ // Check to make sure that any normal attributes are allowed to be on
+ // a definition. Late parsed attributes are checked at the end.
+ if (Tok.isNot(tok::equal)) {
+ AttributeList *DtorAttrs = D.getAttributes();
+ while (DtorAttrs) {
+ if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName())) {
+ Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition)
+ << DtorAttrs->getName()->getName();
+ }
+ DtorAttrs = DtorAttrs->getNext();
+ }
+ }
+
// In delayed template parsing mode, for function template we consume the
// tokens and store them for late parsing at the end of the translation unit.
if (getLang().DelayedTemplateParsing &&
@@ -974,6 +987,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
} else
Actions.ActOnDefaultCtorInitializers(Res);
+ // Late attributes are parsed in the same scope as the function body.
+ if (LateParsedAttrs)
+ ParseLexedAttributeList(*LateParsedAttrs, Res, false, true);
+
return ParseFunctionStatementBody(Res, BodyScope);
}