From a2b4e5d9292688bc67b583592918dbeecae31ea3 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 17 Oct 2011 17:09:53 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142195 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseCXXInlineMethods.cpp | 4 ++-- lib/Parse/ParseDeclCXX.cpp | 23 ++++++++++++++--------- test/SemaCXX/MicrosoftExtensions.cpp | 7 +++++++ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index c9107b466d..04c05d0cc3 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -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 diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 472c64b221..45562d908c 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -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); diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index 63e058b36d..ddf5d9d6a1 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -203,3 +203,10 @@ void f() } +struct PR11150 { + class X { + virtual void f() = 0; + }; + + int array[__is_abstract(X)? 1 : -1]; +}; -- 2.40.0