Restore the invariant that a nested-name-specifier can only contain

class types, dependent types, and namespaces. I had previously
weakened this invariant while working on parsing pseudo-destructor
expressions, but recent work in that area has made these changes
unnecessary.

llvm-svn: 97112
This commit is contained in:
Douglas Gregor 2010-02-25 04:46:04 +00:00
parent 400a6939a8
commit cd3f49fc88
9 changed files with 33 additions and 93 deletions

View File

@ -365,11 +365,6 @@ public:
/// \param II the identifier that represents the scope that this
/// nested-name-specifier refers to, e.g., the "bar" in "foo::bar::".
///
/// \param MayBePseudoDestructor Whether this nested-name-specifier
/// may be part of a pseudo-destructor, meaning that we are in a
/// member access expression (such as p->T::~T()) and a '~' follows
/// the '::'.
///
/// \param ObjectType if this nested-name-specifier occurs as part of a
/// C++ member access expression such as "x->Base::f", the type of the base
/// object (e.g., *x in the example, if "x" were a pointer).
@ -384,7 +379,6 @@ public:
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II,
bool MayBePseudoDestructor,
TypeTy *ObjectType,
bool EnteringContext) {
return 0;
@ -399,7 +393,6 @@ public:
virtual bool IsInvalidUnlessNestedName(Scope *S,
const CXXScopeSpec &SS,
IdentifierInfo &II,
bool MayBePseudoDestructor,
TypeTy *ObjectType,
bool EnteringContext) {
return false;
@ -417,8 +410,7 @@ public:
const CXXScopeSpec &SS,
TypeTy *Type,
SourceRange TypeRange,
SourceLocation CCLoc,
bool MayBePseudoDestructor) {
SourceLocation CCLoc) {
return 0;
}

View File

@ -1004,7 +1004,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
if (LHS.isInvalid())
break;
ParseOptionalCXXScopeSpecifier(SS, ObjectType, false,
ParseOptionalCXXScopeSpecifier(SS, ObjectType, false,
&MayBePseudoDestructor);
}

View File

@ -212,8 +212,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
TypeToken.getAnnotationValue(),
TypeToken.getAnnotationRange(),
CCLoc,
false));
CCLoc));
else
SS.setScopeRep(0);
SS.setEndLoc(CCLoc);
@ -240,15 +239,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
// and emit a fixit hint for it.
if (Next.is(tok::colon) && !ColonIsSacred) {
if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde) &&
!Actions.isNonTypeNestedNameSpecifier(CurScope, SS, Tok.getLocation(),
II, ObjectType)) {
*MayBePseudoDestructor = true;
return HasScopeSpecifier;
}
if (Actions.IsInvalidUnlessNestedName(CurScope, SS, II,
false, ObjectType,
if (Actions.IsInvalidUnlessNestedName(CurScope, SS, II, ObjectType,
EnteringContext) &&
// If the token after the colon isn't an identifier, it's still an
// error, but they probably meant something else strange so don't
@ -287,8 +278,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
SS.setScopeRep(
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
false, ObjectType,
EnteringContext));
ObjectType, EnteringContext));
SS.setEndLoc(CCLoc);
continue;
}

View File

@ -2225,8 +2225,7 @@ public:
virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
SourceLocation CCLoc);
bool isAcceptableNestedNameSpecifier(NamedDecl *SD,
bool MayBePseudoDestructor = false);
bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
virtual bool isNonTypeNestedNameSpecifier(Scope *S, const CXXScopeSpec &SS,
@ -2239,7 +2238,6 @@ public:
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II,
bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *ScopeLookupResult,
bool EnteringContext,
@ -2250,14 +2248,12 @@ public:
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II,
bool MayBePseudoDestructor,
TypeTy *ObjectType,
bool EnteringContext);
virtual bool IsInvalidUnlessNestedName(Scope *S,
const CXXScopeSpec &SS,
IdentifierInfo &II,
bool MayBePseudoDestructor,
TypeTy *ObjectType,
bool EnteringContext);
@ -2273,8 +2269,7 @@ public:
const CXXScopeSpec &SS,
TypeTy *Type,
SourceRange TypeRange,
SourceLocation CCLoc,
bool MayBePseudoDestructor);
SourceLocation CCLoc);
virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);

View File

