[llvm-branch-commits] [clang] 825f80e - [Sema] Introduce function reference conversion, NFC

Aaron Puchert via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Nov 22 11:56:39 PST 2020


Author: Aaron Puchert
Date: 2020-11-22T20:51:57+01:00
New Revision: 825f80e111f2815a009084f65267be3b5bf0897a

URL: https://github.com/llvm/llvm-project/commit/825f80e111f2815a009084f65267be3b5bf0897a
DIFF: https://github.com/llvm/llvm-project/commit/825f80e111f2815a009084f65267be3b5bf0897a.diff

LOG: [Sema] Introduce function reference conversion, NFC

Technically 'noexcept' isn't a qualifier, so this should be a separate conversion.

Also make the test a pure frontend test.

Reviewed By: rsmith

Differential Revision: https://reviews.llvm.org/D67112

Added: 
    clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4-ast.cpp

Modified: 
    clang/include/clang/AST/OperationKinds.def
    clang/include/clang/Sema/Initialization.h
    clang/lib/Sema/SemaInit.cpp

Removed: 
    clang/test/CodeGenCXX/implicit-function-conversion.cpp


################################################################################
diff  --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def
index 6daab1ffcb0a..7c82ab6e57ef 100644
--- a/clang/include/clang/AST/OperationKinds.def
+++ b/clang/include/clang/AST/OperationKinds.def
@@ -77,9 +77,10 @@ CAST_OPERATION(LValueToRValueBitCast)
 CAST_OPERATION(LValueToRValue)
 
 /// CK_NoOp - A conversion which does not affect the type other than
-/// (possibly) adding qualifiers.
+/// (possibly) adding qualifiers or removing noexcept.
 ///   int    -> int
 ///   char** -> const char * const *
+///   void () noexcept -> void ()
 CAST_OPERATION(NoOp)
 
 /// CK_BaseToDerived - A conversion from a C++ class pointer/reference

