aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Parse/Parser.h1
-rw-r--r--lib/Parse/ParseDecl.cpp19
-rw-r--r--lib/Parse/ParseDeclCXX.cpp17
-rw-r--r--lib/Parse/ParseExpr.cpp6
-rw-r--r--lib/Parse/ParseExprCXX.cpp2
-rw-r--r--lib/Parse/Parser.cpp6
-rw-r--r--test/SemaTemplate/instantiate-member-class.cpp22
7 files changed, 56 insertions, 17 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 673b5df093..dba7ffb478 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1997,6 +1997,7 @@ private:
DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
AccessSpecifier AS = AS_none,
+ bool EnteringContext = false,
bool SuppressDeclarations = false);
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
Decl *TagDecl);
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 07a52586e9..3bddd3de13 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1652,6 +1652,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DS.SetRangeEnd(Tok.getLocation());
}
+ bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level);
while (1) {
bool isInvalid = false;
const char *PrevSpec = 0;
@@ -2208,7 +2209,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw_union: {
tok::TokenKind Kind = Tok.getKind();
ConsumeToken();
- ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS);
+ ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS, EnteringContext);
continue;
}
@@ -2500,6 +2501,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
tok::TokenKind Kind = Tok.getKind();
ConsumeToken();
ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS_none,
+ /*EnteringContext=*/false,
SuppressDeclarations);
return true;
}
@@ -2862,7 +2864,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// if a fixed underlying type is allowed.
ColonProtectionRAIIObject X(*this, AllowFixedUnderlyingType);
- if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false))
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
+ /*EnteringContext=*/false))
return;
if (SS.isSet() && Tok.isNot(tok::identifier)) {
@@ -3483,7 +3486,8 @@ bool Parser::isConstructorDeclarator() {
// Parse the C++ scope specifier.
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true)) {
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
+ /*EnteringContext=*/true)) {
TPA.Revert();
return false;
}
@@ -3681,8 +3685,10 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
if (getLang().CPlusPlus &&
(Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
Tok.is(tok::annot_cxxscope))) {
+ bool EnteringContext = D.getContext() == Declarator::FileContext ||
+ D.getContext() == Declarator::MemberContext;
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true); // ignore fail
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext);
if (SS.isNotEmpty()) {
if (Tok.isNot(tok::star)) {
@@ -3848,7 +3854,10 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
// ParseDeclaratorInternal might already have parsed the scope.
if (D.getCXXScopeSpec().isEmpty()) {
- ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), ParsedType(), true);
+ bool EnteringContext = D.getContext() == Declarator::FileContext ||
+ D.getContext() == Declarator::MemberContext;
+ ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), ParsedType(),
+ EnteringContext);
}
if (D.getCXXScopeSpec().isValid()) {
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 1ba1cbfbd6..721d185f53 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -234,7 +234,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_namespace_name);
@@ -382,7 +382,7 @@ Decl *Parser::ParseUsingDirective(unsigned Context,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
IdentifierInfo *NamespcName = 0;
SourceLocation IdentLoc = SourceLocation();
@@ -450,7 +450,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
IsTypeName = false;
// Parse nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
// Check nested-name specifier.
if (SS.isInvalid()) {
@@ -876,7 +876,9 @@ Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
SourceLocation StartLoc, DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo,
- AccessSpecifier AS, bool SuppressDeclarations){
+ AccessSpecifier AS,
+ bool EnteringContext,
+ bool SuppressDeclarations){
DeclSpec::TST TagType;
if (TagTokKind == tok::kw_struct)
TagType = DeclSpec::TST_struct;
@@ -955,7 +957,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// "FOO : BAR" is not a potential typo for "FOO::BAR".
ColonProtectionRAIIObject X(*this);
- if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true))
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
DS.SetTypeSpecError();
if (SS.isSet())
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
@@ -1637,7 +1639,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (isAccessDecl) {
// Collect the scope specifier token we annotated earlier.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
+ /*EnteringContext=*/false);
// Try to parse an unqualified-id.
UnqualifiedId Name;
@@ -2335,7 +2338,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
// parse '::'[opt] nested-name-specifier[opt]
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
ParsedType TemplateTypeTy;
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index f77d8eaf2a..4b8fd76269 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -974,7 +974,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// type, translate it into a type and continue parsing as a
// cast expression.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
+ /*EnteringContext=*/false);
AnnotateTemplateIdTokenAsType();
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
NotCastExpr, isTypeCast);
@@ -1333,7 +1334,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (LHS.isInvalid())
break;
- ParseOptionalCXXScopeSpecifier(SS, ObjectType, false,
+ ParseOptionalCXXScopeSpecifier(SS, ObjectType,
+ /*EnteringContext=*/false,
&MayBePseudoDestructor);
if (SS.isNotEmpty())
ObjectType = ParsedType();
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 2bfb615873..dfc77e17d4 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -487,7 +487,7 @@ ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
// '::' unqualified-id
//
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
UnqualifiedId Name;
if (ParseUnqualifiedId(SS,
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index fabb8e2a59..6e84e42968 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1205,7 +1205,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
// simple-template-id
SourceLocation TypenameLoc = ConsumeToken();
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), false,
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(),
+ /*EnteringContext=*/false,
0, /*IsTypename*/true))
return true;
if (!SS.isSet()) {
@@ -1484,7 +1485,8 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) {
}
// Parse nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(Result.SS, ParsedType(), false);
+ ParseOptionalCXXScopeSpecifier(Result.SS, ParsedType(),
+ /*EnteringContext=*/false);
// Check nested-name specifier.
if (Result.SS.isInvalid()) {
diff --git a/test/SemaTemplate/instantiate-member-class.cpp b/test/SemaTemplate/instantiate-member-class.cpp
index c67eb4022a..bb6427670c 100644
--- a/test/SemaTemplate/instantiate-member-class.cpp
+++ b/test/SemaTemplate/instantiate-member-class.cpp
@@ -118,3 +118,25 @@ namespace AliasTagDef {
int m = F<int>::S().g();
int n = F<int>::U().g();
}
+
+namespace rdar10397846 {
+ template<int I> struct A
+ {
+ struct B
+ {
+ struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
+ };
+ };
+
+ template<int N> void foo()
+ {
+ class A<N>::B::C X; // expected-note{{in instantiation of member function}}
+ int A<N+1>::B::C::*member = 0;
+ }
+
+ void bar()
+ {
+ foo<0>();
+ foo<1>(); // expected-note{{in instantiation of function template}}
+ }
+}