aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/MinimalAction.cpp5
-rw-r--r--lib/Parse/ParseDecl.cpp9
-rw-r--r--lib/Parse/ParseDeclCXX.cpp13
-rw-r--r--lib/Parse/ParseExpr.cpp17
-rw-r--r--lib/Parse/ParseExprCXX.cpp52
-rw-r--r--lib/Parse/Parser.cpp13
6 files changed, 69 insertions, 40 deletions
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index ee23c0038a..d89cc8c3ea 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -160,8 +160,11 @@ bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *,
}
TemplateNameKind
-MinimalAction::isTemplateName(const IdentifierInfo &II, Scope *S,
+MinimalAction::isTemplateName(Scope *S,
+ const IdentifierInfo &II,
+ SourceLocation IdLoc,
const CXXScopeSpec *SS,
+ TypeTy *ObjectType,
bool EnteringScope,
TemplateTy &TemplateDecl) {
return TNK_Non_template;
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 25bed0937b..25ff53ca9f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -743,7 +743,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
->Kind == TNK_Type_template) {
// We have a qualified template-id, e.g., N::A<int>
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, true);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
assert(Tok.is(tok::annot_template_id) &&
"ParseOptionalCXXScopeSpecifier not working");
AnnotateTemplateIdTokenAsType(&SS);
@@ -1596,7 +1596,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
Attr = ParseAttributes();
CXXScopeSpec SS;
- if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS)) {
+ if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) {
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
if (Tok.isNot(tok::l_brace)) {
@@ -2034,7 +2034,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
(Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
Tok.is(tok::annot_cxxscope))) {
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, true)) {
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) {
if(Tok.isNot(tok::star)) {
// The scope spec really belongs to the direct-declarator.
D.getCXXScopeSpec() = SS;
@@ -2191,7 +2191,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
if (D.mayHaveIdentifier()) {
// ParseDeclaratorInternal might already have parsed the scope.
bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
- ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), true);
+ ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
+ true);
if (afterCXXScope) {
// Change the declaration context for name lookup, until this function
// is exited (and the declarator has been parsed).
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 31926ce0f5..f50147c599 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -117,7 +117,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_namespace_name);
@@ -216,7 +216,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
AttributeList *AttrList = 0;
IdentifierInfo *NamespcName = 0;
@@ -273,7 +273,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
IsTypeName = false;
// Parse nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
AttributeList *AttrList = 0;
@@ -538,7 +538,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Parse the (optional) nested-name-specifier.
CXXScopeSpec SS;
- if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, true))
+ if (getLang().CPlusPlus &&
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
Diag(Tok, diag::err_expected_ident);
@@ -813,7 +814,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
// Parse optional '::' and optional nested-name-specifier.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, true);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
// The location of the base class itself.
SourceLocation BaseLoc = Tok.getLocation();
@@ -1299,7 +1300,7 @@ void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
// parse '::'[opt] nested-name-specifier[opt]
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
TypeTy *TemplateTypeTy = 0;
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 36b6dd4a93..8fca14ff98 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -923,14 +923,14 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
tok::TokenKind OpKind = Tok.getKind();
SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token.
- CXXScopeSpec MemberSS;
CXXScopeSpec SS;
+ Action::TypeTy *ObjectType = 0;
if (getLang().CPlusPlus && !LHS.isInvalid()) {
- LHS = Actions.ActOnCXXEnterMemberScope(CurScope, MemberSS, move(LHS),
- OpKind);
+ LHS = Actions.ActOnStartCXXMemberReference(CurScope, move(LHS),
+ OpLoc, OpKind, ObjectType);
if (LHS.isInvalid())
break;
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, ObjectType, false);
}
if (Tok.is(tok::identifier)) {
@@ -947,8 +947,6 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
ConsumeToken();
if (!Tok.is(tok::identifier)) {
- if (getLang().CPlusPlus)
- Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
Diag(Tok, diag::err_expected_ident);
return ExprError();
}
@@ -980,8 +978,6 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
Tok.getLocation(),
ConvType, &SS);
} else {
- if (getLang().CPlusPlus)
- Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
// Don't emit a diagnostic; ParseConversionFunctionId does it for us
return ExprError();
}
@@ -1007,14 +1003,9 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
}
ConsumeToken();
} else {
- if (getLang().CPlusPlus)
- Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
Diag(Tok, diag::err_expected_ident);
return ExprError();
}
-
- if (getLang().CPlusPlus)
- Actions.ActOnCXXExitMemberScope(CurScope, MemberSS);
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index e9cca9fe1d..4cd952e393 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -16,10 +16,11 @@
#include "clang/Parse/DeclSpec.h"
using namespace clang;
-/// ParseOptionalCXXScopeSpecifier - Parse global scope or
-/// nested-name-specifier if present. Returns true if a nested-name-specifier
-/// was parsed from the token stream. Note that this routine will not parse
-/// ::new or ::delete, it will just leave them in the token stream.
+/// \brief Parse global scope or nested-name-specifier if present.
+///
+/// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
+/// may be preceded by '::'). Note that this routine will not parse ::new or
+/// ::delete; it will just leave them in the token stream.
///
/// '::'[opt] nested-name-specifier
/// '::'
@@ -28,9 +29,22 @@ using namespace clang;
/// type-name '::'
/// namespace-name '::'
/// nested-name-specifier identifier '::'
-/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
+/// nested-name-specifier 'template'[opt] simple-template-id '::'
+///
+///
+/// \param SS the scope specifier that will be set to the parsed
+/// nested-name-specifier (or empty)
+///
+/// \param ObjectType if this nested-name-specifier is being parsed following
+/// the "." or "->" of a member access expression, this parameter provides the
+/// type of the object whose members are being accessed.
///
+/// \param EnteringContext whether we will be entering into the context of
+/// the nested-name-specifier after parsing it.
+///
+/// \returns true if a scope specifier was parsed.
bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
+ Action::TypeTy *ObjectType,
bool EnteringContext) {
assert(getLang().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
@@ -59,16 +73,28 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
}
while (true) {
+ if (HasScopeSpecifier) {
+ // C++ [basic.lookup.classref]p5:
+ // If the qualified-id has the form
+ // ::class-name-or-namespace-name::...
+ // the class-name-or-namespace-name is looked up in global scope as a
+ // class-name or namespace-name.
+ //
+ // To implement this, we clear out the object type as soon as we've
+ // seen a leading '::' or part of a nested-name-specifier.
+ ObjectType = 0;
+ }
+
// nested-name-specifier:
// nested-name-specifier 'template'[opt] simple-template-id '::'
// Parse the optional 'template' keyword, then make sure we have
// 'identifier <' after it.
if (Tok.is(tok::kw_template)) {
- // If we don't have a scope specifier, this isn't a
+ // If we don't have a scope specifier or an object type, this isn't a
// nested-name-specifier, since they aren't allowed to start with
// 'template'.
- if (!HasScopeSpecifier)
+ if (!HasScopeSpecifier && !ObjectType)
break;
SourceLocation TemplateKWLoc = ConsumeToken();
@@ -91,7 +117,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
TemplateTy Template
= Actions.ActOnDependentTemplateName(TemplateKWLoc,
*Tok.getIdentifierInfo(),
- Tok.getLocation(), SS);
+ Tok.getLocation(), SS,
+ ObjectType);
if (!Template)
break;
if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
@@ -173,7 +200,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
SS.setScopeRep(
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
- EnteringContext));
+ ObjectType, EnteringContext));
SS.setEndLoc(CCLoc);
continue;
}
@@ -182,7 +209,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// type-name '<'
if (Next.is(tok::less)) {
TemplateTy Template;
- if (TemplateNameKind TNK = Actions.isTemplateName(II, CurScope, &SS,
+ if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, II,
+ Tok.getLocation(),
+ &SS,
+ ObjectType,
EnteringContext,
Template)) {
// We have found a template name, so annotate this this token
@@ -267,7 +297,7 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
// '::' unqualified-id
//
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
// unqualified-id:
// identifier
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 4d37ac7202..36d5db599d 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -884,7 +884,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// simple-template-id
SourceLocation TypenameLoc = ConsumeToken();
CXXScopeSpec SS;
- bool HadNestedNameSpecifier = ParseOptionalCXXScopeSpecifier(SS, false);
+ bool HadNestedNameSpecifier
+ = ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
if (!HadNestedNameSpecifier) {
Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename);
return false;
@@ -928,7 +929,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
CXXScopeSpec SS;
if (getLang().CPlusPlus)
- ParseOptionalCXXScopeSpecifier(SS, EnteringContext);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext);
if (Tok.is(tok::identifier)) {
// Determine whether the identifier is a type name.
@@ -959,8 +960,10 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
if (NextToken().is(tok::less)) {
TemplateTy Template;
if (TemplateNameKind TNK
- = Actions.isTemplateName(*Tok.getIdentifierInfo(),
- CurScope, &SS, EnteringContext, Template))
+ = Actions.isTemplateName(CurScope, *Tok.getIdentifierInfo(),
+ Tok.getLocation(), &SS,
+ /*ObjectType=*/0, EnteringContext,
+ Template))
if (AnnotateTemplateIdToken(Template, TNK, &SS)) {
// If an unrecoverable error occurred, we need to return true here,
// because the token stream is in a damaged state. We may not return
@@ -1022,7 +1025,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
"Cannot be a type or scope token!");
CXXScopeSpec SS;
- if (!ParseOptionalCXXScopeSpecifier(SS, EnteringContext))
+ if (!ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
return Tok.is(tok::annot_template_id);
// Push the current token back into the token stream (or revert it if it is