diff  --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index 6976e7c95c8b..2245c1505001 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -840,6 +840,9 @@ class InitializationSequence {
     /// Perform a qualification conversion, producing an lvalue.
     SK_QualificationConversionLValue,
 
+    /// Perform a function reference conversion, see [dcl.init.ref]p4.
+    SK_FunctionReferenceConversion,
+
     /// Perform a conversion adding _Atomic to a type.
     SK_AtomicConversion,
 
@@ -1288,6 +1291,10 @@ class InitializationSequence {
   void AddQualificationConversionStep(QualType Ty,
                                      ExprValueKind Category);
 
+  /// Add a new step that performs a function reference conversion to the
+  /// given type.
+  void AddFunctionReferenceConversionStep(QualType Ty);
+
   /// Add a new step that performs conversion from non-atomic to atomic
   /// type.
   void AddAtomicConversionStep(QualType Ty);

diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 5131ce446d04..6d2e6094e79c 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -3442,6 +3442,7 @@ void InitializationSequence::Step::Destroy() {
   case SK_QualificationConversionRValue:
   case SK_QualificationConversionXValue:
   case SK_QualificationConversionLValue:
+  case SK_FunctionReferenceConversion:
   case SK_AtomicConversion:
   case SK_ListInitialization:
   case SK_UnwrapInitList:
@@ -3620,6 +3621,13 @@ void InitializationSequence::AddQualificationConversionStep(QualType Ty,
   Steps.push_back(S);
 }
 
+void InitializationSequence::AddFunctionReferenceConversionStep(QualType Ty) {
+  Step S;
+  S.Kind = SK_FunctionReferenceConversion;
+  S.Type = Ty;
+  Steps.push_back(S);
+}
+
 void InitializationSequence::AddAtomicConversionStep(QualType Ty) {
   Step S;
   S.Kind = SK_AtomicConversion;
@@ -4653,7 +4661,7 @@ static OverloadingResult TryRefInitWithConversionFunction(
   else if (RefConv & Sema::ReferenceConversions::ObjC)
     Sequence.AddObjCObjectConversionStep(cv1T1);
   else if (RefConv & Sema::ReferenceConversions::Function)
-    Sequence.AddQualificationConversionStep(cv1T1, VK);
+    Sequence.AddFunctionReferenceConversionStep(cv1T1);
   else if (RefConv & Sema::ReferenceConversions::Qualification) {
     if (!S.Context.hasSameType(cv1T4, cv1T1))
       Sequence.AddQualificationConversionStep(cv1T1, VK);
@@ -4755,12 +4763,12 @@ static void TryReferenceInitializationCore(Sema &S,
           Sequence.AddDerivedToBaseCastStep(cv1T1, VK_LValue);
         else
           Sequence.AddObjCObjectConversionStep(cv1T1);
-      } else if (RefConv & (Sema::ReferenceConversions::Qualification |
-                            Sema::ReferenceConversions::Function)) {
+      } else if (RefConv & Sema::ReferenceConversions::Qualification) {
         // Perform a (possibly multi-level) qualification conversion.
-        // FIXME: Should we use a 
diff erent step kind for function conversions?
         Sequence.AddQualificationConversionStep(cv1T1,
                                                 Initializer->getValueKind());
+      } else if (RefConv & Sema::ReferenceConversions::Function) {
+        Sequence.AddFunctionReferenceConversionStep(cv1T1);
       }
 
       // We only create a temporary here when binding a reference to a
@@ -8038,6 +8046,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
   case SK_QualificationConversionLValue:
   case SK_QualificationConversionXValue:
   case SK_QualificationConversionRValue:
+  case SK_FunctionReferenceConversion:
   case SK_AtomicConversion:
   case SK_ConversionSequence:
   case SK_ConversionSequenceNoNarrowing:
@@ -8303,6 +8312,13 @@ ExprResult InitializationSequence::Perform(Sema &S,
       break;
     }
 
+    case SK_FunctionReferenceConversion:
+      assert(CurInit.get()->isLValue() &&
+             "function reference should be lvalue");
+      CurInit =
+          S.ImpCastExprToType(CurInit.get(), Step->Type, CK_NoOp, VK_LValue);
+      break;
+
     case SK_AtomicConversion: {
       assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic");
       CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
@@ -9563,6 +9579,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
       OS << "qualification conversion (lvalue)";
       break;
 
+    case SK_FunctionReferenceConversion:
+      OS << "function reference conversion";
+      break;
+
     case SK_AtomicConversion:
       OS << "non-atomic-to-atomic conversion";
       break;

diff  --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4-ast.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4-ast.cpp
new file mode 100644
index 000000000000..4fc0a05ae1ec
--- /dev/null
+++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p4-ast.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++17 -ast-dump %s | FileCheck %s
+
+void f() noexcept;
+
+// CHECK: VarDecl {{.*}} ref 'void (&)()' cinit
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void ()':'void ()' lvalue <NoOp>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'void () noexcept' lvalue Function {{.*}} 'f' 'void () noexcept'
+void (&ref)() = f;
+
+struct X {
+  typedef void (&ref)() noexcept;
+  operator ref();
+} x;
+
+// CHECK: VarDecl {{.*}} xp 'void (&)()' cinit
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void ()':'void ()' lvalue <NoOp>
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void () noexcept':'void () noexcept' lvalue <UserDefinedConversion>
+void (&xp)() = x;

diff  --git a/clang/test/CodeGenCXX/implicit-function-conversion.cpp b/clang/test/CodeGenCXX/implicit-function-conversion.cpp
deleted file mode 100644
index bc4b2bc8d15c..000000000000
--- a/clang/test/CodeGenCXX/implicit-function-conversion.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-unknown-linux -std=c++17 | FileCheck %s
-
-double a(double) noexcept;
-int b(double (&)(double));
-
-// CHECK: call i32 @_Z1bRFddE(double (double)* nonnull @_Z1ad)
-int c = b(a);


        


More information about the llvm-branch-commits mailing list