[cfe-commits] r97092 - in /cfe/trunk: include/clang/AST/ExprCXX.h lib/AST/ExprCXX.cpp lib/AST/StmtPrinter.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/TreeTransform.h test/SemaTemplate/destructor-template.cpp test/SemaTemplate/member-access-expr.cpp

Douglas Gregor dgregor at apple.com
Wed Feb 24 17:56:36 PST 2010


Author: dgregor
Date: Wed Feb 24 19:56:36 2010
New Revision: 97092

URL: http://llvm.org/viewvc/llvm-project?rev=97092&view=rev
Log:
Use CXXPseudoDestructorExpr as the stored representation for dependent
expressions that look like pseudo-destructors, e.g.,

  p->T::~T()

where p has dependent type.

At template instantiate time, we determine whether we actually have a
pseudo-destructor or a member access, and funnel down to the
appropriate routine in Sema.

Fixes PR6380.


Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaTemplate/destructor-template.cpp
    cfe/trunk/test/SemaTemplate/member-access-expr.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Feb 24 19:56:36 2010
@@ -997,6 +997,35 @@
   virtual child_iterator child_end();
 };
 
+/// \brief Structure used to store the type being destroyed by a 
+/// pseudo-destructor expression.
+class PseudoDestructorTypeStorage {
+  /// \brief Either the type source information or the name of the type, if 
+  /// it couldn't be resolved due to type-dependence.
+  llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type;
+  
+  /// \brief The starting source location of the pseudo-destructor type.
+  SourceLocation Location;
+  
+public:
+  PseudoDestructorTypeStorage() { }
+  
+  PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc)
+    : Type(II), Location(Loc) { }
+  
+  PseudoDestructorTypeStorage(TypeSourceInfo *Info);
+  
+  TypeSourceInfo *getTypeSourceInfo() const { 
+    return Type.dyn_cast<TypeSourceInfo *>(); 
+  }
+  
+  IdentifierInfo *getIdentifier() const {
+    return Type.dyn_cast<IdentifierInfo *>();
+  }
+  
+  SourceLocation getLocation() const { return Location; }
+};
+  
 /// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
 ///
 /// A pseudo-destructor is an expression that looks like a member access to a
@@ -1050,8 +1079,9 @@
   /// \brief The location of the '~'.
   SourceLocation TildeLoc;
   
-  /// \brief The type being destroyed.
-  TypeSourceInfo *DestroyedType;
+  /// \brief The type being destroyed, or its name if we were unable to 
+  /// resolve the name.
+  PseudoDestructorTypeStorage DestroyedType;
 
 public:
   CXXPseudoDestructorExpr(ASTContext &Context,
@@ -1061,14 +1091,15 @@
                           TypeSourceInfo *ScopeType,
                           SourceLocation ColonColonLoc,
                           SourceLocation TildeLoc,
-                          TypeSourceInfo *DestroyedType)
+                          PseudoDestructorTypeStorage DestroyedType)
     : Expr(CXXPseudoDestructorExprClass,
            Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
                                                           false, 0, false, 
                                                           false, 0, 0, false,
                                                           CC_Default)),
            /*isTypeDependent=*/(Base->isTypeDependent() ||
-                                DestroyedType->getType()->isDependentType()),
+            (DestroyedType.getTypeSourceInfo() &&
+              DestroyedType.getTypeSourceInfo()->getType()->isDependentType())),
            /*isValueDependent=*/Base->isValueDependent()),
       Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
       OperatorLoc(OperatorLoc), Qualifier(Qualifier),
@@ -1120,12 +1151,31 @@
   /// \brief Retrieve the location of the '~'.
   SourceLocation getTildeLoc() const { return TildeLoc; }
   
-  /// \brief Retrieve the type that is being destroyed.
-  QualType getDestroyedType() const { return DestroyedType->getType(); }
-
   /// \brief Retrieve the source location information for the type
   /// being destroyed.