@ -176,15 +176,16 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate: {
if (const TagType *Tag = NNS->getAsType()->getAs<TagType>())
return Tag->getDecl();
break;
}
const TagType *Tag = NNS->getAsType()->getAs<TagType>();
assert(Tag && "Non-tag type in nested-name-specifier");
return Tag->getDecl();
} break;
case NestedNameSpecifier::Global:
return Context.getTranslationUnitDecl();
}
// Required to silence a GCC warning.
return 0;
}
@ -269,8 +270,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
/// \brief Determines whether the given declaration is an valid acceptable
/// result for name lookup of a nested-name-specifier.
bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD,
bool MayBePseudoDestructor) {
bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) {
if (!SD)
return false;
@ -281,11 +281,6 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD,
if (!isa<TypeDecl>(SD))
return false;
// If this may be part of a pseudo-destructor expression, we'll
// accept any type.
if (MayBePseudoDestructor)
return true;
// Determine whether we have a class (or, in C++0x, an enum) or
// a typedef thereof. If so, build the nested-name-specifier.
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
@ -326,7 +321,7 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
return 0;
NamedDecl *Result = Found.getFoundDecl();
if (isAcceptableNestedNameSpecifier(Result, true))
if (isAcceptableNestedNameSpecifier(Result))
return Result;
return 0;
@ -398,7 +393,6 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II,
bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *ScopeLookupResult,
bool EnteringContext,
@ -493,8 +487,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
DeclarationName Name = Found.getLookupName();
if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext) &&
Found.isSingleResult() &&
isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>(),
MayBePseudoDestructor)) {
isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) {
if (LookupCtx)
Diag(Found.getNameLoc(), diag::err_no_member_suggest)
<< Name << LookupCtx << Found.getLookupName() << SS.getRange()
@ -514,7 +507,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
}
NamedDecl *SD = Found.getAsSingle<NamedDecl>();
if (isAcceptableNestedNameSpecifier(SD, MayBePseudoDestructor)) {
if (isAcceptableNestedNameSpecifier(SD)) {
if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) {
// C++ [basic.lookup.classref]p4:
// [...] If the name is found in both contexts, the
@ -526,14 +519,13 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
// scope, reconstruct the result from the template instantiation itself.
NamedDecl *OuterDecl;
if (S) {
LookupResult FoundOuter(*this, &II, IdLoc,
LookupNestedNameSpecifierName);
LookupResult FoundOuter(*this, &II, IdLoc, LookupNestedNameSpecifierName);
LookupName(FoundOuter, S);
OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
} else
OuterDecl = ScopeLookupResult;
if (isAcceptableNestedNameSpecifier(OuterDecl, MayBePseudoDestructor) &&
if (isAcceptableNestedNameSpecifier(OuterDecl) &&
OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() &&
(!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) ||
!Context.hasSameType(
@ -610,11 +602,9 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II,
bool MayBePseudoDestructor,
TypeTy *ObjectTypePtr,
bool EnteringContext) {
return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II,
MayBePseudoDestructor,
QualType::getFromOpaquePtr(ObjectTypePtr),
/*ScopeLookupResult=*/0, EnteringContext,
false);
@ -627,13 +617,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
///
/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
bool Sema::IsInvalidUnlessNestedName(Scope *S, const CXXScopeSpec &SS,
IdentifierInfo &II,
bool MayBePseudoDestructor,
TypeTy *ObjectType,
IdentifierInfo &II, TypeTy *ObjectType,
bool EnteringContext) {
return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(),
II, MayBePseudoDestructor,
QualType::getFromOpaquePtr(ObjectType),
II, QualType::getFromOpaquePtr(ObjectType),
/*ScopeLookupResult=*/0, EnteringContext,
true);
}
@ -642,8 +629,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
const CXXScopeSpec &SS,
TypeTy *Ty,
SourceRange TypeRange,
SourceLocation CCLoc,
bool MayBePseudoDestructor) {
SourceLocation CCLoc) {
NestedNameSpecifier *Prefix
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
QualType T = GetTypeFromParser(Ty);

View File

@ -133,7 +133,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
isDependent = LookupCtx && LookupCtx->isDependentContext();
}
LookInScope = (LookupCtx == 0) && !isDependent;
LookInScope = false;
} else if (ObjectTypePtr) {
// C++ [basic.lookup.classref]p3:
// If the unqualified-id is ~type-name, the type-name is looked up

View File

@ -4925,7 +4925,6 @@ CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB,
NestedNameSpecifier *NNS
= TransformNestedNameSpecifier(T->getQualifier(),
/*FIXME:*/SourceRange(getBaseLocation()),
false,
ObjectType);
if (!NNS)
return QualType();

View File

@ -1486,7 +1486,7 @@ Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
DeclarationName());
return Instantiator.TransformNestedNameSpecifier(NNS, Range, false);
return Instantiator.TransformNestedNameSpecifier(NNS, Range);
}
TemplateName

