diff options
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/DeclSpec.cpp | 8 | ||||
-rw-r--r-- | lib/Parse/MinimalAction.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 49 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 135 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 9 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 3 |
7 files changed, 38 insertions, 178 deletions
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index 3436900027e4..0a4e036e4399 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -334,6 +334,14 @@ bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, return false; } +bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'constexpr constexpr' is ok. + Constexpr_specified = true; + ConstexprLoc = Loc; + return false; +} + void DeclSpec::setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos, unsigned NP, SourceLocation *ProtoLocs, diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index 1e7d397fdf37..bf05b2baccd4 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -42,14 +42,12 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope, return DeclPtrTy(); } -// Defined out-of-line here because of dependecy on AttributeList +// Defined out-of-line here because of dependency on AttributeList Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, SourceLocation UsingLoc, const CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *TargetName, - OverloadedOperatorKind Op, + UnqualifiedId &Name, AttributeList *AttrList, bool IsTypeName) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index e905553fd818..99752b59507f 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -769,6 +769,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, /// [C++] 'virtual' /// [C++] 'explicit' /// 'friend': [C++ dcl.friend] +/// 'constexpr': [C++0x dcl.constexpr] /// void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, @@ -1070,6 +1071,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, } break; + // constexpr + case tok::kw_constexpr: + isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID); + break; + // type-specifier case tok::kw_short: isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 91f86864f81f..154c2923486e 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -285,6 +285,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, bool IsTypeName; // Ignore optional 'typename'. + // FIXME: This is wrong; we should parse this as a typename-specifier. if (Tok.is(tok::kw_typename)) { ConsumeToken(); IsTypeName = true; @@ -302,41 +303,21 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, SkipUntil(tok::semi); return DeclPtrTy(); } - if (Tok.is(tok::annot_template_id)) { - // C++0x N2914 [namespace.udecl]p5: - // A using-declaration shall not name a template-id. - Diag(Tok, diag::err_using_decl_can_not_refer_to_template_spec); - SkipUntil(tok::semi); - return DeclPtrTy(); - } - - IdentifierInfo *TargetName = 0; - OverloadedOperatorKind Op = OO_None; - SourceLocation IdentLoc; - if (Tok.is(tok::kw_operator)) { - IdentLoc = Tok.getLocation(); - - Op = TryParseOperatorFunctionId(); - if (!Op) { - // If there was an invalid operator, skip to end of decl, and eat ';'. - SkipUntil(tok::semi); - return DeclPtrTy(); - } - // FIXME: what about conversion functions? - } else if (Tok.is(tok::identifier)) { - // Parse identifier. - TargetName = Tok.getIdentifierInfo(); - IdentLoc = ConsumeToken(); - } else { - // FIXME: Use a better diagnostic here. - Diag(Tok, diag::err_expected_ident_in_using); - - // If there was invalid identifier, skip to end of decl, and eat ';'. + // Parse the unqualified-id. We allow parsing of both constructor and + // destructor names and allow the action module to diagnose any semantic + // errors. + UnqualifiedId Name; + if (ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/true, + /*AllowConstructorName=*/true, + /*ObjectType=*/0, + Name)) { SkipUntil(tok::semi); return DeclPtrTy(); } - + // Parse (optional) attributes (most likely GNU strong-using extension). if (Tok.is(tok::kw___attribute)) AttrList = ParseAttributes(); @@ -344,10 +325,10 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, // Eat ';'. DeclEnd = Tok.getLocation(); ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - AttrList ? "attributes list" : "namespace name", tok::semi); + AttrList ? "attributes list" : "using declaration", + tok::semi); - return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, - IdentLoc, TargetName, Op, + return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name, AttrList, IsTypeName); } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index a7ca0c54dbe6..a00dfb0b4c36 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1196,141 +1196,6 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, return true; } -/// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded -/// operator name (C++ [over.oper]). If successful, returns the -/// predefined identifier that corresponds to that overloaded -/// operator. Otherwise, returns NULL and does not consume any tokens. -/// -/// operator-function-id: [C++ 13.5] -/// 'operator' operator -/// -/// operator: one of -/// new delete new[] delete[] -/// + - * / % ^ & | ~ -/// ! = < > += -= *= /= %= -/// ^= &= |= << >> >>= <<= == != -/// <= >= && || ++ -- , ->* -> -/// () [] -OverloadedOperatorKind -Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) { - assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); - SourceLocation Loc; - - OverloadedOperatorKind Op = OO_None; - switch (NextToken().getKind()) { - case tok::kw_new: - ConsumeToken(); // 'operator' - Loc = ConsumeToken(); // 'new' - if (Tok.is(tok::l_square)) { - ConsumeBracket(); // '[' - Loc = Tok.getLocation(); - ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' - Op = OO_Array_New; - } else { - Op = OO_New; - } - if (EndLoc) - *EndLoc = Loc; - return Op; - - case tok::kw_delete: - ConsumeToken(); // 'operator' - Loc = ConsumeToken(); // 'delete' - if (Tok.is(tok::l_square)) { - ConsumeBracket(); // '[' - Loc = Tok.getLocation(); - ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' - Op = OO_Array_Delete; - } else { - Op = OO_Delete; - } - if (EndLoc) - *EndLoc = Loc; - return Op; - -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - case tok::Token: Op = OO_##Name; break; -#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) -#include "clang/Basic/OperatorKinds.def" - - case tok::l_paren: - ConsumeToken(); // 'operator' - ConsumeParen(); // '(' - Loc = Tok.getLocation(); - ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); // ')' - if (EndLoc) - *EndLoc = Loc; - return OO_Call; - - case tok::l_square: - ConsumeToken(); // 'operator' - ConsumeBracket(); // '[' - Loc = Tok.getLocation(); - ExpectAndConsume(tok::r_square, diag::err_expected_rsquare); // ']' - if (EndLoc) - *EndLoc = Loc; - return OO_Subscript; - - case tok::code_completion: { - // Code completion for the operator name. - Actions.CodeCompleteOperatorName(CurScope); - - // Consume the 'operator' token, then replace the code-completion token - // with an 'operator' token and try again. - SourceLocation OperatorLoc = ConsumeToken(); - Tok.setLocation(OperatorLoc); - Tok.setKind(tok::kw_operator); - return TryParseOperatorFunctionId(EndLoc); - } - - default: - return OO_None; - } - - ConsumeToken(); // 'operator' - Loc = ConsumeAnyToken(); // the operator itself - if (EndLoc) - *EndLoc = Loc; - return Op; -} - -/// ParseConversionFunctionId - Parse a C++ conversion-function-id, -/// which expresses the name of a user-defined conversion operator -/// (C++ [class.conv.fct]p1). Returns the type that this operator is -/// specifying a conversion for, or NULL if there was an error. -/// -/// conversion-function-id: [C++ 12.3.2] -/// operator conversion-type-id -/// -/// conversion-type-id: -/// type-specifier-seq conversion-declarator[opt] -/// -/// conversion-declarator: -/// ptr-operator conversion-declarator[opt] -Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) { - assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); - ConsumeToken(); // 'operator' - - // Parse the type-specifier-seq. - DeclSpec DS; - if (ParseCXXTypeSpecifierSeq(DS)) - return 0; - - // Parse the conversion-declarator, which is merely a sequence of - // ptr-operators. - Declarator D(DS, Declarator::TypeNameContext); - ParseDeclaratorInternal(D, /*DirectDeclParser=*/0); - if (EndLoc) - *EndLoc = D.getSourceRange().getEnd(); - - // Finish up the type. - Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D); - if (Result.isInvalid()) - return 0; - else - return Result.get(); -} - /// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate /// memory in a typesafe manner and call constructors. /// diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 045acd86ad0f..99578837c21c 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -809,12 +809,11 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get()); if (SS && SS->isNotEmpty()) // it was a C++ qualified type name. Tok.setLocation(SS->getBeginLoc()); + Tok.setAnnotationEndLoc(TemplateId->TemplateNameLoc); - // We might be backtracking, in which case we need to replace the - // template-id annotation token with the type annotation within the - // set of cached tokens. That way, we won't try to form the same - // class template specialization again. - PP.ReplaceLastTokenWithAnnotation(Tok); + // Replace the template-id annotation token, and possible the scope-specifier + // that precedes it, with the typename annotation token. + PP.AnnotateCachedTokens(Tok); TemplateId->Destroy(); } diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index eb6e93540566..7ac297710965 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -503,6 +503,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, /// function-specifier /// 'friend' /// 'typedef' +/// [C++0x] 'constexpr' /// [GNU] attributes declaration-specifiers[opt] /// /// storage-class-specifier: @@ -615,9 +616,11 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { // function-specifier // 'friend' // 'typedef' + // 'constexpr' case tok::kw_friend: case tok::kw_typedef: + case tok::kw_constexpr: // storage-class-specifier case tok::kw_register: case tok::kw_static: |