[cfe-commits] r84545 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/ParseExpr.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/TreeTransform.h test/SemaTemplate/member-template-access-expr.cpp

Douglas Gregor dgregor at apple.com
Mon Oct 19 15:04:39 PDT 2009


Author: dgregor
Date: Mon Oct 19 17:04:39 2009
New Revision: 84545

URL: http://llvm.org/viewvc/llvm-project?rev=84545&view=rev
Log:
Parse a simple-template-id following a '~' when calling a destructor, e.g.,

  t->~T<A0, A1>()

Fixes PR5213.


Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Oct 19 17:04:39 2009
@@ -1390,6 +1390,34 @@
     return ExprEmpty();
   }
 
+  /// \brief Parsed a C++ destructor reference that refers to a type.
+  ///
+  /// This action is used when parsing a destructor reference that uses a 
+  /// template-id, e.g.,
+  ///
+  /// \code
+  /// t->~Tmpl<T1, T2>
+  /// \endcode
+  ///
+  /// \param S the scope in which the destructor reference occurs.
+  /// \param Base the base object of the destructor reference expression.
+  /// \param OpLoc the location of the operator ('.' or '->').
+  /// \param OpKind the kind of the destructor reference operator ('.' or '->').
+  /// \param TypeRange the source range that covers the destructor type.
+  /// \param Type the type that is being destroyed.
+  /// \param SS the scope specifier that precedes the destructor name.
+  /// \param HasTrailingLParen whether the destructor name is followed by a '('.
+  virtual OwningExprResult
+  ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
+                               SourceLocation OpLoc,
+                               tok::TokenKind OpKind,
+                               SourceRange TypeRange,
+                               TypeTy *Type,
+                               const CXXScopeSpec &SS,
+                               bool HasTrailingLParen) {
+    return ExprEmpty();
+  }
+  
   /// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator
   /// reference, for example:
   ///

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Oct 19 17:04:39 2009
@@ -972,13 +972,41 @@
           return ExprError();
         }
 
-        if (!LHS.isInvalid())
-          LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
-                                                     OpLoc, OpKind,
-                                                     Tok.getLocation(),
-                                                     Tok.getIdentifierInfo(),
-                                                     SS,
-                                               NextToken().is(tok::l_paren));
+        if (NextToken().is(tok::less)) {
+          // class-name: 
+          //     ~ simple-template-id
+          TemplateTy Template 
+            = Actions.ActOnDependentTemplateName(SourceLocation(),
+                                                 *Tok.getIdentifierInfo(),   
+                                                 Tok.getLocation(),
+                                                 SS,
+                                                 ObjectType);
+          if (AnnotateTemplateIdToken(Template, TNK_Type_template, &SS, 
+                                      SourceLocation(), true))
+            return ExprError();
+          
+          assert(Tok.is(tok::annot_typename) && 
+                 "AnnotateTemplateIdToken didn't work?");
+          if (!LHS.isInvalid())
+            LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
+                                                       OpLoc, OpKind,
+                                                       Tok.getAnnotationRange(),
+                                                       Tok.getAnnotationValue(),
+                                                       SS,
+                                                 NextToken().is(tok::l_paren));                                                                   
+        } else {
+          // class-name: 
+          //     ~ identifier
+          if (!LHS.isInvalid())
+            LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
+                                                       OpLoc, OpKind,
+                                                       Tok.getLocation(),
+                                                       Tok.getIdentifierInfo(),
+                                                       SS,
+                                                 NextToken().is(tok::l_paren));
+        }
+        
+        // Consume the identifier or template-id token.
         ConsumeToken();
       } else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {
         // We have a reference to a member operator, e.g., t.operator int or

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Oct 19 17:04:39 2009
@@ -2108,6 +2108,15 @@
                                bool HasTrailingLParen);
 
   virtual OwningExprResult
+  ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
+                               SourceLocation OpLoc,
+                               tok::TokenKind OpKind,
+                               SourceRange TypeRange,
+                               TypeTy *Type,
+                               const CXXScopeSpec &SS,
+                               bool HasTrailingLParen);
+    
+  virtual OwningExprResult
   ActOnOverloadedOperatorReferenceExpr(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=84545&r1=84544&r2=84545&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Oct 19 17:04:39 2009
@@ -2099,6 +2099,8 @@
                                        ClassName);
   else {
     TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, &SS);
+    
+    // FIXME: If Base is dependent, we might not be able to resolve it here.
     if (!BaseTy) {
       Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
         << ClassName;
@@ -2108,25 +2110,41 @@
     BaseType = GetTypeFromParser(BaseTy);
   }
 
-  CanQualType CanBaseType = Context.getCanonicalType(BaseType);
-  DeclarationName DtorName =
-    Context.DeclarationNames.getCXXDestructorName(CanBaseType);
+  return ActOnDestructorReferenceExpr(S, move(Base), OpLoc, OpKind,
+                                      SourceRange(ClassNameLoc),
+                                      BaseType.getAsOpaquePtr(),
+                                      SS, HasTrailingLParen);
+}
 
