diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-02-21 18:36:56 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-02-21 18:36:56 +0000 |
commit | b10cd04880672103660e5844e51ee91af7361a20 (patch) | |
tree | 6ea428d3b9d0b09b9533f8bec9ff66f2392dc74c /lib/Sema/SemaCXXScopeSpec.cpp | |
parent | 12116062c8243c6f88d79dac9663a359b77741c6 (diff) |
Implement support for parsing pseudo-destructor expression with a nested-name-specifier, e.g.,
typedef int Int;
int *p;
p->Int::~Int();
This weakens the invariant that the only types in nested-name-specifiers are tag types (restricted to class types in C++98/03). However, we weaken this invariant as little as possible, accepting arbitrary types in nested-name-specifiers only when we're in a member access expression that looks like a pseudo-destructor expression.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96743 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaCXXScopeSpec.cpp')
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 42 |
1 files changed, 28 insertions, 14 deletions
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 52e9e9bc87..315938d2d4 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -176,16 +176,15 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { - const TagType *Tag = NNS->getAsType()->getAs<TagType>(); - assert(Tag && "Non-tag type in nested-name-specifier"); - return Tag->getDecl(); - } break; + if (const TagType *Tag = NNS->getAsType()->getAs<TagType>()) + return Tag->getDecl(); + break; + } case NestedNameSpecifier::Global: return Context.getTranslationUnitDecl(); } - // Required to silence a GCC warning. return 0; } @@ -270,7 +269,8 @@ 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 Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD, + bool MayBePseudoDestructor) { if (!SD) return false; @@ -281,6 +281,11 @@ 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)); @@ -321,7 +326,7 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { return 0; NamedDecl *Result = Found.getFoundDecl(); - if (isAcceptableNestedNameSpecifier(Result)) + if (isAcceptableNestedNameSpecifier(Result, true)) return Result; return 0; @@ -345,6 +350,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, SourceLocation IdLoc, SourceLocation CCLoc, IdentifierInfo &II, + bool MayBePseudoDestructor, QualType ObjectType, NamedDecl *ScopeLookupResult, bool EnteringContext, @@ -439,7 +445,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, DeclarationName Name = Found.getLookupName(); if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext) && Found.isSingleResult() && - isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) { + isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>(), + MayBePseudoDestructor)) { if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_suggest) << Name << LookupCtx << Found.getLookupName() << SS.getRange() @@ -459,7 +466,7 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, } NamedDecl *SD = Found.getAsSingle<NamedDecl>(); - if (isAcceptableNestedNameSpecifier(SD)) { + if (isAcceptableNestedNameSpecifier(SD, MayBePseudoDestructor)) { if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) { // C++ [basic.lookup.classref]p4: // [...] If the name is found in both contexts, the @@ -471,13 +478,14 @@ 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) && + if (isAcceptableNestedNameSpecifier(OuterDecl, MayBePseudoDestructor) && OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() && (!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) || !Context.hasSameType( @@ -554,9 +562,11 @@ 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); @@ -569,10 +579,13 @@ 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, TypeTy *ObjectType, + IdentifierInfo &II, + bool MayBePseudoDestructor, + TypeTy *ObjectType, bool EnteringContext) { return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(), - II, QualType::getFromOpaquePtr(ObjectType), + II, MayBePseudoDestructor, + QualType::getFromOpaquePtr(ObjectType), /*ScopeLookupResult=*/0, EnteringContext, true); } @@ -581,7 +594,8 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, const CXXScopeSpec &SS, TypeTy *Ty, SourceRange TypeRange, - SourceLocation CCLoc) { + SourceLocation CCLoc, + bool MayBePseudoDestructor) { NestedNameSpecifier *Prefix = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); QualType T = GetTypeFromParser(Ty); |