From: Eli Friedman Date: Wed, 22 Jul 2009 21:45:50 +0000 (+0000) Subject: Fix the parsing of default arguments for inline member function X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d33133cdc1af466f9c276249b2621be03867888b;p=clang Fix the parsing of default arguments for inline member function definitions. I'm not very familiar with this code, so please review. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76796 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index bebc874b62..dc6a577771 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1147,6 +1147,8 @@ private: void ParseCXXClassMemberDeclaration(AccessSpecifier AS); void ParseConstructorInitializer(DeclPtrTy ConstructorDecl); MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl); + void HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, + DeclPtrTy ThisDecl); //===--------------------------------------------------------------------===// // C++ 10: Derived classes [class.derived] diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 613e0e33f7..8afffe3815 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -29,6 +29,8 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0); + HandleMemberFunctionDefaultArgs(D, FnD); + // Consume the tokens and store them for later parsing. getCurrentClass().MethodDefs.push_back(LexedMethod(FnD)); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index b9b2979911..930d58dd26 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -852,6 +852,39 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const } } +void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, + DeclPtrTy ThisDecl) { + // We just declared a member function. If this member function + // has any default arguments, we'll need to parse them later. + LateParsedMethodDeclaration *LateMethod = 0; + DeclaratorChunk::FunctionTypeInfo &FTI + = DeclaratorInfo.getTypeObject(0).Fun; + for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) { + if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) { + if (!LateMethod) { + // Push this method onto the stack of late-parsed method + // declarations. + getCurrentClass().MethodDecls.push_back( + LateParsedMethodDeclaration(ThisDecl)); + LateMethod = &getCurrentClass().MethodDecls.back(); + + // Add all of the parameters prior to this one (they don't + // have default arguments). + LateMethod->DefaultArgs.reserve(FTI.NumArgs); + for (unsigned I = 0; I < ParamIdx; ++I) + LateMethod->DefaultArgs.push_back( + LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param)); + } + + // Add this parameter to the list of parameters (it or may + // not have a default argument). + LateMethod->DefaultArgs.push_back( + LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param, + FTI.ArgInfo[ParamIdx].DefaultArgTokens)); + } + } +} + /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration. /// /// member-declaration: @@ -1047,35 +1080,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { if (DeclaratorInfo.isFunctionDeclarator() && DeclaratorInfo.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) { - // We just declared a member function. If this member function - // has any default arguments, we'll need to parse them later. - LateParsedMethodDeclaration *LateMethod = 0; - DeclaratorChunk::FunctionTypeInfo &FTI - = DeclaratorInfo.getTypeObject(0).Fun; - for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) { - if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) { - if (!LateMethod) { - // Push this method onto the stack of late-parsed method - // declarations. - getCurrentClass().MethodDecls.push_back( - LateParsedMethodDeclaration(ThisDecl)); - LateMethod = &getCurrentClass().MethodDecls.back(); - - // Add all of the parameters prior to this one (they don't - // have default arguments). - LateMethod->DefaultArgs.reserve(FTI.NumArgs); - for (unsigned I = 0; I < ParamIdx; ++I) - LateMethod->DefaultArgs.push_back( - LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param)); - } - - // Add this parameter to the list of parameters (it or may - // not have a default argument). - LateMethod->DefaultArgs.push_back( - LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param, - FTI.ArgInfo[ParamIdx].DefaultArgTokens)); - } - } + HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl); } // If we don't have a comma, it is either the end of the list (a ';') diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp index edbd6b3e20..dc83ac489f 100644 --- a/test/SemaCXX/default2.cpp +++ b/test/SemaCXX/default2.cpp @@ -127,3 +127,9 @@ class C2 { static void g(int = f()); // expected-error{{use of default argument to function 'f' that is declared later in class 'C2'}} static int f(int = 10); // expected-note{{default argument declared here}} }; + +// Make sure we actually parse the default argument for an inline definition +class XX { + void A(int length = -1 ) { } + void B() { A(); } +};