aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/DeclSpec.cpp8
-rw-r--r--lib/Parse/MinimalAction.cpp6
-rw-r--r--lib/Parse/ParseDecl.cpp6
-rw-r--r--lib/Parse/ParseDeclCXX.cpp49
-rw-r--r--lib/Parse/ParseExprCXX.cpp135
-rw-r--r--lib/Parse/ParseTemplate.cpp9
-rw-r--r--lib/Parse/ParseTentative.cpp3
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: