diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp | 157 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp | 60 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp | 487 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp | 72 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp | 72 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp | 8 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp | 1 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp | 37 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp | 8 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/Parser.cpp | 155 |
11 files changed, 925 insertions, 138 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp index 87e2f34..f5c6998 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -23,10 +23,11 @@ using namespace clang; /// and store its tokens for parsing after the C++ class is complete. Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS) { + const VirtSpecifiers& VS, ExprResult& Init) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); - assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && - "Current token not a '{', ':' or 'try'!"); + assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try) || + Tok.is(tok::equal)) && + "Current token not a '{', ':', '=', or 'try'!"); MultiTemplateParamsArg TemplateParams(Actions, TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0, @@ -40,13 +41,49 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, else { // FIXME: pass template information through FnD = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS, D, move(TemplateParams), 0, - VS, 0, /*IsDefinition*/true); + VS, Init.release(), + /*HasInit=*/false, + /*IsDefinition*/true); } HandleMemberFunctionDefaultArgs(D, FnD); D.complete(FnD); + if (Tok.is(tok::equal)) { + ConsumeToken(); + + bool Delete = false; + SourceLocation KWLoc; + if (Tok.is(tok::kw_delete)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_deleted_function_accepted_as_extension); + + KWLoc = ConsumeToken(); + Actions.SetDeclDeleted(FnD, KWLoc); + Delete = true; + } else if (Tok.is(tok::kw_default)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_defaulted_function_accepted_as_extension); + + KWLoc = ConsumeToken(); + Actions.SetDeclDefaulted(FnD, KWLoc); + } else { + llvm_unreachable("function definition after = not 'delete' or 'default'"); + } + + if (Tok.is(tok::comma)) { + Diag(KWLoc, diag::err_default_delete_in_multiple_declaration) + << Delete; + SkipUntil(tok::semi); + } else { + ExpectAndConsume(tok::semi, diag::err_expected_semi_after, + Delete ? "delete" : "default", tok::semi); + } + + return FnD; + } + // In delayed template parsing mode, if we are within a class template // or if we are about to parse function member template then consume // the tokens and store them for parsing at the end of the translation unit. @@ -130,8 +167,50 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, return FnD; } +/// ParseCXXNonStaticMemberInitializer - We parsed and verified that the +/// specified Declarator is a well formed C++ non-static data member +/// declaration. Now lex its initializer and store its tokens for parsing +/// after the class is complete. +void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) { + assert((Tok.is(tok::l_brace) || Tok.is(tok::equal)) && + "Current token not a '{' or '='!"); + + LateParsedMemberInitializer *MI = + new LateParsedMemberInitializer(this, VarD); + getCurrentClass().LateParsedDeclarations.push_back(MI); + CachedTokens &Toks = MI->Toks; + + tok::TokenKind kind = Tok.getKind(); + if (kind == tok::equal) { + Toks.push_back(Tok); + ConsumeAnyToken(); + } + + if (kind == tok::l_brace) { + // Begin by storing the '{' token. + Toks.push_back(Tok); + ConsumeBrace(); + + // Consume everything up to (and including) the matching right brace. + ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/true); + } else { + // Consume everything up to (but excluding) the comma or semicolon. + ConsumeAndStoreUntil(tok::comma, Toks, /*StopAtSemi=*/true, + /*ConsumeFinalToken=*/false); + } + + // Store an artificial EOF token to ensure that we don't run off the end of + // the initializer when we come to parse it. + Token Eof; + Eof.startToken(); + Eof.setKind(tok::eof); + Eof.setLocation(Tok.getLocation()); + Toks.push_back(Eof); +} + Parser::LateParsedDeclaration::~LateParsedDeclaration() {} void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {} +void Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {} void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {} Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C) @@ -145,6 +224,10 @@ void Parser::LateParsedClass::ParseLexedMethodDeclarations() { Self->ParseLexedMethodDeclarations(*Class); } +void Parser::LateParsedClass::ParseLexedMemberInitializers() { + Self->ParseLexedMemberInitializers(*Class); +} + void Parser::LateParsedClass::ParseLexedMethodDefs() { Self->ParseLexedMethodDefs(*Class); } @@ -157,6 +240,10 @@ void Parser::LexedMethod::ParseLexedMethodDefs() { Self->ParseLexedMethodDef(*this); } +void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() { + Self->ParseLexedMemberInitializer(*this); +} + /// ParseLexedMethodDeclarations - We finished parsing the member /// specification of a top (non-nested) C++ class. Now go over the /// stack of method declarations with some parts for which parsing was @@ -328,8 +415,70 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { origLoc)) while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) ConsumeAnyToken(); + } +} + +/// ParseLexedMemberInitializers - We finished parsing the member specification +/// of a top (non-nested) C++ class. Now go over the stack of lexed data member +/// initializers that were collected during its parsing and parse them all. +void Parser::ParseLexedMemberInitializers(ParsingClass &Class) { + bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope; + ParseScope ClassTemplateScope(this, Scope::TemplateParamScope, + HasTemplateScope); + if (HasTemplateScope) + Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate); + // Set or update the scope flags to include Scope::ThisScope. + bool AlreadyHasClassScope = Class.TopLevelClass; + unsigned ScopeFlags = Scope::ClassScope|Scope::DeclScope|Scope::ThisScope; + ParseScope ClassScope(this, ScopeFlags, !AlreadyHasClassScope); + ParseScopeFlags ClassScopeFlags(this, ScopeFlags, AlreadyHasClassScope); + + if (!AlreadyHasClassScope) + Actions.ActOnStartDelayedMemberDeclarations(getCurScope(), + Class.TagOrTemplate); + + for (size_t i = 0; i < Class.LateParsedDeclarations.size(); ++i) { + Class.LateParsedDeclarations[i]->ParseLexedMemberInitializers(); } + + if (!AlreadyHasClassScope) + Actions.ActOnFinishDelayedMemberDeclarations(getCurScope(), + Class.TagOrTemplate); + + Actions.ActOnFinishDelayedMemberInitializers(Class.TagOrTemplate); +} + +void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { + if (MI.Field->isInvalidDecl()) + return; + + // Append the current token at the end of the new token stream so that it + // doesn't get lost. + MI.Toks.push_back(Tok); + PP.EnterTokenStream(MI.Toks.data(), MI.Toks.size(), true, false); + + // Consume the previously pushed token. + ConsumeAnyToken(); + + SourceLocation EqualLoc; + ExprResult Init = ParseCXXMemberInitializer(/*IsFunction=*/false, EqualLoc); + + Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release()); + + // The next token should be our artificial terminating EOF token. + if (Tok.isNot(tok::eof)) { + SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); + if (!EndLoc.isValid()) + EndLoc = Tok.getLocation(); + // No fixit; we can't recover as if there were a semicolon here. + Diag(EndLoc, diag::err_expected_semi_decl_list); + + // Consume tokens until we hit the artificial EOF. + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + } + ConsumeAnyToken(); } /// ConsumeAndStoreUntil - Consume and store the token at the passed token diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index a20e90b..ad3fcfe 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -253,9 +253,17 @@ void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &attrs) { SkipUntil(tok::r_paren, true); // skip until ) or ; return; } + while (Tok.getIdentifierInfo()) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); + + // FIXME: Remove this when we have proper __declspec(property()) support. + // Just skip everything inside property(). + if (AttrName->getName() == "property") { + ConsumeParen(); + SkipUntil(tok::r_paren); + } if (Tok.is(tok::l_paren)) { ConsumeParen(); // FIXME: This doesn't parse __declspec(property(get=get_func_name)) @@ -806,8 +814,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // analyzed. if (FRI && Tok.is(tok::colon)) { FRI->ColonLoc = ConsumeToken(); - // FIXME: handle braced-init-list here. - FRI->RangeExpr = ParseExpression(); + if (Tok.is(tok::l_brace)) + FRI->RangeExpr = ParseBraceInitializer(); + else + FRI->RangeExpr = ParseExpression(); Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); Actions.ActOnCXXForRangeDecl(ThisDecl); Actions.FinalizeDeclaration(ThisDecl); @@ -906,6 +916,7 @@ bool Parser::ParseAttributesAfterDeclarator(Declarator &D) { /// [C++] '(' expression-list ')' /// [C++0x] '=' 'default' [TODO] /// [C++0x] '=' 'delete' +/// [C++0x] braced-init-list /// /// According to the standard grammar, =default and =delete are function /// definitions, but that definitely doesn't fit with the parser here. @@ -960,12 +971,17 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, diag::err_invalid_equalequal_after_declarator)) { ConsumeToken(); if (Tok.is(tok::kw_delete)) { - SourceLocation DelLoc = ConsumeToken(); - - if (!getLang().CPlusPlus0x) - Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension); - - Actions.SetDeclDeleted(ThisDecl, DelLoc); + if (D.isFunctionDeclarator()) + Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) + << 1 /* delete */; + else + Diag(ConsumeToken(), diag::err_deleted_non_function); + } else if (Tok.is(tok::kw_default)) { + if (D.isFunctionDeclarator()) + Diag(Tok, diag::err_default_delete_in_multiple_declaration) + << 1 /* delete */; + else + Diag(ConsumeToken(), diag::err_default_special_members); } else { if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) { EnterScope(0); @@ -1028,6 +1044,26 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, RParenLoc, TypeContainsAuto); } + } else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { + // Parse C++0x braced-init-list. + if (D.getCXXScopeSpec().isSet()) { + EnterScope(0); + Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl); + } + + ExprResult Init(ParseBraceInitializer()); + + if (D.getCXXScopeSpec().isSet()) { + Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl); + ExitScope(); + } + + if (Init.isInvalid()) { + Actions.ActOnInitializerError(ThisDecl); + } else + Actions.AddInitializerToDecl(ThisDecl, Init.take(), + /*DirectInit=*/true, TypeContainsAuto); + } else { Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto); } @@ -1846,6 +1882,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParseDecltypeSpecifier(DS); continue; + case tok::kw___underlying_type: + ParseUnderlyingTypeSpecifier(DS); + // OpenCL qualifiers: case tok::kw_private: if (!getLang().OpenCL) @@ -2116,6 +2155,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, ParseDecltypeSpecifier(DS); return true; + // C++0x type traits support. + case tok::kw___underlying_type: + ParseUnderlyingTypeSpecifier(DS); + return true; + // OpenCL qualifiers: case tok::kw_private: if (!getLang().OpenCL) diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index 8c0aa1b..51aa010 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -60,12 +60,20 @@ Decl *Parser::ParseNamespace(unsigned Context, SourceLocation IdentLoc; IdentifierInfo *Ident = 0; + std::vector<SourceLocation> ExtraIdentLoc; + std::vector<IdentifierInfo*> ExtraIdent; + std::vector<SourceLocation> ExtraNamespaceLoc; Token attrTok; if (Tok.is(tok::identifier)) { Ident = Tok.getIdentifierInfo(); IdentLoc = ConsumeToken(); // eat the identifier. + while (Tok.is(tok::coloncolon) && NextToken().is(tok::identifier)) { + ExtraNamespaceLoc.push_back(ConsumeToken()); + ExtraIdent.push_back(Tok.getIdentifierInfo()); + ExtraIdentLoc.push_back(ConsumeToken()); + } } // Read label attributes, if present. @@ -85,7 +93,12 @@ Decl *Parser::ParseNamespace(unsigned Context, return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd); } + if (Tok.isNot(tok::l_brace)) { + if (!ExtraIdent.empty()) { + Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); + } Diag(Tok, Ident ? diag::err_expected_lbrace : diag::err_expected_ident_lbrace); return 0; @@ -96,11 +109,44 @@ Decl *Parser::ParseNamespace(unsigned Context, if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() || getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() || getCurScope()->getFnParent()) { + if (!ExtraIdent.empty()) { + Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); + } Diag(LBrace, diag::err_namespace_nonnamespace_scope); SkipUntil(tok::r_brace, false); return 0; } + if (!ExtraIdent.empty()) { + TentativeParsingAction TPA(*this); + SkipUntil(tok::r_brace, /*StopAtSemi*/false, /*DontConsume*/true); + Token rBraceToken = Tok; + TPA.Revert(); + + if (!rBraceToken.is(tok::r_brace)) { + Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); + } else { + std::string NamespaceFix; + for (std::vector<IdentifierInfo*>::iterator I = ExtraIdent.begin(), + E = ExtraIdent.end(); I != E; ++I) { + NamespaceFix += " { namespace "; + NamespaceFix += (*I)->getName(); + } + + std::string RBraces; + for (unsigned i = 0, e = ExtraIdent.size(); i != e; ++i) + RBraces += "} "; + + Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) + << FixItHint::CreateReplacement(SourceRange(ExtraNamespaceLoc.front(), + ExtraIdentLoc.back()), + NamespaceFix) + << FixItHint::CreateInsertion(rBraceToken.getLocation(), RBraces); + } + } + // If we're still good, complain about inline namespaces in non-C++0x now. if (!getLang().CPlusPlus0x && InlineLoc.isValid()) Diag(InlineLoc, diag::ext_inline_namespace); @@ -115,23 +161,56 @@ Decl *Parser::ParseNamespace(unsigned Context, PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc, "parsing namespace"); - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { - ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); - MaybeParseMicrosoftAttributes(attrs); - ParseExternalDeclaration(attrs); - } + SourceLocation RBraceLoc; + // Parse the contents of the namespace. This includes parsing recovery on + // any improperly nested namespaces. + ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0, + InlineLoc, LBrace, attrs, RBraceLoc); // Leave the namespace scope. NamespaceScope.Exit(); - SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace); Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc); DeclEnd = RBraceLoc; return NamespcDecl; } +/// ParseInnerNamespace - Parse the contents of a namespace. +void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, + std::vector<IdentifierInfo*>& Ident, + std::vector<SourceLocation>& NamespaceLoc, + unsigned int index, SourceLocation& InlineLoc, + SourceLocation& LBrace, + ParsedAttributes& attrs, + SourceLocation& RBraceLoc) { + if (index == Ident.size()) { + while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + ParsedAttributesWithRange attrs(AttrFactory); + MaybeParseCXX0XAttributes(attrs); + MaybeParseMicrosoftAttributes(attrs); + ParseExternalDeclaration(attrs); + } + RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace); + + return; + } + + // Parse improperly nested namespaces. + ParseScope NamespaceScope(this, Scope::DeclScope); + Decl *NamespcDecl = + Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), + NamespaceLoc[index], IdentLoc[index], + Ident[index], LBrace, attrs.getList()); + + ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc, + LBrace, attrs, RBraceLoc); + + NamespaceScope.Exit(); + + Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc); +} + /// ParseNamespaceAlias - Parse the part after the '=' in a namespace /// alias definition. /// @@ -387,13 +466,35 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, bool IsAliasDecl = Tok.is(tok::equal); TypeResult TypeAlias; if (IsAliasDecl) { - // TODO: Do we want to support attributes somewhere in an alias declaration? - // Can't follow GCC since it doesn't support them yet! + // TODO: Attribute support. C++0x attributes may appear before the equals. + // Where can GNU attributes appear? ConsumeToken(); if (!getLang().CPlusPlus0x) Diag(Tok.getLocation(), diag::ext_alias_declaration); + // Type alias templates cannot be specialized. + int SpecKind = -1; + if (TemplateInfo.Kind == ParsedTemplateInfo::Template && + Name.getKind() == UnqualifiedId::IK_TemplateId) + SpecKind = 0; + if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) + SpecKind = 1; + if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) + SpecKind = 2; + if (SpecKind != -1) { + SourceRange Range; + if (SpecKind == 0) + Range = SourceRange(Name.TemplateId->LAngleLoc, + Name.TemplateId->RAngleLoc); + else + Range = TemplateInfo.getSourceRange(); + Diag(Range.getBegin(), diag::err_alias_declaration_specialization) + << SpecKind << Range; + SkipUntil(tok::semi); + return 0; + } + // Name must be an identifier. if (Name.getKind() != UnqualifiedId::IK_Identifier) { Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier); @@ -408,7 +509,9 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) << FixItHint::CreateRemoval(SS.getRange()); - TypeAlias = ParseTypeName(0, Declarator::AliasDeclContext); + TypeAlias = ParseTypeName(0, TemplateInfo.Kind ? + Declarator::AliasTemplateContext : + Declarator::AliasDeclContext); } else // Parse (optional) attributes (most likely GNU strong-using extension). MaybeParseGNUAttributes(attrs); @@ -421,9 +524,9 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, tok::semi); // Diagnose an attempt to declare a templated using-declaration. - // TODO: in C++0x, alias-declarations can be templates: + // In C++0x, alias-declarations can be templates: // template <...> using id = type; - if (TemplateInfo.Kind) { + if (TemplateInfo.Kind && !IsAliasDecl) { SourceRange R = TemplateInfo.getSourceRange(); Diag(UsingLoc, diag::err_templated_using_declaration) << R << FixItHint::CreateRemoval(R); @@ -434,9 +537,14 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, return 0; } - if (IsAliasDecl) - return Actions.ActOnAliasDeclaration(getCurScope(), AS, UsingLoc, Name, - TypeAlias); + if (IsAliasDecl) { + TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; + MultiTemplateParamsArg TemplateParamsArg(Actions, + TemplateParams ? TemplateParams->data() : 0, + TemplateParams ? TemplateParams->size() : 0); + return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, + UsingLoc, Name, TypeAlias); + } return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS, Name, attrs.getList(), @@ -543,6 +651,42 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) { Diag(StartLoc, DiagID) << PrevSpec; } +void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { + assert(Tok.is(tok::kw___underlying_type) && + "Not an underlying type specifier"); + + SourceLocation StartLoc = ConsumeToken(); + SourceLocation LParenLoc = Tok.getLocation(); + + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, + "__underlying_type")) { + SkipUntil(tok::r_paren); + return; + } + + TypeResult Result = ParseTypeName(); + if (Result.isInvalid()) { + SkipUntil(tok::r_paren); + return; + } + + // Match the ')' + SourceLocation RParenLoc; + if (Tok.is(tok::r_paren)) + RParenLoc = ConsumeParen(); + else + MatchRHSPunctuation(tok::r_paren, LParenLoc); + + if (RParenLoc.isInvalid()) + return; + + const char *PrevSpec = 0; + unsigned DiagID; + if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec, + DiagID, Result.release())) + Diag(StartLoc, DiagID) << PrevSpec; +} + /// ParseClassName - Parse a C++ class-name, which names a class. Note /// that we only check that the result names a type; semantic analysis /// will need to verify that the type names a class. The result is @@ -1409,6 +1553,7 @@ bool Parser::isCXX0XFinalKeyword() const { /// member-declarator: /// declarator virt-specifier-seq[opt] pure-specifier[opt] /// declarator constant-initializer[opt] +/// [C++11] declarator brace-or-equal-initializer[opt] /// identifier[opt] ':' constant-expression /// /// virt-specifier-seq: @@ -1515,8 +1660,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, MaybeParseMicrosoftAttributes(attrs); if (Tok.is(tok::kw_using)) { - // FIXME: Check for template aliases - ProhibitAttributes(attrs); // Eat 'using'. @@ -1527,7 +1670,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SkipUntil(tok::semi, true, true); } else { SourceLocation DeclEnd; - // Otherwise, it must be using-declaration. + // Otherwise, it must be a using-declaration or an alias-declaration. ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo, UsingLoc, DeclEnd, AS); } @@ -1547,13 +1690,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::semi)) { ConsumeToken(); Decl *TheDecl = - Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS); + Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS, TemplateParams); DS.complete(TheDecl); return; } ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext); VirtSpecifiers VS; + ExprResult Init; if (Tok.isNot(tok::colon)) { // Don't parse FOO:BAR as if it were a typo for FOO::BAR. @@ -1575,10 +1719,36 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // If attributes exist after the declarator, but before an '{', parse them. MaybeParseGNUAttributes(DeclaratorInfo); + // MSVC permits pure specifier on inline functions declared at class scope. + // Hence check for =0 before checking for function definition. + if (getLang().Microsoft && Tok.is(tok::equal) && + DeclaratorInfo.isFunctionDeclarator() && + NextToken().is(tok::numeric_constant)) { + ConsumeToken(); + Init = ParseInitializer(); + if (Init.isInvalid()) + SkipUntil(tok::comma, true, true); + } + + bool IsDefinition = false; // function-definition: - if (Tok.is(tok::l_brace) - || (DeclaratorInfo.isFunctionDeclarator() && - (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) { + // + // In C++11, a non-function declarator followed by an open brace is a + // braced-init-list for an in-class member initialization, not an + // erroneous function definition. + if (Tok.is(tok::l_brace) && !getLang().CPlusPlus0x) { + IsDefinition = true; + } else if (DeclaratorInfo.isFunctionDeclarator()) { + if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) { + IsDefinition = true; + } else if (Tok.is(tok::equal)) { + const Token &KW = NextToken(); + if (KW.is(tok::kw_default) || KW.is(tok::kw_delete)) + IsDefinition = true; + } + } + + if (IsDefinition) { if (!DeclaratorInfo.isFunctionDeclarator()) { Diag(Tok, diag::err_func_def_no_params); ConsumeBrace(); @@ -1604,10 +1774,12 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return; } - ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS); - // Consume the optional ';' - if (Tok.is(tok::semi)) + ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS, Init); + + // Consume the ';' - it's optional unless we have a delete or default + if (Tok.is(tok::semi)) { ConsumeToken(); + } return; } @@ -1619,13 +1791,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, llvm::SmallVector<Decl *, 8> DeclsInGroup; ExprResult BitfieldSize; - ExprResult Init; - bool Deleted = false; while (1) { // member-declarator: // declarator pure-specifier[opt] - // declarator constant-initializer[opt] + // declarator brace-or-equal-initializer[opt] // identifier[opt] ':' constant-expression if (Tok.is(tok::colon)) { ConsumeToken(); @@ -1634,31 +1804,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SkipUntil(tok::comma, true, true); } - ParseOptionalCXX0XVirtSpecifierSeq(VS); - - // pure-specifier: - // '= 0' - // - // constant-initializer: - // '=' constant-expression - // - // defaulted/deleted function-definition: - // '=' 'default' [TODO] - // '=' 'delete' - if (Tok.is(tok::equal)) { - ConsumeToken(); - if (Tok.is(tok::kw_delete)) { - if (!getLang().CPlusPlus0x) - Diag(Tok, diag::warn_deleted_function_accepted_as_extension); - ConsumeToken(); - Deleted = true; - } else { - Init = ParseInitializer(); - if (Init.isInvalid()) - SkipUntil(tok::comma, true, true); - } - } - // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { SourceLocation Loc; @@ -1673,6 +1818,30 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // If attributes exist after the declarator, parse them. MaybeParseGNUAttributes(DeclaratorInfo); + // FIXME: When g++ adds support for this, we'll need to check whether it + // goes before or after the GNU attributes and __asm__. + ParseOptionalCXX0XVirtSpecifierSeq(VS); + + bool HasDeferredInitializer = false; + if (Tok.is(tok::equal) || Tok.is(tok::l_brace)) { + if (BitfieldSize.get()) { + Diag(Tok, diag::err_bitfield_member_init); + SkipUntil(tok::comma, true, true); + } else { + HasDeferredInitializer = !DeclaratorInfo.isFunctionDeclarator() && + DeclaratorInfo.getDeclSpec().getStorageClassSpec() + != DeclSpec::SCS_static; + + if (!HasDeferredInitializer) { + SourceLocation EqualLoc; + Init = ParseCXXMemberInitializer( + DeclaratorInfo.isFunctionDeclarator(), EqualLoc); + if (Init.isInvalid()) + SkipUntil(tok::comma, true, true); + } + } + } + // NOTE: If Sema is the Action module and declarator is an instance field, // this call will *not* return the created decl; It will return null. // See Sema::ActOnCXXMemberDeclarator for details. @@ -1689,8 +1858,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, move(TemplateParams), BitfieldSize.release(), VS, Init.release(), - /*IsDefinition*/Deleted, - Deleted); + HasDeferredInitializer, + /*IsDefinition*/ false); } if (ThisDecl) DeclsInGroup.push_back(ThisDecl); @@ -1703,6 +1872,24 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DeclaratorInfo.complete(ThisDecl); + if (HasDeferredInitializer) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_nonstatic_member_init_accepted_as_extension); + + if (DeclaratorInfo.isArrayOfUnknownBound()) { + // C++0x [dcl.array]p3: An array bound may also be omitted when the + // declarator is followed by an initializer. + // + // A brace-or-equal-initializer for a member-declarator is not an + // initializer in the gramamr, so this is ill-formed. + Diag(Tok, diag::err_incomplete_array_member_init); + SkipUntil(tok::comma, true, true); + // Avoid later warnings about a class member of incomplete type. + ThisDecl->setInvalidDecl(); + } else + ParseCXXNonStaticMemberInitializer(ThisDecl); + } + // If we don't have a comma, it is either the end of the list (a ';') // or an error, bail out. if (Tok.isNot(tok::comma)) @@ -1716,7 +1903,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, VS.clear(); BitfieldSize = 0; Init = 0; - Deleted = false; // Attributes are only allowed on the second declarator. MaybeParseGNUAttributes(DeclaratorInfo); @@ -1737,6 +1923,66 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, DeclsInGroup.size()); } +/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer or +/// pure-specifier. Also detect and reject any attempted defaulted/deleted +/// function definition. The location of the '=', if any, will be placed in +/// EqualLoc. +/// +/// pure-specifier: +/// '= 0' +/// +/// brace-or-equal-initializer: +/// '=' initializer-expression +/// braced-init-list [TODO] +/// +/// initializer-clause: +/// assignment-expression +/// braced-init-list [TODO] +/// +/// defaulted/deleted function-definition: +/// '=' 'default' +/// '=' 'delete' +/// +/// Prior to C++0x, the assignment-expression in an initializer-clause must +/// be a constant-expression. +ExprResult Parser::ParseCXXMemberInitializer(bool IsFunction, + SourceLocation &EqualLoc) { + assert((Tok.is(tok::equal) || Tok.is(tok::l_brace)) + && "Data member initializer not starting with '=' or '{'"); + + if (Tok.is(tok::equal)) { + EqualLoc = ConsumeToken(); + if (Tok.is(tok::kw_delete)) { + // In principle, an initializer of '= delete p;' is legal, but it will + // never type-check. It's better to diagnose it as an ill-formed expression + // than as an ill-formed deleted non-function member. + // An initializer of '= delete p, foo' will never be parsed, because + // a top-level comma always ends the initializer expression. + const Token &Next = NextToken(); + if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) || + Next.is(tok::eof)) { + if (IsFunction) + Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) + << 1 /* delete */; + else + Diag(ConsumeToken(), diag::err_deleted_non_function); + return ExprResult(); + } + } else if (Tok.is(tok::kw_default)) { + Diag(ConsumeToken(), diag::err_default_special_members); + if (IsFunction) + Diag(Tok, diag::err_default_delete_in_multiple_declaration) + << 0 /* default */; + else + Diag(ConsumeToken(), diag::err_default_special_members); + return ExprResult(); + } + + return ParseInitializer(); + } else + return ExprError(Diag(Tok, diag::err_generalized_initializer_lists)); +} + /// ParseCXXMemberSpecification - Parse the class definition. /// /// member-specification: @@ -1839,6 +2085,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // Each iteration of this loop reads one member-declaration. + if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) || + Tok.is(tok::kw___if_not_exists))) { + ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); + continue; + } + // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { Diag(Tok, diag::ext_extra_struct_semi) @@ -1882,19 +2134,20 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, LBraceLoc, RBraceLoc, attrs.getList()); - // C++ 9.2p2: Within the class member-specification, the class is regarded as - // complete within function bodies, default arguments, - // exception-specifications, and constructor ctor-initializers (including - // such things in nested classes). + // C++0x [class.mem]p2: Within the class member-specification, the class is + // regarded as complete within function bodies, default arguments, exception- + // specifications, and brace-or-equal-initializers for non-static data + // members (including such things in nested classes). // - // FIXME: Only function bodies and constructor ctor-initializers are - // parsed correctly, fix the rest. + // FIXME: Only function bodies and brace-or-equal-initializers are currently + // handled. Fix the others! if (TagDecl && NonNestedClass) { // We are not inside a nested class. This class and its nested classes // are complete and we can parse the delayed portions of method // declarations and the lexed inline method definitions. SourceLocation SavedPrevTokLocation = PrevTokLocation; ParseLexedMethodDeclarations(getCurrentClass()); + ParseLexedMemberInitializers(getCurrentClass()); ParseLexedMethodDefs(getCurrentClass()); PrevTokLocation = SavedPrevTokLocation; } @@ -1982,6 +2235,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { /// /// [C++] mem-initializer: /// mem-initializer-id '(' expression-list[opt] ')' +/// [C++0x] mem-initializer-id braced-init-list /// /// [C++] mem-initializer-id: /// '::'[opt] nested-name-specifier[opt] class-name @@ -2012,31 +2266,37 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { SourceLocation IdLoc = ConsumeToken(); // Parse the '('. - if (Tok.isNot(tok::l_paren)) { - Diag(Tok, diag::err_expected_lparen); + if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { + // FIXME: Do something with the braced-init-list. + ParseBraceInitializer(); return true; - } - SourceLocation LParenLoc = ConsumeParen(); + } else if(Tok.is(tok::l_paren)) { + SourceLocation LParenLoc = ConsumeParen(); - // Parse the optional expression-list. - ExprVector ArgExprs(Actions); - CommaLocsTy CommaLocs; - if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { - SkipUntil(tok::r_paren); - return true; - } + // Parse the optional expression-list. + ExprVector ArgExprs(Actions); + CommaLocsTy CommaLocs; + if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { + SkipUntil(tok::r_paren); + return true; + } - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - SourceLocation EllipsisLoc; - if (Tok.is(tok::ellipsis)) - EllipsisLoc = ConsumeToken(); - - return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, - TemplateTypeTy, IdLoc, - LParenLoc, ArgExprs.take(), - ArgExprs.size(), RParenLoc, - EllipsisLoc); + SourceLocation EllipsisLoc; + if (Tok.is(tok::ellipsis)) + EllipsisLoc = ConsumeToken(); + + return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, + TemplateTypeTy, IdLoc, + LParenLoc, ArgExprs.take(), + ArgExprs.size(), RParenLoc, + EllipsisLoc); + } + + Diag(Tok, getLang().CPlusPlus0x ? diag::err_expected_lparen_or_lbrace + : diag::err_expected_lparen); + return true; } /// \brief Parse a C++ exception-specification if present (C++0x [except.spec]). @@ -2438,3 +2698,64 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs, ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); } } + +void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, + AccessSpecifier& CurAS) { + bool Result; + if (ParseMicrosoftIfExistsCondition(Result)) + return; + + if (Tok.isNot(tok::l_brace)) { + Diag(Tok, diag::err_expected_lbrace); + return; + } + ConsumeBrace(); + + // Condition is false skip all inside the {}. + if (!Result) { + SkipUntil(tok::r_brace, false); + return; + } + + // Condition is true, parse the declaration. + while (Tok.isNot(tok::r_brace)) { + + // __if_exists, __if_not_exists can nest. + if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { + ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); + continue; + } + + // Check for extraneous top-level semicolon. + if (Tok.is(tok::semi)) { + Diag(Tok, diag::ext_extra_struct_semi) + << DeclSpec::getSpecifierName((DeclSpec::TST)TagType) + << FixItHint::CreateRemoval(Tok.getLocation()); + ConsumeToken(); + continue; + } + + AccessSpecifier AS = getAccessSpecifierIfPresent(); + if (AS != AS_none) { + // Current token is a C++ access specifier. + CurAS = AS; + SourceLocation ASLoc = Tok.getLocation(); + ConsumeToken(); + if (Tok.is(tok::colon)) + Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); + else + Diag(Tok, diag::err_expected_colon); + ConsumeToken(); + continue; + } + + // Parse all the comma separated declarators. + ParseCXXClassMemberDeclaration(CurAS); + } + + if (Tok.isNot(tok::r_brace)) { + Diag(Tok, diag::err_expected_rbrace); + return; + } + ConsumeBrace(); +} diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp index 91fe1e1..4e94ed9 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExpr.cpp @@ -480,7 +480,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// [OBJC] '@encode' '(' type-name ')' /// [OBJC] objc-string-literal /// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] +/// [C++0x] simple-type-specifier braced-init-list [C++ 5.2.3] /// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3] +/// [C++0x] typename-specifier braced-init-list [C++ 5.2.3] /// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] @@ -566,6 +568,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// '__is_trivial' /// '__is_union' /// +/// [Clang] unary-type-trait: +/// '__trivially_copyable' +/// /// binary-type-trait: /// [GNU] '__is_base_of' /// [MS] '__is_convertible_to' @@ -782,6 +787,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___builtin_va_arg: case tok::kw___builtin_offsetof: case tok::kw___builtin_choose_expr: + case tok::kw___builtin_astype: // primary-expression: [OCL] as_type() return ParseBuiltinPrimaryExpression(); case tok::kw___null: return Actions.ActOnGNUNullExpr(ConsumeToken()); @@ -919,15 +925,18 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (SavedKind == tok::kw_typename) { // postfix-expression: typename-specifier '(' expression-list[opt] ')' + // typename-specifier braced-init-list if (TryAnnotateTypeOrScopeToken()) return ExprError(); } // postfix-expression: simple-type-specifier '(' expression-list[opt] ')' + // simple-type-specifier braced-init-list // DeclSpec DS(AttrFactory); ParseCXXSimpleTypeSpecifier(DS); - if (Tok.isNot(tok::l_paren)) + if (Tok.isNot(tok::l_paren) && + (!getLang().CPlusPlus0x || Tok.isNot(tok::l_brace))) return ExprError(Diag(Tok, diag::err_expected_lparen_after_type) << DS.getSourceRange()); @@ -1060,6 +1069,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___is_pod: case tok::kw___is_polymorphic: case tok::kw___is_trivial: + case tok::kw___is_trivially_copyable: case tok::kw___is_union: case tok::kw___has_trivial_constructor: case tok::kw___has_trivial_copy: @@ -1117,6 +1127,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// postfix-expression: [C99 6.5.2] /// primary-expression /// postfix-expression '[' expression ']' +/// postfix-expression '[' braced-init-list ']' /// postfix-expression '(' argument-expression-list[opt] ')' /// postfix-expression '.' identifier /// postfix-expression '->' identifier @@ -1172,7 +1183,11 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { return move(LHS); Loc = ConsumeBracket(); - ExprResult Idx(ParseExpression()); + ExprResult Idx; + if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) + Idx = ParseBraceInitializer(); + else + Idx = ParseExpression(); SourceLocation RLoc = Tok.getLocation(); @@ -1529,6 +1544,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { /// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ',' /// assign-expr ')' /// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')' +/// [OCL] '__builtin_astype' '(' type-name expr ')' /// /// [GNU] offsetof-member-designator: /// [GNU] identifier @@ -1673,7 +1689,35 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { Expr2.take(), ConsumeParen()); break; } + case tok::kw___builtin_astype: { + // The first argument is an expression to be converted, followed by a comma. + ExprResult Expr(ParseAssignmentExpression()); + if (Expr.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", + tok::r_paren)) + return ExprError(); + + // Second argument is the type to bitcast to. + TypeResult DestTy = ParseTypeName(); + if (DestTy.isInvalid()) + return ExprError(); + + // Attempt to consume the r-paren. + if (Tok.isNot(tok::r_paren)) { + Diag(Tok, diag::err_expected_rparen); + SkipUntil(tok::r_paren); + return ExprError(); + } + + Res = Actions.ActOnAsTypeExpr(Expr.take(), DestTy.get(), StartLoc, + ConsumeParen()); + break; } +} if (Res.isInvalid()) return ExprError(); @@ -1987,8 +2031,19 @@ ExprResult Parser::ParseGenericSelectionExpression() { /// argument-expression-list , assignment-expression /// /// [C++] expression-list: -/// [C++] assignment-expression ...[opt] -/// [C++] expression-list , assignment-expression ...[opt] +/// [C++] assignment-expression +/// [C++] expression-list , assignment-expression +/// +/// [C++0x] expression-list: +/// [C++0x] initializer-list +/// +/// [C++0x] initializer-list +/// [C++0x] initializer-clause ...[opt] +/// [C++0x] initializer-list , initializer-clause ...[opt] +/// +/// [C++0x] initializer-clause: +/// [C++0x] assignment-expression +/// [C++0x] braced-init-list /// bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs, llvm::SmallVectorImpl<SourceLocation> &CommaLocs, @@ -2005,8 +2060,13 @@ bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs, Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); ConsumeCodeCompletionToken(); } - - ExprResult Expr(ParseAssignmentExpression()); + + ExprResult Expr; + if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) + Expr = ParseBraceInitializer(); + else + Expr = ParseAssignmentExpression(); + if (Tok.is(tok::ellipsis)) Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken()); if (Expr.isInvalid()) diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp index 8bf6f63..eab7114 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseExprCXX.cpp @@ -280,8 +280,11 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, : TemplateId->TemplateNameLoc; SS.SetInvalid(SourceRange(StartLoc, CCLoc)); } - - TemplateId->Destroy(); + + // If we are caching tokens we will process the TemplateId again, + // otherwise destroy it. + if (!PP.isBacktrackEnabled()) + TemplateId->Destroy(); continue; } @@ -806,42 +809,55 @@ ExprResult Parser::ParseCXXThis() { /// Can be interpreted either as function-style casting ("int(x)") /// or class type construction ("ClassType(x,y,z)") /// or creation of a value-initialized type ("int()"). +/// See [C++ 5.2.3]. /// /// postfix-expression: [C++ 5.2p1] -/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] -/// typename-specifier '(' expression-list[opt] ')' [TODO] +/// simple-type-specifier '(' expression-list[opt] ')' +/// [C++0x] simple-type-specifier braced-init-list +/// typename-specifier '(' expression-list[opt] ')' +/// [C++0x] typename-specifier braced-init-list /// ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); - assert(Tok.is(tok::l_paren) && "Expected '('!"); - GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); + assert((Tok.is(tok::l_paren) || + (getLang().CPlusPlus0x && Tok.is(tok::l_brace))) + && "Expected '(' or '{'!"); - SourceLocation LParenLoc = ConsumeParen(); + if (Tok.is(tok::l_brace)) { - ExprVector Exprs(Actions); - CommaLocsTy CommaLocs; + // FIXME: Convert to a proper type construct expression. + return ParseBraceInitializer(); - if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(Exprs, CommaLocs)) { - SkipUntil(tok::r_paren); - return ExprError(); + } else { + GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); + + SourceLocation LParenLoc = ConsumeParen(); + + ExprVector Exprs(Actions); + CommaLocsTy CommaLocs; + + if (Tok.isNot(tok::r_paren)) { + if (ParseExpressionList(Exprs, CommaLocs)) { + SkipUntil(tok::r_paren); + return ExprError(); + } } - } - // Match the ')'. - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + // Match the ')'. + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - // TypeRep could be null, if it references an invalid typedef. - if (!TypeRep) - return ExprError(); + // TypeRep could be null, if it references an invalid typedef. + if (!TypeRep) + return ExprError(); - assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& - "Unexpected number of commas!"); - return Actions.ActOnCXXTypeConstructExpr(TypeRep, LParenLoc, move_arg(Exprs), - RParenLoc); + assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& + "Unexpected number of commas!"); + return Actions.ActOnCXXTypeConstructExpr(TypeRep, LParenLoc, move_arg(Exprs), + RParenLoc); + } } /// ParseCXXCondition - if/switch/while condition expression. @@ -959,6 +975,7 @@ bool Parser::isCXXSimpleTypeSpecifier() const { case tok::kw_bool: case tok::kw_decltype: case tok::kw_typeof: + case tok::kw___underlying_type: return true; default: @@ -1723,7 +1740,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, /// /// new-initializer: /// '(' expression-list[opt] ')' -/// [C++0x] braced-init-list [TODO] +/// [C++0x] braced-init-list /// ExprResult Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { @@ -1812,6 +1829,9 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true); return ExprError(); } + } else if (Tok.is(tok::l_brace)) { + // FIXME: Have to communicate the init-list to ActOnCXXNew. + ParseBraceInitializer(); } return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen, @@ -1921,7 +1941,8 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign; - case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor; + case tok::kw___has_trivial_constructor: + return UTT_HasTrivialDefaultConstructor; case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy; case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor; case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor; @@ -1954,6 +1975,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { case tok::kw___is_signed: return UTT_IsSigned; case tok::kw___is_standard_layout: return UTT_IsStandardLayout; case tok::kw___is_trivial: return UTT_IsTrivial; + case tok::kw___is_trivially_copyable: return UTT_IsTriviallyCopyable; case tok::kw___is_union: return UTT_IsUnion; case tok::kw___is_unsigned: return UTT_IsUnsigned; case tok::kw___is_void: return UTT_IsVoid; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp index fdbedc5..a8c18c0 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseObjc.cpp @@ -874,8 +874,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); Decl *Result = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, IDecl, DSRet, ReturnType, Sel, - 0, + mType, IDecl, DSRet, ReturnType, + selLoc, Sel, 0, CParamInfo.data(), CParamInfo.size(), methodAttrs.getList(), MethodImplKind, false, MethodDefinition); @@ -1000,8 +1000,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, &KeyIdents[0]); Decl *Result = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, IDecl, DSRet, ReturnType, Sel, - &ArgInfos[0], + mType, IDecl, DSRet, ReturnType, + selLoc, Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs.getList(), MethodImplKind, isVariadic, MethodDefinition); diff --git a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp index 46225c8..c30ab75 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParsePragma.cpp @@ -295,7 +295,6 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; return; } - SourceLocation LParenLoc = Tok.getLocation(); // Lex the declaration reference(s). llvm::SmallVector<Token, 5> Identifiers; diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index f0ab531..6cc8b57 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -741,6 +741,12 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { continue; } + if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) || + Tok.is(tok::kw___if_not_exists))) { + ParseMicrosoftIfExistsStatement(Stmts); + continue; + } + StmtResult R; if (Tok.isNot(tok::kw___extension__)) { R = ParseStatementOrDeclaration(Stmts, false); @@ -2000,3 +2006,34 @@ StmtResult Parser::ParseCXXCatchBlock() { return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take()); } + +void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { + bool Result; + if (ParseMicrosoftIfExistsCondition(Result)) + return; + + if (Tok.isNot(tok::l_brace)) { + Diag(Tok, diag::err_expected_lbrace); + return; + } + ConsumeBrace(); + + // Condition is false skip all inside the {}. + if (!Result) { + SkipUntil(tok::r_brace, false); + return; + } + + // Condition is true, parse the statements. + while (Tok.isNot(tok::r_brace)) { + StmtResult R = ParseStatementOrDeclaration(Stmts, false); + if (R.isUsable()) + Stmts.push_back(R.release()); + } + + if (Tok.isNot(tok::r_brace)) { + Diag(Tok, diag::err_expected_rbrace); + return; + } + ConsumeBrace(); +} diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp index 12e38da..aa89d75 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTemplate.cpp @@ -905,10 +905,10 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { // C++0x [temp.arg.template]p1: // A template-argument for a template template-parameter shall be the name - // of a class template or a template alias, expressed as id-expression. + // of a class template or an alias template, expressed as id-expression. // - // We parse an id-expression that refers to a class template or template - // alias. The grammar we parse is: + // We parse an id-expression that refers to a class template or alias + // template. The grammar we parse is: // // nested-name-specifier[opt] template[opt] identifier ...[opt] // @@ -969,7 +969,7 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { MemberOfUnknownSpecialization); if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) { // We have an id-expression that refers to a class template or - // (C++0x) template alias. + // (C++0x) alias template. Result = ParsedTemplateArgument(SS, Template, Name.StartLocation); } } diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp index 1c4e2b3..78d2c90 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseTentative.cpp @@ -664,6 +664,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___is_pod: case tok::kw___is_polymorphic: case tok::kw___is_trivial: + case tok::kw___is_trivially_copyable: case tok::kw___is_union: case tok::kw___uuidof: return TPResult::True(); @@ -693,6 +694,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw_decltype: + case tok::kw___underlying_type: case tok::kw_thread_local: case tok::kw__Decimal32: case tok::kw__Decimal64: @@ -1011,6 +1013,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { case tok::kw_decltype: return TPResult::True(); + // C++0x type traits support + case tok::kw___underlying_type: + return TPResult::True(); + default: return TPResult::False(); } diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 4d08699..f19472c 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -20,6 +20,7 @@ #include "RAIIObjectsForParser.h" #include "ParsePragma.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/ASTConsumer.h" using namespace clang; Parser::Parser(Preprocessor &pp, Sema &actions) @@ -350,7 +351,23 @@ void Parser::ExitScope() { ScopeCache[NumCachedScopes++] = OldScope; } +/// Set the flags for the current scope to ScopeFlags. If ManageFlags is false, +/// this object does nothing. +Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags, + bool ManageFlags) + : CurScope(ManageFlags ? Self->getCurScope() : 0) { + if (CurScope) { + OldFlags = CurScope->getFlags(); + CurScope->setFlags(ScopeFlags); + } +} +/// Restore the flags for the current scope to what they were before this +/// object overrode them. +Parser::ParseScopeFlags::~ParseScopeFlags() { + if (CurScope) + CurScope->setFlags(OldFlags); +} //===----------------------------------------------------------------------===// @@ -653,6 +670,11 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // FIXME: Detect C++ linkage specifications here? goto dont_know; + case tok::kw___if_exists: + case tok::kw___if_not_exists: + ParseMicrosoftIfExistsExternalDeclaration(); + return DeclGroupPtrTy(); + default: dont_know: // We can't tell whether this is a function-definition or declaration yet. @@ -671,7 +693,14 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, /// \brief Determine whether the current token, if it occurs after a /// declarator, continues a declaration or declaration list. -bool Parser::isDeclarationAfterDeclarator() const { +bool Parser::isDeclarationAfterDeclarator() { + // Check for '= delete' or '= default' + if (getLang().CPlusPlus && Tok.is(tok::equal)) { + const Token &KW = NextToken(); + if (KW.is(tok::kw_default) || KW.is(tok::kw_delete)) + return false; + } + return Tok.is(tok::equal) || // int X()= -> not a function def Tok.is(tok::comma) || // int X(), -> not a function def Tok.is(tok::semi) || // int X(); -> not a function def @@ -692,6 +721,11 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { if (!getLang().CPlusPlus && Declarator.getFunctionTypeInfo().isKNRPrototype()) return isDeclarationSpecifier(); + + if (getLang().CPlusPlus && Tok.is(tok::equal)) { + const Token &KW = NextToken(); + return KW.is(tok::kw_default) || KW.is(tok::kw_delete); + } return Tok.is(tok::colon) || // X() : Base() {} (used for ctors) Tok.is(tok::kw_try); // X() try { ... } @@ -814,11 +848,13 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (FTI.isKNRPrototype()) ParseKNRParamDeclarations(D); + // We should have either an opening brace or, in a C++ constructor, // we may have a colon. if (Tok.isNot(tok::l_brace) && (!getLang().CPlusPlus || - (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try)))) { + (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try) && + Tok.isNot(tok::equal)))) { Diag(Tok, diag::err_expected_fn_body); // Skip over garbage, until we get to '{'. Don't eat the '{'. @@ -866,7 +902,6 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, return DP; } - // Enter a scope for the function body. ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); @@ -887,6 +922,43 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // safe because we're always the sole owner. D.getMutableDeclSpec().abort(); + if (Tok.is(tok::equal)) { + assert(getLang().CPlusPlus && "Only C++ function definitions have '='"); + ConsumeToken(); + + Actions.ActOnFinishFunctionBody(Res, 0, false); + + bool Delete = false; + SourceLocation KWLoc; + if (Tok.is(tok::kw_delete)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_deleted_function_accepted_as_extension); + + KWLoc = ConsumeToken(); + Actions.SetDeclDeleted(Res, KWLoc); + Delete = true; + } else if (Tok.is(tok::kw_default)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::warn_defaulted_function_accepted_as_extension); + + KWLoc = ConsumeToken(); + Actions.SetDeclDefaulted(Res, KWLoc); + } else { + llvm_unreachable("function definition after = not 'delete' or 'default'"); + } + + if (Tok.is(tok::comma)) { + Diag(KWLoc, diag::err_default_delete_in_multiple_declaration) + << Delete; + SkipUntil(tok::semi); + } else { + ExpectAndConsume(tok::semi, diag::err_expected_semi_after, + Delete ? "delete" : "default", tok::semi); + } + + return Res; + } + if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res, BodyScope); @@ -1374,3 +1446,80 @@ void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro, void Parser::CodeCompleteNaturalLanguage() { Actions.CodeCompleteNaturalLanguage(); } + +bool Parser::ParseMicrosoftIfExistsCondition(bool& Result) { + assert((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists)) && + "Expected '__if_exists' or '__if_not_exists'"); + Token Condition = Tok; + SourceLocation IfExistsLoc = ConsumeToken(); + + SourceLocation LParenLoc = Tok.getLocation(); + if (Tok.isNot(tok::l_paren)) { + Diag(Tok, diag::err_expected_lparen_after) << IfExistsLoc; + SkipUntil(tok::semi); + return true; + } + ConsumeParen(); // eat the '('. + + // Parse nested-name-specifier. + CXXScopeSpec SS; + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false); + + // Check nested-name specifier. + if (SS.isInvalid()) { + SkipUntil(tok::semi); + return true; + } + + // Parse the unqualified-id. + UnqualifiedId Name; + if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) { + SkipUntil(tok::semi); + return true; + } + + if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid()) + return true; + + // Check if the symbol exists. + bool Exist = Actions.CheckMicrosoftIfExistsSymbol(SS, Name); + + Result = ((Condition.is(tok::kw___if_exists) && Exist) || + (Condition.is(tok::kw___if_not_exists) && !Exist)); + + return false; +} + +void Parser::ParseMicrosoftIfExistsExternalDeclaration() { + bool Result; + if (ParseMicrosoftIfExistsCondition(Result)) + return; + + if (Tok.isNot(tok::l_brace)) { + Diag(Tok, diag::err_expected_lbrace); + return; + } + ConsumeBrace(); + + // Condition is false skip all inside the {}. + if (!Result) { + SkipUntil(tok::r_brace, false); + return; + } + + // Condition is true, parse the declaration. + while (Tok.isNot(tok::r_brace)) { + ParsedAttributesWithRange attrs(AttrFactory); + MaybeParseCXX0XAttributes(attrs); + MaybeParseMicrosoftAttributes(attrs); + DeclGroupPtrTy Result = ParseExternalDeclaration(attrs); + if (Result && !getCurScope()->getParent()) + Actions.getASTConsumer().HandleTopLevelDecl(Result.get()); + } + + if (Tok.isNot(tok::r_brace)) { + Diag(Tok, diag::err_expected_rbrace); + return; + } + ConsumeBrace(); +} |