Tighten up the conditions under which we consider ourselves to be
entering the context of a nested-name-specifier. Fixes <rdar://problem/10397846>. llvm-svn: 143967
This commit is contained in:
parent
7635bb7ae2
commit
df593fbeda
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue