]> granicus.if.org Git - clang/commitdiff
Correctly diagnose [basic.stc.dynamic.allocation]p1
authorAnders Carlsson <andersca@mac.com>
Sat, 12 Dec 2009 00:32:00 +0000 (00:32 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 12 Dec 2009 00:32:00 +0000 (00:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91190 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp [new file with mode: 0644]

index b00b1886f14b0e26dbba3185cbaf6cdbb6b84a8e..08fe28998d944349b1a81364a3d0aeb249918617 100644 (file)
@@ -4604,8 +4604,35 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
   }
 }
 
+static inline bool
+CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, 
+                                       const FunctionDecl *FnDecl) {
+  const DeclContext *DC = FnDecl->getDeclContext()->getLookupContext();
+  if (isa<NamespaceDecl>(DC)) {
+    return SemaRef.Diag(FnDecl->getLocation(), 
+                        diag::err_operator_new_delete_declared_in_namespace)
+      << FnDecl->getDeclName();
+  }
+  
+  if (isa<TranslationUnitDecl>(DC) && 
+      FnDecl->getStorageClass() == FunctionDecl::Static) {
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_declared_static)
+      << FnDecl->getDeclName();
+  }
+  
+  return true;
+}
+
 static bool
 CheckOperatorNewDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
+  // C++ [basic.stc.dynamic.allocation]p1:
+  //   A program is ill-formed if an allocation function is declared in a
+  //   namespace scope other than global scope or declared static in global 
+  //   scope.
+  if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
+    return true;
+  
   bool ret = false;
   if (FunctionDecl::param_iterator Param = FnDecl->param_begin()) {
     QualType SizeTy = 
@@ -4632,17 +4659,8 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
   //   A program is ill-formed if deallocation functions are declared in a
   //   namespace scope other than global scope or declared static in global 
   //   scope.
-  const DeclContext *DC = FnDecl->getDeclContext()->getLookupContext();
-  if (isa<NamespaceDecl>(DC)) {
-    return SemaRef.Diag(FnDecl->getLocation(), 
-                        diag::err_operator_new_delete_declared_in_namespace)
-      << FnDecl->getDeclName();
-  } else if (isa<TranslationUnitDecl>(DC) && 
-             FnDecl->getStorageClass() == FunctionDecl::Static) {
-    return SemaRef.Diag(FnDecl->getLocation(),
-                        diag::err_operator_new_delete_declared_static)
-      << FnDecl->getDeclName();
-  }
+  if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
+    return true;
 
   // C++ [basic.stc.dynamic.deallocation]p2:
   //   Each deallocation function shall return void and its first parameter 
diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp
new file mode 100644 (file)
index 0000000..f8fd9f2
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+#include <stddef.h>
+
+struct A {
+  void *operator new(size_t);
+};
+
+namespace NS {
+  void *operator new(size_t);; // expected-error {{'operator new' cannot be declared inside a namespace}}
+}
+
+static void *operator new(size_t); // expected-error {{'operator new' cannot be declared static in global scope}}