[cfe-commits] r96367 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h test/SemaCXX/destructor.cpp test/SemaCXX/invalid-member-expr.cpp test/SemaCXX/pseudo-destructors.cpp test/SemaTemplate/destructor-template.cpp

Douglas Gregor dgregor at apple.com
Tue Feb 16 11:10:00 PST 2010


Author: dgregor
Date: Tue Feb 16 13:09:40 2010
New Revision: 96367

URL: http://llvm.org/viewvc/llvm-project?rev=96367&view=rev
Log:
Improve parsing and instantiation of destructor names, so that we can
now cope with the destruction of types named as dependent templates,
e.g.,

  y->template Y<T>::~Y()

Nominally, we implement C++0x [basic.lookup.qual]p6. However, we don't
follow the letter of the standard here because that would fail to
parse

  template<typename T, typename U>
  X0<T, U>::~X0() { }

properly. The problem is captured in core issue 339, which gives some
(but not enough!) guidance. I expect to revisit this code when the
resolution of 339 is clear, and/or we start capturing better source
information for DeclarationNames.

Fixes PR6152.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    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/destructor.cpp
    cfe/trunk/test/SemaCXX/invalid-member-expr.cpp
    cfe/trunk/test/SemaCXX/pseudo-destructors.cpp
    cfe/trunk/test/SemaTemplate/destructor-template.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Feb 16 13:09:40 2010
@@ -146,8 +146,6 @@
 def err_unexpected_typedef_ident : Error<
   "unexpected type name %0: expected identifier">;
 def err_expected_class_name : Error<"expected class name">;
-def err_destructor_class_name : Error<
-  "expected the class name after '~' to name a destructor">;
 def err_unspecified_vla_size_with_static : Error<
   "'static' may not be used with an unspecified variable length array size">;
 
@@ -247,8 +245,10 @@
 def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
 def err_using_namespace_in_class : Error<
   "'using namespace' is not allowed in classes">;
-def err_ident_in_pseudo_dtor_not_a_type : Error<
-  "identifier %0 in pseudo-destructor expression does not name a type">;
+def err_destructor_tilde_identifier : Error<
+  "expected a class name after '~' to name a destructor">;
+def err_destructor_template_id : Error<
+  "destructor name %0 does not refer to a template">;
 
 // C++ derived classes
 def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Feb 16 13:09:40 2010
@@ -557,6 +557,10 @@
   "destructor cannot be declared using a typedef %0 of the class name">;
 def err_destructor_name : Error<
   "expected the class name after '~' to name the enclosing class">;
+def err_destructor_class_name : Error<
+  "expected the class name after '~' to name a destructor">;
+def err_ident_in_pseudo_dtor_not_a_type : Error<
+  "identifier %0 in pseudo-destructor expression does not name a type">;
 
 // C++ initialization
 def err_init_conversion_failed : Error<

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Feb 16 13:09:40 2010
@@ -1075,7 +1075,7 @@
                                                    SourceLocation RLoc) {
     return ExprEmpty();
   }
-  
+
   /// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref])
   /// of the form \c x.m or \c p->m.
   ///
@@ -1473,6 +1473,18 @@
 
   //===------------------------- C++ Expressions --------------------------===//
 
+  /// \brief Parsed a destructor name or pseudo-destructor name. 
+  ///
+  /// \returns the type being destructed.
+  virtual TypeTy *getDestructorName(SourceLocation TildeLoc,
+                                    IdentifierInfo &II, SourceLocation NameLoc,
+                                    Scope *S, const CXXScopeSpec &SS,
+                                    TypeTy *ObjectType,
+                                    bool EnteringContext) {
+    return getTypeName(II, NameLoc, S, &SS, false, ObjectType);
+  }
+
+
   /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
   virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
                                              tok::TokenKind Kind,

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Feb 16 13:09:40 2010
@@ -1387,8 +1387,7 @@
   //===--------------------------------------------------------------------===//
   // C++ 9: classes [class] and C structs/unions.
   TypeResult ParseClassName(SourceLocation &EndLocation,
-                            const CXXScopeSpec *SS = 0,
-                            bool DestrExpected = false);
+                            const CXXScopeSpec *SS = 0);
   void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc,
                            DeclSpec &DS,
                 const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Feb 16 13:09:40 2010
@@ -464,8 +464,7 @@
 ///         simple-template-id
 ///
 Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
