diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp | 48 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp | 452 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp | 284 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp | 161 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp | 152 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp | 5 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp | 119 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp | 76 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp | 785 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp | 32 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp | 19 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp | 100 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp | 46 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/Parser.cpp | 153 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h | 447 |
15 files changed, 1786 insertions, 1093 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp index c52b61e..27651c9 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "RAIIObjectsForParser.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" using namespace clang; @@ -166,20 +166,11 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, } if (FnD) { - // If this is a friend function, mark that it's late-parsed so that - // it's still known to be a definition even before we attach the - // parsed body. Sema needs to treat friend function definitions - // differently during template instantiation, and it's possible for - // the containing class to be instantiated before all its member - // function definitions are parsed. - // - // If you remove this, you can remove the code that clears the flag - // after parsing the member. - if (D.getDeclSpec().isFriendSpecified()) { - FunctionDecl *FD = FnD->getAsFunction(); - Actions.CheckForFunctionRedefinition(FD); - FD->setLateTemplateParsed(true); - } + FunctionDecl *FD = FnD->getAsFunction(); + // Track that this function will eventually have a body; Sema needs + // to know this. + Actions.CheckForFunctionRedefinition(FD); + FD->setWillHaveBody(true); } else { // If semantic analysis could not build a function declaration, // just throw away the late-parsed declaration. @@ -344,9 +335,9 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // The argument isn't actually potentially evaluated unless it is // used. - EnterExpressionEvaluationContext Eval(Actions, - Sema::PotentiallyEvaluatedIfUsed, - Param); + EnterExpressionEvaluationContext Eval( + Actions, + Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, Param); ExprResult DefArgResult; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { @@ -558,10 +549,6 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { ParseFunctionStatementBody(LM.D, FnScope); - // Clear the late-template-parsed bit if we set it before. - if (LM.D) - LM.D->getAsFunction()->setLateTemplateParsed(false); - while (Tok.isNot(tok::eof)) ConsumeAnyToken(); @@ -731,19 +718,6 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, ConsumeBrace(); break; - case tok::code_completion: - Toks.push_back(Tok); - ConsumeCodeCompletionToken(); - break; - - case tok::string_literal: - case tok::wide_string_literal: - case tok::utf8_string_literal: - case tok::utf16_string_literal: - case tok::utf32_string_literal: - Toks.push_back(Tok); - ConsumeStringToken(); - break; case tok::semi: if (StopAtSemi) return false; @@ -751,7 +725,7 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, default: // consume this token. Toks.push_back(Tok); - ConsumeToken(); + ConsumeAnyToken(/*ConsumeCodeCompletionTok*/true); break; } isFirstTokenConsumed = false; @@ -902,7 +876,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { // If the opening brace is not preceded by one of these tokens, we are // missing the mem-initializer-id. In order to recover better, we need // to use heuristics to determine if this '{' is most likely the - // begining of a brace-init-list or the function body. + // beginning of a brace-init-list or the function body. // Check the token after the corresponding '}'. TentativeParsingAction PA(*this); if (SkipUntil(tok::r_brace) && diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 2d32087..a461069 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "RAIIObjectsForParser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/AddressSpaces.h" @@ -71,11 +71,18 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } +/// \brief Normalizes an attribute name by dropping prefixed and suffixed __. +static StringRef normalizeAttrName(StringRef Name) { + if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) + return Name.drop_front(2).drop_back(2); + return Name; +} + /// isAttributeLateParsed - Return true if the attribute has arguments that /// require late parsing. static bool isAttributeLateParsed(const IdentifierInfo &II) { #define CLANG_ATTR_LATE_PARSED_LIST - return llvm::StringSwitch<bool>(II.getName()) + return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) #include "clang/Parse/AttrParserStringSwitches.inc" .Default(false); #undef CLANG_ATTR_LATE_PARSED_LIST @@ -200,13 +207,6 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, } } -/// \brief Normalizes an attribute name by dropping prefixed and suffixed __. -static StringRef normalizeAttrName(StringRef Name) { - if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) - Name = Name.drop_front(2).drop_back(2); - return Name; -} - /// \brief Determine whether the given attribute has an identifier argument. static bool attributeHasIdentifierArg(const IdentifierInfo &II) { #define CLANG_ATTR_IDENTIFIER_ARG_LIST @@ -308,7 +308,9 @@ unsigned Parser::ParseAttributeArgsCommon( do { bool Uneval = attributeParsedArgsUnevaluated(*AttrName); EnterExpressionEvaluationContext Unevaluated( - Actions, Uneval ? Sema::Unevaluated : Sema::ConstantEvaluated, + Actions, + Uneval ? Sema::ExpressionEvaluationContext::Unevaluated + : Sema::ExpressionEvaluationContext::ConstantEvaluated, /*LambdaContextDecl=*/nullptr, /*IsDecltype=*/false); @@ -356,6 +358,10 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; + } else if (AttrKind == AttributeList::AT_ExternalSourceSymbol) { + ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); + return; } else if (AttrKind == AttributeList::AT_ObjCBridgeRelated) { ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); @@ -389,6 +395,25 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, ScopeLoc, Syntax); } +unsigned Parser::ParseClangAttributeArgs( + IdentifierInfo *AttrName, SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { + assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); + + AttributeList::Kind AttrKind = + AttributeList::getKind(AttrName, ScopeName, Syntax); + + if (AttrKind == AttributeList::AT_ExternalSourceSymbol) { + ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); + return Attrs.getList() ? Attrs.getList()->getNumArgs() : 0; + } + + return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); +} + bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs) { @@ -1064,6 +1089,119 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, Syntax, StrictLoc, ReplacementExpr.get()); } +/// \brief Parse the contents of the "external_source_symbol" attribute. +/// +/// external-source-symbol-attribute: +/// 'external_source_symbol' '(' keyword-arg-list ')' +/// +/// keyword-arg-list: +/// keyword-arg +/// keyword-arg ',' keyword-arg-list +/// +/// keyword-arg: +/// 'language' '=' <string> +/// 'defined_in' '=' <string> +/// 'generated_declaration' +void Parser::ParseExternalSourceSymbolAttribute( + IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc, + ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { + // Opening '('. + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume()) + return; + + // Initialize the pointers for the keyword identifiers when required. + if (!Ident_language) { + Ident_language = PP.getIdentifierInfo("language"); + Ident_defined_in = PP.getIdentifierInfo("defined_in"); + Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration"); + } + + ExprResult Language; + bool HasLanguage = false; + ExprResult DefinedInExpr; + bool HasDefinedIn = false; + IdentifierLoc *GeneratedDeclaration = nullptr; + + // Parse the language/defined_in/generated_declaration keywords + do { + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_external_source_symbol_expected_keyword); + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + + SourceLocation KeywordLoc = Tok.getLocation(); + IdentifierInfo *Keyword = Tok.getIdentifierInfo(); + if (Keyword == Ident_generated_declaration) { + if (GeneratedDeclaration) { + Diag(Tok, diag::err_external_source_symbol_duplicate_clause) << Keyword; + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + GeneratedDeclaration = ParseIdentifierLoc(); + continue; + } + + if (Keyword != Ident_language && Keyword != Ident_defined_in) { + Diag(Tok, diag::err_external_source_symbol_expected_keyword); + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + + ConsumeToken(); + if (ExpectAndConsume(tok::equal, diag::err_expected_after, + Keyword->getName())) { + SkipUntil(tok::r_paren, StopAtSemi); + return; + } + + bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn; + if (Keyword == Ident_language) + HasLanguage = true; + else + HasDefinedIn = true; + + if (Tok.isNot(tok::string_literal)) { + Diag(Tok, diag::err_expected_string_literal) + << /*Source='external_source_symbol attribute'*/ 3 + << /*language | source container*/ (Keyword != Ident_language); + SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch); + continue; + } + if (Keyword == Ident_language) { + if (HadLanguage) { + Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause) + << Keyword; + ParseStringLiteralExpression(); + continue; + } + Language = ParseStringLiteralExpression(); + } else { + assert(Keyword == Ident_defined_in && "Invalid clause keyword!"); + if (HadDefinedIn) { + Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause) + << Keyword; + ParseStringLiteralExpression(); + continue; + } + DefinedInExpr = ParseStringLiteralExpression(); + } + } while (TryConsumeToken(tok::comma)); + + // Closing ')'. + if (T.consumeClose()) + return; + if (EndLoc) + *EndLoc = T.getCloseLocation(); + + ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(), + GeneratedDeclaration}; + Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()), + ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax); +} + /// \brief Parse the contents of the "objc_bridge_related" attribute. /// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')' /// related_class: @@ -2414,6 +2552,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, } } // Fall through. + LLVM_FALLTHROUGH; } case tok::comma: case tok::equal: @@ -2439,9 +2578,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // and attempt to recover. ParsedType T; IdentifierInfo *II = Tok.getIdentifierInfo(); + bool IsTemplateName = getLangOpts().CPlusPlus && NextToken().is(tok::less); Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T, - getLangOpts().CPlusPlus && - NextToken().is(tok::less)); + IsTemplateName); if (T) { // The action has suggested that the type T could be used. Set that as // the type in the declaration specifiers, consume the would-be type @@ -2466,6 +2605,13 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); + // Eat any following template arguments. + if (IsTemplateName) { + SourceLocation LAngle, RAngle; + TemplateArgList Args; + ParseTemplateIdAfterTemplateName(true, LAngle, Args, RAngle); + } + // TODO: Could inject an invalid typedef decl in an enclosing scope to // avoid rippling error messages on subsequent uses of the same type, // could be useful if #include was forgotten. @@ -2483,6 +2629,8 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { return DSC_class; if (Context == Declarator::FileContext) return DSC_top_level; + if (Context == Declarator::TemplateParamContext) + return DSC_template_param; if (Context == Declarator::TemplateTypeArgContext) return DSC_template_type_arg; if (Context == Declarator::TrailingReturnContext) @@ -2824,48 +2972,27 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ->Kind == TNK_Type_template) { // We have a qualified template-id, e.g., N::A<int> - // C++ [class.qual]p2: - // In a lookup in which the constructor is an acceptable lookup - // result and the nested-name-specifier nominates a class C: - // - // - if the name specified after the - // nested-name-specifier, when looked up in C, is the - // injected-class-name of C (Clause 9), or - // - // - if the name specified after the nested-name-specifier - // is the same as the identifier or the - // simple-template-id's template-name in the last - // component of the nested-name-specifier, + // If this would be a valid constructor declaration with template + // arguments, we will reject the attempt to form an invalid type-id + // referring to the injected-class-name when we annotate the token, + // per C++ [class.qual]p2. // - // the name is instead considered to name the constructor of - // class C. - // - // Thus, if the template-name is actually the constructor - // name, then the code is ill-formed; this interpretation is - // reinforced by the NAD status of core issue 635. + // To improve diagnostics for this case, parse the declaration as a + // constructor (and reject the extra template arguments later). TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next); if ((DSContext == DSC_top_level || DSContext == DSC_class) && TemplateId->Name && - Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS)) { - if (isConstructorDeclarator(/*Unqualified*/false)) { - // The user meant this to be an out-of-line constructor - // definition, but template arguments are not allowed - // there. Just allow this as a constructor; we'll - // complain about it later. - goto DoneWithDeclSpec; - } - - // The user meant this to name a type, but it actually names - // a constructor with some extraneous template - // arguments. Complain, then parse it as a type as the user - // intended. - Diag(TemplateId->TemplateNameLoc, - diag::err_out_of_line_template_id_type_names_constructor) - << TemplateId->Name << 0 /* template name */; + Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) && + isConstructorDeclarator(/*Unqualified*/false)) { + // The user meant this to be an out-of-line constructor + // definition, but template arguments are not allowed + // there. Just allow this as a constructor; we'll + // complain about it later. + goto DoneWithDeclSpec; } DS.getTypeSpecScope() = SS; - ConsumeToken(); // The C++ scope. + ConsumeAnnotationToken(); // The C++ scope. assert(Tok.is(tok::annot_template_id) && "ParseOptionalCXXScopeSpecifier not working"); AnnotateTemplateIdTokenAsType(); @@ -2874,7 +3001,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (Next.is(tok::annot_typename)) { DS.getTypeSpecScope() = SS; - ConsumeToken(); // The C++ scope. + ConsumeAnnotationToken(); // The C++ scope. if (Tok.getAnnotationValue()) { ParsedType T = getTypeAnnotation(Tok); isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, @@ -2886,43 +3013,35 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, else DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); - ConsumeToken(); // The typename + ConsumeAnnotationToken(); // The typename } if (Next.isNot(tok::identifier)) goto DoneWithDeclSpec; - // If we're in a context where the identifier could be a class name, - // check whether this is a constructor declaration. + // Check whether this is a constructor declaration. If we're in a + // context where the identifier could be a class name, and it has the + // shape of a constructor declaration, process it as one. if ((DSContext == DSC_top_level || DSContext == DSC_class) && Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(), - &SS)) { - if (isConstructorDeclarator(/*Unqualified*/false)) - goto DoneWithDeclSpec; - - // As noted in C++ [class.qual]p2 (cited above), when the name - // of the class is qualified in a context where it could name - // a constructor, its a constructor name. However, we've - // looked at the declarator, and the user probably meant this - // to be a type. Complain that it isn't supposed to be treated - // as a type, then proceed to parse it as a type. - Diag(Next.getLocation(), - diag::err_out_of_line_template_id_type_names_constructor) - << Next.getIdentifierInfo() << 1 /* type */; - } + &SS) && + isConstructorDeclarator(/*Unqualified*/ false)) + goto DoneWithDeclSpec; ParsedType TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(), Next.getLocation(), getCurScope(), &SS, false, false, nullptr, /*IsCtorOrDtorName=*/false, - /*NonTrivialSourceInfo=*/true); + /*WantNonTrivialSourceInfo=*/true, + isClassTemplateDeductionContext(DSContext)); // If the referenced identifier is not a type, then this declspec is // erroneous: We already checked about that it has no type specifier, and // C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the // typename. if (!TypeRep) { - ConsumeToken(); // Eat the scope spec so the identifier is current. + // Eat the scope spec so the identifier is current. + ConsumeAnnotationToken(); ParsedAttributesWithRange Attrs(AttrFactory); if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) { if (!Attrs.empty()) { @@ -2935,7 +3054,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } DS.getTypeSpecScope() = SS; - ConsumeToken(); // The C++ scope. + ConsumeAnnotationToken(); // The C++ scope. isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, TypeRep, Policy); @@ -2965,7 +3084,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; DS.SetRangeEnd(Tok.getAnnotationEndLoc()); - ConsumeToken(); // The typename + ConsumeAnnotationToken(); // The typename continue; } @@ -2996,6 +3115,31 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (DS.hasTypeSpecifier()) goto DoneWithDeclSpec; + // If the token is an identifier named "__declspec" and Microsoft + // extensions are not enabled, it is likely that there will be cascading + // parse errors if this really is a __declspec attribute. Attempt to + // recognize that scenario and recover gracefully. + if (!getLangOpts().DeclSpecKeyword && Tok.is(tok::identifier) && + Tok.getIdentifierInfo()->getName().equals("__declspec")) { + Diag(Loc, diag::err_ms_attributes_not_enabled); + + // The next token should be an open paren. If it is, eat the entire + // attribute declaration and continue. + if (NextToken().is(tok::l_paren)) { + // Consume the __declspec identifier. + ConsumeToken(); + + // Eat the parens and everything between them. + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.consumeOpen()) { + assert(false && "Not a left paren?"); + return; + } + T.skipToEnd(); + continue; + } + } + // In C++, check to see if this is a scope specifier like foo::bar::, if // so handle it as such. This is important for ctor parsing. if (getLangOpts().CPlusPlus) { @@ -3029,9 +3173,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; } - ParsedType TypeRep = - Actions.getTypeName(*Tok.getIdentifierInfo(), - Tok.getLocation(), getCurScope()); + ParsedType TypeRep = Actions.getTypeName( + *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr, + false, false, nullptr, false, false, + isClassTemplateDeductionContext(DSContext)); // If this is not a typedef name, don't parse it as part of the declspec, // it must be an implicit int or an error. @@ -3054,6 +3199,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isConstructorDeclarator(/*Unqualified*/true)) goto DoneWithDeclSpec; + // Likewise, if this is a context where the identifier could be a template + // name, check whether this is a deduction guide declaration. + if (getLangOpts().CPlusPlus1z && + (DSContext == DSC_class || DSContext == DSC_top_level) && + Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(), + Tok.getLocation()) && + isConstructorDeclarator(/*Unqualified*/ true, + /*DeductionGuide*/ true)) + goto DoneWithDeclSpec; + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, TypeRep, Policy); if (isInvalid) @@ -3526,6 +3681,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = true; break; }; + LLVM_FALLTHROUGH; case tok::kw___private: case tok::kw___global: case tok::kw___local: @@ -3951,8 +4107,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // anything that's a simple-type-specifier followed by '(' as an // expression. This suffices because function types are not valid // underlying types anyway. - EnterExpressionEvaluationContext Unevaluated(Actions, - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind()); // If the next token starts an expression, we know we're parsing a // bit-field. This is the common case. @@ -4107,7 +4263,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType, - DSC == DSC_type_specifier, &SkipBody); + DSC == DSC_type_specifier, + DSC == DSC_template_param || + DSC == DSC_template_type_arg, &SkipBody); if (SkipBody.ShouldSkip) { assert(TUK == Sema::TUK_Definition && "can only skip a definition"); @@ -4161,8 +4319,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, return; } - if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) - ParseEnumBody(StartLoc, TagDecl); + if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) { + Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl; + ParseEnumBody(StartLoc, D); + if (SkipBody.CheckSameAsPrevious && + !Actions.ActOnDuplicateDefinition(DS, TagDecl, SkipBody)) { + DS.SetTypeSpecError(); + return; + } + } if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, @@ -4234,11 +4399,9 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { } // Install the enumerator constant into EnumDecl. - Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl, - LastEnumConstDecl, - IdentLoc, Ident, - attrs.getList(), EqualLoc, - AssignedVal.get()); + Decl *EnumConstDecl = Actions.ActOnEnumConstant( + getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, + attrs.getList(), EqualLoc, AssignedVal.get()); EnumAvailabilityDiags.back().done(); EnumConstantDecls.push_back(EnumConstDecl); @@ -4673,7 +4836,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { } } -bool Parser::isConstructorDeclarator(bool IsUnqualified) { +bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide) { TentativeParsingAction TPA(*this); // Parse the C++ scope specifier. @@ -4685,15 +4848,21 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) { } // Parse the constructor name. - if (Tok.isOneOf(tok::identifier, tok::annot_template_id)) { + if (Tok.is(tok::identifier)) { // We already know that we have a constructor name; just consume // the token. ConsumeToken(); + } else if (Tok.is(tok::annot_template_id)) { + ConsumeAnnotationToken(); } else { TPA.Revert(); return false; } + // There may be attributes here, appertaining to the constructor name or type + // we just stepped past. + SkipCXX11Attributes(); + // Current class name must be followed by a left parenthesis. if (Tok.isNot(tok::l_paren)) { TPA.Revert(); @@ -4740,7 +4909,7 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) { // be a constructor declaration with an invalid argument type. Keep // looking. if (Tok.is(tok::annot_cxxscope)) - ConsumeToken(); + ConsumeAnnotationToken(); ConsumeToken(); // If this is not a constructor, we must be parsing a declarator, @@ -4761,13 +4930,24 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) { case tok::r_paren: // C(X ) - if (NextToken().is(tok::colon) || NextToken().is(tok::kw_try)) { + + // Skip past the right-paren and any following attributes to get to + // the function body or trailing-return-type. + ConsumeParen(); + SkipCXX11Attributes(); + + if (DeductionGuide) { + // C(X) -> ... is a deduction guide. + IsConstructor = Tok.is(tok::arrow); + break; + } + if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) { // Assume these were meant to be constructors: // C(X) : (the name of a bit-field cannot be parenthesized). // C(X) try (this is otherwise ill-formed). IsConstructor = true; } - if (NextToken().is(tok::semi) || NextToken().is(tok::l_brace)) { + if (Tok.is(tok::semi) || Tok.is(tok::l_brace)) { // If we have a constructor name within the class definition, // assume these were meant to be constructors: // C(X) { @@ -4778,7 +4958,7 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) { // // FIXME: We can actually do this whether or not the name is qualified, // because if it is qualified in this context it must be being used as - // a constructor name. However, we do not implement that rule correctly + // a constructor name. // currently, so we're somewhat conservative here. IsConstructor = IsUnqualified; } @@ -4806,9 +4986,10 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified) { /// [ only if AttReqs & AR_CXX11AttributesParsed ] /// Note: vendor can be GNU, MS, etc and can be explicitly controlled via /// AttrRequirements bitmask values. -void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, - bool AtomicAllowed, - bool IdentifierRequired) { +void Parser::ParseTypeQualifierListOpt( + DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed, + bool IdentifierRequired, + Optional<llvm::function_ref<void()>> CodeCompletionHandler) { if (getLangOpts().CPlusPlus11 && (AttrReqs & AR_CXX11AttributesParsed) && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); @@ -4826,7 +5007,10 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, switch (Tok.getKind()) { case tok::code_completion: - Actions.CodeCompleteTypeQualifiers(DS); + if (CodeCompletionHandler) + (*CodeCompletionHandler)(); + else + Actions.CodeCompleteTypeQualifiers(DS); return cutOffParsing(); case tok::kw_const: @@ -4872,6 +5056,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, if (TryKeywordIdentFallback(false)) continue; } + LLVM_FALLTHROUGH; case tok::kw___sptr: case tok::kw___w64: case tok::kw___ptr64: @@ -4921,6 +5106,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, continue; // do *not* consume the next token! } // otherwise, FALL THROUGH! + LLVM_FALLTHROUGH; default: DoneWithTypeQuals: // If this is not a type-qualifier token, we're done reading type @@ -5309,21 +5495,29 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // We found something that indicates the start of an unqualified-id. // Parse that unqualified-id. bool AllowConstructorName; - if (D.getDeclSpec().hasTypeSpecifier()) + bool AllowDeductionGuide; + if (D.getDeclSpec().hasTypeSpecifier()) { AllowConstructorName = false; - else if (D.getCXXScopeSpec().isSet()) + AllowDeductionGuide = false; + } else if (D.getCXXScopeSpec().isSet()) { AllowConstructorName = (D.getContext() == Declarator::FileContext || D.getContext() == Declarator::MemberContext); - else + AllowDeductionGuide = false; + } else { AllowConstructorName = (D.getContext() == Declarator::MemberContext); + AllowDeductionGuide = + (D.getContext() == Declarator::FileContext || + D.getContext() == Declarator::MemberContext); + } SourceLocation TemplateKWLoc; bool HadScope = D.getCXXScopeSpec().isValid(); if (ParseUnqualifiedId(D.getCXXScopeSpec(), /*EnteringContext=*/true, /*AllowDestructorName=*/true, AllowConstructorName, - nullptr, TemplateKWLoc, D.getName()) || + AllowDeductionGuide, nullptr, TemplateKWLoc, + D.getName()) || // Once we're past the identifier, if the scope was bad, mark the // whole declarator bad. D.getCXXScopeSpec().isInvalid()) { @@ -5361,11 +5555,28 @@ void Parser::ParseDirectDeclarator(Declarator &D) { D.SetRangeEnd(Tok.getLocation()); ConsumeToken(); goto PastIdentifier; - } else if (Tok.is(tok::identifier) && D.diagnoseIdentifier()) { - // A virt-specifier isn't treated as an identifier if it appears after a - // trailing-return-type. - if (D.getContext() != Declarator::TrailingReturnContext || - !isCXX11VirtSpecifier(Tok)) { + } else if (Tok.is(tok::identifier) && !D.mayHaveIdentifier()) { + // We're not allowed an identifier here, but we got one. Try to figure out + // if the user was trying to attach a name to the type, or whether the name + // is some unrelated trailing syntax. + bool DiagnoseIdentifier = false; + if (D.hasGroupingParens()) + // An identifier within parens is unlikely to be intended to be anything + // other than a name being "declared". + DiagnoseIdentifier = true; + else if (D.getContext() == Declarator::TemplateTypeArgContext) + // T<int N> is an accidental identifier; T<int N indicates a missing '>'. + DiagnoseIdentifier = + NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater); + else if (D.getContext() == Declarator::AliasDeclContext || + D.getContext() == Declarator::AliasTemplateContext) + // The most likely error is that the ';' was forgotten. + DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi); + else if (D.getContext() == Declarator::TrailingReturnContext && + !isCXX11VirtSpecifier(Tok)) + DiagnoseIdentifier = NextToken().isOneOf( + tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try); + if (DiagnoseIdentifier) { Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id) << FixItHint::CreateRemoval(Tok.getLocation()); D.SetIdentifier(nullptr, Tok.getLocation()); @@ -5409,6 +5620,21 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (Tok.is(tok::l_square)) return ParseMisplacedBracketDeclarator(D); if (D.getContext() == Declarator::MemberContext) { + // Objective-C++: Detect C++ keywords and try to prevent further errors by + // treating these keyword as valid member names. + if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus && + Tok.getIdentifierInfo() && + Tok.getIdentifierInfo()->isCPlusPlusKeyword(getLangOpts())) { + Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), + diag::err_expected_member_name_or_semi_objcxx_keyword) + << Tok.getIdentifierInfo() + << (D.getDeclSpec().isEmpty() ? SourceRange() + : D.getDeclSpec().getSourceRange()); + D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); + D.SetRangeEnd(Tok.getLocation()); + ConsumeToken(); + goto PastIdentifier; + } Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), diag::err_expected_member_name_or_semi) << (D.getDeclSpec().isEmpty() ? SourceRange() @@ -5744,7 +5970,11 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // Parse cv-qualifier-seq[opt]. ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, - /*AtomicAllowed*/ false); + /*AtomicAllowed*/ false, + /*IdentifierRequired=*/false, + llvm::function_ref<void()>([&]() { + Actions.CodeCompleteFunctionQualifiers(DS, D); + })); if (!DS.getSourceRange().getEnd().isInvalid()) { EndLoc = DS.getSourceRange().getEnd(); ConstQualifierLoc = DS.getConstSpecLoc(); @@ -6097,9 +6327,10 @@ void Parser::ParseParameterDeclarationClause( // The argument isn't actually potentially evaluated unless it is // used. - EnterExpressionEvaluationContext Eval(Actions, - Sema::PotentiallyEvaluatedIfUsed, - Param); + EnterExpressionEvaluationContext Eval( + Actions, + Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed, + Param); ExprResult DefArgResult; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { @@ -6249,8 +6480,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) { if (getLangOpts().CPlusPlus) { NumElements = ParseConstantExpression(); } else { - EnterExpressionEvaluationContext Unevaluated(Actions, - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); NumElements = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); } @@ -6385,8 +6616,9 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { const bool hasParens = Tok.is(tok::l_paren); - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, - Sema::ReuseLambdaContextDecl); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); bool isCastExpr; ParsedType CastTy; @@ -6418,7 +6650,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { return; } - // If we get here, the operand to the typeof was an expresion. + // If we get here, the operand to the typeof was an expression. if (Operand.isInvalid()) { DS.SetTypeSpecError(); return; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index 3f1fe7e..2301284 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/Attributes.h" @@ -20,6 +19,7 @@ #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/PrettyDeclStackTrace.h" @@ -266,15 +266,26 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, CXXScopeSpec SS; // Parse (optional) nested-name-specifier. - ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); + ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false, + /*MayBePseudoDestructor=*/nullptr, + /*IsTypename=*/false, + /*LastII=*/nullptr, + /*OnlyNamespace=*/true); - if (SS.isInvalid() || Tok.isNot(tok::identifier)) { + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_namespace_name); // Skip to end of the definition and eat the ';'. SkipUntil(tok::semi); return nullptr; } + if (SS.isInvalid()) { + // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier. + // Skip to end of the definition and eat the ';'. + SkipUntil(tok::semi); + return nullptr; + } + // Parse identifier. IdentifierInfo *Ident = Tok.getIdentifierInfo(); SourceLocation IdentLoc = ConsumeToken(); @@ -487,13 +498,17 @@ Decl *Parser::ParseUsingDirective(unsigned Context, CXXScopeSpec SS; // Parse (optional) nested-name-specifier. - ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); + ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false, + /*MayBePseudoDestructor=*/nullptr, + /*IsTypename=*/false, + /*LastII=*/nullptr, + /*OnlyNamespace=*/true); IdentifierInfo *NamespcName = nullptr; SourceLocation IdentLoc = SourceLocation(); // Parse namespace-name. - if (SS.isInvalid() || Tok.isNot(tok::identifier)) { + if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_namespace_name); // If there was invalid namespace name, skip to end of decl, and eat ';'. SkipUntil(tok::semi); @@ -501,6 +516,13 @@ Decl *Parser::ParseUsingDirective(unsigned Context, return nullptr; } + if (SS.isInvalid()) { + // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier. + // Skip to end of the definition and eat the ';'. + SkipUntil(tok::semi); + return nullptr; + } + // Parse identifier. NamespcName = Tok.getIdentifierInfo(); IdentLoc = ConsumeToken(); @@ -576,6 +598,7 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) { /*AllowDestructorName=*/true, /*AllowConstructorName=*/!(Tok.is(tok::identifier) && NextToken().is(tok::equal)), + /*AllowDeductionGuide=*/false, nullptr, D.TemplateKWLoc, D.Name)) return true; } @@ -817,7 +840,9 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ return nullptr; } - ExprResult AssertExpr(ParseConstantExpression()); + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult AssertExpr(ParseConstantExpressionInExprEvalContext()); if (AssertExpr.isInvalid()) { SkipMalformedDecl(); return nullptr; @@ -878,7 +903,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { if (Tok.is(tok::annot_decltype)) { Result = getExprAnnotation(Tok); EndLoc = Tok.getAnnotationEndLoc(); - ConsumeToken(); + ConsumeAnnotationToken(); if (Result.isInvalid()) { DS.SetTypeSpecError(); return EndLoc; @@ -912,8 +937,9 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // C++11 [dcl.type.simple]p4: // The operand of the decltype specifier is an unevaluated operand. - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, - nullptr,/*IsDecltype=*/true); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, + /*IsDecltype=*/true); Result = Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; @@ -1076,12 +1102,12 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); if (TemplateId->Kind == TNK_Type_template || TemplateId->Kind == TNK_Dependent_template_name) { - AnnotateTemplateIdTokenAsType(); + AnnotateTemplateIdTokenAsType(/*IsClassName*/true); assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); ParsedType Type = getTypeAnnotation(Tok); EndLocation = Tok.getAnnotationEndLoc(); - ConsumeToken(); + ConsumeAnnotationToken(); if (Type) return Type; @@ -1113,8 +1139,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (!Template) { TemplateArgList TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - ParseTemplateIdAfterTemplateName(nullptr, IdLoc, SS, true, LAngleLoc, - TemplateArgs, RAngleLoc); + ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc); return true; } @@ -1124,10 +1150,10 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // Parse the full template-id, then turn it into a type. if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(), - TemplateName, true)) + TemplateName)) return true; - if (TNK == TNK_Dependent_template_name) - AnnotateTemplateIdTokenAsType(); + if (TNK == TNK_Type_template || TNK == TNK_Dependent_template_name) + AnnotateTemplateIdTokenAsType(/*IsClassName*/true); // If we didn't end up with a typename token, there's nothing more we // can do. @@ -1138,16 +1164,17 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // return. EndLocation = Tok.getAnnotationEndLoc(); ParsedType Type = getTypeAnnotation(Tok); - ConsumeToken(); + ConsumeAnnotationToken(); return Type; } // We have an identifier; check whether it is actually a type. IdentifierInfo *CorrectedII = nullptr; - ParsedType Type = - Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true, false, nullptr, - /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo=*/true, &CorrectedII); + ParsedType Type = Actions.getTypeName( + *Id, IdLoc, getCurScope(), &SS, /*IsClassName=*/true, false, nullptr, + /*IsCtorOrDtorName=*/false, + /*NonTrivialTypeSourceInfo=*/true, + /*IsClassTemplateDeductionContext*/ false, &CorrectedII); if (!Type) { Diag(IdLoc, diag::err_expected_class_name); return true; @@ -1381,6 +1408,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, !Tok.isAnnotation() && Tok.getIdentifierInfo() && Tok.isOneOf(tok::kw___is_abstract, + tok::kw___is_aggregate, tok::kw___is_arithmetic, tok::kw___is_array, tok::kw___is_assignable, @@ -1504,8 +1532,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // a class (or template thereof). TemplateArgList TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - if (ParseTemplateIdAfterTemplateName( - nullptr, NameLoc, SS, true, LAngleLoc, TemplateArgs, RAngleLoc)) { + if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc)) { // We couldn't parse the template argument list at all, so don't // try to give any location information for the list. LAngleLoc = RAngleLoc = SourceLocation(); @@ -1539,7 +1567,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, } } else if (Tok.is(tok::annot_template_id)) { TemplateId = takeTemplateIdAnnotation(Tok); - NameLoc = ConsumeToken(); + NameLoc = ConsumeAnnotationToken(); if (TemplateId->Kind != TNK_Type_template && TemplateId->Kind != TNK_Dependent_template_name) { @@ -1859,7 +1887,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation(), false, clang::TypeResult(), DSC == DSC_type_specifier, - &SkipBody); + DSC == DSC_template_param || + DSC == DSC_template_type_arg, &SkipBody); // If ActOnTag said the type was dependent, try again with the // less common call. @@ -1881,10 +1910,24 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, else if (getLangOpts().CPlusPlus) ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType, TagOrTempResult.get()); - else - ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get()); + else { + Decl *D = + SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get(); + // Parse the definition body. + ParseStructUnionBody(StartLoc, TagType, D); + if (SkipBody.CheckSameAsPrevious && + !Actions.ActOnDuplicateDefinition(DS, TagOrTempResult.get(), + SkipBody)) { + DS.SetTypeSpecError(); + return; + } + } } + if (!TagOrTempResult.isInvalid()) + // Delayed processing of attributes. + Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList()); + const char *PrevSpec = nullptr; unsigned DiagID; bool Result; @@ -2283,7 +2326,11 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( // GNU-style and C++11 attributes are not allowed here, but they will be // handled by the caller. Diagnose everything else. - ParseTypeQualifierListOpt(DS, AR_NoAttributesParsed, false); + ParseTypeQualifierListOpt( + DS, AR_NoAttributesParsed, false, + /*IdentifierRequired=*/false, llvm::function_ref<void()>([&]() { + Actions.CodeCompleteFunctionQualifiers(DS, D, &VS); + })); D.ExtendWithDeclSpec(DS); if (D.isFunctionDeclarator()) { @@ -2425,8 +2472,8 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Try to parse an unqualified-id. SourceLocation TemplateKWLoc; UnqualifiedId Name; - if (ParseUnqualifiedId(SS, false, true, true, nullptr, TemplateKWLoc, - Name)) { + if (ParseUnqualifiedId(SS, false, true, true, false, nullptr, + TemplateKWLoc, Name)) { SkipUntil(tok::semi); return nullptr; } @@ -2457,9 +2504,10 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::kw_template)) { assert(!TemplateInfo.TemplateParams && "Nested template improperly parsed?"); + ObjCDeclContextSwitch ObjCDC(*this); SourceLocation DeclEnd; return DeclGroupPtrTy::make( - DeclGroupRef(ParseDeclarationStartingWithTemplate( + DeclGroupRef(ParseTemplateDeclarationOrSpecialization( Declarator::MemberContext, DeclEnd, AS, AccessAttrs))); } @@ -2864,9 +2912,8 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, assert(Tok.isOneOf(tok::equal, tok::l_brace) && "Data member initializer not starting with '=' or '{'"); - EnterExpressionEvaluationContext Context(Actions, - Sema::PotentiallyEvaluated, - D); + EnterExpressionEvaluationContext Context( + Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, D); if (TryConsumeToken(tok::equal, EqualLoc)) { if (Tok.is(tok::kw_delete)) { // In principle, an initializer of '= delete p;' is legal, but it will @@ -2957,56 +3004,50 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs, DeclSpec::TST TagType, Decl *TagDecl) { - if (getLangOpts().MicrosoftExt && - Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { + switch (Tok.getKind()) { + case tok::kw___if_exists: + case tok::kw___if_not_exists: ParseMicrosoftIfExistsClassDeclaration(TagType, AS); return nullptr; - } - // Check for extraneous top-level semicolon. - if (Tok.is(tok::semi)) { + case tok::semi: + // Check for extraneous top-level semicolon. ConsumeExtraSemi(InsideStruct, TagType); return nullptr; - } - if (Tok.is(tok::annot_pragma_vis)) { + // Handle pragmas that can appear as member declarations. + case tok::annot_pragma_vis: HandlePragmaVisibility(); return nullptr; - } - - if (Tok.is(tok::annot_pragma_pack)) { + case tok::annot_pragma_pack: HandlePragmaPack(); return nullptr; - } - - if (Tok.is(tok::annot_pragma_align)) { + case tok::annot_pragma_align: HandlePragmaAlign(); return nullptr; - } - - if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) { + case tok::annot_pragma_ms_pointers_to_members: HandlePragmaMSPointersToMembers(); return nullptr; - } - - if (Tok.is(tok::annot_pragma_ms_pragma)) { + case tok::annot_pragma_ms_pragma: HandlePragmaMSPragma(); return nullptr; - } - - if (Tok.is(tok::annot_pragma_ms_vtordisp)) { + case tok::annot_pragma_ms_vtordisp: HandlePragmaMSVtorDisp(); return nullptr; - } + case tok::annot_pragma_dump: + HandlePragmaDump(); + return nullptr; - // If we see a namespace here, a close brace was missing somewhere. - if (Tok.is(tok::kw_namespace)) { + case tok::kw_namespace: + // If we see a namespace here, a close brace was missing somewhere. DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl)); return nullptr; - } - AccessSpecifier NewAS = getAccessSpecifierIfPresent(); - if (NewAS != AS_none) { + case tok::kw_public: + case tok::kw_protected: + case tok::kw_private: { + AccessSpecifier NewAS = getAccessSpecifierIfPresent(); + assert(NewAS != AS_none); // Current token is a C++ access specifier. AS = NewAS; SourceLocation ASLoc = Tok.getLocation(); @@ -3041,12 +3082,13 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( return nullptr; } - if (Tok.is(tok::annot_pragma_openmp)) + case tok::annot_pragma_openmp: return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, AccessAttrs, TagType, TagDecl); - // Parse all the comma separated declarators. - return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList()); + default: + return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList()); + } } /// ParseCXXMemberSpecification - Parse the class definition. @@ -3376,39 +3418,42 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // parse '::'[opt] nested-name-specifier[opt] CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); - ParsedType TemplateTypeTy; - if (Tok.is(tok::annot_template_id)) { - TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); - if (TemplateId->Kind == TNK_Type_template || - TemplateId->Kind == TNK_Dependent_template_name) { - AnnotateTemplateIdTokenAsType(); - assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); - TemplateTypeTy = getTypeAnnotation(Tok); - } - } - // Uses of decltype will already have been converted to annot_decltype by - // ParseOptionalCXXScopeSpecifier at this point. - if (!TemplateTypeTy && Tok.isNot(tok::identifier) - && Tok.isNot(tok::annot_decltype)) { - Diag(Tok, diag::err_expected_member_or_base_name); - return true; - } + // : identifier IdentifierInfo *II = nullptr; - DeclSpec DS(AttrFactory); SourceLocation IdLoc = Tok.getLocation(); - if (Tok.is(tok::annot_decltype)) { + // : declype(...) + DeclSpec DS(AttrFactory); + // : template_name<...> + ParsedType TemplateTypeTy; + + if (Tok.is(tok::identifier)) { + // Get the identifier. This may be a member name or a class name, + // but we'll let the semantic analysis determine which it is. + II = Tok.getIdentifierInfo(); + ConsumeToken(); + } else if (Tok.is(tok::annot_decltype)) { // Get the decltype expression, if there is one. + // Uses of decltype will already have been converted to annot_decltype by + // ParseOptionalCXXScopeSpecifier at this point. + // FIXME: Can we get here with a scope specifier? ParseDecltypeSpecifier(DS); } else { - if (Tok.is(tok::identifier)) - // Get the identifier. This may be a member name or a class name, - // but we'll let the semantic analysis determine which it is. - II = Tok.getIdentifierInfo(); - ConsumeToken(); + TemplateIdAnnotation *TemplateId = Tok.is(tok::annot_template_id) + ? takeTemplateIdAnnotation(Tok) + : nullptr; + if (TemplateId && (TemplateId->Kind == TNK_Type_template || + TemplateId->Kind == TNK_Dependent_template_name)) { + AnnotateTemplateIdTokenAsType(/*IsClassName*/true); + assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); + TemplateTypeTy = getTypeAnnotation(Tok); + ConsumeAnnotationToken(); + } else { + Diag(Tok, diag::err_expected_member_or_base_name); + return true; + } } - // Parse the '('. if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); @@ -3817,36 +3862,44 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, return false; } - if (ScopeName && ScopeName->getName() == "gnu") + if (ScopeName && ScopeName->getName() == "gnu") { // GNU-scoped attributes have some special cases to handle GNU-specific // behaviors. ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, AttributeList::AS_CXX11, nullptr); - else { - unsigned NumArgs = + return true; + } + + unsigned NumArgs; + // Some Clang-scoped attributes have some special parsing behavior. + if (ScopeName && ScopeName->getName() == "clang") + NumArgs = + ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, + ScopeLoc, AttributeList::AS_CXX11); + else + 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. - Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; - Attr->setInvalid(true); - } 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 - << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); - Attr->setInvalid(true); - } + + 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. + Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; + Attr->setInvalid(true); + } 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 + << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); + Attr->setInvalid(true); } } return true; @@ -4114,8 +4167,6 @@ void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) { } if (!T.consumeClose()) { - // FIXME: Warn that this syntax is deprecated, with a Fix-It suggesting - // using __declspec(uuid()) instead. Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr, SourceLocation(), ArgExprs.data(), ArgExprs.size(), AttributeList::AS_Microsoft); @@ -4177,6 +4228,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. + LLVM_FALLTHROUGH; case IEB_Skip: Braces.skipToEnd(); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index 852e226..44b87af 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -21,10 +21,10 @@ /// //===----------------------------------------------------------------------===// -#include "RAIIObjectsForParser.h" +#include "clang/Parse/Parser.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/PrettyStackTrace.h" -#include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -192,18 +192,25 @@ Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc, return ParseRHSOfBinaryExpression(R, prec::Assignment); } +ExprResult +Parser::ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast) { + assert(Actions.ExprEvalContexts.back().Context == + Sema::ExpressionEvaluationContext::ConstantEvaluated && + "Call this function only if your ExpressionEvaluationContext is " + "already ConstantEvaluated"); + ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); + ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); + return Actions.ActOnConstantExpression(Res); +} ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { // C++03 [basic.def.odr]p2: // An expression is potentially evaluated unless it appears where an // integral constant expression is required (see 5.19) [...]. // C++98 and C++11 have no such rule, but this is only a defect in C++98. - EnterExpressionEvaluationContext ConstantEvaluated(Actions, - Sema::ConstantEvaluated); - - ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); - ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); - return Actions.ActOnConstantExpression(Res); + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + return ParseConstantExpressionInExprEvalContext(isTypeCast); } /// \brief Parse a constraint-expression. @@ -235,6 +242,30 @@ bool Parser::isNotExpressionStart() { return isKnownToBeDeclarationSpecifier(); } +/// We've parsed something that could plausibly be intended to be a template +/// name (\p LHS) followed by a '<' token, and the following code can't possibly +/// be an expression. Determine if this is likely to be a template-id and if so, +/// diagnose it. +bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) { + TentativeParsingAction TPA(*this); + // FIXME: We could look at the token sequence in a lot more detail here. + if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater, + StopAtSemi | StopBeforeMatch)) { + TPA.Commit(); + + SourceLocation Greater; + ParseGreaterThanInTemplateList(Greater, true, false); + Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS, + Less, Greater); + return true; + } + + // There's no matching '>' token, this probably isn't supposed to be + // interpreted as a template-id. Parse it as an (ill-formed) comparison. + TPA.Revert(); + return false; +} + static bool isFoldOperator(prec::Level Level) { return Level > prec::Unknown && Level != prec::Conditional; } @@ -276,6 +307,16 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { return LHS; } + // If a '<' token is followed by a type that can be a template argument and + // cannot be an expression, then this is ill-formed, but might be intended + // to be a template-id. + if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName(LHS) && + (isKnownToBeDeclarationSpecifier() || + Tok.isOneOf(tok::greater, tok::greatergreater, + tok::greatergreatergreater)) && + diagnoseUnknownTemplateId(LHS, OpToken.getLocation())) + return ExprError(); + // If the next token is an ellipsis, then this is a fold-expression. Leave // it alone so we can handle it in the paren expression. if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) { @@ -339,7 +380,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { ColonLoc = Tok.getLocation(); } } - + // Code completion for the right-hand side of an assignment expression // goes through a special hook that takes the left-hand side into account. if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) { @@ -347,7 +388,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { cutOffParsing(); return ExprError(); } - + // Parse another leaf here for the RHS of the operator. // ParseCastExpression works here because all RHS expressions in C have it // as a prefix, at least. However, in C++, an assignment-expression could @@ -456,6 +497,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { if (!getLangOpts().CPlusPlus) continue; } + // Ensure potential typos aren't left undiagnosed. if (LHS.isInvalid()) { Actions.CorrectDelayedTyposInExpr(OrigLHS); @@ -473,12 +515,14 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, - TypeCastState isTypeCast) { + TypeCastState isTypeCast, + bool isVectorLiteral) { bool NotCastExpr; ExprResult Res = ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, - isTypeCast); + isTypeCast, + isVectorLiteral); if (NotCastExpr) Diag(Tok, diag::err_expected_expression); return Res; @@ -674,6 +718,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// '__is_union' /// /// [Clang] unary-type-trait: +/// '__is_aggregate' /// '__trivially_copyable' /// /// binary-type-trait: @@ -694,7 +739,8 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { ExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, bool &NotCastExpr, - TypeCastState isTypeCast) { + TypeCastState isTypeCast, + bool isVectorLiteral) { ExprResult Res; tok::TokenKind SavedKind = Tok.getKind(); NotCastExpr = false; @@ -722,6 +768,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/, isTypeCast == IsTypeCast, CastTy, RParenLoc); + if (isVectorLiteral) + return Res; + switch (ParenExprType) { case SimpleExpr: break; // Nothing else to do. case CompoundStmt: break; // Nothing else to do. @@ -762,7 +811,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::annot_primary_expr: assert(Res.get() == nullptr && "Stray primary-expression annotation?"); Res = getExprAnnotation(Tok); - ConsumeToken(); + ConsumeAnnotationToken(); break; case tok::kw___super: @@ -798,6 +847,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, = RTT_JOIN(tok::kw_,Name) REVERTIBLE_TYPE_TRAIT(__is_abstract); + REVERTIBLE_TYPE_TRAIT(__is_aggregate); REVERTIBLE_TYPE_TRAIT(__is_arithmetic); REVERTIBLE_TYPE_TRAIT(__is_array); REVERTIBLE_TYPE_TRAIT(__is_assignable); @@ -1156,7 +1206,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (Ty.isInvalid()) break; - ConsumeToken(); + ConsumeAnnotationToken(); Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(), Ty.get(), nullptr); break; @@ -1264,6 +1314,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, } // Fall through to treat the template-id as an id-expression. + LLVM_FALLTHROUGH; } case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id @@ -1307,7 +1358,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // C++11 [expr.unary.noexcept]p1: // The noexcept operator determines whether the evaluation of its operand, // which is an unevaluated operand, can throw an exception. - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated); ExprResult Result = ParseExpression(); T.consumeClose(); @@ -1433,9 +1485,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { nullptr, LHS.get()); break; } - // Fall through; this isn't a message send. - + LLVM_FALLTHROUGH; + default: // Not a postfix-expression suffix. return LHS; case tok::l_square: { // postfix-expression: p-e '[' expression ']' @@ -1693,6 +1745,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /*AllowDestructorName=*/true, /*AllowConstructorName=*/ getLangOpts().MicrosoftExt, + /*AllowDeductionGuide=*/false, ObjectType, TemplateKWLoc, Name)) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); @@ -1813,7 +1866,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, } } - // If we get here, the operand to the typeof/sizeof/alignof was an expresion. + // If we get here, the operand to the typeof/sizeof/alignof was an expression. isCastExpr = false; return Operand; } @@ -1875,9 +1928,10 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { if (!Name) return ExprError(); - - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, - Sema::ReuseLambdaContextDecl); + + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); return Actions.ActOnSizeofParameterPackExpr(getCurScope(), OpTok.getLocation(), @@ -1888,8 +1942,9 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof)) Diag(OpTok, diag::warn_cxx98_compat_alignof); - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, - Sema::ReuseLambdaContextDecl); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); bool isCastExpr; ParsedType CastTy; @@ -1917,7 +1972,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { if (OpTok.isOneOf(tok::kw_alignof, tok::kw__Alignof)) Diag(OpTok, diag::ext_alignof_expr) << OpTok.getIdentifierInfo(); - // If we get here, the operand to the sizeof/alignof was an expresion. + // If we get here, the operand to the sizeof/alignof was an expression. if (!Operand.isInvalid()) Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), ExprKind, @@ -2349,6 +2404,48 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc); } + if (Tok.is(tok::l_paren)) { + // This could be OpenCL vector Literals + if (getLangOpts().OpenCL) + { + TypeResult Ty; + { + InMessageExpressionRAIIObject InMessage(*this, false); + Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); + } + if(Ty.isInvalid()) + { + return ExprError(); + } + QualType QT = Ty.get().get().getCanonicalType(); + if (QT->isVectorType()) + { + // We parsed '(' vector-type-name ')' followed by '(' + + // Parse the cast-expression that follows it next. + // isVectorLiteral = true will make sure we don't parse any + // Postfix expression yet + Result = ParseCastExpression(/*isUnaryExpression=*/false, + /*isAddressOfOperand=*/false, + /*isTypeCast=*/IsTypeCast, + /*isVectorLiteral=*/true); + + if (!Result.isInvalid()) { + Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc, + DeclaratorInfo, CastTy, + RParenLoc, Result.get()); + } + + // After we performed the cast we can check for postfix-expr pieces. + if (!Result.isInvalid()) { + Result = ParsePostfixExpressionSuffix(Result); + } + + return Result; + } + } + } + if (ExprType == CastExpr) { // We parsed '(' type-name ')' and the thing after it wasn't a '{'. @@ -2520,7 +2617,8 @@ ExprResult Parser::ParseGenericSelectionExpression() { { // C11 6.5.1.1p3 "The controlling expression of a generic selection is // not evaluated." - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated); ControllingExpr = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (ControllingExpr.isInvalid()) { @@ -2933,6 +3031,11 @@ Optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() { return AvailabilitySpec(ConsumeToken()); } else { // Parse the platform name. + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteAvailabilityPlatformName(); + cutOffParsing(); + return None; + } if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_avail_query_expected_platform_name); return None; @@ -2945,12 +3048,14 @@ Optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() { if (Version.empty()) return None; - StringRef Platform = PlatformIdentifier->Ident->getName(); + StringRef GivenPlatform = PlatformIdentifier->Ident->getName(); + StringRef Platform = + AvailabilityAttr::canonicalizePlatformName(GivenPlatform); if (AvailabilityAttr::getPrettyPlatformName(Platform).empty()) { Diag(PlatformIdentifier->Loc, diag::err_avail_query_unrecognized_platform_name) - << Platform; + << GivenPlatform; return None; } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index 124266a..dcafbad 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -10,13 +10,13 @@ // This file implements the Expression parsing implementation for C++. // //===----------------------------------------------------------------------===// +#include "clang/Parse/Parser.h" #include "clang/AST/ASTContext.h" -#include "RAIIObjectsForParser.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" -#include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -141,13 +141,16 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, /// filled in with the leading identifier in the last component of the /// nested-name-specifier, if any. /// +/// \param OnlyNamespace If true, only considers namespaces in lookup. +/// /// \returns true if there was an error parsing a scope specifier bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ParsedType ObjectType, bool EnteringContext, bool *MayBePseudoDestructor, bool IsTypename, - IdentifierInfo **LastII) { + IdentifierInfo **LastII, + bool OnlyNamespace) { assert(getLangOpts().CPlusPlus && "Call sites of this function should be guarded by checking for C++"); @@ -157,7 +160,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); - ConsumeToken(); + ConsumeAnnotationToken(); return false; } @@ -216,7 +219,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, SourceLocation EndLoc = ParseDecltypeSpecifier(DS); SourceLocation CCLoc; - if (!TryConsumeToken(tok::coloncolon, CCLoc)) { + // Work around a standard defect: 'decltype(auto)::' is not a + // nested-name-specifier. + if (DS.getTypeSpecType() == DeclSpec::TST_decltype_auto || + !TryConsumeToken(tok::coloncolon, CCLoc)) { AnnotateExistingDecltypeSpecifier(DS, DeclLoc, EndLoc); return false; } @@ -310,11 +316,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Commit to parsing the template-id. TPA.Commit(); TemplateTy Template; - if (TemplateNameKind TNK - = Actions.ActOnDependentTemplateName(getCurScope(), - SS, TemplateKWLoc, TemplateName, - ObjectType, EnteringContext, - Template)) { + if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName( + getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType, + EnteringContext, Template, /*AllowInjectedClassName*/ true)) { if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateKWLoc, TemplateName, false)) return true; @@ -342,7 +346,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, *LastII = TemplateId->Name; // Consume the template-id token. - ConsumeToken(); + ConsumeAnnotationToken(); assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); @@ -449,9 +453,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, bool IsCorrectedToColon = false; bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr; - if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), IdInfo, - EnteringContext, SS, - false, CorrectionFlagPtr)) { + if (Actions.ActOnCXXNestedNameSpecifier( + getCurScope(), IdInfo, EnteringContext, SS, false, + CorrectionFlagPtr, OnlyNamespace)) { // Identifier is not recognized as a nested name, but we can have // mistyped '::' instead of ':'. if (CorrectionFlagPtr && IsCorrectedToColon) { @@ -509,12 +513,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, Diag(Tok.getLocation(), DiagID) << II.getName() << FixItHint::CreateInsertion(Tok.getLocation(), "template "); - - if (TemplateNameKind TNK - = Actions.ActOnDependentTemplateName(getCurScope(), - SS, SourceLocation(), - TemplateName, ObjectType, - EnteringContext, Template)) { + + if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName( + getCurScope(), SS, SourceLocation(), TemplateName, ObjectType, + EnteringContext, Template, /*AllowInjectedClassName*/ true)) { // Consume the identifier. ConsumeToken(); if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(), @@ -550,6 +552,7 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe /*EnteringContext=*/false, /*AllowDestructorName=*/false, /*AllowConstructorName=*/false, + /*AllowDeductionGuide=*/false, /*ObjectType=*/nullptr, TemplateKWLoc, Name)) return ExprError(); @@ -863,8 +866,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // Each lambda init-capture forms its own full expression, which clears // Actions.MaybeODRUseExprs. So create an expression evaluation context // to save the necessary state, and restore it later. - EnterExpressionEvaluationContext EC(Actions, - Sema::PotentiallyEvaluated); + EnterExpressionEvaluationContext EC( + Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); if (TryConsumeToken(tok::equal)) InitKind = LambdaCaptureInitKind::CopyInit; @@ -917,7 +920,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, PP.AnnotateCachedTokens(Tok); // Consume the annotated initializer. - ConsumeToken(); + ConsumeAnnotationToken(); } } } else @@ -1402,8 +1405,9 @@ ExprResult Parser::ParseCXXTypeid() { // We enter the unevaluated context before trying to determine whether we // have a type-id, because the tentative parse logic will try to resolve // names, and must treat them as unevaluated. - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated, - Sema::ReuseLambdaContextDecl); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated, + Sema::ReuseLambdaContextDecl); if (isTypeIdInParens()) { TypeResult Ty = ParseTypeName(); @@ -1466,7 +1470,8 @@ ExprResult Parser::ParseCXXUuidof() { Ty.get().getAsOpaquePtr(), T.getCloseLocation()); } else { - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated); Result = ParseExpression(); // Match the ')'. @@ -1523,7 +1528,7 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, // store it in the pseudo-dtor node (to be used when instantiating it). FirstTypeName.setTemplateId( (TemplateIdAnnotation *)Tok.getAnnotationValue()); - ConsumeToken(); + ConsumeAnnotationToken(); assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail"); CCLoc = ConsumeToken(); } else { @@ -1643,9 +1648,10 @@ ExprResult Parser::ParseCXXThis() { /// typename-specifier '(' expression-list[opt] ')' /// [C++0x] typename-specifier braced-init-list /// +/// In C++1z onwards, the type specifier can also be a template-name. ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, Declarator::FunctionalCastContext); ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); assert((Tok.is(tok::l_paren) || @@ -1876,7 +1882,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); - ConsumeToken(); + ConsumeAnnotationToken(); DS.Finish(Actions, Policy); return; @@ -1945,11 +1951,8 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.Finish(Actions, Policy); return; } - if (Tok.is(tok::annot_typename)) - DS.SetRangeEnd(Tok.getAnnotationEndLoc()); - else - DS.SetRangeEnd(Tok.getLocation()); - ConsumeToken(); + ConsumeAnyToken(); + DS.SetRangeEnd(PrevTokLocation); DS.Finish(Actions, Policy); } @@ -2020,9 +2023,11 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, case UnqualifiedId::IK_OperatorFunctionId: case UnqualifiedId::IK_LiteralOperatorId: if (AssumeTemplateId) { - TNK = Actions.ActOnDependentTemplateName(getCurScope(), SS, TemplateKWLoc, - Id, ObjectType, EnteringContext, - Template); + // We defer the injected-class-name checks until we've found whether + // this template-id is used to form a nested-name-specifier or not. + TNK = Actions.ActOnDependentTemplateName( + getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext, + Template, /*AllowInjectedClassName*/ true); if (TNK == TNK_Non_template) return true; } else { @@ -2051,10 +2056,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword) << Name << FixItHint::CreateInsertion(Id.StartLocation, "template "); - TNK = Actions.ActOnDependentTemplateName(getCurScope(), - SS, TemplateKWLoc, Id, - ObjectType, EnteringContext, - Template); + TNK = Actions.ActOnDependentTemplateName( + getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext, + Template, /*AllowInjectedClassName*/ true); if (TNK == TNK_Non_template) return true; } @@ -2077,10 +2081,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, bool MemberOfUnknownSpecialization; TemplateName.setIdentifier(Name, NameLoc); if (ObjectType) { - TNK = Actions.ActOnDependentTemplateName(getCurScope(), - SS, TemplateKWLoc, TemplateName, - ObjectType, EnteringContext, - Template); + TNK = Actions.ActOnDependentTemplateName( + getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType, + EnteringContext, Template, /*AllowInjectedClassName*/ true); if (TNK == TNK_Non_template) return true; } else { @@ -2108,11 +2111,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - if (Tok.is(tok::less) && - ParseTemplateIdAfterTemplateName(Template, Id.StartLocation, - SS, true, LAngleLoc, - TemplateArgs, - RAngleLoc)) + if (Tok.is(tok::less) && ParseTemplateIdAfterTemplateName( + true, LAngleLoc, TemplateArgs, RAngleLoc)) return true; if (Id.getKind() == UnqualifiedId::IK_Identifier || @@ -2120,31 +2120,18 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) { // Form a parsed representation of the template-id to be stored in the // UnqualifiedId. - TemplateIdAnnotation *TemplateId - = TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds); // FIXME: Store name for literal operator too. - if (Id.getKind() == UnqualifiedId::IK_Identifier) { - TemplateId->Name = Id.Identifier; - TemplateId->Operator = OO_None; - TemplateId->TemplateNameLoc = Id.StartLocation; - } else { - TemplateId->Name = nullptr; - TemplateId->Operator = Id.OperatorFunctionId.Operator; - TemplateId->TemplateNameLoc = Id.StartLocation; - } + IdentifierInfo *TemplateII = + Id.getKind() == UnqualifiedId::IK_Identifier ? Id.Identifier : nullptr; + OverloadedOperatorKind OpKind = Id.getKind() == UnqualifiedId::IK_Identifier + ? OO_None + : Id.OperatorFunctionId.Operator; + + TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create( + SS, TemplateKWLoc, Id.StartLocation, TemplateII, OpKind, Template, TNK, + LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds); - TemplateId->SS = SS; - TemplateId->TemplateKWLoc = TemplateKWLoc; - TemplateId->Template = Template; - TemplateId->Kind = TNK; - TemplateId->LAngleLoc = LAngleLoc; - TemplateId->RAngleLoc = RAngleLoc; - ParsedTemplateArgument *Args = TemplateId->getTemplateArgs(); - for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); - Arg != ArgEnd; ++Arg) - Args[Arg] = TemplateArgs[Arg]; - Id.setTemplateId(TemplateId); return false; } @@ -2155,7 +2142,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Constructor and destructor names. TypeResult Type = Actions.ActOnTemplateIdType(SS, TemplateKWLoc, - Template, NameLoc, + Template, Name, NameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc, /*IsCtorOrDtorName=*/true); if (Type.isInvalid()) @@ -2432,6 +2419,8 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, /// /// \param AllowConstructorName whether we allow parsing a constructor name. /// +/// \param AllowDeductionGuide whether we allow parsing a deduction guide name. +/// /// \param ObjectType if this unqualified-id occurs within a member access /// expression, the type of the base object whose member is being accessed. /// @@ -2441,6 +2430,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, + bool AllowDeductionGuide, ParsedType ObjectType, SourceLocation& TemplateKWLoc, UnqualifiedId &Result) { @@ -2469,6 +2459,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, return false; } + ParsedTemplateTy TemplateName; if (AllowConstructorName && Actions.isCurrentClassName(*Id, getCurScope(), &SS)) { // We have parsed a constructor name. @@ -2477,6 +2468,12 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, /*IsCtorOrDtorName=*/true, /*NonTrivialTypeSourceInfo=*/true); Result.setConstructorName(Ty, IdLoc, IdLoc); + } else if (getLangOpts().CPlusPlus1z && + AllowDeductionGuide && SS.isEmpty() && + Actions.isDeductionGuideName(getCurScope(), *Id, IdLoc, + &TemplateName)) { + // We have parsed a template-name naming a deduction guide. + Result.setDeductionGuideName(TemplateName, IdLoc); } else { // We have parsed an identifier. Result.setIdentifier(Id, IdLoc); @@ -2516,12 +2513,12 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, /*NontrivialTypeSourceInfo=*/true); Result.setConstructorName(Ty, TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); - ConsumeToken(); + ConsumeAnnotationToken(); return false; } Result.setConstructorTemplateId(TemplateId); - ConsumeToken(); + ConsumeAnnotationToken(); return false; } @@ -2529,7 +2526,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // our unqualified-id. Result.setTemplateId(TemplateId); TemplateKWLoc = TemplateId->TemplateKWLoc; - ConsumeToken(); + ConsumeAnnotationToken(); return false; } @@ -2569,7 +2566,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, if (SS.isEmpty() && Tok.is(tok::kw_decltype)) { DeclSpec DS(AttrFactory); SourceLocation EndLoc = ParseDecltypeSpecifier(DS); - if (ParsedType Type = Actions.getDestructorType(DS, ObjectType)) { + if (ParsedType Type = + Actions.getDestructorTypeForDecltype(DS, ObjectType)) { Result.setDestructorName(TildeLoc, Type, EndLoc); return false; } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp index fa6b75d..90f3561 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseInit.cpp @@ -11,9 +11,9 @@ // //===----------------------------------------------------------------------===// -#include "RAIIObjectsForParser.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/SmallString.h" @@ -501,7 +501,8 @@ bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists) << Result.IsIfExists; // Fall through to skip. - + LLVM_FALLTHROUGH; + case IEB_Skip: Braces.skipToEnd(); return false; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp index 81761bf..01b1bf4 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/CharInfo.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" @@ -137,8 +137,7 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { while (1) { MaybeSkipAttributes(tok::objc_class); - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; + if (expectIdentifier()) { SkipUntil(tok::semi); return Actions.ConvertDeclToDeclGroup(nullptr); } @@ -229,11 +228,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, MaybeSkipAttributes(tok::objc_interface); - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) - << tok::identifier; // missing class or category name. - return nullptr; - } + if (expectIdentifier()) + return nullptr; // missing class or category name. // We have a class or category name - consume it. IdentifierInfo *nameId = Tok.getIdentifierInfo(); @@ -278,11 +274,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, T.consumeClose(); if (T.getCloseLocation().isInvalid()) return nullptr; - - if (!attrs.empty()) { // categories don't support attributes. - Diag(nameLoc, diag::err_objc_no_attributes_on_category); - attrs.clear(); - } // Next, we need to check for any protocol references. assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols"); @@ -294,16 +285,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, /*consumeLastToken=*/true)) return nullptr; - Decl *CategoryType = - Actions.ActOnStartCategoryInterface(AtLoc, - nameId, nameLoc, - typeParameterList, - categoryId, categoryLoc, - ProtocolRefs.data(), - ProtocolRefs.size(), - ProtocolLocs.data(), - EndProtoLoc); - + Decl *CategoryType = Actions.ActOnStartCategoryInterface( + AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc, + ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), + EndProtoLoc, attrs.getList()); + if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc); @@ -329,11 +315,8 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, return nullptr; } - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) - << tok::identifier; // missing super class name. - return nullptr; - } + if (expectIdentifier()) + return nullptr; // missing super class name. superClassId = Tok.getIdentifierInfo(); superClassLoc = ConsumeToken(); @@ -929,7 +912,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { if (IsSetter) { DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter); - DS.setSetterName(SelIdent); + DS.setSetterName(SelIdent, SelLoc); if (ExpectAndConsume(tok::colon, diag::err_expected_colon_after_setter_name)) { @@ -938,7 +921,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { } } else { DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter); - DS.setGetterName(SelIdent); + DS.setGetterName(SelIdent, SelLoc); } } else if (II->isStr("nonnull")) { if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability) @@ -1024,6 +1007,10 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { switch (Tok.getKind()) { default: return nullptr; + case tok::colon: + // Empty selector piece uses the location of the ':'. + SelectorLoc = Tok.getLocation(); + return nullptr; case tok::ampamp: case tok::ampequal: case tok::amp: @@ -1448,12 +1435,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, cutOffParsing(); return nullptr; } - - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) - << tok::identifier; // missing argument name. - break; - } + + if (expectIdentifier()) + break; // missing argument name. ArgInfo.Name = Tok.getIdentifierInfo(); ArgInfo.NameLoc = Tok.getLocation(); @@ -1562,8 +1546,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, return true; } - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; + if (expectIdentifier()) { SkipUntil(tok::greater, StopAtSemi); return true; } @@ -2045,10 +2028,8 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, MaybeSkipAttributes(tok::objc_protocol); - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; // missing protocol name. - return nullptr; - } + if (expectIdentifier()) + return nullptr; // missing protocol name. // Save the protocol name, then consume it. IdentifierInfo *protocolName = Tok.getIdentifierInfo(); SourceLocation nameLoc = ConsumeToken(); @@ -2068,8 +2049,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, // Parse the list of forward declarations. while (1) { ConsumeToken(); // the ',' - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; + if (expectIdentifier()) { SkipUntil(tok::semi); return nullptr; } @@ -2136,11 +2116,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { MaybeSkipAttributes(tok::objc_implementation); - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) - << tok::identifier; // missing class or category name. - return nullptr; - } + if (expectIdentifier()) + return nullptr; // missing class or category name. // We have a class or category name - consume it. IdentifierInfo *nameId = Tok.getIdentifierInfo(); SourceLocation nameLoc = ConsumeToken(); // consume class or category name @@ -2210,11 +2187,8 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { IdentifierInfo *superClassId = nullptr; if (TryConsumeToken(tok::colon)) { // We have a super class - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) - << tok::identifier; // missing super class name. - return nullptr; - } + if (expectIdentifier()) + return nullptr; // missing super class name. superClassId = Tok.getIdentifierInfo(); superClassLoc = ConsumeToken(); // Consume super class name } @@ -2285,7 +2259,7 @@ Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() { void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) { assert(!Finished); - P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl); + P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl, AtEnd.getBegin()); for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], true/*Methods*/); @@ -2314,16 +2288,12 @@ Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) && "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias"); ConsumeToken(); // consume compatibility_alias - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; + if (expectIdentifier()) return nullptr; - } IdentifierInfo *aliasId = Tok.getIdentifierInfo(); SourceLocation aliasLoc = ConsumeToken(); // consume alias-name - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; + if (expectIdentifier()) return nullptr; - } IdentifierInfo *classId = Tok.getIdentifierInfo(); SourceLocation classLoc = ConsumeToken(); // consume class-name; ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias"); @@ -2371,11 +2341,9 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { cutOffParsing(); return nullptr; } - - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; + + if (expectIdentifier()) break; - } propertyIvar = Tok.getIdentifierInfo(); propertyIvarLoc = ConsumeToken(); // consume ivar-name } @@ -2433,9 +2401,8 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { cutOffParsing(); return nullptr; } - - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected) << tok::identifier; + + if (expectIdentifier()) { SkipUntil(tok::semi); return nullptr; } @@ -3571,8 +3538,8 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - if (Tok.isNot(tok::identifier)) - return ExprError(Diag(Tok, diag::err_expected) << tok::identifier); + if (expectIdentifier()) + return ExprError(); IdentifierInfo *protocolId = Tok.getIdentifierInfo(); SourceLocation ProtoIdLoc = ConsumeToken(); @@ -3664,6 +3631,14 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { SourceLocation OrigLoc = Tok.getLocation(); assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!"); + // Store an artificial EOF token to ensure that we don't run off the end of + // the method's body when we come to parse it. + Token Eof; + Eof.startToken(); + Eof.setKind(tok::eof); + Eof.setEofData(MCDecl); + Eof.setLocation(OrigLoc); + LM.Toks.push_back(Eof); // Append the current token at the end of the new token stream so that it // doesn't get lost. LM.Toks.push_back(Tok); @@ -3695,7 +3670,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { Actions.ActOnDefaultCtorInitializers(MCDecl); ParseFunctionStatementBody(MCDecl, BodyScope); } - + if (Tok.getLocation() != OrigLoc) { // Due to parsing error, we either went over the cached tokens or // there are still cached tokens left. If it's the latter case skip the @@ -3707,4 +3682,6 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof)) ConsumeAnyToken(); } + // Clean up the remaining EOF token. + ConsumeAnyToken(); } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp index cab7d34..d9a0885 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp @@ -11,11 +11,11 @@ /// //===----------------------------------------------------------------------===// -#include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/StmtOpenMP.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/PointerIntPair.h" @@ -192,6 +192,7 @@ static DeclarationName parseOpenMPReductionId(Parser &P) { case tok::identifier: // identifier if (!WithOperator) break; + LLVM_FALLTHROUGH; default: P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, @@ -532,7 +533,7 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, ConsumeAnyToken(); } // Skip the last annot_pragma_openmp_end. - SourceLocation EndLoc = ConsumeToken(); + SourceLocation EndLoc = ConsumeAnnotationToken(); if (!IsError) { return Actions.ActOnOpenMPDeclareSimdDirective( Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, @@ -562,7 +563,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); ParenBraceBracketBalancer BalancerRAIIObj(*this); - SourceLocation Loc = ConsumeToken(); + SourceLocation Loc = ConsumeAnnotationToken(); auto DKind = ParseOpenMPDirectiveKind(*this); switch (DKind) { @@ -578,7 +579,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); } // Skip the last annot_pragma_openmp_end. - ConsumeToken(); + ConsumeAnnotationToken(); return Actions.ActOnOpenMPThreadprivateDirective(Loc, Helper.getIdentifiers()); } @@ -596,7 +597,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ConsumeAnyToken(); } // Skip the last annot_pragma_openmp_end. - ConsumeToken(); + ConsumeAnnotationToken(); return Res; } break; @@ -686,7 +687,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ParseExternalDeclaration(attrs); if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { TentativeParsingAction TPA(*this); - ConsumeToken(); + ConsumeAnnotationToken(); DKind = ParseOpenMPDirectiveKind(*this); if (DKind != OMPD_end_declare_target) TPA.Revert(); @@ -806,7 +807,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( /// annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( - AllowedContsructsKind Allowed) { + AllowedConstructsKind Allowed) { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); ParenBraceBracketBalancer BalancerRAIIObj(*this); SmallVector<OMPClause *, 5> Clauses; @@ -814,7 +815,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( FirstClauses(OMPC_unknown + 1); unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope; - SourceLocation Loc = ConsumeToken(), EndLoc; + SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; auto DKind = ParseOpenMPDirectiveKind(*this); OpenMPDirectiveKind CancelRegion = OMPD_unknown; // Name of critical directive. @@ -869,6 +870,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( // pseudo-clause OMPFlushClause. PP.EnterToken(Tok); } + LLVM_FALLTHROUGH; case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: @@ -883,6 +885,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( } HasAssociatedStatement = false; // Fall through for further analysis. + LLVM_FALLTHROUGH; case OMPD_parallel: case OMPD_simd: case OMPD_for: @@ -973,7 +976,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( // End location of the directive. EndLoc = Tok.getLocation(); // Consume final annot_pragma_openmp_end. - ConsumeToken(); + ConsumeAnnotationToken(); // OpenMP [2.13.8, ordered Construct, Syntax] // If the depend clause is specified, the ordered construct is a stand-alone @@ -1053,7 +1056,7 @@ bool Parser::ParseOpenMPSimpleVarList( IsCorrect = false; SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); - } else if (ParseUnqualifiedId(SS, false, false, false, nullptr, + } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr, TemplateKWLoc, Name)) { IsCorrect = false; SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, @@ -1099,7 +1102,7 @@ bool Parser::ParseOpenMPSimpleVarList( /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | /// thread_limit-clause | priority-clause | grainsize-clause | /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | -/// from-clause | is_device_ptr-clause +/// from-clause | is_device_ptr-clause | task_reduction-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -1184,6 +1187,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } + LLVM_FALLTHROUGH; case OMPC_if: Clause = ParseOpenMPSingleExprWithArgClause(CKind); @@ -1216,6 +1220,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_lastprivate: case OMPC_shared: case OMPC_reduction: + case OMPC_task_reduction: case OMPC_linear: case OMPC_aligned: case OMPC_copyin: @@ -1557,8 +1562,9 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, } return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, /*AllowDestructorName*/ false, - /*AllowConstructorName*/ false, nullptr, - TemplateKWLoc, ReductionId); + /*AllowConstructorName*/ false, + /*AllowDeductionGuide*/ false, + nullptr, TemplateKWLoc, ReductionId); } /// Parses clauses with list. @@ -1580,7 +1586,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, BalancedDelimiterTracker LinearT(*this, tok::l_paren, tok::annot_pragma_openmp_end); // Handle reduction-identifier for reduction clause. - if (Kind == OMPC_reduction) { + if (Kind == OMPC_reduction || Kind == OMPC_task_reduction) { ColonProtectionRAIIObject ColonRAII(*this); if (getLangOpts().CPlusPlus) ParseOptionalCXXScopeSpecifier(Data.ReductionIdScopeSpec, @@ -1689,6 +1695,30 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.MapType = OMPC_MAP_tofrom; Data.IsMapTypeImplicit = true; } + } else if (IsMapClauseModifierToken(PP.LookAhead(0))) { + if (PP.LookAhead(1).is(tok::colon)) { + Data.MapTypeModifier = Data.MapType; + if (Data.MapTypeModifier != OMPC_MAP_always) { + Diag(Tok, diag::err_omp_unknown_map_type_modifier); + Data.MapTypeModifier = OMPC_MAP_unknown; + } else + MapTypeModifierSpecified = true; + + ConsumeToken(); + + Data.MapType = + IsMapClauseModifierToken(Tok) + ? static_cast<OpenMPMapClauseKind>( + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))) + : OMPC_MAP_unknown; + if (Data.MapType == OMPC_MAP_unknown || + Data.MapType == OMPC_MAP_always) + Diag(Tok, diag::err_omp_unknown_map_type); + ConsumeToken(); + } else { + Data.MapType = OMPC_MAP_tofrom; + Data.IsMapTypeImplicit = true; + } } else { Data.MapType = OMPC_MAP_tofrom; Data.IsMapTypeImplicit = true; @@ -1704,13 +1734,13 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Diag(Tok, diag::warn_pragma_expected_colon) << "map type"; } - bool IsComma = - (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map) || - (Kind == OMPC_reduction && !InvalidReductionId) || - (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown && - (!MapTypeModifierSpecified || - Data.MapTypeModifier == OMPC_MAP_always)) || - (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); + bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction && + Kind != OMPC_depend && Kind != OMPC_map) || + (Kind == OMPC_reduction && !InvalidReductionId) || + (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown && + (!MapTypeModifierSpecified || + Data.MapTypeModifier == OMPC_MAP_always)) || + (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { @@ -1766,7 +1796,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, } /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', -/// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'. +/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction' or 'task_reduction'. /// /// private-clause: /// 'private' '(' list ')' @@ -1782,6 +1812,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, /// 'aligned' '(' list [ ':' alignment ] ')' /// reduction-clause: /// 'reduction' '(' reduction-identifier ':' list ')' +/// task_reduction-clause: +/// 'task_reduction' '(' reduction-identifier ':' list ')' /// copyprivate-clause: /// 'copyprivate' '(' list ')' /// flush-clause: diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp index 8973323..2627437 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp @@ -11,13 +11,13 @@ // //===----------------------------------------------------------------------===// -#include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/PragmaKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/LoopHint.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/StringSwitch.h" @@ -49,6 +49,15 @@ struct PragmaPackHandler : public PragmaHandler { Token &FirstToken) override; }; +struct PragmaClangSectionHandler : public PragmaHandler { + explicit PragmaClangSectionHandler(Sema &S) + : PragmaHandler("section"), Actions(S) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +private: + Sema &Actions; +}; + struct PragmaMSStructHandler : public PragmaHandler { explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {} void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, @@ -86,6 +95,12 @@ struct PragmaFPContractHandler : public PragmaHandler { Token &FirstToken) override; }; +struct PragmaFPHandler : public PragmaHandler { + PragmaFPHandler() : PragmaHandler("fp") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + struct PragmaNoOpenMPHandler : public PragmaHandler { PragmaNoOpenMPHandler() : PragmaHandler("omp") { } void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, @@ -177,6 +192,17 @@ private: Sema &Actions; }; +/// PragmaAttributeHandler - "\#pragma clang attribute ...". +struct PragmaAttributeHandler : public PragmaHandler { + PragmaAttributeHandler(AttributeFactory &AttrFactory) + : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; + + /// A pool of attributes that were parsed in \#pragma clang attribute. + ParsedAttributes AttributesForPragmaAttribute; +}; + } // end namespace void Parser::initializePragmaHandlers() { @@ -207,6 +233,9 @@ void Parser::initializePragmaHandlers() { FPContractHandler.reset(new PragmaFPContractHandler()); PP.AddPragmaHandler("STDC", FPContractHandler.get()); + PCSectionHandler.reset(new PragmaClangSectionHandler(Actions)); + PP.AddPragmaHandler("clang", PCSectionHandler.get()); + if (getLangOpts().OpenCL) { OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); @@ -266,6 +295,12 @@ void Parser::initializePragmaHandlers() { NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll")); PP.AddPragmaHandler(NoUnrollHintHandler.get()); + + FPHandler.reset(new PragmaFPHandler()); + PP.AddPragmaHandler("clang", FPHandler.get()); + + AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory)); + PP.AddPragmaHandler("clang", AttributePragmaHandler.get()); } void Parser::resetPragmaHandlers() { @@ -300,6 +335,9 @@ void Parser::resetPragmaHandlers() { MSCommentHandler.reset(); } + PP.RemovePragmaHandler("clang", PCSectionHandler.get()); + PCSectionHandler.reset(); + if (getLangOpts().MicrosoftExt) { PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); MSDetectMismatchHandler.reset(); @@ -344,6 +382,12 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler(NoUnrollHintHandler.get()); NoUnrollHintHandler.reset(); + + PP.RemovePragmaHandler("clang", FPHandler.get()); + FPHandler.reset(); + + PP.RemovePragmaHandler("clang", AttributePragmaHandler.get()); + AttributePragmaHandler.reset(); } /// \brief Handle the annotation token produced for #pragma unused(...) @@ -353,7 +397,7 @@ void Parser::resetPragmaHandlers() { /// annot_pragma_unused 'x' annot_pragma_unused 'y' void Parser::HandlePragmaUnused() { assert(Tok.is(tok::annot_pragma_unused)); - SourceLocation UnusedLoc = ConsumeToken(); + SourceLocation UnusedLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc); ConsumeToken(); // The argument token. } @@ -362,7 +406,7 @@ void Parser::HandlePragmaVisibility() { assert(Tok.is(tok::annot_pragma_vis)); const IdentifierInfo *VisType = static_cast<IdentifierInfo *>(Tok.getAnnotationValue()); - SourceLocation VisLoc = ConsumeToken(); + SourceLocation VisLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaVisibility(VisType, VisLoc); } @@ -378,7 +422,7 @@ void Parser::HandlePragmaPack() { assert(Tok.is(tok::annot_pragma_pack)); PragmaPackInfo *Info = static_cast<PragmaPackInfo *>(Tok.getAnnotationValue()); - SourceLocation PragmaLoc = ConsumeToken(); + SourceLocation PragmaLoc = ConsumeAnnotationToken(); ExprResult Alignment; if (Info->Alignment.is(tok::numeric_constant)) { Alignment = Actions.ActOnNumericConstant(Info->Alignment); @@ -394,7 +438,7 @@ void Parser::HandlePragmaMSStruct() { PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>( reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); Actions.ActOnPragmaMSStruct(Kind); - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); } void Parser::HandlePragmaAlign() { @@ -402,7 +446,7 @@ void Parser::HandlePragmaAlign() { Sema::PragmaOptionsAlignKind Kind = static_cast<Sema::PragmaOptionsAlignKind>( reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); - SourceLocation PragmaLoc = ConsumeToken(); + SourceLocation PragmaLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); } @@ -411,12 +455,12 @@ void Parser::HandlePragmaDump() { IdentifierInfo *II = reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue()); Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II); - ConsumeToken(); + ConsumeAnnotationToken(); } void Parser::HandlePragmaWeak() { assert(Tok.is(tok::annot_pragma_weak)); - SourceLocation PragmaLoc = ConsumeToken(); + SourceLocation PragmaLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc, Tok.getLocation()); ConsumeToken(); // The weak name. @@ -424,7 +468,7 @@ void Parser::HandlePragmaWeak() { void Parser::HandlePragmaWeakAlias() { assert(Tok.is(tok::annot_pragma_weakalias)); - SourceLocation PragmaLoc = ConsumeToken(); + SourceLocation PragmaLoc = ConsumeAnnotationToken(); IdentifierInfo *WeakName = Tok.getIdentifierInfo(); SourceLocation WeakNameLoc = Tok.getLocation(); ConsumeToken(); @@ -438,7 +482,7 @@ void Parser::HandlePragmaWeakAlias() { void Parser::HandlePragmaRedefineExtname() { assert(Tok.is(tok::annot_pragma_redefine_extname)); - SourceLocation RedefLoc = ConsumeToken(); + SourceLocation RedefLoc = ConsumeAnnotationToken(); IdentifierInfo *RedefName = Tok.getIdentifierInfo(); SourceLocation RedefNameLoc = Tok.getLocation(); ConsumeToken(); @@ -454,14 +498,28 @@ void Parser::HandlePragmaFPContract() { tok::OnOffSwitch OOS = static_cast<tok::OnOffSwitch>( reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); - Actions.ActOnPragmaFPContract(OOS); - ConsumeToken(); // The annotation token. + + LangOptions::FPContractModeKind FPC; + switch (OOS) { + case tok::OOS_ON: + FPC = LangOptions::FPC_On; + break; + case tok::OOS_OFF: + FPC = LangOptions::FPC_Off; + break; + case tok::OOS_DEFAULT: + FPC = getLangOpts().getDefaultFPContractMode(); + break; + } + + Actions.ActOnPragmaFPContract(FPC); + ConsumeAnnotationToken(); } StmtResult Parser::HandlePragmaCaptured() { assert(Tok.is(tok::annot_pragma_captured)); - ConsumeToken(); + ConsumeAnnotationToken(); if (Tok.isNot(tok::l_brace)) { PP.Diag(Tok, diag::err_expected) << tok::l_brace; @@ -498,7 +556,7 @@ void Parser::HandlePragmaOpenCLExtension() { auto State = Data->second; auto Ident = Data->first; SourceLocation NameLoc = Tok.getLocation(); - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); auto &Opt = Actions.getOpenCLOptions(); auto Name = Ident->getName(); @@ -537,7 +595,7 @@ void Parser::HandlePragmaMSPointersToMembers() { LangOptions::PragmaMSPointersToMembersKind RepresentationMethod = static_cast<LangOptions::PragmaMSPointersToMembersKind>( reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); - SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. + SourceLocation PragmaLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc); } @@ -547,7 +605,7 @@ void Parser::HandlePragmaMSVtorDisp() { Sema::PragmaMsStackAction Action = static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF); MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF); - SourceLocation PragmaLoc = ConsumeToken(); // The annotation token. + SourceLocation PragmaLoc = ConsumeAnnotationToken(); Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode); } @@ -557,7 +615,7 @@ void Parser::HandlePragmaMSPragma() { auto TheTokens = (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue(); PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true); - SourceLocation PragmaLocation = ConsumeToken(); // The annotation token. + SourceLocation PragmaLocation = ConsumeAnnotationToken(); assert(Tok.isAnyIdentifier()); StringRef PragmaName = Tok.getIdentifierInfo()->getName(); PP.Lex(Tok); // pragma kind @@ -853,7 +911,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { bool PragmaUnroll = PragmaNameInfo->getName() == "unroll"; bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll"; if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) { - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); Hint.Range = Info->PragmaName.getLocation(); return true; } @@ -880,7 +938,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute; // Verify loop hint has an argument. if (Toks[0].is(tok::eof)) { - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument) << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll << /*AssumeSafetyKeyword=*/AssumeSafetyArg; @@ -889,7 +947,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { // Validate the argument. if (StateOption) { - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); SourceLocation StateLoc = Toks[0].getLocation(); IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo(); @@ -912,7 +970,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { } else { // Enter constant expression including eof terminator into token stream. PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false); - ConsumeToken(); // The annotation token. + ConsumeAnnotationToken(); ExprResult R = ParseConstantExpression(); @@ -940,6 +998,422 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { return true; } +namespace { +struct PragmaAttributeInfo { + enum ActionType { Push, Pop }; + ParsedAttributes &Attributes; + ActionType Action; + ArrayRef<Token> Tokens; + + PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {} +}; + +#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc" + +} // end anonymous namespace + +static StringRef getIdentifier(const Token &Tok) { + if (Tok.is(tok::identifier)) + return Tok.getIdentifierInfo()->getName(); + const char *S = tok::getKeywordSpelling(Tok.getKind()); + if (!S) + return ""; + return S; +} + +static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) { + using namespace attr; + switch (Rule) { +#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \ + case Value: \ + return IsAbstract; +#include "clang/Basic/AttrSubMatchRulesList.inc" + } + llvm_unreachable("Invalid attribute subject match rule"); + return false; +} + +static void diagnoseExpectedAttributeSubjectSubRule( + Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, + SourceLocation SubRuleLoc) { + auto Diagnostic = + PRef.Diag(SubRuleLoc, + diag::err_pragma_attribute_expected_subject_sub_identifier) + << PrimaryRuleName; + if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule)) + Diagnostic << /*SubRulesSupported=*/1 << SubRules; + else + Diagnostic << /*SubRulesSupported=*/0; +} + +static void diagnoseUnknownAttributeSubjectSubRule( + Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName, + StringRef SubRuleName, SourceLocation SubRuleLoc) { + + auto Diagnostic = + PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule) + << SubRuleName << PrimaryRuleName; + if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule)) + Diagnostic << /*SubRulesSupported=*/1 << SubRules; + else + Diagnostic << /*SubRulesSupported=*/0; +} + +bool Parser::ParsePragmaAttributeSubjectMatchRuleSet( + attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc, + SourceLocation &LastMatchRuleEndLoc) { + bool IsAny = false; + BalancedDelimiterTracker AnyParens(*this, tok::l_paren); + if (getIdentifier(Tok) == "any") { + AnyLoc = ConsumeToken(); + IsAny = true; + if (AnyParens.expectAndConsume()) + return true; + } + + do { + // Parse the subject matcher rule. + StringRef Name = getIdentifier(Tok); + if (Name.empty()) { + Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier); + return true; + } + std::pair<Optional<attr::SubjectMatchRule>, + Optional<attr::SubjectMatchRule> (*)(StringRef, bool)> + Rule = isAttributeSubjectMatchRule(Name); + if (!Rule.first) { + Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name; + return true; + } + attr::SubjectMatchRule PrimaryRule = *Rule.first; + SourceLocation RuleLoc = ConsumeToken(); + + BalancedDelimiterTracker Parens(*this, tok::l_paren); + if (isAbstractAttrMatcherRule(PrimaryRule)) { + if (Parens.expectAndConsume()) + return true; + } else if (Parens.consumeOpen()) { + if (!SubjectMatchRules + .insert( + std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc))) + .second) + Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject) + << Name + << FixItHint::CreateRemoval(SourceRange( + RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc)); + LastMatchRuleEndLoc = RuleLoc; + continue; + } + + // Parse the sub-rules. + StringRef SubRuleName = getIdentifier(Tok); + if (SubRuleName.empty()) { + diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name, + Tok.getLocation()); + return true; + } + attr::SubjectMatchRule SubRule; + if (SubRuleName == "unless") { + SourceLocation SubRuleLoc = ConsumeToken(); + BalancedDelimiterTracker Parens(*this, tok::l_paren); + if (Parens.expectAndConsume()) + return true; + SubRuleName = getIdentifier(Tok); + if (SubRuleName.empty()) { + diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name, + SubRuleLoc); + return true; + } + auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true); + if (!SubRuleOrNone) { + std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")"; + diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name, + SubRuleUnlessName, SubRuleLoc); + return true; + } + SubRule = *SubRuleOrNone; + ConsumeToken(); + if (Parens.consumeClose()) + return true; + } else { + auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false); + if (!SubRuleOrNone) { + diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name, + SubRuleName, Tok.getLocation()); + return true; + } + SubRule = *SubRuleOrNone; + ConsumeToken(); + } + SourceLocation RuleEndLoc = Tok.getLocation(); + LastMatchRuleEndLoc = RuleEndLoc; + if (Parens.consumeClose()) + return true; + if (!SubjectMatchRules + .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc))) + .second) { + Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject) + << attr::getSubjectMatchRuleSpelling(SubRule) + << FixItHint::CreateRemoval(SourceRange( + RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc)); + continue; + } + } while (IsAny && TryConsumeToken(tok::comma)); + + if (IsAny) + if (AnyParens.consumeClose()) + return true; + + return false; +} + +namespace { + +/// Describes the stage at which attribute subject rule parsing was interruped. +enum class MissingAttributeSubjectRulesRecoveryPoint { + Comma, + ApplyTo, + Equals, + Any, + None, +}; + +MissingAttributeSubjectRulesRecoveryPoint +getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) { + if (const auto *II = Tok.getIdentifierInfo()) { + if (II->isStr("apply_to")) + return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo; + if (II->isStr("any")) + return MissingAttributeSubjectRulesRecoveryPoint::Any; + } + if (Tok.is(tok::equal)) + return MissingAttributeSubjectRulesRecoveryPoint::Equals; + return MissingAttributeSubjectRulesRecoveryPoint::None; +} + +/// Creates a diagnostic for the attribute subject rule parsing diagnostic that +/// suggests the possible attribute subject rules in a fix-it together with +/// any other missing tokens. +DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic( + unsigned DiagID, AttributeList &Attribute, + MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) { + SourceLocation Loc = PRef.getEndOfPreviousToken(); + if (Loc.isInvalid()) + Loc = PRef.getCurToken().getLocation(); + auto Diagnostic = PRef.Diag(Loc, DiagID); + std::string FixIt; + MissingAttributeSubjectRulesRecoveryPoint EndPoint = + getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken()); + if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma) + FixIt = ", "; + if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo && + EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo) + FixIt += "apply_to"; + if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals && + EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals) + FixIt += " = "; + SourceRange FixItRange(Loc); + if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) { + // Gather the subject match rules that are supported by the attribute. + SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet; + Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet); + if (SubjectMatchRuleSet.empty()) { + // FIXME: We can emit a "fix-it" with a subject list placeholder when + // placeholders will be supported by the fix-its. + return Diagnostic; + } + FixIt += "any("; + bool NeedsComma = false; + for (const auto &I : SubjectMatchRuleSet) { + // Ensure that the missing rule is reported in the fix-it only when it's + // supported in the current language mode. + if (!I.second) + continue; + if (NeedsComma) + FixIt += ", "; + else + NeedsComma = true; + FixIt += attr::getSubjectMatchRuleSpelling(I.first); + } + FixIt += ")"; + // Check if we need to remove the range + PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch); + FixItRange.setEnd(PRef.getCurToken().getLocation()); + } + if (FixItRange.getBegin() == FixItRange.getEnd()) + Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt); + else + Diagnostic << FixItHint::CreateReplacement( + CharSourceRange::getCharRange(FixItRange), FixIt); + return Diagnostic; +} + +} // end anonymous namespace + +void Parser::HandlePragmaAttribute() { + assert(Tok.is(tok::annot_pragma_attribute) && + "Expected #pragma attribute annotation token"); + SourceLocation PragmaLoc = Tok.getLocation(); + auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue()); + if (Info->Action == PragmaAttributeInfo::Pop) { + ConsumeAnnotationToken(); + Actions.ActOnPragmaAttributePop(PragmaLoc); + return; + } + // Parse the actual attribute with its arguments. + assert(Info->Action == PragmaAttributeInfo::Push && + "Unexpected #pragma attribute command"); + PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false); + ConsumeAnnotationToken(); + + ParsedAttributes &Attrs = Info->Attributes; + Attrs.clearListOnly(); + + auto SkipToEnd = [this]() { + SkipUntil(tok::eof, StopBeforeMatch); + ConsumeToken(); + }; + + if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) { + // Parse the CXX11 style attribute. + ParseCXX11AttributeSpecifier(Attrs); + } else if (Tok.is(tok::kw___attribute)) { + ConsumeToken(); + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, + "attribute")) + return SkipToEnd(); + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) + return SkipToEnd(); + + if (Tok.isNot(tok::identifier)) { + Diag(Tok, diag::err_pragma_attribute_expected_attribute_name); + SkipToEnd(); + return; + } + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + SourceLocation AttrNameLoc = ConsumeToken(); + + if (Tok.isNot(tok::l_paren)) + Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, + AttributeList::AS_GNU); + else + ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr, + /*ScopeName=*/nullptr, + /*ScopeLoc=*/SourceLocation(), + AttributeList::AS_GNU, + /*Declarator=*/nullptr); + + if (ExpectAndConsume(tok::r_paren)) + return SkipToEnd(); + if (ExpectAndConsume(tok::r_paren)) + return SkipToEnd(); + } else if (Tok.is(tok::kw___declspec)) { + ParseMicrosoftDeclSpecs(Attrs); + } else { + Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax); + if (Tok.getIdentifierInfo()) { + // If we suspect that this is an attribute suggest the use of + // '__attribute__'. + if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, + AttributeList::AS_GNU) != + AttributeList::UnknownAttribute) { + SourceLocation InsertStartLoc = Tok.getLocation(); + ConsumeToken(); + if (Tok.is(tok::l_paren)) { + ConsumeAnyToken(); + SkipUntil(tok::r_paren, StopBeforeMatch); + if (Tok.isNot(tok::r_paren)) + return SkipToEnd(); + } + Diag(Tok, diag::note_pragma_attribute_use_attribute_kw) + << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((") + << FixItHint::CreateInsertion(Tok.getEndLoc(), "))"); + } + } + SkipToEnd(); + return; + } + + if (!Attrs.getList() || Attrs.getList()->isInvalid()) { + SkipToEnd(); + return; + } + + // Ensure that we don't have more than one attribute. + if (Attrs.getList()->getNext()) { + SourceLocation Loc = Attrs.getList()->getNext()->getLoc(); + Diag(Loc, diag::err_pragma_attribute_multiple_attributes); + SkipToEnd(); + return; + } + + if (!Attrs.getList()->isSupportedByPragmaAttribute()) { + Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) + << Attrs.getList()->getName(); + SkipToEnd(); + return; + } + AttributeList &Attribute = *Attrs.getList(); + + // Parse the subject-list. + if (!TryConsumeToken(tok::comma)) { + createExpectedAttributeSubjectRulesTokenDiagnostic( + diag::err_expected, Attribute, + MissingAttributeSubjectRulesRecoveryPoint::Comma, *this) + << tok::comma; + SkipToEnd(); + return; + } + + if (Tok.isNot(tok::identifier)) { + createExpectedAttributeSubjectRulesTokenDiagnostic( + diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute, + MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this); + SkipToEnd(); + return; + } + const IdentifierInfo *II = Tok.getIdentifierInfo(); + if (!II->isStr("apply_to")) { + createExpectedAttributeSubjectRulesTokenDiagnostic( + diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute, + MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this); + SkipToEnd(); + return; + } + ConsumeToken(); + + if (!TryConsumeToken(tok::equal)) { + createExpectedAttributeSubjectRulesTokenDiagnostic( + diag::err_expected, Attribute, + MissingAttributeSubjectRulesRecoveryPoint::Equals, *this) + << tok::equal; + SkipToEnd(); + return; + } + + attr::ParsedSubjectMatchRuleSet SubjectMatchRules; + SourceLocation AnyLoc, LastMatchRuleEndLoc; + if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc, + LastMatchRuleEndLoc)) { + SkipToEnd(); + return; + } + + // Tokens following an ill-formed attribute will remain in the token stream + // and must be removed. + if (Tok.isNot(tok::eof)) { + Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute); + SkipToEnd(); + return; + } + + // Consume the eof terminator token. + ConsumeToken(); + + Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc, + std::move(SubjectMatchRules)); +} + // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' @@ -1155,6 +1629,51 @@ void PragmaMSStructHandler::HandlePragma(Preprocessor &PP, PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true); } +// #pragma clang section bss="abc" data="" rodata="def" text="" +void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, Token &FirstToken) { + + Token Tok; + auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid; + + PP.Lex(Tok); // eat 'section' + while (Tok.isNot(tok::eod)) { + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; + return; + } + + const IdentifierInfo *SecType = Tok.getIdentifierInfo(); + if (SecType->isStr("bss")) + SecKind = Sema::PragmaClangSectionKind::PCSK_BSS; + else if (SecType->isStr("data")) + SecKind = Sema::PragmaClangSectionKind::PCSK_Data; + else if (SecType->isStr("rodata")) + SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata; + else if (SecType->isStr("text")) + SecKind = Sema::PragmaClangSectionKind::PCSK_Text; + else { + PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section"; + return; + } + + PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text'] + if (Tok.isNot(tok::equal)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind; + return; + } + + std::string SecName; + if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false)) + return; + + Actions.ActOnPragmaClangSection(Tok.getLocation(), + (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set : + Sema::PragmaClangSectionAction::PCSA_Clear), + SecKind, SecName); + } +} + // #pragma 'align' '=' {'native','natural','mac68k','power','reset'} // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, @@ -1947,6 +2466,129 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP, Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation()); } +namespace { +/// Used as the annotation value for tok::annot_pragma_fp. +struct TokFPAnnotValue { + enum FlagKinds { Contract }; + enum FlagValues { On, Off, Fast }; + + FlagKinds FlagKind; + FlagValues FlagValue; +}; +} // end anonymous namespace + +void PragmaFPHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + // fp + Token PragmaName = Tok; + SmallVector<Token, 1> TokenList; + + PP.Lex(Tok); + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) + << /*MissingOption=*/true << ""; + return; + } + + while (Tok.is(tok::identifier)) { + IdentifierInfo *OptionInfo = Tok.getIdentifierInfo(); + + auto FlagKind = + llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>( + OptionInfo->getName()) + .Case("contract", TokFPAnnotValue::Contract) + .Default(None); + if (!FlagKind) { + PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) + << /*MissingOption=*/false << OptionInfo; + return; + } + PP.Lex(Tok); + + // Read '(' + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) + << PP.getSpelling(Tok) << OptionInfo->getName(); + return; + } + const IdentifierInfo *II = Tok.getIdentifierInfo(); + + auto FlagValue = + llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>( + II->getName()) + .Case("on", TokFPAnnotValue::On) + .Case("off", TokFPAnnotValue::Off) + .Case("fast", TokFPAnnotValue::Fast) + .Default(llvm::None); + + if (!FlagValue) { + PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) + << PP.getSpelling(Tok) << OptionInfo->getName(); + return; + } + PP.Lex(Tok); + + // Read ')' + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; + return; + } + PP.Lex(Tok); + + auto *AnnotValue = new (PP.getPreprocessorAllocator()) + TokFPAnnotValue{*FlagKind, *FlagValue}; + // Generate the loop hint token. + Token FPTok; + FPTok.startToken(); + FPTok.setKind(tok::annot_pragma_fp); + FPTok.setLocation(PragmaName.getLocation()); + FPTok.setAnnotationEndLoc(PragmaName.getLocation()); + FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue)); + TokenList.push_back(FPTok); + } + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "clang fp"; + return; + } + + auto TokenArray = llvm::make_unique<Token[]>(TokenList.size()); + std::copy(TokenList.begin(), TokenList.end(), TokenArray.get()); + + PP.EnterTokenStream(std::move(TokenArray), TokenList.size(), + /*DisableMacroExpansion=*/false); +} + +void Parser::HandlePragmaFP() { + assert(Tok.is(tok::annot_pragma_fp)); + auto *AnnotValue = + reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue()); + + LangOptions::FPContractModeKind FPC; + switch (AnnotValue->FlagValue) { + case TokFPAnnotValue::On: + FPC = LangOptions::FPC_On; + break; + case TokFPAnnotValue::Fast: + FPC = LangOptions::FPC_Fast; + break; + case TokFPAnnotValue::Off: + FPC = LangOptions::FPC_Off; + break; + } + + Actions.ActOnPragmaFPContract(FPC); + ConsumeAnnotationToken(); +} + /// \brief Parses loop or unroll pragma hint value and fills in Info. static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, Token Option, bool ValueInParens, @@ -2246,3 +2888,104 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma( PP.Diag(FirstTok.getLocation(), diag::warn_pragma_force_cuda_host_device_bad_arg); } + +/// \brief Handle the #pragma clang attribute directive. +/// +/// The syntax is: +/// \code +/// #pragma clang attribute push(attribute, subject-set) +/// #pragma clang attribute pop +/// \endcode +/// +/// The subject-set clause defines the set of declarations which receive the +/// attribute. Its exact syntax is described in the LanguageExtensions document +/// in Clang's documentation. +/// +/// This directive instructs the compiler to begin/finish applying the specified +/// attribute to the set of attribute-specific declarations in the active range +/// of the pragma. +void PragmaAttributeHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &FirstToken) { + Token Tok; + PP.Lex(Tok); + auto *Info = new (PP.getPreprocessorAllocator()) + PragmaAttributeInfo(AttributesForPragmaAttribute); + + // Parse the 'push' or 'pop'. + if (Tok.isNot(tok::identifier)) { + PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop); + return; + } + const auto *II = Tok.getIdentifierInfo(); + if (II->isStr("push")) + Info->Action = PragmaAttributeInfo::Push; + else if (II->isStr("pop")) + Info->Action = PragmaAttributeInfo::Pop; + else { + PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument) + << PP.getSpelling(Tok); + return; + } + PP.Lex(Tok); + + // Parse the actual attribute. + if (Info->Action == PragmaAttributeInfo::Push) { + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren; + return; + } + PP.Lex(Tok); + + // Lex the attribute tokens. + SmallVector<Token, 16> AttributeTokens; + int OpenParens = 1; + while (Tok.isNot(tok::eod)) { + if (Tok.is(tok::l_paren)) + OpenParens++; + else if (Tok.is(tok::r_paren)) { + OpenParens--; + if (OpenParens == 0) + break; + } + + AttributeTokens.push_back(Tok); + PP.Lex(Tok); + } + + if (AttributeTokens.empty()) { + PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute); + return; + } + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren; + return; + } + SourceLocation EndLoc = Tok.getLocation(); + PP.Lex(Tok); + + // Terminate the attribute for parsing. + Token EOFTok; + EOFTok.startToken(); + EOFTok.setKind(tok::eof); + EOFTok.setLocation(EndLoc); + AttributeTokens.push_back(EOFTok); + + Info->Tokens = + llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator()); + } + + if (Tok.isNot(tok::eod)) + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "clang attribute"; + + // Generate the annotated pragma token. + auto TokenArray = llvm::make_unique<Token[]>(1); + TokenArray[0].startToken(); + TokenArray[0].setKind(tok::annot_pragma_attribute); + TokenArray[0].setLocation(FirstToken.getLocation()); + TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation()); + TokenArray[0].setAnnotationValue(static_cast<void *>(Info)); + PP.EnterTokenStream(std::move(TokenArray), 1, + /*DisableMacroExpansion=*/false); +} diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index 30e392f..b1fbb20 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -12,10 +12,10 @@ // //===----------------------------------------------------------------------===// -#include "RAIIObjectsForParser.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/LoopHint.h" #include "clang/Sema/PrettyDeclStackTrace.h" @@ -97,7 +97,7 @@ StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc, /// StmtResult Parser::ParseStatementOrDeclaration(StmtVector &Stmts, - AllowedContsructsKind Allowed, + AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc) { ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -150,7 +150,7 @@ private: StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts, - AllowedContsructsKind Allowed, SourceLocation *TrailingElseLoc, + AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) { const char *SemiError = nullptr; StmtResult Res; @@ -203,6 +203,7 @@ Retry: } // Fall through + LLVM_FALLTHROUGH; } default: { @@ -338,7 +339,13 @@ Retry: case tok::annot_pragma_fp_contract: ProhibitAttributes(Attrs); Diag(Tok, diag::err_pragma_fp_contract_scope); - ConsumeToken(); + ConsumeAnnotationToken(); + return StmtError(); + + case tok::annot_pragma_fp: + ProhibitAttributes(Attrs); + Diag(Tok, diag::err_pragma_fp_scope); + ConsumeAnnotationToken(); return StmtError(); case tok::annot_pragma_opencl_extension: @@ -376,6 +383,10 @@ Retry: case tok::annot_pragma_dump: HandlePragmaDump(); return StmtEmpty(); + + case tok::annot_pragma_attribute: + HandlePragmaAttribute(); + return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. @@ -900,6 +911,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); break; + case tok::annot_pragma_fp: + HandlePragmaFP(); + break; case tok::annot_pragma_ms_pointers_to_members: HandlePragmaMSPointersToMembers(); break; @@ -1179,7 +1193,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { StmtResult ThenStmt; { EnterExpressionEvaluationContext PotentiallyDiscarded( - Actions, Sema::DiscardedStatement, nullptr, false, + Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr, + false, /*ShouldEnter=*/ConstexprCondition && !*ConstexprCondition); ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc); } @@ -1212,7 +1227,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { Tok.is(tok::l_brace)); EnterExpressionEvaluationContext PotentiallyDiscarded( - Actions, Sema::DiscardedStatement, nullptr, false, + Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr, + false, /*ShouldEnter=*/ConstexprCondition && *ConstexprCondition); ElseStmt = ParseStatement(); @@ -1898,12 +1914,12 @@ StmtResult Parser::ParseReturnStatement() { } } if (IsCoreturn) - return Actions.ActOnCoreturnStmt(ReturnLoc, R.get()); + return Actions.ActOnCoreturnStmt(getCurScope(), ReturnLoc, R.get()); return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope()); } StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, - AllowedContsructsKind Allowed, + AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) { // Create temporary attribute list. diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp index 293de78..d6f16bb 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmtAsm.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/MC/MCAsmInfo.h" @@ -224,6 +224,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, /*EnteringContext=*/false, /*AllowDestructorName=*/false, /*AllowConstructorName=*/false, + /*AllowDeductionGuide=*/false, /*ObjectType=*/nullptr, TemplateKWLoc, Id); // Perform the lookup. Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, @@ -451,12 +452,17 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { // We're no longer in a comment. InAsmComment = false; if (isAsm) { - // If this is a new __asm {} block we want to process it seperately + // If this is a new __asm {} block we want to process it separately // from the single-line __asm statements if (PP.LookAhead(0).is(tok::l_brace)) break; LineNo = SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second); SkippedStartOfLine = Tok.isAtStartOfLine(); + } else if (Tok.is(tok::semi)) { + // A multi-line asm-statement, where next line is a comment + InAsmComment = true; + FID = ExpLoc.first; + LineNo = SrcMgr.getLineNumber(FID, ExpLoc.second); } } else if (!InAsmComment && Tok.is(tok::r_brace)) { // In MSVC mode, braces only participate in brace matching and @@ -615,10 +621,11 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { MII.get(), IP.get(), Callback)) return StmtError(); - // Filter out "fpsw". Clang doesn't accept it, and it always lists flags and - // fpsr as clobbers. - auto End = std::remove(Clobbers.begin(), Clobbers.end(), "fpsw"); - Clobbers.erase(End, Clobbers.end()); + // Filter out "fpsw" and "mxcsr". They aren't valid GCC asm clobber + // constraints. Clang always adds fpsr to the clobber list anyway. + llvm::erase_if(Clobbers, [](const std::string &C) { + return C == "fpsw" || C == "mxcsr"; + }); // Build the vector of clobber StringRefs. ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end()); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index 6a09ea7..944cd77 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -11,11 +11,11 @@ // //===----------------------------------------------------------------------===// -#include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -674,7 +674,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // FIXME: The type should probably be restricted in some way... Not all // declarators (parts of declarators?) are accepted for parameters. DeclSpec DS(AttrFactory); - ParseDeclarationSpecifiers(DS); + ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, + DSC_template_param); // Parse this as a typename. Declarator ParamDecl(DS, Declarator::TemplateParamContext); @@ -701,8 +702,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // end of the template-parameter-list rather than a greater-than // operator. GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); - EnterExpressionEvaluationContext ConstantEvaluated(Actions, - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (DefaultArg.isInvalid()) @@ -886,22 +887,12 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, /// list ('<' template-parameter-list [opt] '>') and placing the /// results into a form that can be transferred to semantic analysis. /// -/// \param Template the template declaration produced by isTemplateName -/// -/// \param TemplateNameLoc the source location of the template name -/// -/// \param SS if non-NULL, the nested-name-specifier preceding the -/// template name. -/// /// \param ConsumeLastToken if true, then we will consume the last /// token that forms the template-id. Otherwise, we will leave the /// last token in the stream (e.g., so that it can be replaced with an /// annotation token). bool -Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, - SourceLocation TemplateNameLoc, - const CXXScopeSpec &SS, - bool ConsumeLastToken, +Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, SourceLocation &RAngleLoc) { @@ -983,9 +974,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - bool Invalid = ParseTemplateIdAfterTemplateName(Template, - TemplateNameLoc, - SS, false, LAngleLoc, + bool Invalid = ParseTemplateIdAfterTemplateName(false, LAngleLoc, TemplateArgs, RAngleLoc); @@ -1000,13 +989,13 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // Build the annotation token. if (TNK == TNK_Type_template && AllowTypeAnnotation) { - TypeResult Type - = Actions.ActOnTemplateIdType(SS, TemplateKWLoc, - Template, TemplateNameLoc, - LAngleLoc, TemplateArgsPtr, RAngleLoc); + TypeResult Type = Actions.ActOnTemplateIdType( + SS, TemplateKWLoc, Template, TemplateName.Identifier, + TemplateNameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc); if (Type.isInvalid()) { - // If we failed to parse the template ID but skipped ahead to a >, we're not - // going to be able to form a token annotation. Eat the '>' if present. + // If we failed to parse the template ID but skipped ahead to a >, we're + // not going to be able to form a token annotation. Eat the '>' if + // present. TryConsumeToken(tok::greater); return true; } @@ -1023,25 +1012,21 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // Build a template-id annotation token that can be processed // later. Tok.setKind(tok::annot_template_id); - TemplateIdAnnotation *TemplateId - = TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds); - TemplateId->TemplateNameLoc = TemplateNameLoc; - if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) { - TemplateId->Name = TemplateName.Identifier; - TemplateId->Operator = OO_None; - } else { - TemplateId->Name = nullptr; - TemplateId->Operator = TemplateName.OperatorFunctionId.Operator; - } - TemplateId->SS = SS; - TemplateId->TemplateKWLoc = TemplateKWLoc; - TemplateId->Template = Template; - TemplateId->Kind = TNK; - TemplateId->LAngleLoc = LAngleLoc; - TemplateId->RAngleLoc = RAngleLoc; - ParsedTemplateArgument *Args = TemplateId->getTemplateArgs(); - for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) - Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]); + + IdentifierInfo *TemplateII = + TemplateName.getKind() == UnqualifiedId::IK_Identifier + ? TemplateName.Identifier + : nullptr; + + OverloadedOperatorKind OpKind = + TemplateName.getKind() == UnqualifiedId::IK_Identifier + ? OO_None + : TemplateName.OperatorFunctionId.Operator; + + TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
+ SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
+ LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds); + Tok.setAnnotationValue(TemplateId); if (TemplateKWLoc.isValid()) Tok.setLocation(TemplateKWLoc); @@ -1064,7 +1049,12 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, /// If there was a failure when forming the type from the template-id, /// a type annotation token will still be created, but will have a /// NULL type pointer to signify an error. -void Parser::AnnotateTemplateIdTokenAsType() { +/// +/// \param IsClassName Is this template-id appearing in a context where we +/// know it names a class, such as in an elaborated-type-specifier or +/// base-specifier? ('typename' and 'template' are unneeded and disallowed +/// in those contexts.) +void Parser::AnnotateTemplateIdTokenAsType(bool IsClassName) { assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens"); TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); @@ -1079,10 +1069,13 @@ void Parser::AnnotateTemplateIdTokenAsType() { = Actions.ActOnTemplateIdType(TemplateId->SS, TemplateId->TemplateKWLoc, TemplateId->Template, + TemplateId->Name, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, - TemplateId->RAngleLoc); + TemplateId->RAngleLoc, + /*IsCtorOrDtorName*/false, + IsClassName); // Create the new "type" annotation token. Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Type.isInvalid() ? nullptr : Type.get()); @@ -1190,7 +1183,13 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // expression is resolved to a type-id, regardless of the form of // the corresponding template-parameter. // - // Therefore, we initially try to parse a type-id. + // Therefore, we initially try to parse a type-id - and isCXXTypeId might look + // up and annotate an identifier as an id-expression during disambiguation, + // so enter the appropriate context for a constant expression template + // argument before trying to disambiguate. + + EnterExpressionEvaluationContext EnterConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); if (isCXXTypeId(TypeIdAsTemplateArgument)) { SourceLocation Loc = Tok.getLocation(); TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr, @@ -1220,7 +1219,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // Parse a non-type template argument. SourceLocation Loc = Tok.getLocation(); - ExprResult ExprArg = ParseConstantExpression(MaybeTypeCast); + ExprResult ExprArg = ParseConstantExpressionInExprEvalContext(MaybeTypeCast); if (ExprArg.isInvalid() || !ExprArg.get()) return ParsedTemplateArgument(); @@ -1238,7 +1237,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { } Tentative(*this); while (Skip) { - ConsumeToken(); + ConsumeAnyToken(); --Skip; } @@ -1252,7 +1251,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { // See whether we have declaration specifiers, which indicate a type. while (isCXXDeclarationSpecifier() == TPResult::True) - ConsumeToken(); + ConsumeAnyToken(); // If we have a '>' or a ',' then this is a template argument list. return Tok.isOneOf(tok::greater, tok::comma); @@ -1266,8 +1265,7 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) { /// template-argument-list ',' template-argument bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { - // Template argument lists are constant-evaluation contexts. - EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated); + ColonProtectionRAIIObject ColonProtection(*this, false); do { diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp index 0ea3f8d..d6684c3 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp @@ -208,17 +208,20 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() { TryAnnotateCXXScopeToken()) return TPResult::Error; if (Tok.is(tok::annot_cxxscope)) + ConsumeAnnotationToken(); + if (Tok.is(tok::identifier)) ConsumeToken(); - if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) + else if (Tok.is(tok::annot_template_id)) + ConsumeAnnotationToken(); + else return TPResult::Error; - ConsumeToken(); break; case tok::annot_cxxscope: - ConsumeToken(); + ConsumeAnnotationToken(); // Fall through. default: - ConsumeToken(); + ConsumeAnyToken(); if (getLangOpts().ObjC1 && Tok.is(tok::less)) return TryParseProtocolQualifiers(); @@ -478,10 +481,10 @@ Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement) { /// the corresponding ')'. If the context is /// TypeIdAsTemplateArgument, we've already parsed the '<' or ',' /// before this template argument, and will cease lookahead when we - /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id - /// and false for an expression. If during the disambiguation - /// process a parsing error is encountered, the function returns - /// true to let the declaration parsing code handle it. + /// hit a '>', '>>' (in C++0x), or ','; or, in C++0x, an ellipsis immediately + /// preceding such. Returns true for a type-id and false for an expression. + /// If during the disambiguation process a parsing error is encountered, + /// the function returns true to let the declaration parsing code handle it. /// /// type-id: /// type-specifier-seq abstract-declarator[opt] @@ -530,10 +533,15 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { // We are supposed to be inside a template argument, so if after // the abstract declarator we encounter a '>', '>>' (in C++0x), or - // ',', this is a type-id. Otherwise, it's an expression. + // ','; or, in C++0x, an ellipsis immediately preceding such, this + // is a type-id. Otherwise, it's an expression. } else if (Context == TypeIdAsTemplateArgument && (Tok.isOneOf(tok::greater, tok::comma) || - (getLangOpts().CPlusPlus11 && Tok.is(tok::greatergreater)))) { + (getLangOpts().CPlusPlus11 && + (Tok.is(tok::greatergreater) || + (Tok.is(tok::ellipsis) && + NextToken().isOneOf(tok::greater, tok::greatergreater, + tok::comma)))))) { TPR = TPResult::True; isAmbiguous = true; @@ -706,7 +714,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() { if (Tok.isOneOf(tok::star, tok::amp, tok::caret, tok::ampamp) || (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) { // ptr-operator - ConsumeToken(); + ConsumeAnyToken(); while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict, tok::kw__Nonnull, tok::kw__Nullable, tok::kw__Null_unspecified)) @@ -826,14 +834,14 @@ Parser::TPResult Parser::TryParseOperatorId() { /// abstract-declarator: /// ptr-operator abstract-declarator[opt] /// direct-abstract-declarator -/// ... /// /// direct-abstract-declarator: /// direct-abstract-declarator[opt] -/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] +/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] /// exception-specification[opt] /// direct-abstract-declarator[opt] '[' constant-expression[opt] ']' /// '(' abstract-declarator ')' +/// [C++0x] ... /// /// ptr-operator: /// '*' cv-qualifier-seq[opt] @@ -883,7 +891,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, mayHaveIdentifier) { // declarator-id if (Tok.is(tok::annot_cxxscope)) - ConsumeToken(); + ConsumeAnnotationToken(); else if (Tok.is(tok::identifier)) TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo()); if (Tok.is(tok::kw_operator)) { @@ -925,10 +933,6 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, while (1) { TPResult TPR(TPResult::Ambiguous); - // abstract-declarator: ... - if (Tok.is(tok::ellipsis)) - ConsumeToken(); - if (Tok.is(tok::l_paren)) { // Check whether we have a function declarator or a possible ctor-style // initializer that follows the declarator. Note that ctor-style @@ -1399,7 +1403,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, SS); if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) { RevertingTentativeParsingAction PA(*this); - ConsumeToken(); + ConsumeAnnotationToken(); ConsumeToken(); bool isIdentifier = Tok.is(tok::identifier); TPResult TPR = TPResult::False; @@ -1446,6 +1450,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::False; } // If that succeeded, fallthrough into the generic simple-type-id case. + LLVM_FALLTHROUGH; // The ambiguity resides in a simple-type-specifier/typename-specifier // followed by a '('. The '(' could either be the start of: @@ -1471,7 +1476,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, if (getLangOpts().ObjC1 && NextToken().is(tok::less)) { // Tentatively parse the protocol qualifiers. RevertingTentativeParsingAction PA(*this); - ConsumeToken(); // The type token + ConsumeAnyToken(); // The type token TPResult TPR = TryParseProtocolQualifiers(); bool isFollowedByParen = Tok.is(tok::l_paren); @@ -1488,6 +1493,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, return TPResult::True; } + LLVM_FALLTHROUGH; case tok::kw_char: case tok::kw_wchar_t: diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 52e5194..1ed7ef9 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -12,11 +12,11 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "RAIIObjectsForParser.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -37,26 +37,6 @@ public: return false; } }; - -/// \brief RAIIObject to destroy the contents of a SmallVector of -/// TemplateIdAnnotation pointers and clear the vector. -class DestroyTemplateIdAnnotationsRAIIObj { - SmallVectorImpl<TemplateIdAnnotation *> &Container; - -public: - DestroyTemplateIdAnnotationsRAIIObj( - SmallVectorImpl<TemplateIdAnnotation *> &Container) - : Container(Container) {} - - ~DestroyTemplateIdAnnotationsRAIIObj() { - for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I = - Container.begin(), - E = Container.end(); - I != E; ++I) - (*I)->Destroy(); - Container.clear(); - } -}; } // end anonymous namespace IdentifierInfo *Parser::getSEHExceptKeyword() { @@ -231,6 +211,21 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) { << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); } +bool Parser::expectIdentifier() { + if (Tok.is(tok::identifier)) + return false; + if (const auto *II = Tok.getIdentifierInfo()) { + if (II->isCPlusPlusKeyword(getLangOpts())) { + Diag(Tok, diag::err_expected_token_instead_of_objcxx_keyword) + << tok::identifier << Tok.getIdentifierInfo(); + // Objective-C++: Recover by treating this keyword as a valid identifier. + return false; + } + } + Diag(Tok, diag::err_expected) << tok::identifier; + return true; +} + //===----------------------------------------------------------------------===// // Error recovery. //===----------------------------------------------------------------------===// @@ -342,21 +337,13 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { ConsumeBrace(); break; - case tok::string_literal: - case tok::wide_string_literal: - case tok::utf8_string_literal: - case tok::utf16_string_literal: - case tok::utf32_string_literal: - ConsumeStringToken(); - break; - case tok::semi: if (HasFlagsSet(Flags, StopAtSemi)) return false; // FALL THROUGH. default: // Skip this token. - ConsumeToken(); + ConsumeAnyToken(); break; } isFirstTokenSkipped = false; @@ -493,6 +480,8 @@ void Parser::Initialize() { Ident_strict = nullptr; Ident_replacement = nullptr; + Ident_language = Ident_defined_in = Ident_generated_declaration = nullptr; + Ident__except = nullptr; Ident__exception_code = Ident__exception_info = nullptr; @@ -537,22 +526,7 @@ void Parser::LateTemplateParserCleanupCallback(void *P) { } bool Parser::ParseFirstTopLevelDecl(DeclGroupPtrTy &Result) { - // C++ Modules TS: module-declaration must be the first declaration in the - // file. (There can be no preceding preprocessor directives, but we expect - // the lexer to check that.) - if (Tok.is(tok::kw_module)) { - Result = ParseModuleDecl(); - return false; - } else if (getLangOpts().getCompilingModule() == - LangOptions::CMK_ModuleInterface) { - // FIXME: We avoid providing this diagnostic when generating an object file - // from an existing PCM file. This is not a good way to detect this - // condition; we should provide a mechanism to indicate whether we've - // already parsed a declaration in this translation unit and avoid calling - // ParseFirstTopLevelDecl in that case. - if (Actions.TUKind == TU_Module) - Diag(Tok, diag::err_expected_module_interface_decl); - } + Actions.ActOnStartOfTranslationUnit(); // C11 6.9p1 says translation units must have at least one top-level // declaration. C++ doesn't have this restriction. We also don't want to @@ -586,23 +560,35 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { Result = ParseModuleImport(SourceLocation()); return false; + case tok::kw_export: + if (NextToken().isNot(tok::kw_module)) + break; + LLVM_FALLTHROUGH; + case tok::kw_module: + Result = ParseModuleDecl(); + return false; + case tok::annot_module_include: Actions.ActOnModuleInclude(Tok.getLocation(), reinterpret_cast<Module *>( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); return false; case tok::annot_module_begin: Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast<Module *>( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); return false; case tok::annot_module_end: Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast<Module *>( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); + return false; + + case tok::annot_pragma_attribute: + HandlePragmaAttribute(); return false; case tok::eof: @@ -688,6 +674,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); return nullptr; + case tok::annot_pragma_fp: + HandlePragmaFP(); + break; case tok::annot_pragma_opencl_extension: HandlePragmaOpenCLExtension(); return nullptr; @@ -776,6 +765,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, } // This must be 'export template'. Parse it so we can diagnose our lack // of support. + LLVM_FALLTHROUGH; case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: @@ -847,6 +837,10 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, default: dont_know: + if (Tok.isEditorPlaceholder()) { + ConsumeToken(); + return nullptr; + } // We can't tell whether this is a function-definition or declaration yet. return ParseDeclarationOrFunctionDefinition(attrs, DS); } @@ -1675,6 +1669,8 @@ bool Parser::TryAnnotateTypeOrScopeToken() { return false; } } + if (Tok.isEditorPlaceholder()) + return true; Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename); return true; @@ -1701,6 +1697,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, TemplateId->TemplateKWLoc, TemplateId->Template, + TemplateId->Name, TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, @@ -1742,7 +1739,8 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS, false, NextToken().is(tok::period), nullptr, /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo*/ true)) { + /*NonTrivialTypeSourceInfo*/ true, + /*IsClassTemplateDeductionContext*/GreaterThanIsOperator)) { SourceLocation BeginLoc = Tok.getLocation(); if (SS.isNotEmpty()) // it was a C++ qualified type name. BeginLoc = SS.getBeginLoc(); @@ -1880,6 +1878,7 @@ bool Parser::isTokenEqualOrEqualTypo() { Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal) << Kind << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); + LLVM_FALLTHROUGH; case tok::equal: return true; } @@ -1964,8 +1963,10 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { // Parse the unqualified-id. SourceLocation TemplateKWLoc; // FIXME: parsed, but unused. - if (ParseUnqualifiedId(Result.SS, false, true, true, nullptr, TemplateKWLoc, - Result.Name)) { + if (ParseUnqualifiedId( + Result.SS, /*EnteringContext*/false, /*AllowDestructorName*/true, + /*AllowConstructorName*/true, /*AllowDeductionGuide*/false, nullptr, + TemplateKWLoc, Result.Name)) { T.skipToEnd(); return true; } @@ -2035,30 +2036,28 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { /// Parse a C++ Modules TS module declaration, which appears at the beginning /// of a module interface, module partition, or module implementation file. /// -/// module-declaration: [Modules TS + P0273R0] -/// 'module' module-kind[opt] module-name attribute-specifier-seq[opt] ';' -/// module-kind: -/// 'implementation' -/// 'partition' +/// module-declaration: [Modules TS + P0273R0 + P0629R0] +/// 'export'[opt] 'module' 'partition'[opt] +/// module-name attribute-specifier-seq[opt] ';' /// -/// Note that the module-kind values are context-sensitive keywords. +/// Note that 'partition' is a context-sensitive keyword. Parser::DeclGroupPtrTy Parser::ParseModuleDecl() { - assert(Tok.is(tok::kw_module) && getLangOpts().ModulesTS && - "should not be parsing a module declaration"); + SourceLocation StartLoc = Tok.getLocation(); + + Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export) + ? Sema::ModuleDeclKind::Module + : Sema::ModuleDeclKind::Implementation; + + assert(Tok.is(tok::kw_module) && "not a module declaration"); SourceLocation ModuleLoc = ConsumeToken(); - // Check for a module-kind. - Sema::ModuleDeclKind MDK = Sema::ModuleDeclKind::Module; - if (Tok.is(tok::identifier) && NextToken().is(tok::identifier)) { - if (Tok.getIdentifierInfo()->isStr("implementation")) - MDK = Sema::ModuleDeclKind::Implementation; - else if (Tok.getIdentifierInfo()->isStr("partition")) - MDK = Sema::ModuleDeclKind::Partition; - else { - Diag(Tok, diag::err_unexpected_module_kind) << Tok.getIdentifierInfo(); - SkipUntil(tok::semi); - return nullptr; - } + if (Tok.is(tok::identifier) && NextToken().is(tok::identifier) && + Tok.getIdentifierInfo()->isStr("partition")) { + // If 'partition' is present, this must be a module interface unit. + if (MDK != Sema::ModuleDeclKind::Module) + Diag(Tok.getLocation(), diag::err_module_implementation_partition) + << FixItHint::CreateInsertion(ModuleLoc, "export "); + MDK = Sema::ModuleDeclKind::Partition; ConsumeToken(); } @@ -2066,14 +2065,14 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() { if (ParseModuleName(ModuleLoc, Path, /*IsImport*/false)) return nullptr; + // We don't support any module attributes yet; just parse them and diagnose. ParsedAttributesWithRange Attrs(AttrFactory); MaybeParseCXX11Attributes(Attrs); - // We don't support any module attributes yet. ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_module_attr); ExpectAndConsumeSemi(diag::err_module_expected_semi); - return Actions.ActOnModuleDecl(ModuleLoc, MDK, Path); + return Actions.ActOnModuleDecl(StartLoc, ModuleLoc, MDK, Path); } /// Parse a module import declaration. This is essentially the same for @@ -2166,7 +2165,7 @@ bool Parser::parseMisplacedModuleImport() { Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast<Module *>( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); continue; } // Inform caller that recovery failed, the error must be handled at upper @@ -2178,7 +2177,7 @@ bool Parser::parseMisplacedModuleImport() { Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast<Module *>( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); ++MisplacedModuleBeginCount; continue; case tok::annot_module_include: @@ -2187,7 +2186,7 @@ bool Parser::parseMisplacedModuleImport() { Actions.ActOnModuleInclude(Tok.getLocation(), reinterpret_cast<Module *>( Tok.getAnnotationValue())); - ConsumeToken(); + ConsumeAnnotationToken(); // If there is another module import, process it. continue; default: diff --git a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h b/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h deleted file mode 100644 index 36d87eb..0000000 --- a/contrib/llvm/tools/clang/lib/Parse/RAIIObjectsForParser.h +++ /dev/null @@ -1,447 +0,0 @@ -//===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines and implements the some simple RAII objects that are used -// by the parser to manage bits in recursion. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H -#define LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H - -#include "clang/Parse/ParseDiagnostic.h" -#include "clang/Parse/Parser.h" -#include "clang/Sema/DelayedDiagnostic.h" -#include "clang/Sema/Sema.h" - -namespace clang { - // TODO: move ParsingClassDefinition here. - // TODO: move TentativeParsingAction here. - - /// \brief A RAII object used to temporarily suppress access-like - /// checking. Access-like checks are those associated with - /// controlling the use of a declaration, like C++ access control - /// errors and deprecation warnings. They are contextually - /// dependent, in that they can only be resolved with full - /// information about what's being declared. They are also - /// suppressed in certain contexts, like the template arguments of - /// an explicit instantiation. However, those suppression contexts - /// cannot necessarily be fully determined in advance; for - /// example, something starting like this: - /// template <> class std::vector<A::PrivateType> - /// might be the entirety of an explicit instantiation: - /// template <> class std::vector<A::PrivateType>; - /// or just an elaborated type specifier: - /// template <> class std::vector<A::PrivateType> make_vector<>(); - /// Therefore this class collects all the diagnostics and permits - /// them to be re-delayed in a new context. - class SuppressAccessChecks { - Sema &S; - sema::DelayedDiagnosticPool DiagnosticPool; - Sema::ParsingDeclState State; - bool Active; - - public: - /// Begin suppressing access-like checks - SuppressAccessChecks(Parser &P, bool activate = true) - : S(P.getActions()), DiagnosticPool(nullptr) { - if (activate) { - State = S.PushParsingDeclaration(DiagnosticPool); - Active = true; - } else { - Active = false; - } - } - SuppressAccessChecks(SuppressAccessChecks &&Other) - : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)), - State(Other.State), Active(Other.Active) { - Other.Active = false; - } - void operator=(SuppressAccessChecks &&Other) = delete; - - void done() { - assert(Active && "trying to end an inactive suppression"); - S.PopParsingDeclaration(State, nullptr); - Active = false; - } - - void redelay() { - assert(!Active && "redelaying without having ended first"); - if (!DiagnosticPool.pool_empty()) - S.redelayDiagnostics(DiagnosticPool); - assert(DiagnosticPool.pool_empty()); - } - - ~SuppressAccessChecks() { - if (Active) done(); - } - }; - - /// \brief RAII object used to inform the actions that we're - /// currently parsing a declaration. This is active when parsing a - /// variable's initializer, but not when parsing the body of a - /// class or function definition. - class ParsingDeclRAIIObject { - Sema &Actions; - sema::DelayedDiagnosticPool DiagnosticPool; - Sema::ParsingDeclState State; - bool Popped; - - ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete; - void operator=(const ParsingDeclRAIIObject &) = delete; - - public: - enum NoParent_t { NoParent }; - ParsingDeclRAIIObject(Parser &P, NoParent_t _) - : Actions(P.getActions()), DiagnosticPool(nullptr) { - push(); - } - - /// Creates a RAII object whose pool is optionally parented by another. - ParsingDeclRAIIObject(Parser &P, - const sema::DelayedDiagnosticPool *parentPool) - : Actions(P.getActions()), DiagnosticPool(parentPool) { - push(); - } - - /// Creates a RAII object and, optionally, initialize its - /// diagnostics pool by stealing the diagnostics from another - /// RAII object (which is assumed to be the current top pool). - ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other) - : Actions(P.getActions()), - DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) { - if (other) { - DiagnosticPool.steal(other->DiagnosticPool); - other->abort(); - } - push(); - } - - ~ParsingDeclRAIIObject() { - abort(); - } - - sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() { - return DiagnosticPool; - } - const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { - return DiagnosticPool; - } - - /// Resets the RAII object for a new declaration. - void reset() { - abort(); - push(); - } - - /// Signals that the context was completed without an appropriate - /// declaration being parsed. - void abort() { - pop(nullptr); - } - - void complete(Decl *D) { - assert(!Popped && "ParsingDeclaration has already been popped!"); - pop(D); - } - - /// Unregister this object from Sema, but remember all the - /// diagnostics that were emitted into it. - void abortAndRemember() { - pop(nullptr); - } - - private: - void push() { - State = Actions.PushParsingDeclaration(DiagnosticPool); - Popped = false; - } - - void pop(Decl *D) { - if (!Popped) { - Actions.PopParsingDeclaration(State, D); - Popped = true; - } - } - }; - - /// A class for parsing a DeclSpec. - class ParsingDeclSpec : public DeclSpec { - ParsingDeclRAIIObject ParsingRAII; - - public: - ParsingDeclSpec(Parser &P) - : DeclSpec(P.getAttrFactory()), - ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {} - ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII) - : DeclSpec(P.getAttrFactory()), - ParsingRAII(P, RAII) {} - - const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { - return ParsingRAII.getDelayedDiagnosticPool(); - } - - void complete(Decl *D) { - ParsingRAII.complete(D); - } - - void abort() { - ParsingRAII.abort(); - } - }; - - /// A class for parsing a declarator. - class ParsingDeclarator : public Declarator { - ParsingDeclRAIIObject ParsingRAII; - - public: - ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C) - : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { - } - - const ParsingDeclSpec &getDeclSpec() const { - return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec()); - } - - ParsingDeclSpec &getMutableDeclSpec() const { - return const_cast<ParsingDeclSpec&>(getDeclSpec()); - } - - void clear() { - Declarator::clear(); - ParsingRAII.reset(); - } - - void complete(Decl *D) { - ParsingRAII.complete(D); - } - }; - - /// A class for parsing a field declarator. - class ParsingFieldDeclarator : public FieldDeclarator { - ParsingDeclRAIIObject ParsingRAII; - - public: - ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS) - : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { - } - - const ParsingDeclSpec &getDeclSpec() const { - return static_cast<const ParsingDeclSpec&>(D.getDeclSpec()); - } - - ParsingDeclSpec &getMutableDeclSpec() const { - return const_cast<ParsingDeclSpec&>(getDeclSpec()); - } - - void complete(Decl *D) { - ParsingRAII.complete(D); - } - }; - - /// ExtensionRAIIObject - This saves the state of extension warnings when - /// constructed and disables them. When destructed, it restores them back to - /// the way they used to be. This is used to handle __extension__ in the - /// parser. - class ExtensionRAIIObject { - ExtensionRAIIObject(const ExtensionRAIIObject &) = delete; - void operator=(const ExtensionRAIIObject &) = delete; - - DiagnosticsEngine &Diags; - public: - ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) { - Diags.IncrementAllExtensionsSilenced(); - } - - ~ExtensionRAIIObject() { - Diags.DecrementAllExtensionsSilenced(); - } - }; - - /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and - /// restores it when destroyed. This says that "foo:" should not be - /// considered a possible typo for "foo::" for error recovery purposes. - class ColonProtectionRAIIObject { - Parser &P; - bool OldVal; - public: - ColonProtectionRAIIObject(Parser &p, bool Value = true) - : P(p), OldVal(P.ColonIsSacred) { - P.ColonIsSacred = Value; - } - - /// restore - This can be used to restore the state early, before the dtor - /// is run. - void restore() { - P.ColonIsSacred = OldVal; - } - - ~ColonProtectionRAIIObject() { - restore(); - } - }; - - /// \brief RAII object that makes '>' behave either as an operator - /// or as the closing angle bracket for a template argument list. - class GreaterThanIsOperatorScope { - bool &GreaterThanIsOperator; - bool OldGreaterThanIsOperator; - public: - GreaterThanIsOperatorScope(bool >IO, bool Val) - : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) { - GreaterThanIsOperator = Val; - } - - ~GreaterThanIsOperatorScope() { - GreaterThanIsOperator = OldGreaterThanIsOperator; - } - }; - - class InMessageExpressionRAIIObject { - bool &InMessageExpression; - bool OldValue; - - public: - InMessageExpressionRAIIObject(Parser &P, bool Value) - : InMessageExpression(P.InMessageExpression), - OldValue(P.InMessageExpression) { - InMessageExpression = Value; - } - - ~InMessageExpressionRAIIObject() { - InMessageExpression = OldValue; - } - }; - - /// \brief RAII object that makes sure paren/bracket/brace count is correct - /// after declaration/statement parsing, even when there's a parsing error. - class ParenBraceBracketBalancer { - Parser &P; - unsigned short ParenCount, BracketCount, BraceCount; - public: - ParenBraceBracketBalancer(Parser &p) - : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount), - BraceCount(p.BraceCount) { } - - ~ParenBraceBracketBalancer() { - P.ParenCount = ParenCount; - P.BracketCount = BracketCount; - P.BraceCount = BraceCount; - } - }; - - class PoisonSEHIdentifiersRAIIObject { - PoisonIdentifierRAIIObject Ident_AbnormalTermination; - PoisonIdentifierRAIIObject Ident_GetExceptionCode; - PoisonIdentifierRAIIObject Ident_GetExceptionInfo; - PoisonIdentifierRAIIObject Ident__abnormal_termination; - PoisonIdentifierRAIIObject Ident__exception_code; - PoisonIdentifierRAIIObject Ident__exception_info; - PoisonIdentifierRAIIObject Ident___abnormal_termination; - PoisonIdentifierRAIIObject Ident___exception_code; - PoisonIdentifierRAIIObject Ident___exception_info; - public: - PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue) - : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue), - Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue), - Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue), - Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue), - Ident__exception_code(Self.Ident__exception_code, NewValue), - Ident__exception_info(Self.Ident__exception_info, NewValue), - Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue), - Ident___exception_code(Self.Ident___exception_code, NewValue), - Ident___exception_info(Self.Ident___exception_info, NewValue) { - } - }; - - /// \brief RAII class that helps handle the parsing of an open/close delimiter - /// pair, such as braces { ... } or parentheses ( ... ). - class BalancedDelimiterTracker : public GreaterThanIsOperatorScope { - Parser& P; - tok::TokenKind Kind, Close, FinalToken; - SourceLocation (Parser::*Consumer)(); - SourceLocation LOpen, LClose; - - unsigned short &getDepth() { - switch (Kind) { - case tok::l_brace: return P.BraceCount; - case tok::l_square: return P.BracketCount; - case tok::l_paren: return P.ParenCount; - default: llvm_unreachable("Wrong token kind"); - } - } - - enum { MaxDepth = 256 }; - - bool diagnoseOverflow(); - bool diagnoseMissingClose(); - - public: - BalancedDelimiterTracker(Parser& p, tok::TokenKind k, - tok::TokenKind FinalToken = tok::semi) - : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true), - P(p), Kind(k), FinalToken(FinalToken) - { - switch (Kind) { - default: llvm_unreachable("Unexpected balanced token"); - case tok::l_brace: - Close = tok::r_brace; - Consumer = &Parser::ConsumeBrace; - break; - case tok::l_paren: - Close = tok::r_paren; - Consumer = &Parser::ConsumeParen; - break; - - case tok::l_square: - Close = tok::r_square; - Consumer = &Parser::ConsumeBracket; - break; - } - } - - SourceLocation getOpenLocation() const { return LOpen; } - SourceLocation getCloseLocation() const { return LClose; } - SourceRange getRange() const { return SourceRange(LOpen, LClose); } - - bool consumeOpen() { - if (!P.Tok.is(Kind)) - return true; - - if (getDepth() < P.getLangOpts().BracketDepth) { - LOpen = (P.*Consumer)(); - return false; - } - - return diagnoseOverflow(); - } - - bool expectAndConsume(unsigned DiagID = diag::err_expected, - const char *Msg = "", - tok::TokenKind SkipToTok = tok::unknown); - bool consumeClose() { - if (P.Tok.is(Close)) { - LClose = (P.*Consumer)(); - return false; - } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) { - SourceLocation SemiLoc = P.ConsumeToken(); - P.Diag(SemiLoc, diag::err_unexpected_semi) - << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc)); - LClose = (P.*Consumer)(); - return false; - } - - return diagnoseMissingClose(); - } - void skipToEnd(); - }; - -} // end namespace clang - -#endif |