-  TypeSourceInfo *getDestroyedTypeInfo() const { return DestroyedType; }
+  ///
+  /// This type-source information is available for non-dependent 
+  /// pseudo-destructor expressions and some dependent pseudo-destructor
+  /// expressions. Returns NULL if we only have the identifier for a
+  /// dependent pseudo-destructor expression.
+  TypeSourceInfo *getDestroyedTypeInfo() const { 
+    return DestroyedType.getTypeSourceInfo(); 
+  }
+  
+  /// \brief In a dependent pseudo-destructor expression for which we do not
+  /// have full type information on the destroyed type, provides the name
+  /// of the destroyed type.
+  IdentifierInfo *getDestroyedTypeIdentifier() const {
+    return DestroyedType.getIdentifier();
+  }
+  
+  /// \brief Retrieve the type being destroyed.
+  QualType getDestroyedType() const;
+  
+  /// \brief Retrieve the starting location of the type being destroyed.
+  SourceLocation getDestroyedTypeLoc() const { 
+    return DestroyedType.getLocation(); 
+  }
 
   virtual SourceRange getSourceRange() const;
 

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Feb 24 19:56:36 2010
@@ -122,9 +122,24 @@
   return &Base + 1;
 }
 
+PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
+ : Type(Info) 
+{
+  Location = Info->getTypeLoc().getSourceRange().getBegin();
+}
+
+QualType CXXPseudoDestructorExpr::getDestroyedType() const {
+  if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
+    return TInfo->getType();
+  
+  return QualType();
+}
+
 SourceRange CXXPseudoDestructorExpr::getSourceRange() const {
-  return SourceRange(Base->getLocStart(), 
-                     DestroyedType->getTypeLoc().getSourceRange().getEnd());
+  SourceLocation End = DestroyedType.getLocation();
+  if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
+    End = TInfo->getTypeLoc().getSourceRange().getEnd();
+  return SourceRange(Base->getLocStart(), End);
 }
 
 

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Feb 24 19:56:36 2010
@@ -1120,7 +1120,10 @@
     E->getQualifier()->print(OS, Policy);
 
   std::string TypeS;
-  E->getDestroyedType().getAsStringInternal(TypeS, Policy);
+  if (IdentifierInfo *II = E->getDestroyedTypeIdentifier())
+    OS << II->getName();
+  else
+    E->getDestroyedType().getAsStringInternal(TypeS, Policy);
   OS << TypeS;
 }
 

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb 24 19:56:36 2010
@@ -95,6 +95,7 @@
   class ObjCMethodDecl;
   class ObjCPropertyDecl;
   class ObjCContainerDecl;
+  class PseudoDestructorTypeStorage;
   class FunctionProtoType;
   class CXXBasePath;
   class CXXBasePaths;
@@ -2188,20 +2189,9 @@
                                              TypeSourceInfo *ScopeType,
                                              SourceLocation CCLoc,
                                              SourceLocation TildeLoc,
-                                             TypeSourceInfo *DestroyedType,
+                                     PseudoDestructorTypeStorage DestroyedType,
                                              bool HasTrailingLParen);
-  
-  OwningExprResult ActOnDependentPseudoDestructorExpr(Scope *S, 
-                                                      ExprArg Base,
-                                                      SourceLocation OpLoc,
-                                                      tok::TokenKind OpKind,
-                                                      const CXXScopeSpec &SS,
-                                                  UnqualifiedId &FirstTypeName,
-                                                      SourceLocation CCLoc,
-                                                      SourceLocation TildeLoc,
-                                                  UnqualifiedId &SecondTypeName,
-                                                      bool HasTrailingLParen);
-  
+    
   virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
                                                      SourceLocation OpLoc,
                                                      tok::TokenKind OpKind,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb 24 19:56:36 2010
@@ -161,7 +161,7 @@
     Found.clear();
     if (Step == 0 && LookupCtx)
       LookupQualifiedName(Found, LookupCtx);