-                                          const CXXScopeSpec *SS,
-                                          bool DestrExpected) {
+                                          const CXXScopeSpec *SS) {
   // Check whether we have a template-id that names a type.
   if (Tok.is(tok::annot_template_id)) {
     TemplateIdAnnotation *TemplateId
@@ -536,8 +535,7 @@
   // We have an identifier; check whether it is actually a type.
   TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true);
   if (!Type) {    
-    Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name
-                            : diag::err_expected_class_name);
+    Diag(IdLoc, diag::err_expected_class_name);
     return true;
   }
 

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Feb 16 13:09:40 2010
@@ -846,13 +846,8 @@
                                    EnteringContext, Template);
       
       if (TNK == TNK_Non_template && Id.DestructorName == 0) {
-        // The identifier following the destructor did not refer to a template
-        // or to a type. Complain.
-        if (ObjectType)
-          Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
-            << Name;        
-        else
-          Diag(NameLoc, diag::err_destructor_class_name);
+        Diag(NameLoc, diag::err_destructor_template_id)
+          << Name << SS.getRange();
         return true;        
       }
     }
@@ -1258,7 +1253,7 @@
     
     // Parse the class-name.
     if (Tok.isNot(tok::identifier)) {
-      Diag(Tok, diag::err_destructor_class_name);
+      Diag(Tok, diag::err_destructor_tilde_identifier);
       return true;
     }
 
@@ -1273,17 +1268,13 @@
     }
     
     // Note that this is a destructor name.
-    Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
-                                             CurScope, &SS, false, ObjectType);
-    if (!Ty) {
-      if (ObjectType)
-        Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
-          << ClassName;        
-      else
-        Diag(ClassNameLoc, diag::err_destructor_class_name);
+    Action::TypeTy *Ty = Actions.getDestructorName(TildeLoc, *ClassName, 
+                                                   ClassNameLoc, CurScope,
+                                                   SS, ObjectType,
+                                                   EnteringContext);
+    if (!Ty)
       return true;
-    }
-    
+
     Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
     return false;
   }

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Feb 16 13:09:40 2010
@@ -2056,6 +2056,12 @@
                                SourceLocation Loc,                                    
                       ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs);
     
+  virtual TypeTy *getDestructorName(SourceLocation TildeLoc,
+                                    IdentifierInfo &II, SourceLocation NameLoc,
+                                    Scope *S, const CXXScopeSpec &SS,
+                                    TypeTy *ObjectType,
+                                    bool EnteringContext);
+
   /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
   virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
                                              tok::TokenKind Kind,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Feb 16 13:09:40 2010
@@ -24,6 +24,232 @@
 #include "llvm/ADT/STLExtras.h"
 using namespace clang;
 
+Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
+                                        IdentifierInfo &II, 
+                                        SourceLocation NameLoc,
+                                        Scope *S, const CXXScopeSpec &SS,
+                                        TypeTy *ObjectTypePtr,
+                                        bool EnteringContext) {
+  // Determine where to perform name lookup.
+
+  // FIXME: This area of the standard is very messy, and the current
+  // wording is rather unclear about which scopes we search for the
+  // destructor name; see core issues 399 and 555. Issue 399 in
+  // particular shows where the current description of destructor name
+  // lookup is completely out of line with existing practice, e.g.,
+  // this appears to be ill-formed:
+  //
+  //   namespace N {
+  //     template <typename T> struct S {
+  //       ~S();
+  //     };
+  //   }
+  //
+  //   void f(N::S<int>* s) {
+  //     s->N::S<int>::~S();
+  //   }
+  //
+  // 
+  QualType SearchType;
+  DeclContext *LookupCtx = 0;
+  bool isDependent = false;
+  bool LookInScope = false;
+
+  // If we have an object type, it's because we are in a
+  // pseudo-destructor-expression or a member access expression, and
+  // we know what type we're looking for.
+  if (ObjectTypePtr)
+    SearchType = GetTypeFromParser(ObjectTypePtr);
+
+  if (SS.isSet()) {
+    // C++ [basic.lookup.qual]p6:
+    //   If a pseudo-destructor-name (5.2.4) contains a
+    //   nested-name-specifier, the type-names are looked up as types
+    //   in the scope designated by the nested-name-specifier. Similarly, in 
+    //   a qualified-id of theform:
+    //
+    //     :: [opt] nested-name-specifier[opt] class-name :: ~class-name 
+    //
+    //   the second class-name is looked up in the same scope as the first.
+    //
+    // To implement this, we look at the prefix of the
+    // nested-name-specifier we were given, and determine the lookup
+    // context from that.
+    NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+    if (NestedNameSpecifier *Prefix = NNS->getPrefix()) {
+      CXXScopeSpec PrefixSS;
+      PrefixSS.setScopeRep(Prefix);
+      LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
+      isDependent = isDependentScopeSpecifier(PrefixSS);
+    } else if (ObjectTypePtr) {
+      LookupCtx = computeDeclContext(SearchType);
+      isDependent = SearchType->isDependentType();
+    } else {
+      LookupCtx = computeDeclContext(SS, EnteringContext);
+      if (LookupCtx && !LookupCtx->isTranslationUnit()) {
+        LookupCtx = LookupCtx->getParent();
+        isDependent = LookupCtx->isDependentContext();
+      } else {
+        isDependent = false;
+      }
+    }
+
+    LookInScope = false;
+  } else if (ObjectTypePtr) {
+    // C++ [basic.lookup.classref]p3:
+    //   If the unqualified-id is ~type-name, the type-name is looked up
+    //   in the context of the entire postfix-expression. If the type T
+    //   of the object expression is of a class type C, the type-name is
+    //   also looked up in the scope of class C. At least one of the
+    //   lookups shall find a name that refers to (possibly
+    //   cv-qualified) T.
+    LookupCtx = computeDeclContext(SearchType);
+    isDependent = SearchType->isDependentType();
+    assert((isDependent || !SearchType->isIncompleteType()) && 
+           "Caller should have completed object type");
+
+    LookInScope = true;
+  } else {
+    // Perform lookup into the current scope (only).
+    LookInScope = true;
+  }
+
+  LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName);
+  for (unsigned Step = 0; Step != 2; ++Step) {
+    // Look for the name first in the computed lookup context (if we
+    // have one) and, if that fails to find a match, in the sope (if
+    // we're allowed to look there).
+    Found.clear();
+    if (Step == 0 && LookupCtx)
+      LookupQualifiedName(Found, LookupCtx);
+    else if (Step == 1 && LookInScope)
+      LookupName(Found, S);
+    else
+      continue;
+
+    // FIXME: Should we be suppressing ambiguities here?
+    if (Found.isAmbiguous())
+      return 0;
+
+    if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) {
+      QualType T = Context.getTypeDeclType(Type);
+      // If we found the injected-class-name of a class template, retrieve the
+      // type of that template.
+      // FIXME: We really shouldn't need to do this.
+      if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Type))
+        if (Record->isInjectedClassName())
+          if (Record->getDescribedClassTemplate())
+            T = Record->getDescribedClassTemplate()
+                                           ->getInjectedClassNameType(Context);
+
+      if (SearchType.isNull() || SearchType->isDependentType() ||
+          Context.hasSameUnqualifiedType(T, SearchType)) {
+        // We found our type!
+
+        return T.getAsOpaquePtr();
+      }
+    }
+
+    // If the name that we found is a class template name, and it is
+    // the same name as the template name in the last part of the
+    // nested-name-specifier (if present) or the object type, then
+    // this is the destructor for that class.
+    // FIXME: This is a workaround until we get real drafting for core
+    // issue 399, for which there isn't even an obvious direction. 
+    if (ClassTemplateDecl *Template = Found.getAsSingle<ClassTemplateDecl>()) {
+      QualType MemberOfType;
+      if (SS.isSet()) {
+        if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) {
+          // Figure out the type of the context, if it has one.
+          if (ClassTemplateSpecializationDecl *Spec
+                          = dyn_cast<ClassTemplateSpecializationDecl>(Ctx))
+            MemberOfType = Context.getTypeDeclType(Spec);
+          else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) {
+            if (Record->getDescribedClassTemplate())
+              MemberOfType = Record->getDescribedClassTemplate()
+                                          ->getInjectedClassNameType(Context);
+            else
+              MemberOfType = Context.getTypeDeclType(Record);
+          }
+        }
+      }
+      if (MemberOfType.isNull())
+        MemberOfType = SearchType;
+      
+      if (MemberOfType.isNull())
+        continue;
+
+      // We're referring into a class template specialization. If the
+      // class template we found is the same as the template being
+      // specialized, we found what we are looking for.
+      if (const RecordType *Record = MemberOfType->getAs<RecordType>()) {
+        if (ClassTemplateSpecializationDecl *Spec
+              = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
+          if (Spec->getSpecializedTemplate()->getCanonicalDecl() ==
+                Template->getCanonicalDecl())
+            return MemberOfType.getAsOpaquePtr();
+        }
+
+        continue;
+      }
+      
+      // We're referring to an unresolved class template
+      // specialization. Determine whether we class template we found
+      // is the same as the template being specialized or, if we don't
+      // know which template is being specialized, that it at least
+      // has the same name.
+      if (const TemplateSpecializationType *SpecType
+            = MemberOfType->getAs<TemplateSpecializationType>()) {
+        TemplateName SpecName = SpecType->getTemplateName();
+
+        // The class template we found is the same template being
+        // specialized.
+        if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) {
+          if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl())
+            return MemberOfType.getAsOpaquePtr();
+
+          continue;
+        }
+
+        // The class template we found has the same name as the
+        // (dependent) template name being specialized.
+        if (DependentTemplateName *DepTemplate 
+                                    = SpecName.getAsDependentTemplateName()) {
+          if (DepTemplate->isIdentifier() &&
+              DepTemplate->getIdentifier() == Template->getIdentifier())
+            return MemberOfType.getAsOpaquePtr();
+
+          continue;
+        }
+      }
+    }
+  }
+
+  if (isDependent) {
+    // We didn't find our type, but that's okay: it's dependent
+    // anyway.
+    NestedNameSpecifier *NNS = 0;
+    SourceRange Range;
+    if (SS.isSet()) {
+      NNS = (NestedNameSpecifier *)SS.getScopeRep();
+      Range = SourceRange(SS.getRange().getBegin(), NameLoc);
+    } else {
+      NNS = NestedNameSpecifier::Create(Context, &II);
+      Range = SourceRange(NameLoc);
+    }
+
+    return CheckTypenameType(NNS, II, Range).getAsOpaquePtr();
+  }
+
+  if (ObjectTypePtr)
+    Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+      << &II;        
+  else
+    Diag(NameLoc, diag::err_destructor_class_name);
+
+  return 0;
+}
+
 /// ActOnCXXTypeidOfType - Parse typeid( type-id ).
 Action::OwningExprResult
 Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Feb 16 13:09:40 2010
