[cfe-commits] r89475 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/SemaTemplate/instantiate-member-template.cpp

Douglas Gregor dgregor at apple.com
Fri Nov 20 11:42:02 PST 2009


Author: dgregor
Date: Fri Nov 20 13:42:02 2009
New Revision: 89475

URL: http://llvm.org/viewvc/llvm-project?rev=89475&view=rev
Log:
Teach FixOverloadedFunctionReference to build new expression ASTs rather
than tweaking existing ASTs, since we were (*gasp*) stomping on ASTs
within templates. I'm glad we found this little stick of TNT early...


Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Nov 20 13:42:02 2009
@@ -5238,7 +5238,12 @@
       return true;
     }
 
-    FixOverloadedFunctionReference(MemExpr, Method);
+    MemExprE = FixOverloadedFunctionReference(MemExprE, Method);
+    if (ParenExpr *ParenE = dyn_cast<ParenExpr>(MemExprE))
+      MemExpr = dyn_cast<MemberExpr>(ParenE->getSubExpr());
+    else
+      MemExpr = dyn_cast<MemberExpr>(MemExprE);
+    
   } else {
     Method = dyn_cast<CXXMethodDecl>(MemExpr->getMemberDecl());
   }
@@ -5604,16 +5609,28 @@
 /// refer (possibly indirectly) to Fn. Returns the new expr.
 Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
   if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
-    Expr *NewExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn);
-    PE->setSubExpr(NewExpr);
-    PE->setType(NewExpr->getType());
-  } else if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
-    Expr *NewExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn);
+    Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn);
+    if (SubExpr == PE->getSubExpr())
+      return PE->Retain();
+    
+    return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr);
+  } 
+  
+  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+    Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn);
     assert(Context.hasSameType(ICE->getSubExpr()->getType(), 
-                               NewExpr->getType()) &&
+                               SubExpr->getType()) &&
            "Implicit cast type cannot be determined from overload");
-    ICE->setSubExpr(NewExpr);
-  } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
+    if (SubExpr == ICE->getSubExpr())
+      return ICE->Retain();
+    
+    return new (Context) ImplicitCastExpr(ICE->getType(), 
+                                          ICE->getCastKind(),
+                                          SubExpr,
+                                          ICE->isLvalueCast());
+  } 
+  
+  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
     assert(UnOp->getOpcode() == UnaryOperator::AddrOf &&
            "Can only take the address of an overloaded function");
     if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
@@ -5625,59 +5642,109 @@
           // We have taken the address of a pointer to member
           // function. Perform the computation here so that we get the
           // appropriate pointer to member type.
-          DRE->setDecl(Fn);
-          DRE->setType(Fn->getType());
           QualType ClassType
-            = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
-          E->setType(Context.getMemberPointerType(Fn->getType(),
-                                                  ClassType.getTypePtr()));
-          return E;
+            = Context.getTypeDeclType(
+                                  cast<RecordDecl>(Method->getDeclContext()));
+          QualType MemPtrType
+            = Context.getMemberPointerType(Fn->getType(), 
+                                           ClassType.getTypePtr());
+
+          DeclRefExpr *NewDRE 
+            = DeclRefExpr::Create(Context,
+                                  DRE->getQualifier(),
+                                  DRE->getQualifierRange(),
+                                  Fn,
+                                  DRE->getLocation(),
+                                  DRE->hasExplicitTemplateArgumentList(),
+                                  DRE->getLAngleLoc(),
+                                  DRE->getTemplateArgs(),
+                                  DRE->getNumTemplateArgs(),
+                                  DRE->getRAngleLoc(),
+                                  Fn->getType(),
+                                  DRE->isTypeDependent(),
+                                  DRE->isValueDependent());
+          
+          return new (Context) UnaryOperator(NewDRE, UnaryOperator::AddrOf,
+                                             MemPtrType,
+                                             UnOp->getOperatorLoc());
         }
       }
       // FIXME: TemplateIdRefExpr referring to a member function template
       // specialization!
     }
-    Expr *NewExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
-    UnOp->setSubExpr(NewExpr);
-    UnOp->setType(Context.getPointerType(NewExpr->getType()));
+    Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
+    if (SubExpr == UnOp->getSubExpr())
+      return UnOp->Retain();
     
