diff options
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
| -rw-r--r-- | lib/Parse/ParseDecl.cpp | 268 | 
1 files changed, 187 insertions, 81 deletions
| diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4d05e16491b0..bd114d7e34a7 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -529,64 +529,72 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,  /// [MS] extended-decl-modifier-seq:  ///             extended-decl-modifier[opt]  ///             extended-decl-modifier extended-decl-modifier-seq -void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &Attrs) { +void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs, +                                     SourceLocation *End) { +  assert((getLangOpts().MicrosoftExt || getLangOpts().Borland || +          getLangOpts().CUDA) && +         "Incorrect language options for parsing __declspec");    assert(Tok.is(tok::kw___declspec) && "Not a declspec!"); -  ConsumeToken(); -  BalancedDelimiterTracker T(*this, tok::l_paren); -  if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec", -                         tok::r_paren)) -    return; - -  // An empty declspec is perfectly legal and should not warn.  Additionally, -  // you can specify multiple attributes per declspec. -  while (Tok.isNot(tok::r_paren)) { -    // Attribute not present. -    if (TryConsumeToken(tok::comma)) -      continue; - -    // We expect either a well-known identifier or a generic string.  Anything -    // else is a malformed declspec. -    bool IsString = Tok.getKind() == tok::string_literal ? true : false; -    if (!IsString && Tok.getKind() != tok::identifier && -        Tok.getKind() != tok::kw_restrict) { -      Diag(Tok, diag::err_ms_declspec_type); -      T.skipToEnd(); +  while (Tok.is(tok::kw___declspec)) { +    ConsumeToken(); +    BalancedDelimiterTracker T(*this, tok::l_paren); +    if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec", +                           tok::r_paren))        return; -    } -    IdentifierInfo *AttrName; -    SourceLocation AttrNameLoc; -    if (IsString) { -      SmallString<8> StrBuffer; -      bool Invalid = false; -      StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid); -      if (Invalid) { +    // An empty declspec is perfectly legal and should not warn.  Additionally, +    // you can specify multiple attributes per declspec. +    while (Tok.isNot(tok::r_paren)) { +      // Attribute not present. +      if (TryConsumeToken(tok::comma)) +        continue; + +      // We expect either a well-known identifier or a generic string.  Anything +      // else is a malformed declspec. +      bool IsString = Tok.getKind() == tok::string_literal; +      if (!IsString && Tok.getKind() != tok::identifier && +          Tok.getKind() != tok::kw_restrict) { +        Diag(Tok, diag::err_ms_declspec_type);          T.skipToEnd();          return;        } -      AttrName = PP.getIdentifierInfo(Str); -      AttrNameLoc = ConsumeStringToken(); -    } else { -      AttrName = Tok.getIdentifierInfo(); -      AttrNameLoc = ConsumeToken(); -    } -    bool AttrHandled = false; +      IdentifierInfo *AttrName; +      SourceLocation AttrNameLoc; +      if (IsString) { +        SmallString<8> StrBuffer; +        bool Invalid = false; +        StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid); +        if (Invalid) { +          T.skipToEnd(); +          return; +        } +        AttrName = PP.getIdentifierInfo(Str); +        AttrNameLoc = ConsumeStringToken(); +      } else { +        AttrName = Tok.getIdentifierInfo(); +        AttrNameLoc = ConsumeToken(); +      } + +      bool AttrHandled = false; -    // Parse attribute arguments. -    if (Tok.is(tok::l_paren)) -      AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs); -    else if (AttrName->getName() == "property") -      // The property attribute must have an argument list. -      Diag(Tok.getLocation(), diag::err_expected_lparen_after) -          << AttrName->getName(); +      // Parse attribute arguments. +      if (Tok.is(tok::l_paren)) +        AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs); +      else if (AttrName->getName() == "property") +        // The property attribute must have an argument list. +        Diag(Tok.getLocation(), diag::err_expected_lparen_after) +            << AttrName->getName(); -    if (!AttrHandled) -      Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, -                   AttributeList::AS_Declspec); +      if (!AttrHandled) +        Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, +                     AttributeList::AS_Declspec); +    } +    T.consumeClose(); +    if (End) +      *End = T.getCloseLocation();    } -  T.consumeClose();  }  void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { @@ -1360,6 +1368,46 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &attrs) {    }  } +// As an exception to the rule, __declspec(align(...)) before the +// class-key affects the type instead of the variable. +void Parser::handleDeclspecAlignBeforeClassKey(ParsedAttributesWithRange &Attrs, +                                               DeclSpec &DS, +                                               Sema::TagUseKind TUK) { +  if (TUK == Sema::TUK_Reference) +    return; + +  ParsedAttributes &PA = DS.getAttributes(); +  AttributeList *AL = PA.getList(); +  AttributeList *Prev = nullptr; +  while (AL) { +    AttributeList *Next = AL->getNext(); + +    // We only consider attributes using the appropriate '__declspec' spelling, +    // this behavior doesn't extend to any other spellings. +    if (AL->getKind() == AttributeList::AT_Aligned && +        AL->isDeclspecAttribute()) { +      // Stitch the attribute into the tag's attribute list. +      AL->setNext(nullptr); +      Attrs.add(AL); + +      // Remove the attribute from the variable's attribute list. +      if (Prev) { +        // Set the last variable attribute's next attribute to be the attribute +        // after the current one. +        Prev->setNext(Next); +      } else { +        // Removing the head of the list requires us to reset the head to the +        // next attribute. +        PA.set(Next); +      } +    } else { +      Prev = AL; +    } + +    AL = Next; +  } +} +  /// ParseDeclaration - Parse a full 'declaration', which consists of  /// declaration-specifiers, some number of declarators, and a semicolon.  /// 'Context' should be a Declarator::TheContext value.  This returns the @@ -1691,11 +1739,12 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,        }        if (isDeclarationSpecifier()) { -        // If there is an invalid declaration specifier right after the function -        // prototype, then we must be in a missing semicolon case where this isn't -        // actually a body.  Just fall through into the code that handles it as a -        // prototype, and let the top-level code handle the erroneous declspec -        // where it would otherwise expect a comma or semicolon. +        // If there is an invalid declaration specifier right after the +        // function prototype, then we must be in a missing semicolon case +        // where this isn't actually a body.  Just fall through into the code +        // that handles it as a prototype, and let the top-level code handle +        // the erroneous declspec where it would otherwise expect a comma or +        // semicolon.        } else {          Diag(Tok, diag::err_expected_fn_body);          SkipUntil(tok::semi); @@ -1993,7 +2042,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(        Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl);      } -    if (ParseExpressionList(Exprs, CommaLocs)) { +    if (ParseExpressionList(Exprs, CommaLocs, [&] { +          Actions.CodeCompleteConstructor(getCurScope(), +                 cast<VarDecl>(ThisDecl)->getType()->getCanonicalTypeInternal(), +                                          ThisDecl->getLocation(), Exprs); +       })) {        Actions.ActOnInitializerError(ThisDecl);        SkipUntil(tok::r_paren, StopAtSemi); @@ -2564,7 +2617,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,    bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);    bool AttrsLastTime = false;    ParsedAttributesWithRange attrs(AttrFactory); -  const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); +  // We use Sema's policy to get bool macros right. +  const PrintingPolicy &Policy = Actions.getPrintingPolicy();    while (1) {      bool isInvalid = false;      bool isStorageClass = false; @@ -2871,9 +2925,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,                              Tok.getLocation(), getCurScope());        // MSVC: If we weren't able to parse a default template argument, and it's -      // just a simple identifier, create a DependentNameType.  This will allow us -      // to defer the name lookup to template instantiation time, as long we forge a -      // NestedNameSpecifier for the current context. +      // just a simple identifier, create a DependentNameType.  This will allow +      // us to defer the name lookup to template instantiation time, as long we +      // forge a NestedNameSpecifier for the current context.        if (!TypeRep && DSContext == DSC_template_type_arg &&            getLangOpts().MSVCCompat && getCurScope()->isTemplateParamScope()) {          TypeRep = Actions.ActOnDelayedDefaultTemplateArg( @@ -2950,7 +3004,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,      // Microsoft declspec support.      case tok::kw___declspec: -      ParseMicrosoftDeclSpec(DS.getAttributes()); +      ParseMicrosoftDeclSpecs(DS.getAttributes());        continue;      // Microsoft single token adornments. @@ -3594,10 +3648,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,    ParsedAttributesWithRange attrs(AttrFactory);    MaybeParseGNUAttributes(attrs);    MaybeParseCXX11Attributes(attrs); - -  // If declspecs exist after tag, parse them. -  while (Tok.is(tok::kw___declspec)) -    ParseMicrosoftDeclSpec(attrs); +  MaybeParseMicrosoftDeclSpecs(attrs);    SourceLocation ScopedEnumKWLoc;    bool IsScopedUsingClassTag = false; @@ -3616,8 +3667,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,      // They are allowed afterwards, though.      MaybeParseGNUAttributes(attrs);      MaybeParseCXX11Attributes(attrs); -    while (Tok.is(tok::kw___declspec)) -      ParseMicrosoftDeclSpec(attrs); +    MaybeParseMicrosoftDeclSpecs(attrs);    }    // C++11 [temp.explicit]p12: @@ -3644,11 +3694,12 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,      // if a fixed underlying type is allowed.      ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType); -    if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), +    CXXScopeSpec Spec; +    if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(),                                         /*EnteringContext=*/true))        return; -    if (SS.isSet() && Tok.isNot(tok::identifier)) { +    if (Spec.isSet() && Tok.isNot(tok::identifier)) {        Diag(Tok, diag::err_expected) << tok::identifier;        if (Tok.isNot(tok::l_brace)) {          // Has no name and is not a definition. @@ -3657,6 +3708,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,          return;        }      } + +    SS = Spec;    }    // Must have either 'enum name' or 'enum {...}'. @@ -3842,6 +3895,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,      return;    } +  handleDeclspecAlignBeforeClassKey(attrs, DS, TUK); + +  Sema::SkipBodyInfo SkipBody; +  if (!Name && TUK == Sema::TUK_Definition && Tok.is(tok::l_brace) && +      NextToken().is(tok::identifier)) +    SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(), +                                              NextToken().getIdentifierInfo(), +                                              NextToken().getLocation()); +    bool Owned = false;    bool IsDependent = false;    const char *PrevSpec = nullptr; @@ -3851,7 +3913,22 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,                                     AS, DS.getModulePrivateSpecLoc(), TParams,                                     Owned, IsDependent, ScopedEnumKWLoc,                                     IsScopedUsingClassTag, BaseType, -                                   DSC == DSC_type_specifier); +                                   DSC == DSC_type_specifier, &SkipBody); + +  if (SkipBody.ShouldSkip) { +    assert(TUK == Sema::TUK_Definition && "can only skip a definition"); + +    BalancedDelimiterTracker T(*this, tok::l_brace); +    T.consumeOpen(); +    T.skipToEnd(); + +    if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, +                           NameLoc.isValid() ? NameLoc : StartLoc, +                           PrevSpec, DiagID, TagDecl, Owned, +                           Actions.getASTContext().getPrintingPolicy())) +      Diag(StartLoc, DiagID) << PrevSpec; +    return; +  }    if (IsDependent) {      // This enum has a dependent nested-name-specifier. Handle it as a @@ -3923,6 +4000,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {      Diag(Tok, diag::error_empty_enum);    SmallVector<Decl *, 32> EnumConstantDecls; +  SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;    Decl *LastEnumConstDecl = nullptr; @@ -3953,7 +4031,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {      SourceLocation EqualLoc;      ExprResult AssignedVal; -    ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); +    EnumAvailabilityDiags.emplace_back(*this);      if (TryConsumeToken(tok::equal, EqualLoc)) {        AssignedVal = ParseConstantExpression(); @@ -3967,7 +4045,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {                                                      IdentLoc, Ident,                                                      attrs.getList(), EqualLoc,                                                      AssignedVal.get()); -    PD.complete(EnumConstDecl); +    EnumAvailabilityDiags.back().done();      EnumConstantDecls.push_back(EnumConstDecl);      LastEnumConstDecl = EnumConstDecl; @@ -4023,6 +4101,14 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {                          getCurScope(),                          attrs.getList()); +  // Now handle enum constant availability diagnostics. +  assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size()); +  for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) { +    ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); +    EnumAvailabilityDiags[i].redelay(); +    PD.complete(EnumConstantDecls[i]); +  } +    EnumScope.Exit();    Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl,                                     T.getCloseLocation()); @@ -4773,7 +4859,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D,        D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,                                                  DS.getConstSpecLoc(),                                                  DS.getVolatileSpecLoc(), -                                                DS.getRestrictSpecLoc()), +                                                DS.getRestrictSpecLoc(), +                                                DS.getAtomicSpecLoc()),                      DS.getAttributes(),                      SourceLocation());      else @@ -4916,7 +5003,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {      }      if (D.getCXXScopeSpec().isValid()) { -      if (Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec())) +      if (Actions.ShouldEnterDeclaratorScope(getCurScope(), +                                             D.getCXXScopeSpec()))          // Change the declaration context for name lookup, until this function          // is exited (and the declarator has been parsed).          DeclScopeObj.EnterDeclaratorScope(); @@ -4968,6 +5056,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {          AllowConstructorName = (D.getContext() == Declarator::MemberContext);        SourceLocation TemplateKWLoc; +      bool HadScope = D.getCXXScopeSpec().isValid();        if (ParseUnqualifiedId(D.getCXXScopeSpec(),                               /*EnteringContext=*/true,                               /*AllowDestructorName=*/true, @@ -4981,6 +5070,13 @@ void Parser::ParseDirectDeclarator(Declarator &D) {          D.SetIdentifier(nullptr, Tok.getLocation());          D.setInvalidType(true);        } else { +        // ParseUnqualifiedId might have parsed a scope specifier during error +        // recovery. If it did so, enter that scope. +        if (!HadScope && D.getCXXScopeSpec().isValid() && +            Actions.ShouldEnterDeclaratorScope(getCurScope(), +                                               D.getCXXScopeSpec())) +          DeclScopeObj.EnterDeclaratorScope(); +          // Parsed the unqualified-id; update range information and move along.          if (D.getSourceRange().getBegin().isInvalid())            D.SetRangeBegin(D.getName().getSourceRange().getBegin()); @@ -5022,7 +5118,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {        // If there was an error parsing parenthesized declarator, declarator        // scope may have been entered before. Don't do it again.        if (!D.isInvalidType() && -          Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec())) +          Actions.ShouldEnterDeclaratorScope(getCurScope(), +                                             D.getCXXScopeSpec()))          // Change the declaration context for name lookup, until this function          // is exited (and the declarator has been parsed).          DeclScopeObj.EnterDeclaratorScope(); @@ -5310,7 +5407,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D,      if (getLangOpts().CPlusPlus) {        // FIXME: Accept these components in any order, and produce fixits to        // correct the order if the user gets it wrong. Ideally we should deal -      // with the virt-specifier-seq and pure-specifier in the same way. +      // with the pure-specifier in the same way.        // Parse cv-qualifier-seq[opt].        ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, @@ -5323,15 +5420,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D,        }        // Parse ref-qualifier[opt]. -      if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) { -        Diag(Tok, getLangOpts().CPlusPlus11 ? -             diag::warn_cxx98_compat_ref_qualifier : -             diag::ext_ref_qualifier); - -        RefQualifierIsLValueRef = Tok.is(tok::amp); -        RefQualifierLoc = ConsumeToken(); +      if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc))          EndLoc = RefQualifierLoc; -      }        // C++11 [expr.prim.general]p3:        //   If a declaration declares a member function or member function @@ -5427,6 +5517,22 @@ void Parser::ParseFunctionDeclarator(Declarator &D,                  FnAttrs, EndLoc);  } +/// ParseRefQualifier - Parses a member function ref-qualifier. Returns +/// true if a ref-qualifier is found. +bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef, +                               SourceLocation &RefQualifierLoc) { +  if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) { +    Diag(Tok, getLangOpts().CPlusPlus11 ? +         diag::warn_cxx98_compat_ref_qualifier : +         diag::ext_ref_qualifier); + +    RefQualifierIsLValueRef = Tok.is(tok::amp); +    RefQualifierLoc = ConsumeToken(); +    return true; +  } +  return false; +} +  /// isFunctionDeclaratorIdentifierList - This parameter list may have an  /// identifier list form for a K&R-style function:  void foo(a,b,c)  /// | 