@@ -4911,18 +4911,21 @@
     /// \brief Transforms a typename type by determining whether the type now
     /// refers to a member of the current instantiation, and then
     /// type-checking and building a QualifiedNameType (when possible).
-    QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL);
+    QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL, 
+                                   QualType ObjectType);
   };
 }
 
 QualType
 CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB,
-                                                     TypenameTypeLoc TL) {
+                                                     TypenameTypeLoc TL, 
+                                                     QualType ObjectType) {
   TypenameType *T = TL.getTypePtr();
 
   NestedNameSpecifier *NNS
     = TransformNestedNameSpecifier(T->getQualifier(),
-                              /*FIXME:*/SourceRange(getBaseLocation()));
+                                   /*FIXME:*/SourceRange(getBaseLocation()),
+                                   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=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Feb 16 13:09:40 2010
@@ -570,7 +570,8 @@
     /// \brief Transforms a template type parameter type by performing
     /// substitution of the corresponding template type argument.
     QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
-                                           TemplateTypeParmTypeLoc TL);
+                                           TemplateTypeParmTypeLoc TL,
+                                           QualType ObjectType);
   };
 }
 
@@ -859,7 +860,8 @@
 
 QualType
 TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
-                                                TemplateTypeParmTypeLoc TL) {
+                                                TemplateTypeParmTypeLoc TL, 
+                                                    QualType ObjectType) {
   TemplateTypeParmType *T = TL.getTypePtr();
   if (T->getDepth() < TemplateArgs.getNumLevels()) {
     // Replace the template type parameter with its corresponding

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Feb 16 13:09:40 2010
@@ -191,7 +191,7 @@
   /// switched to storing TypeSourceInfos.
   ///
   /// \returns the transformed type.
-  QualType TransformType(QualType T);
+  QualType TransformType(QualType T, QualType ObjectType = QualType());
 
   /// \brief Transforms the given type-with-location into a new
   /// type-with-location.
@@ -201,13 +201,15 @@
   /// may override this function (to take over all type
   /// transformations) or some set of the TransformXXXType functions
   /// to alter the transformation.
-  TypeSourceInfo *TransformType(TypeSourceInfo *DI);
+  TypeSourceInfo *TransformType(TypeSourceInfo *DI, 
+                                QualType ObjectType = QualType());
 
   /// \brief Transform the given type-with-location into a new
   /// type, collecting location information in the given builder
   /// as necessary.
   ///
-  QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);
+  QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL, 
+                         QualType ObjectType = QualType());
 
   /// \brief Transform the given statement.
   ///
@@ -307,20 +309,17 @@
 
 #define ABSTRACT_TYPELOC(CLASS, PARENT)
 #define TYPELOC(CLASS, PARENT)                                   \
-  QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
+  QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T, \
+                                  QualType ObjectType = QualType());
 #include "clang/AST/TypeLocNodes.def"
 
