From d3d0cf105b80dc5107a28aea41cba3a3a83b7deb Mon Sep 17 00:00:00 2001
From: David Majnemer <david.majnemer@gmail.com>
Date: Wed, 19 Feb 2014 03:00:56 +0000
Subject: [PATCH] Implement DR577

DR18 previously forebode typedefs to be used as parameter types if they
were of type 'void'.  DR577 allows 'void' to be used as a function
parameter type regardless from where it came.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201631 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticSemaKinds.td      |  2 --
 include/clang/Sema/Sema.h                       |  1 -
 lib/Sema/SemaDecl.cpp                           | 17 -----------------
 lib/Sema/SemaLambda.cpp                         |  1 -
 test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp |  2 +-
 test/CXX/drs/dr0xx.cpp                          |  5 +----
 test/SemaCXX/alias-template.cpp                 |  2 +-
 7 files changed, 3 insertions(+), 27 deletions(-)

diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index e4d0f941b72..8984116ad0e 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2510,8 +2510,6 @@ def err_ident_list_in_fn_declaration : Error<
   "a parameter list without types is only allowed in a function definition">;
 def ext_param_not_declared : Extension<
   "parameter %0 was not declared, defaulting to type 'int'">;
-def err_param_typedef_of_void : Error<
-  "empty parameter list defined with a %select{typedef|type alias}0 of 'void' not allowed%select{ in C++|}0">;
 def err_param_default_argument : Error<
   "C does not support default arguments">;
 def err_param_default_argument_redefinition : Error<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 894e43493f6..9cb6635c3fd 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1521,7 +1521,6 @@ public:
                                      MultiTemplateParamsArg TemplateParamLists,
                                      bool &AddToScope);
   bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
-  void checkVoidParamDecl(ParmVarDecl *Param);
 
   bool CheckConstexprFunctionDecl(const FunctionDecl *FD);
   bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 72210757f34..c147681f03f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -6357,22 +6357,6 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
   }
 }
 
-void Sema::checkVoidParamDecl(ParmVarDecl *Param) {
-  // In C++, the empty parameter-type-list must be spelled "void"; a
-  // typedef of void is not permitted.
-  if (getLangOpts().CPlusPlus &&
-      Param->getType().getUnqualifiedType() != Context.VoidTy) {
-    bool IsTypeAlias = false;
-    if (const TypedefType *TT = Param->getType()->getAs<TypedefType>())
-      IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl());
-    else if (const TemplateSpecializationType *TST =
-               Param->getType()->getAs<TemplateSpecializationType>())
-      IsTypeAlias = TST->isTypeAlias();
-    Diag(Param->getLocation(), diag::err_param_typedef_of_void)
-      << IsTypeAlias;
-  }
-}
-
 enum OpenCLParamType {
   ValidKernelParam,
   PtrPtrKernelParam,
@@ -6915,7 +6899,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
         FTI.ArgInfo[0].Param &&
         cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
       // Empty arg list, don't push any params.
-      checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param));
     } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
       for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
         ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 8c1b57fd0fa..0e10bfdf6f8 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -901,7 +901,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
     if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
         cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
       // Empty arg list, don't push any params.
-      checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param));
     } else {
       Params.reserve(FTI.NumArgs);
       for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
index 89a28adcc65..cc44f74a554 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
@@ -154,5 +154,5 @@ namespace Access {
 namespace VoidArg {
   using V = void;
   V f(int); // ok
-  V g(V); // expected-error {{empty parameter list defined with a type alias of 'void' not allowed}}
+  V g(V); // ok (DR577)
 }
diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp
index 9f6f2eaef11..f11bb9d6873 100644
--- a/test/CXX/drs/dr0xx.cpp
+++ b/test/CXX/drs/dr0xx.cpp
@@ -194,10 +194,7 @@ namespace dr17 { // dr17: yes
   };
 }
 
-namespace dr18 { // dr18: yes
-  typedef void Void;
-  void f(Void); // expected-error {{empty parameter list defined with a typedef of 'void'}}
-}
+// dr18: sup 577
 
 namespace dr19 { // dr19: yes
   struct A {
diff --git a/test/SemaCXX/alias-template.cpp b/test/SemaCXX/alias-template.cpp
index db9c82afd59..5b3c3146368 100644
--- a/test/SemaCXX/alias-template.cpp
+++ b/test/SemaCXX/alias-template.cpp
@@ -136,7 +136,7 @@ namespace Access {
 namespace VoidArg {
   template<typename Z> using V = void;
   V<int> f(int); // ok
-  V<char> g(V<double>); // expected-error {{empty parameter list defined with a type alias of 'void' not allowed}}
+  V<char> g(V<double>); // ok (DR577)
 }
 
 namespace Curried {
-- 
GitLab