From 6a24747beed797b2f1184c66ca45beb4db20eb08 Mon Sep 17 00:00:00 2001 From: Francois Pichet Date: Wed, 11 May 2011 02:14:46 +0000 Subject: [PATCH] In Microsoft mode, allow pure specifier (=0) on inline functions declared at class scope. This removes 2 errors when parsing MFC code with clang Example: class A { virtual void f() = 0 { } } git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131175 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 3 +++ include/clang/Parse/Parser.h | 2 +- lib/Parse/ParseCXXInlineMethods.cpp | 5 +++-- lib/Parse/ParseDeclCXX.cpp | 15 +++++++++++++-- lib/Sema/SemaDecl.cpp | 5 +++++ test/Parser/MicrosoftExtensions.cpp | 5 +++++ 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index f65e268b85..0d975f2a43 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -721,6 +721,9 @@ def err_member_function_initialization : Error< "initializer on function does not look like a pure-specifier">; def err_non_virtual_pure : Error< "%0 is not virtual and cannot be declared pure">; +def warn_pure_function_definition : ExtWarn< + "function definition with pure-specifier is a Microsoft extension">, + InGroup; def err_implicit_object_parameter_init : Error< "cannot initialize object parameter of type %0 with an expression " "of type %1">; diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 611c5d63aa..613acb1cbc 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -973,7 +973,7 @@ private: Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS); + const VirtSpecifiers& VS, ExprResult& Init); void ParseLexedMethodDeclarations(ParsingClass &Class); void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM); void ParseLexedMethodDefs(ParsingClass &Class); diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 87e2f34374..1e1a0e2b07 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -23,7 +23,7 @@ using namespace clang; /// and store its tokens for parsing after the C++ class is complete. Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS) { + const VirtSpecifiers& VS, ExprResult& Init) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && "Current token not a '{', ':' or 'try'!"); @@ -40,7 +40,8 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, else { // FIXME: pass template information through FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, move(TemplateParams), 0, - VS, 0, /*IsDefinition*/true); + VS, Init.release(), + /*IsDefinition*/true); } HandleMemberFunctionDefaultArgs(D, FnD); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index ccc245016e..ecf66a79db 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1581,6 +1581,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext); VirtSpecifiers VS; + ExprResult Init; if (Tok.isNot(tok::colon)) { // Don't parse FOO:BAR as if it were a typo for FOO::BAR. @@ -1602,6 +1603,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // If attributes exist after the declarator, but before an '{', parse them. MaybeParseGNUAttributes(DeclaratorInfo); + // MSVC permits pure specifier on inline functions declared at class scope. + // Hence check for =0 before checking for function definition. + if (getLang().Microsoft && Tok.is(tok::equal) && + DeclaratorInfo.isFunctionDeclarator() && + NextToken().is(tok::numeric_constant)) { + ConsumeToken(); + Init = ParseInitializer(); + if (Init.isInvalid()) + SkipUntil(tok::comma, true, true); + } + // function-definition: if (Tok.is(tok::l_brace) || (DeclaratorInfo.isFunctionDeclarator() && @@ -1631,7 +1643,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return; } - ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS); + ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS, Init); // Consume the optional ';' if (Tok.is(tok::semi)) ConsumeToken(); @@ -1646,7 +1658,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, llvm::SmallVector DeclsInGroup; ExprResult BitfieldSize; - ExprResult Init; bool Deleted = false; SourceLocation DefaultLoc; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b598b46743..29343886f7 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6308,6 +6308,11 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, WP.disableCheckFallThrough(); } + // MSVC permits the use of pure specifier (=0) on function definition, + // defined at class scope, warn about this non standard construct. + if (getLangOptions().Microsoft && FD->isPure()) + Diag(FD->getLocation(), diag::warn_pure_function_definition); + if (!FD->isInvalidDecl()) { DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(), diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp index f441a5705c..adf93b62d1 100644 --- a/test/Parser/MicrosoftExtensions.cpp +++ b/test/Parser/MicrosoftExtensions.cpp @@ -212,6 +212,11 @@ __if_not_exists(IF_EXISTS::Type_not) { int __identifier(generic) = 3; +class inline_definition_pure_spec { + virtual int f() = 0 { return 0; }// expected-warning {{function definition with pure-specifier is a Microsoft extension}} + virtual int f2() = 0; +}; + int main () { // Necessary to force instantiation in -fdelayed-template-parsing mode. -- 2.40.0