-  QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL);
+  QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL, 
+                                  QualType ObjectType);
 
   QualType 
   TransformTemplateSpecializationType(const TemplateSpecializationType *T,
                                       QualType ObjectType);
 
-  QualType
-  TransformTemplateSpecializationType(TypeLocBuilder &TLB,
-                                      TemplateSpecializationTypeLoc TL,
-                                      QualType ObjectType);
-  
   OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
 
 #define STMT(Node, Parent)                        \
@@ -1779,7 +1778,8 @@
   case NestedNameSpecifier::TypeSpecWithTemplate:
   case NestedNameSpecifier::TypeSpec: {
     TemporaryBase Rebase(*this, Range.getBegin(), DeclarationName());
-    QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0));
+    QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0),
+                                            ObjectType);
     if (T.isNull())
       return 0;
 
@@ -1820,14 +1820,8 @@
   case DeclarationName::CXXDestructorName:
   case DeclarationName::CXXConversionFunctionName: {
     TemporaryBase Rebase(*this, Loc, Name);
-    QualType T;
-    if (!ObjectType.isNull() && 
-        isa<TemplateSpecializationType>(Name.getCXXNameType())) {
-      TemplateSpecializationType *SpecType
-        = cast<TemplateSpecializationType>(Name.getCXXNameType());
-      T = TransformTemplateSpecializationType(SpecType, ObjectType);
-    } else
-      T = getDerived().TransformType(Name.getCXXNameType());
+    QualType T = getDerived().TransformType(Name.getCXXNameType(), 
+                                            ObjectType);
     if (T.isNull())
       return DeclarationName();
 
@@ -1847,7 +1841,8 @@
   if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
     NestedNameSpecifier *NNS
       = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
-                      /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+                        /*FIXME:*/SourceRange(getDerived().getBaseLocation()),
+                                                  ObjectType);
     if (!NNS)
       return TemplateName();
 
@@ -1873,7 +1868,8 @@
   if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
     NestedNameSpecifier *NNS
       = getDerived().TransformNestedNameSpecifier(DTN->getQualifier(),
-                        /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+                        /*FIXME:*/SourceRange(getDerived().getBaseLocation()),
+                                                  ObjectType);
     if (!NNS && DTN->getQualifier())
       return TemplateName();
 
@@ -2055,7 +2051,8 @@
 //===----------------------------------------------------------------------===//
 
 template<typename Derived>
-QualType TreeTransform<Derived>::TransformType(QualType T) {
+QualType TreeTransform<Derived>::TransformType(QualType T, 
+                                               QualType ObjectType) {
   if (getDerived().AlreadyTransformed(T))
     return T;
 
@@ -2064,7 +2061,7 @@
   TypeSourceInfo *DI = getSema().Context.CreateTypeSourceInfo(T);
   DI->getTypeLoc().initialize(getDerived().getBaseLocation());
   
-  TypeSourceInfo *NewDI = getDerived().TransformType(DI);
+  TypeSourceInfo *NewDI = getDerived().TransformType(DI, ObjectType);
 
   if (!NewDI)
     return QualType();
@@ -2073,7 +2070,8 @@
 }
 
 template<typename Derived>
-TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) {
+TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI,
+                                                      QualType ObjectType) {
   if (getDerived().AlreadyTransformed(DI->getType()))
     return DI;
 
@@ -2082,7 +2080,7 @@
   TypeLoc TL = DI->getTypeLoc();
   TLB.reserve(TL.getFullDataSize());
 
-  QualType Result = getDerived().TransformType(TLB, TL);
+  QualType Result = getDerived().TransformType(TLB, TL, ObjectType);
   if (Result.isNull())
     return 0;
 
@@ -2091,12 +2089,14 @@
 
 template<typename Derived>
 QualType
-TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) {
+TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T,
+                                      QualType ObjectType) {
   switch (T.getTypeLocClass()) {
 #define ABSTRACT_TYPELOC(CLASS, PARENT)
 #define TYPELOC(CLASS, PARENT) \
   case TypeLoc::CLASS: \
-    return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T));
+    return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T), \
+                                               ObjectType);
 #include "clang/AST/TypeLocNodes.def"
   }
 
@@ -2112,10 +2112,12 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
-                                               QualifiedTypeLoc T) {
+                                               QualifiedTypeLoc T,
+                                               QualType ObjectType) {
   Qualifiers Quals = T.getType().getLocalQualifiers();
 
-  QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc());
+  QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc(),
+                                               ObjectType);
   if (Result.isNull())
     return QualType();
 
