[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