When we end up having to parse the initializer of a C++ member early

in -fms-extensions mode, make sure we actually use that initializer
after having handled the declaration. Fixes PR11150.

llvm-svn: 142195
This commit is contained in:
Douglas Gregor 2011-10-17 17:09:53 +00:00
parent 0ade47acd0
commit 50cefbf212
3 changed files with 23 additions and 11 deletions

View File

@ -43,13 +43,13 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
else {
FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D,
move(TemplateParams), 0,
VS, /*HasInit=*/false);
VS, /*HasDeferredInit=*/false);
if (FnD) {
Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs,
false, true);
bool TypeSpecContainsAuto
= D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
if (Init.get())
if (Init.isUsable())
Actions.AddInitializerToDecl(FnD, Init.get(), false,
TypeSpecContainsAuto);
else

View File

@ -1711,6 +1711,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Hold late-parsed attributes so we can attach a Decl to them later.
LateParsedAttrList LateParsedAttrs;
SourceLocation EqualLoc;
bool HasInitializer = false;
ExprResult Init;
if (Tok.isNot(tok::colon)) {
// Don't parse FOO:BAR as if it were a typo for FOO::BAR.
ColonProtectionRAIIObject X(*this);
@ -1733,14 +1736,15 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// MSVC permits pure specifier on inline functions declared at class scope.
// Hence check for =0 before checking for function definition.
ExprResult Init;
if (getLang().MicrosoftExt && Tok.is(tok::equal) &&
DeclaratorInfo.isFunctionDeclarator() &&
NextToken().is(tok::numeric_constant)) {
ConsumeToken();
EqualLoc = ConsumeToken();
Init = ParseInitializer();
if (Init.isInvalid())
SkipUntil(tok::comma, true, true);
else
HasInitializer = true;
}
bool IsDefinition = false;
@ -1842,9 +1846,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// goes before or after the GNU attributes and __asm__.
ParseOptionalCXX0XVirtSpecifierSeq(VS);
bool HasInitializer = false;
bool HasDeferredInitializer = false;
if (Tok.is(tok::equal) || Tok.is(tok::l_brace)) {
if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) {
if (BitfieldSize.get()) {
Diag(Tok, diag::err_bitfield_member_init);
SkipUntil(tok::comma, true, true);
@ -1905,15 +1908,15 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ParseCXXNonStaticMemberInitializer(ThisDecl);
} else if (HasInitializer) {
// Normal initializer.
SourceLocation EqualLoc;
ExprResult Init
= ParseCXXMemberInitializer(DeclaratorInfo.isDeclarationOfFunction(),
EqualLoc);
if (!Init.isUsable())
Init = ParseCXXMemberInitializer(
DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
if (Init.isInvalid())
SkipUntil(tok::comma, true, true);
else if (ThisDecl)
Actions.AddInitializerToDecl(ThisDecl, Init.get(), false,
DS.getTypeSpecType() == DeclSpec::TST_auto);
DS.getTypeSpecType() == DeclSpec::TST_auto);
} else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) {
// No initializer.
Actions.ActOnUninitializedDecl(ThisDecl,
@ -1945,6 +1948,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
DeclaratorInfo.clear();
VS.clear();
BitfieldSize = true;
Init = true;
HasInitializer = false;
// Attributes are only allowed on the second declarator.
MaybeParseGNUAttributes(DeclaratorInfo);

View File

@ -203,3 +203,10 @@ void f()
}
struct PR11150 {
class X {
virtual void f() = 0;
};
int array[__is_abstract(X)? 1 : -1];
};