]> granicus.if.org Git - clang/commitdiff
Canonicalization and profiling for overloaded function declarations,
authorDouglas Gregor <dgregor@apple.com>
Fri, 31 Jul 2009 05:24:01 +0000 (05:24 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 31 Jul 2009 05:24:01 +0000 (05:24 +0000)
for those extra-esoteric cases. Not that any two given C++ compilers
agree on this test case, but this change gives us a strong definition
of equivalent types.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77664 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTContext.cpp
lib/AST/StmtProfile.cpp
test/SemaTemplate/canonical-expr-type.cpp

index 1b73679beb7c2f7f4b285566f2871c0c9d363d61..c4740843e5b59ade7cf2c3ea3338dc9188e6dd36 100644 (file)
@@ -2118,9 +2118,25 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
 
   // If this template name refers to a set of overloaded function templates, 
   /// the canonical template name merely stores the set of function templates.
-  if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl())
-    // FIXME: Can't really canonicalize a set of overloaded functions, can we?
-    return TemplateName(Ovl);
+  if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl()) {
+    OverloadedFunctionDecl *CanonOvl = 0;
+    for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
+                                                FEnd = Ovl->function_end();
+         F != FEnd; ++F) {
+      Decl *Canon = F->get()->getCanonicalDecl();
+      if (CanonOvl || Canon != F->get()) {
+        if (!CanonOvl)
+          CanonOvl = OverloadedFunctionDecl::Create(*this, 
+                                                    Ovl->getDeclContext(), 
+                                                    Ovl->getDeclName());
+        
+        CanonOvl->addOverload(
+                    AnyFunctionDecl::getFromNamedDecl(cast<NamedDecl>(Canon)));
+      }
+    }
+    
+    return TemplateName(CanonOvl? CanonOvl : Ovl);
+  }
   
   DependentTemplateName *DTN = Name.getAsDependentTemplateName();
   assert(DTN && "Non-dependent template names must refer to template decls.");
index 8039d97731561dde1659304a3ff88d199c5e4934..5714c682a2eb56164455079b004bb83c79012d88 100644 (file)
@@ -603,8 +603,7 @@ void StmtProfiler::VisitObjCIsaExpr(ObjCIsaExpr *S) {
 
 void StmtProfiler::VisitDecl(Decl *D) {
   if (Canonical && D) {
-    if (NonTypeTemplateParmDecl *NTTP 
-        = dyn_cast<NonTypeTemplateParmDecl>(D)) {
+    if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
       ID.AddInteger(NTTP->getDepth());
       ID.AddInteger(NTTP->getIndex());
       VisitType(NTTP->getType());
@@ -612,6 +611,29 @@ void StmtProfiler::VisitDecl(Decl *D) {
     }
     
     // FIXME: Template template parameters?
+    
+    if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
+      // Canonicalize all of the function declarations within the overload
+      // set.
+      llvm::SmallVector<Decl *, 4> Functions;
+      for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
+                                                  FEnd = Ovl->function_end();
+           F != FEnd; ++F)
+        Functions.push_back(F->get()->getCanonicalDecl());
+      
+      // Sorting the functions based on the point means that the ID generated
+      // will be different from one execution of the compiler to another.
+      // Since these IDs don't persist over time, the change in ordering will
+      // not affect compilation.
+      std::sort(Functions.begin(), Functions.end());
+      
+      for (llvm::SmallVector<Decl *, 4>::iterator F = Functions.begin(),
+                                               FEnd = Functions.end();
+           F != FEnd; ++F)
+        VisitDecl(*F);
+
+      return;
+    }
   }
   
   ID.AddPointer(D? D->getCanonicalDecl() : 0);
index 48147f0e4c6e0e9cb9a5d483e7cbf3fd642a4f80..f8cc57bc1ab9054a76304ef7f752604f75a5d8b8 100644 (file)
@@ -15,6 +15,23 @@ void f0(T x, __typeof__((f)(N)) y) { }
 template<typename U, U M>
 void f0(U u, __typeof__(f(M))) { } // expected-error{{redefinition}}
 
+// Test insane typeof(expr) overload set canonicalization
+void f(int);
+void f(double);
+
+template<typename T, T N>
+void f0a(T x, __typeof__(f(N)) y) { } // expected-note{{previous}}
+
+void f(int);
+
+template<typename T, T N>
+void f0a(T x, __typeof__(f(N)) y) { } // expected-error{{redefinition}}
+
+void f(float);
+
+template<typename T, T N>
+void f0a(T x, __typeof__(f(N)) y) { }
+
 // Test dependently-sized array canonicalization
 template<typename T, int N, int M>
 void f1(T (&array)[N + M]) { } // expected-note{{previous}}