]> granicus.if.org Git - clang/commitdiff
In Microsoft mode, allow pure specifier (=0) on inline functions declared at class...
authorFrancois Pichet <pichet2000@gmail.com>
Wed, 11 May 2011 02:14:46 +0000 (02:14 +0000)
committerFrancois Pichet <pichet2000@gmail.com>
Wed, 11 May 2011 02:14:46 +0000 (02:14 +0000)
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
include/clang/Parse/Parser.h
lib/Parse/ParseCXXInlineMethods.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Sema/SemaDecl.cpp
test/Parser/MicrosoftExtensions.cpp

index f65e268b850efba1ade027858f82a65688b820e2..0d975f2a43cc1bfdd586fd7cbe84fc966b9fff6f 100644 (file)
@@ -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<Microsoft>;
 def err_implicit_object_parameter_init : Error<
   "cannot initialize object parameter of type %0 with an expression "
   "of type %1">;
index 611c5d63aab71db91c99aa351617cf11b50c9192..613acb1cbc46672eb0dd85d97ce09cba9a1d88bd 100644 (file)
@@ -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);
index 87e2f343748e55bc57304005160e530dee349a2e..1e1a0e2b0700cde55f808f3c46d317b623d9bd39 100644 (file)
@@ -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);
index ccc245016e468d993944cc4563fe42458d06d022..ecf66a79dba50a073ab6abd1cf4ae6bf788b0cdb 100644 (file)
@@ -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<Decl *, 8> DeclsInGroup;
   ExprResult BitfieldSize;
-  ExprResult Init;
   bool Deleted = false;
   SourceLocation DefaultLoc;
 
index b598b46743c5468a98b2828572b80209ed8d64ef..29343886f75deacbfd86e61e10e5fbe59b79f305 100644 (file)
@@ -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(),
index f441a5705c065a561035cfa8b0d3a808685cf7e5..adf93b62d1ab2446ad9257202937abe1b487a0a7 100644 (file)
@@ -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.