diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp | 103 | 
1 files changed, 87 insertions, 16 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index b2a65ff0f326..b9b51d751822 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -1534,13 +1534,35 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const {    }  } -void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo, -                                             Decl *ThisDecl) { +/// \brief If the given declarator has any parts for which parsing has to be +/// delayed, e.g., default arguments or an exception-specification, create a +/// late-parsed method declaration record to handle the parsing at the end of +/// the class definition. +void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, +                                            Decl *ThisDecl) {    // We just declared a member function. If this member function -  // has any default arguments, we'll need to parse them later. +  // has any default arguments or an exception-specification, we'll need to +  // parse them later.    LateParsedMethodDeclaration *LateMethod = 0;    DeclaratorChunk::FunctionTypeInfo &FTI      = DeclaratorInfo.getFunctionTypeInfo(); +   +  // If there was a delayed exception-specification, hold onto its tokens. +  if (FTI.getExceptionSpecType() == EST_Delayed) { +    // Push this method onto the stack of late-parsed method +    // declarations. +    LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); +    getCurrentClass().LateParsedDeclarations.push_back(LateMethod); +    LateMethod->TemplateScope = getCurScope()->isTemplateParamScope(); + +    // Stash the exception-specification tokens in the late-pased mthod. +    LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; +    FTI.ExceptionSpecTokens = 0; + +    // Reserve space for the parameters. +    LateMethod->DefaultArgs.reserve(FTI.NumArgs); +  } +      for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {      if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {        if (!LateMethod) { @@ -1558,7 +1580,7 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,                               LateParsedDefaultArgument(FTI.ArgInfo[I].Param));        } -      // Add this parameter to the list of parameters (it or may +      // Add this parameter to the list of parameters (it may or may        // not have a default argument).        LateMethod->DefaultArgs.push_back(          LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param, @@ -1824,7 +1846,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,      // Parse the first declarator.      ParseDeclarator(DeclaratorInfo); -    // Error parsing the declarator? +    // Error parsin g the declarator?      if (!DeclaratorInfo.hasName()) {        // If so, skip until the semi-colon or a }.        SkipUntil(tok::r_brace, true, true); @@ -2046,7 +2068,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,      if (DeclaratorInfo.isFunctionDeclarator() &&          DeclaratorInfo.getDeclSpec().getStorageClassSpec()            != DeclSpec::SCS_typedef) { -      HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl); +      HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl);      }      DeclaratorInfo.complete(ThisDecl); @@ -2334,13 +2356,11 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,                                                T.getCloseLocation(),                                                attrs.getList()); -  // C++0x [class.mem]p2: Within the class member-specification, the class is -  // regarded as complete within function bodies, default arguments, exception- -  // specifications, and brace-or-equal-initializers for non-static data -  // members (including such things in nested classes). -  // -  // FIXME: Only function bodies and brace-or-equal-initializers are currently -  // handled. Fix the others! +  // C++11 [class.mem]p2: +  //   Within the class member-specification, the class is regarded as complete +  //   within function bodies, default arguments, exception-specifications, and +  //   brace-or-equal-initializers for non-static data members (including such +  //   things in nested classes).    if (TagDecl && NonNestedClass) {      // We are not inside a nested class. This class and its nested classes      // are complete and we can parse the delayed portions of method @@ -2535,12 +2555,63 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {  ///         'noexcept'  ///         'noexcept' '(' constant-expression ')'  ExceptionSpecificationType -Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange, +Parser::tryParseExceptionSpecification(bool Delayed, +                    SourceRange &SpecificationRange,                      SmallVectorImpl<ParsedType> &DynamicExceptions,                      SmallVectorImpl<SourceRange> &DynamicExceptionRanges, -                    ExprResult &NoexceptExpr) { +                    ExprResult &NoexceptExpr, +                    CachedTokens *&ExceptionSpecTokens) {    ExceptionSpecificationType Result = EST_None; - +  ExceptionSpecTokens = 0; +   +  // Handle delayed parsing of exception-specifications. +  if (Delayed) { +    if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept)) +      return EST_None; + +    // Consume and cache the starting token. +    bool IsNoexcept = Tok.is(tok::kw_noexcept); +    Token StartTok = Tok; +    SpecificationRange = SourceRange(ConsumeToken()); + +    // Check for a '('. +    if (!Tok.is(tok::l_paren)) { +      // If this is a bare 'noexcept', we're done. +      if (IsNoexcept) { +        Diag(Tok, diag::warn_cxx98_compat_noexcept_decl); +        NoexceptExpr = 0; +        return EST_BasicNoexcept; +      } +       +      Diag(Tok, diag::err_expected_lparen_after) << "throw"; +      return EST_DynamicNone; +    } +     +    // Cache the tokens for the exception-specification. +    ExceptionSpecTokens = new CachedTokens; +    ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept' +    ExceptionSpecTokens->push_back(Tok); // '(' +    SpecificationRange.setEnd(ConsumeParen()); // '(' +     +    if (!ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens, +                              /*StopAtSemi=*/true, +                              /*ConsumeFinalToken=*/true)) { +      NoexceptExpr = 0; +      delete ExceptionSpecTokens; +      ExceptionSpecTokens = 0; +      return IsNoexcept? EST_BasicNoexcept : EST_DynamicNone; +    } +    SpecificationRange.setEnd(Tok.getLocation()); +     +    // Add the 'stop' token. +    Token End; +    End.startToken(); +    End.setKind(tok::cxx_exceptspec_end); +    End.setLocation(Tok.getLocation()); +    ExceptionSpecTokens->push_back(End); +    return EST_Delayed; +  } +      // See if there's a dynamic specification.    if (Tok.is(tok::kw_throw)) {      Result = ParseDynamicExceptionSpecification(SpecificationRange,  | 