View File

@ -265,7 +265,6 @@ public:
/// alternate behavior.
NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
bool MayBePseudoDestructor,
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = 0);
@ -556,7 +555,6 @@ public:
NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
IdentifierInfo &II,
bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *FirstQualifierInScope);
@ -579,8 +577,7 @@ public:
NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
bool TemplateKW,
QualType T,
bool MayBePseudoDestructor);
QualType T);
/// \brief Build a new template name given a nested name specifier, a flag
/// indicating whether the "template" keyword was provided, and the template
@ -1712,7 +1709,6 @@ template<typename Derived>
NestedNameSpecifier *
TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
if (!NNS)
@ -1722,7 +1718,6 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
NestedNameSpecifier *Prefix = NNS->getPrefix();
if (Prefix) {
Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range,
false,
ObjectType,
FirstQualifierInScope);
if (!Prefix)
@ -1744,7 +1739,6 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
*NNS->getAsIdentifier(),
MayBePseudoDestructor,
ObjectType,
FirstQualifierInScope);
@ -1780,8 +1774,7 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
T,
MayBePseudoDestructor);
T);
}
}
@ -1833,7 +1826,6 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
/*FIXME:*/SourceRange(getDerived().getBaseLocation()),
false,
ObjectType);
if (!NNS)
return TemplateName();
@ -1861,7 +1853,6 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(DTN->getQualifier(),
/*FIXME:*/SourceRange(getDerived().getBaseLocation()),
false,
ObjectType);
if (!NNS && DTN->getQualifier())
return TemplateName();
@ -2921,7 +2912,6 @@ TreeTransform<Derived>::TransformQualifiedNameType(TypeLocBuilder &TLB,
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(T->getQualifier(),
SourceRange(),
false,
ObjectType);
if (!NNS)
return QualType();
@ -2956,7 +2946,7 @@ QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB,
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR,
false, ObjectType);
ObjectType);
if (!NNS)
return QualType();
@ -3592,8 +3582,7 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
NestedNameSpecifier *Qualifier = 0;
if (E->getQualifier()) {
Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange(),
false);
E->getQualifierRange());
if (!Qualifier)
return SemaRef.ExprError();
}
@ -3802,8 +3791,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
if (E->hasQualifier()) {
Qualifier
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange(),
false);
E->getQualifierRange());
if (Qualifier == 0)
return SemaRef.ExprError();
}
@ -4685,7 +4673,6 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
NestedNameSpecifier *Qualifier
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange(),
true,
ObjectType);
if (E->getQualifier() && !Qualifier)
return SemaRef.ExprError();
@ -4786,8 +4773,7 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
NestedNameSpecifier *Qualifier = 0;
if (Old->getQualifier()) {
Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
Old->getQualifierRange(),
false);
Old->getQualifierRange());
if (!Qualifier)
return SemaRef.ExprError();
@ -4843,8 +4829,7 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *E) {
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange(),
false);
E->getQualifierRange());
if (!NNS)
return SemaRef.ExprError();
@ -5093,11 +5078,8 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
NestedNameSpecifier *Qualifier = 0;
if (E->getQualifier()) {
bool MayBePseudoDestructor
= E->getMember().getNameKind() == DeclarationName::CXXDestructorName;
Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange(),
MayBePseudoDestructor,
ObjectType,
FirstQualifierInScope);
if (!Qualifier)
@ -5172,8 +5154,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
if (Old->getQualifier()) {
Qualifier
= getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
Old->getQualifierRange(),
false);
Old->getQualifierRange());
if (Qualifier == 0)
return SemaRef.ExprError();
}
@ -5598,7 +5579,6 @@ NestedNameSpecifier *
TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
IdentifierInfo &II,
bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
CXXScopeSpec SS;
@ -5608,7 +5588,6 @@ TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
return static_cast<NestedNameSpecifier *>(
SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(),
Range.getEnd(), II,
MayBePseudoDestructor,
ObjectType,
FirstQualifierInScope,
false, false));
@ -5627,9 +5606,8 @@ NestedNameSpecifier *
TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
bool TemplateKW,
QualType T,
bool MayBePseudoDestructor) {
if (MayBePseudoDestructor || T->isDependentType() || T->isRecordType() ||
QualType T) {
if (T->isDependentType() || T->isRecordType() ||
(SemaRef.getLangOptions().CPlusPlus0x && T->isEnumeralType())) {
assert(!T.hasLocalQualifiers() && "Can't get cv-qualifiers here");
return NestedNameSpecifier::Create(SemaRef.Context, Prefix, TemplateKW,