-    else if (Step == 1 && LookInScope)
+    else if (Step == 1 && LookInScope && S)
       LookupName(Found, S);
     else
       continue;
@@ -2441,9 +2441,9 @@
                                                  TypeSourceInfo *ScopeTypeInfo,
                                                        SourceLocation CCLoc,
                                                        SourceLocation TildeLoc,
-                                             TypeSourceInfo *DestructedTypeInfo,
+                                         PseudoDestructorTypeStorage Destructed,
                                                        bool HasTrailingLParen) {
-  assert(DestructedTypeInfo && "No destructed type in pseudo-destructor expr?");
+  TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo();
   
   // C++ [expr.pseudo]p2:
   //   The left-hand side of the dot operator shall be of scalar type. The 
@@ -2475,21 +2475,24 @@
   // C++ [expr.pseudo]p2:
   //   [...] The cv-unqualified versions of the object type and of the type 
   //   designated by the pseudo-destructor-name shall be the same type.
-  QualType DestructedType = DestructedTypeInfo->getType();
-  SourceLocation DestructedTypeStart
-    = DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin();
-  if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
-      !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
-    Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
-      << ObjectType << DestructedType << BaseE->getSourceRange()
-      << DestructedTypeInfo->getTypeLoc().getSourceRange();
-    
-    // Recover by 
-    DestructedType = ObjectType;
-    DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
-                                                         DestructedTypeStart);
+  if (DestructedTypeInfo) {
+    QualType DestructedType = DestructedTypeInfo->getType();
+    SourceLocation DestructedTypeStart
+      = DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin();
+    if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
+        !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
+      Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
+        << ObjectType << DestructedType << BaseE->getSourceRange()
+        << DestructedTypeInfo->getTypeLoc().getSourceRange();
+      
+      // Recover by setting the destructed type to the object type.
+      DestructedType = ObjectType;
+      DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
+                                                           DestructedTypeStart);
+      Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+    }
   }
-   
+  
   // C++ [expr.pseudo]p2:
   //   [...] Furthermore, the two type-names in a pseudo-destructor-name of the
   //   form
@@ -2522,148 +2525,12 @@
                                                   ScopeTypeInfo,
                                                   CCLoc,
                                                   TildeLoc,
-                                                  DestructedTypeInfo));
+                                                  Destructed));
+            
   if (HasTrailingLParen)
     return move(Result);
   
