[cfe-commits] r96743 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseExpr.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/Sema.h lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h test/SemaCXX/pseudo-destructors.cpp
Douglas Gregor
dgregor at apple.com
Sun Feb 21 10:36:56 PST 2010
Author: dgregor
Date: Sun Feb 21 12:36:56 2010
New Revision: 96743
URL: http://llvm.org/viewvc/llvm-project?rev=96743&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/SemaCXX/pseudo-destructors.cpp
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sun Feb 21 12:36:56 2010
@@ -352,6 +352,11 @@
/// \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).
@@ -366,6 +371,7 @@
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II,
+ bool MayBePseudoDestructor,
TypeTy *ObjectType,
bool EnteringContext) {
return 0;
@@ -380,6 +386,7 @@
virtual bool IsInvalidUnlessNestedName(Scope *S,
const CXXScopeSpec &SS,
IdentifierInfo &II,
+ bool MayBePseudoDestructor,
TypeTy *ObjectType,
bool EnteringContext) {
return false;
@@ -397,7 +404,8 @@
const CXXScopeSpec &SS,
TypeTy *Type,
SourceRange TypeRange,
- SourceLocation CCLoc) {
+ SourceLocation CCLoc,
+ bool MayBePseudoDestructor) {
return 0;
}
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sun Feb 21 12:36:56 2010
@@ -962,7 +962,8 @@
bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
TypeTy *ObjectType,
- bool EnteringContext);
+ bool EnteringContext,
+ bool InMemberAccessExpr = false);
//===--------------------------------------------------------------------===//
// C++ 5.2p1: C++ Casts
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Sun Feb 21 12:36:56 2010
@@ -1001,7 +1001,7 @@
OpLoc, OpKind, ObjectType);
if (LHS.isInvalid())
break;
- ParseOptionalCXXScopeSpecifier(SS, ObjectType, false);
+ ParseOptionalCXXScopeSpecifier(SS, ObjectType, false, true);
}
if (Tok.is(tok::code_completion)) {
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sun Feb 21 12:36:56 2010
@@ -45,10 +45,14 @@
/// \param EnteringContext whether we will be entering into the context of
/// the nested-name-specifier after parsing it.
///
+/// \param InMemberAccessExpr Whether this scope specifier is within a
+/// member access expression, e.g., the \p T:: in \p p->T::m.
+///
/// \returns true if a scope specifier was parsed.
bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
Action::TypeTy *ObjectType,
- bool EnteringContext) {
+ bool EnteringContext,
+ bool InMemberAccessExpr) {
assert(getLang().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
@@ -169,7 +173,8 @@
// convert it into a type within the nested-name-specifier.
TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
-
+ bool MayBePseudoDestructor
+ = InMemberAccessExpr && GetLookAheadToken(2).is(tok::tilde);
if (TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) {
AnnotateTemplateIdTokenAsType(&SS);
@@ -191,7 +196,8 @@
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
TypeToken.getAnnotationValue(),
TypeToken.getAnnotationRange(),
- CCLoc));
+ CCLoc,
+ MayBePseudoDestructor));
else
SS.setScopeRep(0);
SS.setEndLoc(CCLoc);
@@ -217,18 +223,23 @@
// 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 &&
- 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
- // recover like this.
- PP.LookAhead(1).is(tok::identifier)) {
- Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
- << CodeModificationHint::CreateReplacement(Next.getLocation(), "::");
+ if (Next.is(tok::colon) && !ColonIsSacred) {
+ bool MayBePseudoDestructor
+ = InMemberAccessExpr && GetLookAheadToken(2).is(tok::tilde);
- // Recover as if the user wrote '::'.
- Next.setKind(tok::coloncolon);
+ if (Actions.IsInvalidUnlessNestedName(CurScope, SS, II,
+ MayBePseudoDestructor, 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
+ // recover like this.
+ PP.LookAhead(1).is(tok::identifier)) {
+ Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
+ << CodeModificationHint::CreateReplacement(Next.getLocation(), "::");
+
+ // Recover as if the user wrote '::'.
+ Next.setKind(tok::coloncolon);
+ }
}
if (Next.is(tok::coloncolon)) {
@@ -247,9 +258,12 @@
if (SS.isInvalid())
continue;
+ bool MayBePseudoDestructor = InMemberAccessExpr && Tok.is(tok::tilde);
+
SS.setScopeRep(
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
- ObjectType, EnteringContext));
+ MayBePseudoDestructor, ObjectType,
+ EnteringContext));
SS.setEndLoc(CCLoc);
continue;
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Feb 21 12:36:56 2010
@@ -2198,7 +2198,8 @@
virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
SourceLocation CCLoc);
- bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
+ bool isAcceptableNestedNameSpecifier(NamedDecl *SD,
+ bool MayBePseudoDestructor = false);
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
@@ -2207,6 +2208,7 @@
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II,
+ bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *ScopeLookupResult,
bool EnteringContext,
@@ -2217,12 +2219,14 @@
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);
@@ -2238,7 +2242,8 @@
const CXXScopeSpec &SS,
TypeTy *Type,
SourceRange TypeRange,
- SourceLocation CCLoc);
+ SourceLocation CCLoc,
+ bool MayBePseudoDestructor);
virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Sun Feb 21 12:36:56 2010
@@ -176,16 +176,15 @@
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 @@
/// \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 @@
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 @@
return 0;
NamedDecl *Result = Found.getFoundDecl();
- if (isAcceptableNestedNameSpecifier(Result))
+ if (isAcceptableNestedNameSpecifier(Result, true))
return Result;
return 0;
@@ -345,6 +350,7 @@
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II,
+ bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *ScopeLookupResult,
bool EnteringContext,
@@ -439,7 +445,8 @@
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 @@
}
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 @@
// 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 @@
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 @@
///
/// 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 @@
const CXXScopeSpec &SS,
TypeTy *Ty,
SourceRange TypeRange,
- SourceLocation CCLoc) {
+ SourceLocation CCLoc,
+ bool MayBePseudoDestructor) {
NestedNameSpecifier *Prefix
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
QualType T = GetTypeFromParser(Ty);
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Feb 21 12:36:56 2010
@@ -85,10 +85,11 @@
isDependent = SearchType->isDependentType();
} else {
LookupCtx = computeDeclContext(SS, EnteringContext);
- isDependent = LookupCtx->isDependentContext();
+ if (LookupCtx)
+ isDependent = LookupCtx->isDependentContext();
}
- LookInScope = false;
+ LookInScope = (LookupCtx == 0) && !isDependent;
} else if (ObjectTypePtr) {
// C++ [basic.lookup.classref]p3:
// If the unqualified-id is ~type-name, the type-name is looked up
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sun Feb 21 12:36:56 2010
@@ -4925,6 +4925,7 @@
NestedNameSpecifier *NNS
= TransformNestedNameSpecifier(T->getQualifier(),
/*FIXME:*/SourceRange(getBaseLocation()),
+ false,
ObjectType);
if (!NNS)
return QualType();
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Sun Feb 21 12:36:56 2010
@@ -1486,7 +1486,7 @@
const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
DeclarationName());
- return Instantiator.TransformNestedNameSpecifier(NNS, Range);
+ return Instantiator.TransformNestedNameSpecifier(NNS, Range, false);
}
TemplateName
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Sun Feb 21 12:36:56 2010
@@ -265,6 +265,7 @@
/// alternate behavior.
NestedNameSpecifier *TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
+ bool MayBePseudoDestructor,
QualType ObjectType = QualType(),
NamedDecl *FirstQualifierInScope = 0);
@@ -555,6 +556,7 @@
NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
IdentifierInfo &II,
+ bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *FirstQualifierInScope);
@@ -577,7 +579,8 @@
NestedNameSpecifier *RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
bool TemplateKW,
- QualType T);
+ QualType T,
+ bool MayBePseudoDestructor);
/// \brief Build a new template name given a nested name specifier, a flag
/// indicating whether the "template" keyword was provided, and the template
@@ -1725,6 +1728,7 @@
NestedNameSpecifier *
TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
+ bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
if (!NNS)
@@ -1734,6 +1738,7 @@
NestedNameSpecifier *Prefix = NNS->getPrefix();
if (Prefix) {
Prefix = getDerived().TransformNestedNameSpecifier(Prefix, Range,
+ false,
ObjectType,
FirstQualifierInScope);
if (!Prefix)
@@ -1755,6 +1760,7 @@
return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
*NNS->getAsIdentifier(),
+ MayBePseudoDestructor,
ObjectType,
FirstQualifierInScope);
@@ -1790,7 +1796,8 @@
return getDerived().RebuildNestedNameSpecifier(Prefix, Range,
NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
- T);
+ T,
+ MayBePseudoDestructor);
}
}
@@ -1842,6 +1849,7 @@
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
/*FIXME:*/SourceRange(getDerived().getBaseLocation()),
+ false,
ObjectType);
if (!NNS)
return TemplateName();
@@ -1869,6 +1877,7 @@
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(DTN->getQualifier(),
/*FIXME:*/SourceRange(getDerived().getBaseLocation()),
+ false,
ObjectType);
if (!NNS && DTN->getQualifier())
return TemplateName();
@@ -2928,6 +2937,7 @@
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(T->getQualifier(),
SourceRange(),
+ false,
ObjectType);
if (!NNS)
return QualType();
@@ -2962,7 +2972,7 @@
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR,
- ObjectType);
+ false, ObjectType);
if (!NNS)
return QualType();
@@ -3598,7 +3608,8 @@
NestedNameSpecifier *Qualifier = 0;
if (E->getQualifier()) {
Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
+ E->getQualifierRange(),
+ false);
if (!Qualifier)
return SemaRef.ExprError();
}
@@ -3807,7 +3818,8 @@
if (E->hasQualifier()) {
Qualifier
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
+ E->getQualifierRange(),
+ false);
if (Qualifier == 0)
return SemaRef.ExprError();
}
@@ -4677,7 +4689,8 @@
NestedNameSpecifier *Qualifier
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
+ E->getQualifierRange(),
+ true);
if (E->getQualifier() && !Qualifier)
return SemaRef.ExprError();
@@ -4747,7 +4760,8 @@
NestedNameSpecifier *Qualifier = 0;
if (Old->getQualifier()) {
Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
- Old->getQualifierRange());
+ Old->getQualifierRange(),
+ false);
if (!Qualifier)
return SemaRef.ExprError();
@@ -4803,7 +4817,8 @@
DependentScopeDeclRefExpr *E) {
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
- E->getQualifierRange());
+ E->getQualifierRange(),
+ false);
if (!NNS)
return SemaRef.ExprError();
@@ -5050,8 +5065,11 @@
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)
@@ -5126,7 +5144,8 @@
if (Old->getQualifier()) {
Qualifier
= getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
- Old->getQualifierRange());
+ Old->getQualifierRange(),
+ false);
if (Qualifier == 0)
return SemaRef.ExprError();
}
@@ -5551,6 +5570,7 @@
TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
IdentifierInfo &II,
+ bool MayBePseudoDestructor,
QualType ObjectType,
NamedDecl *FirstQualifierInScope) {
CXXScopeSpec SS;
@@ -5560,6 +5580,7 @@
return static_cast<NestedNameSpecifier *>(
SemaRef.BuildCXXNestedNameSpecifier(0, SS, Range.getEnd(),
Range.getEnd(), II,
+ MayBePseudoDestructor,
ObjectType,
FirstQualifierInScope,
false, false));
@@ -5578,8 +5599,9 @@
TreeTransform<Derived>::RebuildNestedNameSpecifier(NestedNameSpecifier *Prefix,
SourceRange Range,
bool TemplateKW,
- QualType T) {
- if (T->isDependentType() || T->isRecordType() ||
+ QualType T,
+ bool MayBePseudoDestructor) {
+ if (MayBePseudoDestructor || 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,
Modified: cfe/trunk/test/SemaCXX/pseudo-destructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/pseudo-destructors.cpp?rev=96743&r1=96742&r2=96743&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/pseudo-destructors.cpp (original)
+++ cfe/trunk/test/SemaCXX/pseudo-destructors.cpp Sun Feb 21 12:36:56 2010
@@ -5,6 +5,7 @@
typedef Foo Bar;
typedef int Integer;
+typedef double Double;
void g();
@@ -12,7 +13,7 @@
typedef Foo Wibble;
}
-void f(A* a, Foo *f, int *i) {
+void f(A* a, Foo *f, int *i, double *d) {
a->~A();
a->A::~A();
@@ -31,6 +32,11 @@
f->N::~Wibble(); // FIXME: Cannot use typedef name in destructor id.
f->::~Bar(17, 42); // expected-error{{cannot have any arguments}}
+
+ i->~Integer();
+ i->Integer::~Integer();
+
+ i->Integer::~Double(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('double') in pseudo-destructor expression}}
}
typedef int Integer;
More information about the cfe-commits
mailing list