@@ -2166,7 +2168,8 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB,
-                                                      BuiltinTypeLoc T) {
+                                                      BuiltinTypeLoc T,
+                                                      QualType ObjectType) {
   BuiltinTypeLoc NewT = TLB.push<BuiltinTypeLoc>(T.getType());
   NewT.setBuiltinLoc(T.getBuiltinLoc());
   if (T.needsExtraLocalData())
@@ -2176,21 +2179,24 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB,
-                                                      ComplexTypeLoc T) {
+                                                      ComplexTypeLoc T,
+                                                      QualType ObjectType) {
   // FIXME: recurse?
   return TransformTypeSpecType(TLB, T);
 }
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB,
-                                                      PointerTypeLoc TL) {
+                                                      PointerTypeLoc TL, 
+                                                      QualType ObjectType) {
   TransformPointerLikeType(PointerType);
 }
 
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB,
-                                                  BlockPointerTypeLoc TL) {
+                                                  BlockPointerTypeLoc TL,
+                                                  QualType ObjectType) {
   TransformPointerLikeType(BlockPointerType);
 }
 
@@ -2201,7 +2207,8 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB,
-                                               ReferenceTypeLoc TL) {
+                                               ReferenceTypeLoc TL,
+                                               QualType ObjectType) {
   const ReferenceType *T = TL.getTypePtr();
 
   // Note that this works with the pointee-as-written.
@@ -2233,21 +2240,24 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB,
-                                                 LValueReferenceTypeLoc TL) {
-  return TransformReferenceType(TLB, TL);
+                                                 LValueReferenceTypeLoc TL,
+                                                     QualType ObjectType) {
+  return TransformReferenceType(TLB, TL, ObjectType);
 }
 
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB,
-                                                 RValueReferenceTypeLoc TL) {
-  return TransformReferenceType(TLB, TL);
+                                                 RValueReferenceTypeLoc TL,
+                                                     QualType ObjectType) {
+  return TransformReferenceType(TLB, TL, ObjectType);
 }
 
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
-                                                   MemberPointerTypeLoc TL) {
+                                                   MemberPointerTypeLoc TL,
+                                                   QualType ObjectType) {
   MemberPointerType *T = TL.getTypePtr();
 
   QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc());
