]> granicus.if.org Git - clang/commitdiff
Teach the allocation function overload handling to deal with templates, and
authorChandler Carruth <chandlerc@gmail.com>
Wed, 3 Feb 2010 11:02:14 +0000 (11:02 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Wed, 3 Feb 2010 11:02:14 +0000 (11:02 +0000)
prevent a crash on templates when looking for an existing declaration of the
predefined global operators. This fixes PR5918.

Added an easy test case for the overload handling, but testing the crash is
a bit trickier. Created a new test that can use multiple runs with a define to
trigger which test case is used so we can test this type of issue.

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

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/new-delete-predefined-decl.cpp [new file with mode: 0644]
test/SemaCXX/new-delete.cpp

index 7671995d609a19f7d4a1f8a20b63af2d4debe29b..850308e1477dd160d8ea4628a11764ed2df30014 100644 (file)
@@ -630,14 +630,19 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
        Alloc != AllocEnd; ++Alloc) {
     // Even member operator new/delete are implicitly treated as
     // static, so don't use AddMemberCandidate.
-    if (FunctionDecl *Fn = 
-          dyn_cast<FunctionDecl>((*Alloc)->getUnderlyingDecl())) {
-      AddOverloadCandidate(Fn, Alloc.getAccess(), Args, NumArgs, Candidates,
-                           /*SuppressUserConversions=*/false);
+
+    if (FunctionTemplateDecl *FnTemplate = 
+          dyn_cast<FunctionTemplateDecl>((*Alloc)->getUnderlyingDecl())) {
+      AddTemplateOverloadCandidate(FnTemplate, Alloc.getAccess(),
+                                   /*ExplicitTemplateArgs=*/0, Args, NumArgs,
+                                   Candidates,
+                                   /*SuppressUserConversions=*/false);
       continue;
-    } 
-    
-    // FIXME: Handle function templates
+    }
+
+    FunctionDecl *Fn = cast<FunctionDecl>((*Alloc)->getUnderlyingDecl());
+    AddOverloadCandidate(Fn, Alloc.getAccess(), Args, NumArgs, Candidates,
+                         /*SuppressUserConversions=*/false);
   }
 
   // Do the resolution.
@@ -768,12 +773,16 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
     DeclContext::lookup_iterator Alloc, AllocEnd;
     for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name);
          Alloc != AllocEnd; ++Alloc) {
-      // FIXME: Do we need to check for default arguments here?
-      FunctionDecl *Func = cast<FunctionDecl>(*Alloc);
-      if (Func->getNumParams() == 1 &&
+      // Only look at non-template functions, as it is the predefined,
+      // non-templated allocation function we are trying to declare here.
+      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) {
+        QualType InitialParamType =
           Context.getCanonicalType(
-            Func->getParamDecl(0)->getType().getUnqualifiedType()) == Argument)
-        return;
+            Func->getParamDecl(0)->getType().getUnqualifiedType());
+        // FIXME: Do we need to check for default arguments here?
+        if (Func->getNumParams() == 1 && InitialParamType == Argument)
+          return;
+      }
     }
   }
 
diff --git a/test/SemaCXX/new-delete-predefined-decl.cpp b/test/SemaCXX/new-delete-predefined-decl.cpp
new file mode 100644 (file)
index 0000000..6234b74
--- /dev/null
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -DTEMPLATE_OVERLOAD -fsyntax-only -verify %s
+
+#include <stddef.h>
+
+// Note that each test must be run separately so it can be the first operator
+// new declaration in the file.
+
+#if defined(TEMPLATE_OVERLOAD)
+// Don't crash on global template operator new overloads.
+template<typename T> void* operator new(size_t, T);
+void test_template_overload() {
+  (void)new(0) double;
+}
+#endif
+
+void test_predefined() {
+  (void)new double;
+}
index b058fc13d96f336944449e872dab3625b5437220..6f8955534311abd2f88d0c6e3f2376bf3dd70f66 100644 (file)
@@ -216,3 +216,10 @@ static void* f(void* g)
 {
     return new (g) X13();
 }
+
+namespace PR5918 { // Look for template operator new overloads.
+  struct S { template<typename T> static void* operator new(size_t, T); };
+  void test() {
+    (void)new(0) S;
+  }
+}