-    return UnOp;
-  } else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
-    assert((isa<OverloadedFunctionDecl>(DR->getDecl()) ||
-            isa<FunctionTemplateDecl>(DR->getDecl()) ||
-            isa<FunctionDecl>(DR->getDecl())) &&
+    return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf,
+                                     Context.getPointerType(SubExpr->getType()),
+                                       UnOp->getOperatorLoc());
+  }
+  
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    assert((isa<OverloadedFunctionDecl>(DRE->getDecl()) ||
+            isa<FunctionTemplateDecl>(DRE->getDecl()) ||
+            isa<FunctionDecl>(DRE->getDecl())) &&
            "Expected function or function template");
-    DR->setDecl(Fn);
-    E->setType(Fn->getType());
-  } else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {
-    MemExpr->setMemberDecl(Fn);
-    E->setType(Fn->getType());
-  } else if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) {
-    E = DeclRefExpr::Create(Context, 
-                            TID->getQualifier(), TID->getQualifierRange(),
-                            Fn, TID->getTemplateNameLoc(), 
-                            true,
-                            TID->getLAngleLoc(),
-                            TID->getTemplateArgs(),
-                            TID->getNumTemplateArgs(),
-                            TID->getRAngleLoc(),
-                            Fn->getType(), 
-                            /*FIXME?*/false, /*FIXME?*/false);
-    
+    return DeclRefExpr::Create(Context,
+                               DRE->getQualifier(),
+                               DRE->getQualifierRange(),
+                               Fn,
+                               DRE->getLocation(),
+                               DRE->hasExplicitTemplateArgumentList(),
+                               DRE->getLAngleLoc(),
+                               DRE->getTemplateArgs(),
+                               DRE->getNumTemplateArgs(),
+                               DRE->getRAngleLoc(),
+                               Fn->getType(),
+                               DRE->isTypeDependent(),
+                               DRE->isValueDependent());
+  } 
+  
+  if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {
+    assert((isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
+            isa<FunctionTemplateDecl>(MemExpr->getMemberDecl()) ||
+            isa<FunctionDecl>(MemExpr->getMemberDecl())) &&
+           "Expected member function or member function template");
+    return MemberExpr::Create(Context, MemExpr->getBase()->Retain(),
+                              MemExpr->isArrow(), 
+                              MemExpr->getQualifier(), 
+                              MemExpr->getQualifierRange(),
+                              Fn, 
+                              MemExpr->getMemberLoc(), 
+                              MemExpr->hasExplicitTemplateArgumentList(),
+                              MemExpr->getLAngleLoc(), 
+                              MemExpr->getTemplateArgs(),
+                              MemExpr->getNumTemplateArgs(),
+                              MemExpr->getRAngleLoc(),
+                              Fn->getType());
+  }
+  
+  if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) {
     // FIXME: Don't destroy TID here, since we need its template arguments
     // to survive.
     // TID->Destroy(Context);
-  } else if (isa<UnresolvedFunctionNameExpr>(E)) {
+    return DeclRefExpr::Create(Context, 
+                               TID->getQualifier(), TID->getQualifierRange(),
+                               Fn, TID->getTemplateNameLoc(), 
+                               true,
+                               TID->getLAngleLoc(),
+                               TID->getTemplateArgs(),
+                               TID->getNumTemplateArgs(),
+                               TID->getRAngleLoc(),
+                               Fn->getType(), 
+                               /*FIXME?*/false, /*FIXME?*/false);    
+  } 
+  
+  if (isa<UnresolvedFunctionNameExpr>(E))
     return DeclRefExpr::Create(Context, 
                                /*Qualifier=*/0,
                                /*QualifierRange=*/SourceRange(),
                                Fn, E->getLocStart(),
                                Fn->getType(), false, false);
-  } else {
-    assert(false && "Invalid reference to overloaded function");
-  }
   
-  return E;
+  assert(false && "Invalid reference to overloaded function");
+  return E->Retain();
 }
 
 } // end namespace clang

Modified: cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp?rev=89475&r1=89474&r2=89475&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp Fri Nov 20 13:42:02 2009
@@ -116,3 +116,18 @@
 
 X2<int&> x2a; // expected-note{{instantiation}}
 X2<float> x2b; // expected-note{{instantiation}}
+
+namespace N0 {
+  template<typename T>
+  struct X0 { };
+  
+  struct X1 {
+    template<typename T> void f(X0<T>& vals) { g(vals); }
+    template<typename T> void g(X0<T>& vals) { }
+  };
+  
+  void test(X1 x1, X0<int> x0i, X0<long> x0l) {
+    x1.f(x0i);
+    x1.f(x0l);
+  }  
+}





More information about the cfe-commits mailing list