+Sema::OwningExprResult
+Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
+                             SourceLocation OpLoc,
+                             tok::TokenKind OpKind,
+                             SourceRange TypeRange,
+                             TypeTy *T,
+                             const CXXScopeSpec &SS,
+                             bool HasTrailingLParen) {
+  QualType Type = QualType::getFromOpaquePtr(T);
+  CanQualType CanType = Context.getCanonicalType(Type);
+  DeclarationName DtorName =
+    Context.DeclarationNames.getCXXDestructorName(CanType);
+  
   OwningExprResult Result
-    = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc,
-                               DtorName, DeclPtrTy(), &SS);
+    = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, 
+                               TypeRange.getBegin(), DtorName, DeclPtrTy(), 
+                               &SS);
   if (Result.isInvalid() || HasTrailingLParen)
     return move(Result);
-
+  
   // The only way a reference to a destructor can be used is to
   // immediately call them. Since the next token is not a '(', produce a
   // diagnostic and build the call now.
   Expr *E = (Expr *)Result.get();
-  SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(E->getLocEnd());
+  SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(TypeRange.getEnd());
   Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
     << isa<CXXPseudoDestructorExpr>(E)
     << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()");
-
+  
   return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,
                        MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);
 }

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

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Oct 19 17:04:39 2009
@@ -253,7 +253,8 @@
   /// Identifiers and selectors are returned unmodified. Sublcasses may
   /// override this function to provide alternate behavior.
   DeclarationName TransformDeclarationName(DeclarationName Name,
-                                           SourceLocation Loc);
+                                           SourceLocation Loc,
+                                           QualType ObjectType = QualType());
 
   /// \brief Transform the given template name.
   ///
@@ -276,6 +277,10 @@
   QualType Transform##CLASS##Type(const CLASS##Type *T);
 #include "clang/AST/TypeNodes.def"
 
+  QualType 
+  TransformTemplateSpecializationType(const TemplateSpecializationType *T,
+                                      QualType ObjectType);
+  
   OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
 
 #define STMT(Node, Parent)                        \
@@ -1734,7 +1739,8 @@
 template<typename Derived>
 DeclarationName
 TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
-                                                 SourceLocation Loc) {
+                                                 SourceLocation Loc,
+                                                 QualType ObjectType) {
   if (!Name)
     return Name;
 
@@ -1751,7 +1757,14 @@
   case DeclarationName::CXXDestructorName:
   case DeclarationName::CXXConversionFunctionName: {
     TemporaryBase Rebase(*this, Loc, Name);
-    QualType T = getDerived().TransformType(Name.getCXXNameType());
+    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());
     if (T.isNull())
       return DeclarationName();
 
@@ -1814,7 +1827,8 @@
       return TemplateName();
 
     if (!getDerived().AlwaysRebuild() &&
-        NNS == DTN->getQualifier())
+        NNS == DTN->getQualifier() &&
+        ObjectType.isNull())
       return Name;
 
     return getDerived().RebuildTemplateName(NNS, *DTN->getName(), ObjectType);
@@ -2336,10 +2350,18 @@
 }
 
 template<typename Derived>
+inline QualType 
+TreeTransform<Derived>::TransformTemplateSpecializationType(
+                                          const TemplateSpecializationType *T) {
+  return TransformTemplateSpecializationType(T, QualType());
+}
+  
+template<typename Derived>
 QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
-                                        const TemplateSpecializationType *T) {
+                                        const TemplateSpecializationType *T,
+                                                          QualType ObjectType) {
   TemplateName Template
-    = getDerived().TransformTemplateName(T->getTemplateName());
+    = getDerived().TransformTemplateName(T->getTemplateName(), ObjectType);
   if (Template.isNull())
     return QualType();
 
@@ -4186,7 +4208,7 @@
   // refer to a built-in type!).
   NamedDecl *FirstQualifierInScope
     = cast_or_null<NamedDecl>(
-              getDerived().TransformDecl(E->getFirstQualifierFoundInScope()));
+               getDerived().TransformDecl(E->getFirstQualifierFoundInScope()));
 
   NestedNameSpecifier *Qualifier = 0;
   if (E->getQualifier()) {
@@ -4199,7 +4221,8 @@
   }
 
   DeclarationName Name
-    = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc());
+    = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc(),
+                                       QualType::getFromOpaquePtr(ObjectType));
   if (!Name)
     return SemaRef.ExprError();
 

Modified: cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp?rev=84545&r1=84544&r2=84545&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp (original)
+++ cfe/trunk/test/SemaTemplate/member-template-access-expr.cpp Mon Oct 19 17:04:39 2009
@@ -28,3 +28,26 @@
 //  int &ir = f1<X>(xd);
 }
 
+// PR5213
+template <class T>
+struct A {};
+
+template<class T>
+class B
+{
+  A<T> a_;
+  
+public:
+  void destroy();
+};
+
+template<class T>
+void
+B<T>::destroy()
+{
+  a_.~A<T>();
+}
+
+void do_destroy_B(B<int> b) {
+  b.destroy();
+}





More information about the cfe-commits mailing list