-  return DiagnoseDtorReference(
-                  DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin(),
-                               move(Result));  
-}
-
-Sema::OwningExprResult 
-Sema::ActOnDependentPseudoDestructorExpr(Scope *S, 
-                                         ExprArg Base,
-                                         SourceLocation OpLoc,
-                                         tok::TokenKind OpKind,
-                                         const CXXScopeSpec &SS,
-                                         UnqualifiedId &FirstTypeName,
-                                         SourceLocation CCLoc,
-                                         SourceLocation TildeLoc,
-                                         UnqualifiedId &SecondTypeName,
-                                         bool HasTrailingLParen) {
-  Expr *BaseE = (Expr *)Base.get();
-  QualType ObjectType = BaseE->getType();
-  assert(ObjectType->isDependentType());
-  
-  // The nested-name-specifier provided by the parser, then extended
-  // by the "type-name ::" in the pseudo-destructor-name, if present.
-  CXXScopeSpec ExtendedSS = SS;
-  
-  if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || 
-      FirstTypeName.Identifier) {
-    // We have a pseudo-destructor with a "type-name ::". 
-    // FIXME: As a temporary hack, we go ahead and resolve this to part of
-    // a nested-name-specifier.
-    if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
-      // Resolve the identifier to a nested-name-specifier.
-      CXXScopeTy *FinalScope
-      = ActOnCXXNestedNameSpecifier(S, SS, 
-                                    FirstTypeName.StartLocation,
-                                    CCLoc,
-                                    *FirstTypeName.Identifier,
-                                    true,
-                                    ObjectType.getAsOpaquePtr(),
-                                    false);
-      if (SS.getBeginLoc().isInvalid())
-        ExtendedSS.setBeginLoc(FirstTypeName.StartLocation);
-      ExtendedSS.setEndLoc(CCLoc);
-      ExtendedSS.setScopeRep(FinalScope);
-    } else {
-      // Resolve the template-id to a type, and that to a
-      // nested-name-specifier.
-      TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId;
-      ASTTemplateArgsPtr TemplateArgsPtr(*this,
-                                         TemplateId->getTemplateArgs(),
-                                         TemplateId->NumArgs);
-      TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
-                                         TemplateId->TemplateNameLoc,
-                                         TemplateId->LAngleLoc,
-                                         TemplateArgsPtr,
-                                         TemplateId->RAngleLoc);
-      if (!T.isInvalid()) {
-        CXXScopeTy *FinalScope
-        = ActOnCXXNestedNameSpecifier(S, SS, T.get(), 
-                                      SourceRange(TemplateId->TemplateNameLoc,
-                                                  TemplateId->RAngleLoc),
-                                      CCLoc,
-                                      true);
-        if (SS.getBeginLoc().isInvalid())
-          ExtendedSS.setBeginLoc(TemplateId->TemplateNameLoc);
-        ExtendedSS.setEndLoc(CCLoc);
-        ExtendedSS.setScopeRep(FinalScope);        
-      }
-    }
-  }
-  
-  // Produce a destructor name based on the second type-name (which
-  // follows the tilde).
-  TypeTy *DestructedType;
-  SourceLocation EndLoc;
-  if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
-    const CXXScopeSpec *LookupSS = &SS;
-    bool isDependent = isDependentScopeSpecifier(ExtendedSS);
-    if (isDependent || computeDeclContext(ExtendedSS))
-      LookupSS = &ExtendedSS;
-    
-    DestructedType = getTypeName(*SecondTypeName.Identifier, 
-                                 SecondTypeName.StartLocation,
-                                 S, LookupSS, true, ObjectType.getTypePtr());
-    if (!DestructedType && isDependent) {
-      // We didn't find our type, but that's okay: it's dependent
-      // anyway.
-      // FIXME: We should not be building a typename type here!
-      NestedNameSpecifier *NNS = 0;
-      SourceRange Range;
-      if (SS.isSet()) {
-        NNS = (NestedNameSpecifier *)ExtendedSS.getScopeRep();
-        Range = SourceRange(ExtendedSS.getRange().getBegin(), 
-                            SecondTypeName.StartLocation);
-      } else {
-        NNS = NestedNameSpecifier::Create(Context, SecondTypeName.Identifier);
-        Range = SourceRange(SecondTypeName.StartLocation);
-      }
-      
-      DestructedType = CheckTypenameType(NNS, *SecondTypeName.Identifier, 
-                                         Range).getAsOpaquePtr();
-      if (!DestructedType)
-        return ExprError();
-    }
-    
-    if (!DestructedType) {
-      // FIXME: Crummy diagnostic.
-      Diag(SecondTypeName.StartLocation, diag::err_destructor_class_name);
-      return ExprError();
-    }
-    
-    EndLoc = SecondTypeName.EndLocation;
-  } else {
-    // Resolve the template-id to a type, and that to a
-    // nested-name-specifier.
-    TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId;
-    ASTTemplateArgsPtr TemplateArgsPtr(*this,
-                                       TemplateId->getTemplateArgs(),
-                                       TemplateId->NumArgs);
-    EndLoc = TemplateId->RAngleLoc;
-    TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
-                                       TemplateId->TemplateNameLoc,
-                                       TemplateId->LAngleLoc,
-                                       TemplateArgsPtr,
-                                       TemplateId->RAngleLoc);
-    if (T.isInvalid() || !T.get())
-      return ExprError();
-    
-    DestructedType = T.get();
-  }
-  
-  // Form a (possibly fake) destructor name and let the member access
-  // expression code deal with this.
-  // FIXME: Don't do this! It's totally broken!
-  UnqualifiedId Destructor;
-  Destructor.setDestructorName(TildeLoc, DestructedType, EndLoc);
-  return ActOnMemberAccessExpr(S, move(Base), OpLoc, OpKind, ExtendedSS, 
-                               Destructor, DeclPtrTy(), HasTrailingLParen);
-  
+  return DiagnoseDtorReference(Destructed.getLocation(), move(Result));
 }
 
 Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