@@ -2279,7 +2289,8 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
-                                                   ConstantArrayTypeLoc TL) {
+                                                   ConstantArrayTypeLoc TL,
+                                                   QualType ObjectType) {
   ConstantArrayType *T = TL.getTypePtr();
   QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
   if (ElementType.isNull())
@@ -2314,7 +2325,8 @@
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformIncompleteArrayType(
                                               TypeLocBuilder &TLB,
-                                              IncompleteArrayTypeLoc TL) {
+                                              IncompleteArrayTypeLoc TL,
+                                              QualType ObjectType) {
   IncompleteArrayType *T = TL.getTypePtr();
   QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
   if (ElementType.isNull())
@@ -2342,7 +2354,8 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
-                                                   VariableArrayTypeLoc TL) {
+                                                   VariableArrayTypeLoc TL,
+                                                   QualType ObjectType) {
   VariableArrayType *T = TL.getTypePtr();
   QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
   if (ElementType.isNull())
@@ -2383,7 +2396,8 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
-                                             DependentSizedArrayTypeLoc TL) {
+                                             DependentSizedArrayTypeLoc TL,
+                                                        QualType ObjectType) {
   DependentSizedArrayType *T = TL.getTypePtr();
   QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
   if (ElementType.isNull())
@@ -2426,7 +2440,8 @@
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
                                       TypeLocBuilder &TLB,
-                                      DependentSizedExtVectorTypeLoc TL) {
+                                      DependentSizedExtVectorTypeLoc TL,
+                                      QualType ObjectType) {
   DependentSizedExtVectorType *T = TL.getTypePtr();
 
   // FIXME: ext vector locs should be nested
@@ -2468,7 +2483,8 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
-                                                     VectorTypeLoc TL) {
+                                                     VectorTypeLoc TL,
+                                                     QualType ObjectType) {
   VectorType *T = TL.getTypePtr();
   QualType ElementType = getDerived().TransformType(T->getElementType());
   if (ElementType.isNull())
@@ -2491,7 +2507,8 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
-                                                        ExtVectorTypeLoc TL) {
+                                                        ExtVectorTypeLoc TL,
+                                                        QualType ObjectType) {
   VectorType *T = TL.getTypePtr();
   QualType ElementType = getDerived().TransformType(T->getElementType());
   if (ElementType.isNull())
@@ -2516,7 +2533,8 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
-                                                   FunctionProtoTypeLoc TL) {
+                                                   FunctionProtoTypeLoc TL,
+                                                   QualType ObjectType) {
   FunctionProtoType *T = TL.getTypePtr();
   QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
   if (ResultType.isNull())
@@ -2592,7 +2610,8 @@
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
                                                  TypeLocBuilder &TLB,
-                                                 FunctionNoProtoTypeLoc TL) {
+                                                 FunctionNoProtoTypeLoc TL,
+                                                 QualType ObjectType) {
   FunctionNoProtoType *T = TL.getTypePtr();
   QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
   if (ResultType.isNull())
@@ -2612,7 +2631,8 @@
 
 template<typename Derived> QualType
 TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
-                                                 UnresolvedUsingTypeLoc TL) {
+                                                 UnresolvedUsingTypeLoc TL,
+                                                     QualType ObjectType) {
   UnresolvedUsingType *T = TL.getTypePtr();
   Decl *D = getDerived().TransformDecl(T->getDecl());
   if (!D)
@@ -2635,7 +2655,8 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
-                                                      TypedefTypeLoc TL) {
+                                                      TypedefTypeLoc TL,
+                                                      QualType ObjectType) {
   TypedefType *T = TL.getTypePtr();
   TypedefDecl *Typedef
     = cast_or_null<TypedefDecl>(getDerived().TransformDecl(T->getDecl()));
@@ -2658,7 +2679,8 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
-                                                      TypeOfExprTypeLoc TL) {
+                                                      TypeOfExprTypeLoc TL,
+                                                       QualType ObjectType) {
   // typeof expressions are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
 
@@ -2685,7 +2707,8 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB,
-                                                     TypeOfTypeLoc TL) {
+                                                     TypeOfTypeLoc TL,
+                                                     QualType ObjectType) {
   TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo();
   TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI);
   if (!New_Under_TI)
@@ -2709,7 +2732,8 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
-                                                       DecltypeTypeLoc TL) {
+                                                       DecltypeTypeLoc TL,
+                                                       QualType ObjectType) {
   DecltypeType *T = TL.getTypePtr();
 
   // decltype expressions are not potentially evaluated contexts
@@ -2736,7 +2760,8 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB,
-                                                     RecordTypeLoc TL) {
+                                                     RecordTypeLoc TL,
+                                                     QualType ObjectType) {
   RecordType *T = TL.getTypePtr();
   RecordDecl *Record
     = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));
@@ -2759,7 +2784,8 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB,
-                                                   EnumTypeLoc TL) {
+                                                   EnumTypeLoc TL,
+                                                   QualType ObjectType) {
   EnumType *T = TL.getTypePtr();
   EnumDecl *Enum
     = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));
@@ -2782,7 +2808,8 @@
 
 template <typename Derived>
 QualType TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB,
-                                                      ElaboratedTypeLoc TL) {
+                                                         ElaboratedTypeLoc TL,
+                                                       QualType ObjectType) {
   ElaboratedType *T = TL.getTypePtr();
 
   // FIXME: this should be a nested type.
@@ -2808,26 +2835,20 @@
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTemplateTypeParmType(
                                                 TypeLocBuilder &TLB,
-                                                TemplateTypeParmTypeLoc TL) {
+                                                TemplateTypeParmTypeLoc TL,
+                                                QualType ObjectType) {
   return TransformTypeSpecType(TLB, TL);
 }
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
                                          TypeLocBuilder &TLB,
-                                         SubstTemplateTypeParmTypeLoc TL) {
+                                         SubstTemplateTypeParmTypeLoc TL,
+                                         QualType ObjectType) {
   return TransformTypeSpecType(TLB, TL);
 }
 
 template<typename Derived>
-inline QualType 
-TreeTransform<Derived>::TransformTemplateSpecializationType(
-                                          TypeLocBuilder &TLB,
-                                          TemplateSpecializationTypeLoc TL) {
-  return TransformTemplateSpecializationType(TLB, TL, QualType());
-}
-
-template<typename Derived>
 QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
                                       const TemplateSpecializationType *TST,
                                                         QualType ObjectType) {
@@ -2901,11 +2922,13 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformQualifiedNameType(TypeLocBuilder &TLB,
-                                                   QualifiedNameTypeLoc TL) {
+                                                   QualifiedNameTypeLoc TL,
+                                                   QualType ObjectType) {
   QualifiedNameType *T = TL.getTypePtr();
   NestedNameSpecifier *NNS
     = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
-                                                SourceRange());
+                                                SourceRange(),
+                                                ObjectType);
   if (!NNS)
     return QualType();
 
