diff options
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 21 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 61 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 49 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 58 | ||||
-rw-r--r-- | lib/Parse/ParseOpenMP.cpp | 41 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 197 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 28 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 3 |
11 files changed, 370 insertions, 91 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 331c5e42fd..07e606c986 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -261,7 +261,7 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, 0, AttrNameLoc, 0, 0, AttributeList::AS_GNU); } -void Parser::ParseAttributeArgsCommon( +unsigned Parser::ParseAttributeArgsCommon( IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { @@ -302,7 +302,7 @@ void Parser::ParseAttributeArgsCommon( ExprResult ArgExpr(ParseAssignmentExpression()); if (ArgExpr.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); - return; + return 0; } ArgExprs.push_back(ArgExpr.release()); // Eat the comma, move to the next argument @@ -318,6 +318,8 @@ void Parser::ParseAttributeArgsCommon( if (EndLoc) *EndLoc = RParen; + + return static_cast<unsigned>(ArgExprs.size()); } /// Parse the arguments to a parameterized GNU attribute or @@ -392,6 +394,8 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, return false; } + SourceLocation OpenParenLoc = Tok.getLocation(); + if (AttrName->getName() == "property") { // The property declspec is more complex in that it can take one or two // assignment expressions as a parameter, but the lhs of the assignment @@ -505,8 +509,17 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, return !HasInvalidAccessor; } - ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr, - SourceLocation(), AttributeList::AS_Declspec); + unsigned NumArgs = + ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr, + SourceLocation(), AttributeList::AS_Declspec); + + // If this attribute's args were parsed, and it was expected to have + // arguments but none were provided, emit a diagnostic. + const AttributeList *Attr = Attrs.getList(); + if (Attr && Attr->getMaxArgs() && !NumArgs) { + Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName; + return false; + } return true; } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index cef748f2aa..7ef04730ac 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1541,18 +1541,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } // Build the class template specialization. - TagOrTempResult - = Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK, - StartLoc, DS.getModulePrivateSpecLoc(), SS, - TemplateId->Template, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc, - attrs.getList(), - MultiTemplateParamsArg( - TemplateParams? &(*TemplateParams)[0] : 0, - TemplateParams? TemplateParams->size() : 0)); + TagOrTempResult = Actions.ActOnClassTemplateSpecialization( + getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), + *TemplateId, attrs.getList(), + MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : 0, + TemplateParams ? TemplateParams->size() : 0)); } } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation && TUK == Sema::TUK_Declaration) { @@ -2648,6 +2641,11 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, continue; } + if (Tok.is(tok::annot_pragma_ms_pragma)) { + HandlePragmaMSPragma(); + continue; + } + // If we see a namespace here, a close brace was missing somewhere. if (Tok.is(tok::kw_namespace)) { DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl)); @@ -3189,6 +3187,7 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, switch (AttributeList::getKind(AttrName, ScopeName, AttributeList::AS_CXX11)) { case AttributeList::AT_CarriesDependency: + case AttributeList::AT_Deprecated: case AttributeList::AT_FallThrough: case AttributeList::AT_CXX11NoReturn: { return true; @@ -3220,6 +3219,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, IdentifierInfo *ScopeName, SourceLocation ScopeLoc) { assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); + SourceLocation LParenLoc = Tok.getLocation(); // If the attribute isn't known, we will not attempt to parse any // arguments. @@ -3236,9 +3236,33 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, // behaviors. ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, AttributeList::AS_CXX11, 0); - else - ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, AttributeList::AS_CXX11); + else { + unsigned NumArgs = + ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, AttributeList::AS_CXX11); + + const AttributeList *Attr = Attrs.getList(); + if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { + // If the attribute is a standard or built-in attribute and we are + // parsing an argument list, we need to determine whether this attribute + // was allowed to have an argument list (such as [[deprecated]]), and how + // many arguments were parsed (so we can diagnose on [[deprecated()]]). + if (Attr->getMaxArgs() && !NumArgs) {
+ // The attribute was allowed to have arguments, but none were provided
+ // even though the attribute parsed successfully. This is an error.
+ // FIXME: This is a good place for a fixit which removes the parens.
+ Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
+ return false;
+ } else if (!Attr->getMaxArgs()) {
+ // The attribute parsed successfully, but was not allowed to have any
+ // arguments. It doesn't matter whether any were provided -- the
+ // presence of the argument list (even if empty) is diagnosed. + Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) + << AttrName; + return false; + } + } + } return true; } @@ -3319,14 +3343,9 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, << AttrName << SourceRange(SeenAttrs[AttrName]); // Parse attribute arguments - if (Tok.is(tok::l_paren)) { - if (StandardAttr) - Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments) - << AttrName->getName(); - + if (Tok.is(tok::l_paren)) AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, attrs, endLoc, ScopeName, ScopeLoc); - } if (!AttrParsed) attrs.addNew(AttrName, diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index ed9d72d338..15b327d1ef 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -835,6 +835,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2] case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU] case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS] + case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS] case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS] case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU] Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index f10ca6ab78..614949c935 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -365,15 +365,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Consume the template-id token. ConsumeToken(); - + assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); HasScopeSpecifier = true; - + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); - + if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, TemplateId->TemplateKWLoc, @@ -393,7 +393,6 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, continue; } - // The rest of the nested-name-specifier possibilities start with // tok::identifier. if (Tok.isNot(tok::identifier)) @@ -418,9 +417,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // error, but they probably meant something else strange so don't // recover like this. PP.LookAhead(1).is(tok::identifier)) { - Diag(Next, diag::err_unexected_colon_in_nested_name_spec) + Diag(Next, diag::err_unexpected_colon_in_nested_name_spec) << FixItHint::CreateReplacement(Next.getLocation(), "::"); - // Recover as if the user wrote '::'. Next.setKind(tok::coloncolon); } @@ -434,23 +432,52 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (ColonIsSacred) { + const Token &Next2 = GetLookAheadToken(2); + if (Next2.is(tok::kw_private) || Next2.is(tok::kw_protected) || + Next2.is(tok::kw_public) || Next2.is(tok::kw_virtual)) { + Diag(Next2, diag::err_unexpected_token_in_nested_name_spec) + << Next2.getName() + << FixItHint::CreateReplacement(Next.getLocation(), ":"); + Token ColonColon; + PP.Lex(ColonColon); + ColonColon.setKind(tok::colon); + PP.EnterToken(ColonColon); + break; + } + } + if (LastII) *LastII = &II; // We have an identifier followed by a '::'. Lookup this name // as the name in a nested-name-specifier. + Token Identifier = Tok; SourceLocation IdLoc = ConsumeToken(); assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) && "NextToken() not working properly!"); + Token ColonColon = Tok; SourceLocation CCLoc = ConsumeToken(); CheckForLParenAfterColonColon(); - HasScopeSpecifier = true; + bool IsCorrectedToColon = false; + bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : 0; if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc, - ObjectType, EnteringContext, SS)) + ObjectType, EnteringContext, SS, + false, CorrectionFlagPtr)) { + // Identifier is not recognized as a nested name, but we can have + // mistyped '::' instead of ':'. + if (CorrectionFlagPtr && IsCorrectedToColon) { + ColonColon.setKind(tok::colon); + PP.EnterToken(Tok); + PP.EnterToken(ColonColon); + Tok = Identifier; + break; + } SS.SetInvalid(SourceRange(IdLoc, CCLoc)); - + } + HasScopeSpecifier = true; continue; } @@ -837,8 +864,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // [..., x = expr // // We need to find the end of the following expression in order to - // determine whether this is an Obj-C message send's receiver, or a - // lambda init-capture. + // determine whether this is an Obj-C message send's receiver, a + // C99 designator, or a lambda init-capture. // // Parse the expression to find where it ends, and annotate it back // onto the tokens. We would have parsed this expression the same way diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 44053f193b..bdd4513167 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -66,45 +66,29 @@ bool Parser::MayBeDesignationStart() { } // Parse up to (at most) the token after the closing ']' to determine - // whether this is a C99 designator or a lambda. + // whether this is a C99 designator or a lambda. TentativeParsingAction Tentative(*this); - ConsumeBracket(); - while (true) { - switch (Tok.getKind()) { - case tok::equal: - case tok::amp: - case tok::identifier: - case tok::kw_this: - // These tokens can occur in a capture list or a constant-expression. - // Keep looking. - ConsumeToken(); - continue; - - case tok::comma: - // Since a comma cannot occur in a constant-expression, this must - // be a lambda. - Tentative.Revert(); - return false; - - case tok::r_square: { - // Once we hit the closing square bracket, we look at the next - // token. If it's an '=', this is a designator. Otherwise, it's a - // lambda expression. This decision favors lambdas over the older - // GNU designator syntax, which allows one to omit the '=', but is - // consistent with GCC. - ConsumeBracket(); - tok::TokenKind Kind = Tok.getKind(); - Tentative.Revert(); - return Kind == tok::equal; - } - - default: - // Anything else cannot occur in a lambda capture list, so it - // must be a designator. - Tentative.Revert(); - return true; - } + + LambdaIntroducer Intro; + bool SkippedInits = false; + Optional<unsigned> DiagID(ParseLambdaIntroducer(Intro, &SkippedInits)); + + if (DiagID) { + // If this can't be a lambda capture list, it's a designator. + Tentative.Revert(); + return true; } + + // Once we hit the closing square bracket, we look at the next + // token. If it's an '=', this is a designator. Otherwise, it's a + // lambda expression. This decision favors lambdas over the older + // GNU designator syntax, which allows one to omit the '=', but is + // consistent with GCC. + tok::TokenKind Kind = Tok.getKind(); + // FIXME: If we didn't skip any inits, parse the lambda from here + // rather than throwing away then reparsing the LambdaIntroducer. + Tentative.Revert(); + return Kind == tok::equal; } static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index f1b61077b3..bf3753fd81 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -258,7 +258,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, /// /// clause: /// if-clause | num_threads-clause | safelen-clause | default-clause | -/// private-clause | firstprivate-clause | shared-clause +/// private-clause | firstprivate-clause | shared-clause | linear-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -301,6 +301,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_private: case OMPC_firstprivate: case OMPC_shared: + case OMPC_linear: case OMPC_copyin: Clause = ParseOpenMPVarListClause(CKind); break; @@ -392,10 +393,13 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { /// 'firstprivate' '(' list ')' /// shared-clause: /// 'shared' '(' list ')' +/// linear-clause: +/// 'linear' '(' list [ ':' linear-step ] ')' /// OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); + SourceLocation ColonLoc = SourceLocation(); // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, @@ -404,8 +408,10 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { SmallVector<Expr *, 5> Vars; bool IsComma = true; - while (IsComma || (Tok.isNot(tok::r_paren) && + const bool MayHaveTail = (Kind == OMPC_linear); + while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { + ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); // Parse variable ExprResult VarExpr = ParseAssignmentExpression(); if (VarExpr.isUsable()) { @@ -416,21 +422,34 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { } // Skip ',' if any IsComma = Tok.is(tok::comma); - if (IsComma) { + if (IsComma) ConsumeToken(); - } else if (Tok.isNot(tok::r_paren) && - Tok.isNot(tok::annot_pragma_openmp_end)) { - Diag(Tok, diag::err_omp_expected_punc) - << getOpenMPClauseName(Kind); - } + else if (Tok.isNot(tok::r_paren) && + Tok.isNot(tok::annot_pragma_openmp_end) && + (!MayHaveTail || Tok.isNot(tok::colon))) + Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind); + } + + // Parse ':' linear-step + Expr *TailExpr = 0; + const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); + if (MustHaveTail) { + ColonLoc = Tok.getLocation(); + ConsumeToken(); + ExprResult Tail = ParseAssignmentExpression(); + if (Tail.isUsable()) + TailExpr = Tail.take(); + else + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); } // Parse ')'. T.consumeClose(); - if (Vars.empty()) + if (Vars.empty() || (MustHaveTail && !TailExpr)) return 0; - return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen, - Tok.getLocation()); + return Actions.ActOnOpenMPVarListClause(Kind, Vars, TailExpr, Loc, LOpen, + ColonLoc, Tok.getLocation()); } diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 29e17715b3..4b687a8b2e 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "RAIIObjectsForParser.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" @@ -124,6 +125,12 @@ struct PragmaMSVtorDisp : public PragmaHandler { Token &FirstToken) override; }; +struct PragmaMSPragma : public PragmaHandler { + explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + } // end namespace void Parser::initializePragmaHandlers() { @@ -175,6 +182,18 @@ void Parser::initializePragmaHandlers() { PP.AddPragmaHandler(MSPointersToMembers.get()); MSVtorDisp.reset(new PragmaMSVtorDisp()); PP.AddPragmaHandler(MSVtorDisp.get()); + MSInitSeg.reset(new PragmaMSPragma("init_seg")); + PP.AddPragmaHandler(MSInitSeg.get()); + MSDataSeg.reset(new PragmaMSPragma("data_seg")); + PP.AddPragmaHandler(MSDataSeg.get()); + MSBSSSeg.reset(new PragmaMSPragma("bss_seg")); + PP.AddPragmaHandler(MSBSSSeg.get()); + MSConstSeg.reset(new PragmaMSPragma("const_seg")); + PP.AddPragmaHandler(MSConstSeg.get()); + MSCodeSeg.reset(new PragmaMSPragma("code_seg")); + PP.AddPragmaHandler(MSCodeSeg.get()); + MSSection.reset(new PragmaMSPragma("section")); + PP.AddPragmaHandler(MSSection.get()); } } @@ -214,6 +233,18 @@ void Parser::resetPragmaHandlers() { MSPointersToMembers.reset(); PP.RemovePragmaHandler(MSVtorDisp.get()); MSVtorDisp.reset(); + PP.RemovePragmaHandler(MSInitSeg.get()); + MSInitSeg.reset(); + PP.RemovePragmaHandler(MSDataSeg.get()); + MSDataSeg.reset(); + PP.RemovePragmaHandler(MSBSSSeg.get()); + MSBSSSeg.reset(); + PP.RemovePragmaHandler(MSConstSeg.get()); + MSConstSeg.reset(); + PP.RemovePragmaHandler(MSCodeSeg.get()); + MSCodeSeg.reset(); + PP.RemovePragmaHandler(MSSection.get()); + MSSection.reset(); } PP.RemovePragmaHandler("STDC", FPContractHandler.get()); @@ -400,6 +431,145 @@ void Parser::HandlePragmaMSVtorDisp() { Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode); } +void Parser::HandlePragmaMSPragma() { + assert(Tok.is(tok::annot_pragma_ms_pragma)); + // Grab the tokens out of the annotation and enter them into the stream. + auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue(); + PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true); + SourceLocation PragmaLocation = ConsumeToken(); // The annotation token. + assert(Tok.isAnyIdentifier()); + llvm::StringRef PragmaName = Tok.getIdentifierInfo()->getName(); + PP.Lex(Tok); // pragma kind + // Figure out which #pragma we're dealing with. The switch has no default + // because lex shouldn't emit the annotation token for unrecognized pragmas. + typedef unsigned (Parser::*PragmaHandler)(llvm::StringRef, SourceLocation); + PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName) + .Case("data_seg", &Parser::HandlePragmaMSSegment) + .Case("bss_seg", &Parser::HandlePragmaMSSegment) + .Case("const_seg", &Parser::HandlePragmaMSSegment) + .Case("code_seg", &Parser::HandlePragmaMSSegment) + .Case("section", &Parser::HandlePragmaMSSection) + .Case("init_seg", &Parser::HandlePragmaMSInitSeg); + if (auto DiagID = (this->*Handler)(PragmaName, PragmaLocation)) { + PP.Diag(PragmaLocation, DiagID) << PragmaName; + while (Tok.isNot(tok::eof)) + PP.Lex(Tok); + PP.Lex(Tok); + } +} + +unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName, + SourceLocation PragmaLocation) { + if (Tok.isNot(tok::l_paren)) + return diag::warn_pragma_expected_lparen; + PP.Lex(Tok); // ( + // Parsing code for pragma section + if (Tok.isNot(tok::string_literal)) + return diag::warn_pragma_expected_section_name; + StringLiteral *SegmentName = + cast<StringLiteral>(ParseStringLiteralExpression().get()); + int SectionFlags = 0; + while (Tok.is(tok::comma)) { + PP.Lex(Tok); // , + if (!Tok.isAnyIdentifier()) + return diag::warn_pragma_expected_action_or_r_paren; + Sema::PragmaSectionFlag Flag = + llvm::StringSwitch<Sema::PragmaSectionFlag>( + Tok.getIdentifierInfo()->getName()) + .Case("read", Sema::PSF_Read) + .Case("write", Sema::PSF_Write) + .Case("execute", Sema::PSF_Execute) + .Case("shared", Sema::PSF_Invalid) + .Case("nopage", Sema::PSF_Invalid) + .Case("nocache", Sema::PSF_Invalid) + .Case("discard", Sema::PSF_Invalid) + .Case("remove", Sema::PSF_Invalid) + .Default(Sema::PSF_None); + if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) { + PP.Diag(PragmaLocation, Flag == Sema::PSF_None ? + diag::warn_pragma_invalid_specific_action : + diag::warn_pragma_unsupported_action) + << PragmaName << Tok.getIdentifierInfo()->getName(); + while (Tok.isNot(tok::eof)) + PP.Lex(Tok); + PP.Lex(Tok); + return 0; + } + SectionFlags |= Flag; + PP.Lex(Tok); // Identifier + } + if (Tok.isNot(tok::r_paren)) + return diag::warn_pragma_expected_rparen; + PP.Lex(Tok); // ) + if (Tok.isNot(tok::eof)) + return diag::warn_pragma_extra_tokens_at_eol; + PP.Lex(Tok); // eof + Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName); + return 0; +} + +unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName, + SourceLocation PragmaLocation) { + if (Tok.isNot(tok::l_paren)) + return diag::warn_pragma_expected_lparen; + PP.Lex(Tok); // ( + Sema::PragmaMsStackAction Action = Sema::PSK_Reset; + llvm::StringRef SlotLabel; + if (Tok.isAnyIdentifier()) { + llvm::StringRef PushPop = Tok.getIdentifierInfo()->getName(); + if (PushPop == "push") + Action = Sema::PSK_Push; + else if (PushPop == "pop") + Action = Sema::PSK_Pop; + else + return diag::warn_pragma_expected_section_push_pop_or_name; + if (Action != Sema::PSK_Reset) { + PP.Lex(Tok); // push | pop + if (Tok.is(tok::comma)) { + PP.Lex(Tok); // , + // If we've got a comma, we either need a label or a string. + if (Tok.isAnyIdentifier()) { + SlotLabel = Tok.getIdentifierInfo()->getName(); + PP.Lex(Tok); // identifier + if (Tok.is(tok::comma)) + PP.Lex(Tok); + else if (Tok.isNot(tok::r_paren)) + return diag::warn_pragma_expected_punc; + } + } else if (Tok.isNot(tok::r_paren)) + return diag::warn_pragma_expected_punc; + } + } + // Grab the string literal for our section name. + StringLiteral *SegmentName = nullptr; + if (Tok.isNot(tok::r_paren)) { + if (Tok.isNot(tok::string_literal)) + return Action != Sema::PSK_Reset ? !SlotLabel.empty() ? + diag::warn_pragma_expected_section_name : + diag::warn_pragma_expected_section_label_or_name : + diag::warn_pragma_expected_section_push_pop_or_name; + SegmentName = cast<StringLiteral>(ParseStringLiteralExpression().get()); + // Setting section "" has no effect + if (SegmentName->getLength()) + Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set); + } + if (Tok.isNot(tok::r_paren)) + return diag::warn_pragma_expected_rparen; + PP.Lex(Tok); // ) + if (Tok.isNot(tok::eof)) + return diag::warn_pragma_extra_tokens_at_eol; + PP.Lex(Tok); // eof + Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel, + SegmentName, PragmaName); + return 0; +} + +unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName, + SourceLocation PragmaLocation) { + return PP.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Error, "'#pragma %0' not implemented."); +} + // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' @@ -1204,6 +1374,33 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, PP.EnterToken(AnnotTok); } +/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting +/// an annotation token. +void PragmaMSPragma::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + Token EoF, AnnotTok; + EoF.startToken(); + EoF.setKind(tok::eof); + AnnotTok.startToken(); + AnnotTok.setKind(tok::annot_pragma_ms_pragma); + AnnotTok.setLocation(Tok.getLocation()); + SmallVector<Token, 8> TokenVector; + // Suck up all of the tokens before the eod. + for (; Tok.isNot(tok::eod); PP.Lex(Tok)) + TokenVector.push_back(Tok); + // Add a sentinal EoF token to the end of the list. + TokenVector.push_back(EoF); + // We must allocate this array with new because EnterTokenStream is going to + // delete it later. + Token *TokenArray = new Token[TokenVector.size()]; + std::copy(TokenVector.begin(), TokenVector.end(), TokenArray); + auto Value = new (PP.getPreprocessorAllocator()) + std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size())); + AnnotTok.setAnnotationValue(Value); + PP.EnterToken(AnnotTok); +} + /// \brief Handle the Microsoft \#pragma detect_mismatch extension. /// /// The syntax is: diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 7254eb3c11..88c6126311 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -26,12 +26,15 @@ #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" @@ -350,6 +353,10 @@ Retry: HandlePragmaMSPointersToMembers(); return StmtEmpty(); + case tok::annot_pragma_ms_pragma: + ProhibitAttributes(Attrs); + HandlePragmaMSPragma(); + return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. @@ -639,8 +646,9 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { ColonProtection.restore(); if (TryConsumeToken(tok::colon, ColonLoc)) { - } else if (TryConsumeToken(tok::semi, ColonLoc)) { - // Treat "case blah;" as a typo for "case blah:". + } else if (TryConsumeToken(tok::semi, ColonLoc) || + TryConsumeToken(tok::coloncolon, ColonLoc)) { + // Treat "case blah;" or "case blah::" as a typo for "case blah:". Diag(ColonLoc, diag::err_expected_after) << "'case'" << tok::colon << FixItHint::CreateReplacement(ColonLoc, ":"); @@ -828,6 +836,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_ms_pointers_to_members: HandlePragmaMSPointersToMembers(); break; + case tok::annot_pragma_ms_pragma: + HandlePragmaMSPragma(); + break; default: checkForPragmas = false; break; @@ -2166,7 +2177,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT)); // Get the instruction descriptor. - const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); + std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo()); std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); std::unique_ptr<llvm::MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TT, "", "")); @@ -2182,11 +2193,14 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); std::unique_ptr<llvm::MCAsmParser> Parser( createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI)); + + // FIXME: init MCOptions from sanitizer flags here. + llvm::MCTargetOptions MCOptions; std::unique_ptr<llvm::MCTargetAsmParser> TargetParser( - TheTarget->createMCAsmParser(*STI, *Parser, *MII)); + TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions)); - llvm::MCInstPrinter *IP = - TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); + std::unique_ptr<llvm::MCInstPrinter> IP( + TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI)); // Change to the Intel dialect. Parser->setAssemblerDialect(1); @@ -2208,7 +2222,7 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { SmallVector<std::string, 4> Clobbers; if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs, NumInputs, OpExprs, Constraints, - Clobbers, MII, IP, Callback)) + Clobbers, MII.get(), IP.get(), Callback)) return StmtError(); // Filter out "fpsw". Clang doesn't accept it, and it always lists flags and diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 777fd01aa2..e81c41da67 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -1161,6 +1161,7 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { // Template argument lists are constant-evaluation contexts. EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated); + ColonProtectionRAIIObject ColonProtection(*this, false); do { ParsedTemplateArgument Arg = ParseTemplateArgument(); diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 330e541659..71d19613a7 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -936,6 +936,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___real: case tok::kw___FUNCTION__: case tok::kw___FUNCDNAME__: + case tok::kw___FUNCSIG__: case tok::kw_L__FUNCTION__: case tok::kw___PRETTY_FUNCTION__: case tok::kw___uuidof: diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 9936a5a3ab..9d3f251a55 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -631,6 +631,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_ms_vtordisp: HandlePragmaMSVtorDisp(); return DeclGroupPtrTy(); + case tok::annot_pragma_ms_pragma: + HandlePragmaMSPragma(); + return DeclGroupPtrTy(); case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), |