@@ -2683,11 +2550,6 @@
          "Invalid second type name in pseudo-destructor");
 
   Expr *BaseE = (Expr *)Base.get();
-  if (BaseE->isTypeDependent())
-    return ActOnDependentPseudoDestructorExpr(S, move(Base), OpLoc, OpKind,
-                                              SS, FirstTypeName, CCLoc, 
-                                              TildeLoc, SecondTypeName,
-                                              HasTrailingLParen);
   
   // C++ [expr.pseudo]p2:
   //   The left-hand side of the dot operator shall be of scalar type. The 
@@ -2697,27 +2559,46 @@
   if (OpKind == tok::arrow) {
     if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
       ObjectType = Ptr->getPointeeType();
-    } else if (!BaseE->isTypeDependent()) {
+    } else if (!ObjectType->isDependentType()) {
       // The user wrote "p->" when she probably meant "p."; fix it.
       Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
-      << ObjectType << true
-      << CodeModificationHint::CreateReplacement(OpLoc, ".");
+        << ObjectType << true
+        << CodeModificationHint::CreateReplacement(OpLoc, ".");
       if (isSFINAEContext())
         return ExprError();
       
       OpKind = tok::period;
     }
   }
+
+  // Compute the object type that we should use for name lookup purposes. Only
+  // record types and dependent types matter.
+  void *ObjectTypePtrForLookup = 0;
+  if (!SS.isSet()) {
+    ObjectTypePtrForLookup = (void *)ObjectType->getAs<RecordType>();
+    if (!ObjectTypePtrForLookup && ObjectType->isDependentType())
+      ObjectTypePtrForLookup = Context.DependentTy.getAsOpaquePtr();
+  }
   
   // Convert the name of the type being destructed (following the ~) into a 
   // type (with source-location information).
   QualType DestructedType;
   TypeSourceInfo *DestructedTypeInfo = 0;
+  PseudoDestructorTypeStorage Destructed;
   if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
     TypeTy *T = getTypeName(*SecondTypeName.Identifier, 
                             SecondTypeName.StartLocation,
-                            S, &SS);
-    if (!T) {
+                            S, &SS, true, ObjectTypePtrForLookup);
+    if (!T && 
+        ((SS.isSet() && !computeDeclContext(SS, false)) ||
+         (!SS.isSet() && ObjectType->isDependentType()))) {
+      // The name of the type being destroyed is a dependent name, and we 
+      // couldn't find anything useful in scope. Just store the identifier and
+      // it's location, and we'll perform (qualified) name lookup again at
+      // template instantiation time.
+      Destructed = PseudoDestructorTypeStorage(SecondTypeName.Identifier,
+                                               SecondTypeName.StartLocation);
+    } else if (!T) {
       Diag(SecondTypeName.StartLocation, 
            diag::err_pseudo_dtor_destructor_non_type)
         << SecondTypeName.Identifier << ObjectType;
@@ -2748,9 +2629,12 @@
   
   // If we've performed some kind of recovery, (re-)build the type source 
   // information.
-  if (!DestructedTypeInfo)
-    DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
+  if (!DestructedType.isNull()) {
+    if (!DestructedTypeInfo)
+      DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
                                                   SecondTypeName.StartLocation);
+    Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+  }
   
   // Convert the name of the scope type (the type prior to '::') into a type.
   TypeSourceInfo *ScopeTypeInfo = 0;