@@ -2930,14 +2953,16 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB,
-                                                       TypenameTypeLoc TL) {
+                                                       TypenameTypeLoc TL,
+                                                       QualType ObjectType) {
   TypenameType *T = TL.getTypePtr();
 
   /* FIXME: preserve source information better than this */
   SourceRange SR(TL.getNameLoc());
 
   NestedNameSpecifier *NNS
-    = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR);
+    = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR,
+                                                ObjectType);
   if (!NNS)
     return QualType();
 
@@ -2970,7 +2995,8 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB,
-                                                   ObjCInterfaceTypeLoc TL) {
+                                                   ObjCInterfaceTypeLoc TL,
+                                                   QualType ObjectType) {
   assert(false && "TransformObjCInterfaceType unimplemented");
   return QualType();
 }
@@ -2978,7 +3004,8 @@
 template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
-                                               ObjCObjectPointerTypeLoc TL) {
+                                               ObjCObjectPointerTypeLoc TL,
+                                                       QualType ObjectType) {
   assert(false && "TransformObjCObjectPointerType unimplemented");
   return QualType();
 }

Modified: cfe/trunk/test/SemaCXX/destructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/destructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/destructor.cpp Tue Feb 16 13:09:40 2010
@@ -40,9 +40,9 @@
   ~F(); // expected-error {{destructor cannot be redeclared}}
 };
 
-~; // expected-error {{expected the class name after '~' to name a destructor}}
+~; // expected-error {{expected a class name after '~' to name a destructor}}
 ~undef(); // expected-error {{expected the class name after '~' to name a destructor}}
-~operator+(int, int);  // expected-error {{expected the class name after '~' to name a destructor}}
+~operator+(int, int);  // expected-error {{expected a class name after '~' to name a destructor}}
 ~F(){} // expected-error {{destructor must be a non-static member function}}
 
 struct G {

Modified: cfe/trunk/test/SemaCXX/invalid-member-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/invalid-member-expr.cpp?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/invalid-member-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/invalid-member-expr.cpp Tue Feb 16 13:09:40 2010
@@ -6,7 +6,7 @@
   X x;
 
   x.int; // expected-error{{expected unqualified-id}}
-  x.~int(); // expected-error{{expected the class name}}
+  x.~int(); // expected-error{{expected a class name}}
   x.operator; // expected-error{{missing type specifier after 'operator'}}
   x.operator typedef; // expected-error{{missing type specifier after 'operator'}}
 }
@@ -15,7 +15,7 @@
   X *x;
 
   x->int; // expected-error{{expected unqualified-id}}
-  x->~int(); // expected-error{{expected the class name}}
+  x->~int(); // expected-error{{expected a class name}}
   x->operator; // expected-error{{missing type specifier after 'operator'}}
   x->operator typedef; // expected-error{{missing type specifier after 'operator'}}
 }

Modified: cfe/trunk/test/SemaCXX/pseudo-destructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/pseudo-destructors.cpp?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/pseudo-destructors.cpp (original)
+++ cfe/trunk/test/SemaCXX/pseudo-destructors.cpp Tue Feb 16 13:09:40 2010
@@ -18,8 +18,8 @@
   
   a->~foo(); // expected-error{{identifier 'foo' in pseudo-destructor expression does not name a type}}
   
-  // FIXME: the type printed below isn't wonderful
-  a->~Bar(); // expected-error{{no member named}}
+  // FIXME: the diagnostic below isn't wonderful
+  a->~Bar(); // expected-error{{does not name a type}}
   
   f->~Bar();
   f->~Foo();
@@ -28,7 +28,7 @@
   g().~Bar(); // expected-error{{non-scalar}}
   
   f->::~Bar();
-  f->N::~Wibble();
+  f->N::~Wibble(); // expected-error{{expected the class name after '~' to name a destructor}}
   
   f->::~Bar(17, 42); // expected-error{{cannot have any arguments}}
 }

Modified: cfe/trunk/test/SemaTemplate/destructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/destructor-template.cpp?rev=96367&r1=96366&r2=96367&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/destructor-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/destructor-template.cpp Tue Feb 16 13:09:40 2010
@@ -17,3 +17,16 @@
 }
 
 template void destroy_me(Incomplete*);
+
+namespace PR6152 {
+  template<typename T> struct X { void f(); };
+  template<typename T> struct Y { };
+  template<typename T>
+  void X<T>::f() {
+    Y<T> *y;
+    y->template Y<T>::~Y();
+  }
+  
+  template struct X<int>;
+}
+





More information about the cfe-commits mailing list