@@ -2760,7 +2644,7 @@
     if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
       TypeTy *T = getTypeName(*FirstTypeName.Identifier, 
                               FirstTypeName.StartLocation,
-                              S, &SS);
+                              S, &SS, false, ObjectTypePtrForLookup);
       if (!T) {
         Diag(FirstTypeName.StartLocation, 
              diag::err_pseudo_dtor_destructor_non_type)
@@ -2799,7 +2683,7 @@
     
   return BuildPseudoDestructorExpr(move(Base), OpLoc, OpKind, SS,
                                    ScopeTypeInfo, CCLoc, TildeLoc,
-                                   DestructedTypeInfo, HasTrailingLParen);
+                                   Destructed, HasTrailingLParen);
 }
 
 CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, 

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Feb 24 19:56:36 2010
@@ -884,12 +884,12 @@
   OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base,
                                                   SourceLocation OperatorLoc,
                                                   bool isArrow,
-                                                  NestedNameSpecifier *Qualifier,
+                                                NestedNameSpecifier *Qualifier,
                                                   SourceRange QualifierRange,
                                                   TypeSourceInfo *ScopeType,
                                                   SourceLocation CCLoc,
                                                   SourceLocation TildeLoc,
-                                                TypeSourceInfo *DestroyedType);
+                                        PseudoDestructorTypeStorage Destroyed);
 
   /// \brief Build a new unary operator expression.
   ///
@@ -4671,34 +4671,67 @@
   if (Base.isInvalid())
     return SemaRef.ExprError();
 
+  Sema::TypeTy *ObjectTypePtr = 0;
+  bool MayBePseudoDestructor = false;
+  Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base), 
+                                              E->getOperatorLoc(),
+                                        E->isArrow()? tok::arrow : tok::period,
+                                              ObjectTypePtr,
+                                              MayBePseudoDestructor);
+  if (Base.isInvalid())
+    return SemaRef.ExprError();
+                                              
+  QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
   NestedNameSpecifier *Qualifier
     = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
                                                 E->getQualifierRange(),
-                                                true);
+                                                true,
+                                                ObjectType);
   if (E->getQualifier() && !Qualifier)
     return SemaRef.ExprError();
 
-  // FIXME: Object type!
-  TypeSourceInfo *DestroyedTypeInfo
-    = getDerived().TransformType(E->getDestroyedTypeInfo());
-  if (!DestroyedTypeInfo)
-    return SemaRef.ExprError();
+  PseudoDestructorTypeStorage Destroyed;
+  if (E->getDestroyedTypeInfo()) {
+    TypeSourceInfo *DestroyedTypeInfo
+      = getDerived().TransformType(E->getDestroyedTypeInfo(), ObjectType);
+    if (!DestroyedTypeInfo)
+      return SemaRef.ExprError();
+    Destroyed = DestroyedTypeInfo;
+  } else if (ObjectType->isDependentType()) {
+    // We aren't likely to be able to resolve the identifier down to a type
+    // now anyway, so just retain the identifier.
+    Destroyed = PseudoDestructorTypeStorage(E->getDestroyedTypeIdentifier(),
+                                            E->getDestroyedTypeLoc());
+  } else {
+    // Look for a destructor known with the given name.
+    CXXScopeSpec SS;
+    if (Qualifier) {
+      SS.setScopeRep(Qualifier);
+      SS.setRange(E->getQualifierRange());
+    }
+    
+    Sema::TypeTy *T = SemaRef.getDestructorName(E->getTildeLoc(),
+                                              *E->getDestroyedTypeIdentifier(),
+                                                E->getDestroyedTypeLoc(),
+                                                /*Scope=*/0,
+                                                SS, ObjectTypePtr,
+                                                false);
+    if (!T)
+      return SemaRef.ExprError();
+    
+    Destroyed
+      = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.GetTypeFromParser(T),
+                                                 E->getDestroyedTypeLoc());
+  }
 
-  // FIXME: Object type!
   TypeSourceInfo *ScopeTypeInfo = 0;
   if (E->getScopeTypeInfo()) {
-    ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo());
+    ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo(), 
+                                               ObjectType);
     if (!ScopeTypeInfo)
       return SemaRef.ExprError();
   }
   
-  if (!getDerived().AlwaysRebuild() &&
-      Base.get() == E->getBase() &&
-      Qualifier == E->getQualifier() &&
-      ScopeTypeInfo == E->getScopeTypeInfo() &&
-      DestroyedTypeInfo == E->getDestroyedTypeInfo())
-    return SemaRef.Owned(E->Retain());
-
   return getDerived().RebuildCXXPseudoDestructorExpr(move(Base),
                                                      E->getOperatorLoc(),
                                                      E->isArrow(),
@@ -4707,7 +4740,7 @@
                                                      ScopeTypeInfo,
                                                      E->getColonColonLoc(),
                                                      E->getTildeLoc(),
-                                                     DestroyedTypeInfo);
+                                                     Destroyed);
 }
 
 template<typename Derived>
@@ -5758,7 +5791,7 @@
                                                      TypeSourceInfo *ScopeType,
                                                        SourceLocation CCLoc,
                                                        SourceLocation TildeLoc,
-                                               TypeSourceInfo *DestroyedType) {
+                                        PseudoDestructorTypeStorage Destroyed) {
   CXXScopeSpec SS;
   if (Qualifier) {
     SS.setRange(QualifierRange);
@@ -5767,18 +5800,19 @@
 
   Expr *BaseE = (Expr *)Base.get();
   QualType BaseType = BaseE->getType();
-  if (BaseE->isTypeDependent() ||
+  if (BaseE->isTypeDependent() || Destroyed.getIdentifier() ||
       (!isArrow && !BaseType->getAs<RecordType>()) ||
       (isArrow && BaseType->getAs<PointerType>() && 
-       !BaseType->getAs<PointerType>()->getAs<RecordType>())) {
+       !BaseType->getAs<PointerType>()->getPointeeType()->getAs<RecordType>())){
     // This pseudo-destructor expression is still a pseudo-destructor.
     return SemaRef.BuildPseudoDestructorExpr(move(Base), OperatorLoc,
                                              isArrow? tok::arrow : tok::period,
                                              SS, ScopeType, CCLoc, TildeLoc,
-                                             DestroyedType, 
+                                             Destroyed,
                                              /*FIXME?*/true);
   }
   
+  TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo();
   DeclarationName Name
     = SemaRef.Context.DeclarationNames.getCXXDestructorName(
                 SemaRef.Context.getCanonicalType(DestroyedType->getType()));
@@ -5788,8 +5822,7 @@
   return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
                                             OperatorLoc, isArrow,
                                             SS, /*FIXME: FirstQualifier*/ 0,
-                                            Name, 
-                        DestroyedType->getTypeLoc().getSourceRange().getBegin(),
+                                            Name, Destroyed.getLocation(),
                                             /*TemplateArgs*/ 0);
 }
 

Modified: cfe/trunk/test/SemaTemplate/destructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/destructor-template.cpp?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/destructor-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/destructor-template.cpp Wed Feb 24 19:56:36 2010
@@ -25,6 +25,8 @@
   void X<T>::f() {
     Y<T> *y;
     y->template Y<T>::~Y();
+    y->template Y<T>::~Y<T>();
+    y->~Y();
   }
   
   template struct X<int>;

Modified: cfe/trunk/test/SemaTemplate/member-access-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-access-expr.cpp?rev=97092&r1=97091&r2=97092&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/member-access-expr.cpp (original)
+++ cfe/trunk/test/SemaTemplate/member-access-expr.cpp Wed Feb 24 19:56:36 2010
@@ -63,11 +63,13 @@
 template<typename T>
 void destruct(T* ptr) {
   ptr->~T();
+  ptr->T::~T();
 }
 
 template<typename T>
 void destruct_intptr(int *ip) {
   ip->~T();
+  ip->T::~T();
 }
 
 void test_destruct(X2 *x2p, int *ip) {





More information about the cfe-commits mailing list