Anastasia created this revision.
Anastasia added a reviewer: rjmccall.
Herald added a subscriber: ebevhan.
Anastasia edited the summary of this revision.
Anastasia marked 3 inline comments as done.
Anastasia added inline comments.


================
Comment at: lib/Sema/SemaInit.cpp:3771
     else {
-      // C++ [over.match.copy]p1:
-      //   - When initializing a temporary to be bound to the first parameter
-      //     of a constructor [for type T] that takes a reference to possibly
-      //     cv-qualified T as its first argument, called with a single
-      //     argument in the context of direct-initialization, explicit
-      //     conversion functions are also considered.
-      // FIXME: What if a constructor template instantiates to such a 
signature?
-      bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
-                               Args.size() == 1 &&
-                               hasCopyOrMoveCtorParam(S.Context, Info);
-      S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
-                             CandidateSet, SuppressUserConversions,
-                             /*PartialOverloading=*/false,
-                             /*AllowExplicit=*/AllowExplicitConv);
+      // Check that address space match to resolve the constructors correctly.
+      if (Info.Constructor->getMethodQualifiers().isAddressSpaceSupersetOf(
----------------
matches


================
Comment at: lib/Sema/SemaInit.cpp:5023
           else
+              // Check that address space match to resolve the constructors
+              // correctly.
----------------
matches


================
Comment at: test/CodeGenOpenCLCXX/addrspace-ctor.cl:7
+  int i;
+  void bar();
+};
----------------
remove unused bar


If we construct an object in some arbitrary non-default addr space it should 
fail unless either:

1. There is an implicit conversion from the address space to default/generic 
address space.
2. There is a matching ctor qualified with an address space that is either 
exactly matching or convertible to the address space of an object.

Example - case 1:

  struct MyType {
     MyType(int i)  : i(i) {}
     int i;
   };
  __constant MyType m(1); // error: can't convert from __constant to __generic

Example - case 2:

  struct MyType {
     MyType(int i) __constant  : i(i) {}
     MyType(int i)  : i(i) {}
     int i;
   };
  __constant MyType c(1); // there is __constant qualified ctor
  __global MyType g(1); // there is a valid conversion between __global and 
__generic




https://reviews.llvm.org/D62156

Files:
  include/clang/Sema/DeclSpec.h
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaInit.cpp
  test/CodeGenCXX/address-space-of-this.cpp
  test/CodeGenOpenCLCXX/addrspace-ctor.cl
  test/SemaCXX/address-space-ctor.cpp

Index: test/SemaCXX/address-space-ctor.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/address-space-ctor.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 %s -std=c++14 -triple=spir -verify -fsyntax-only
+// RUN: %clang_cc1 %s -std=c++17 -triple=spir -verify -fsyntax-only
+
+struct MyType {
+  MyType(int i) : i(i) {}
+  int i;
+};
+
+// FIXME: We can't implicitly convert between address spaces yet.
+MyType __attribute__((address_space(10))) m1 = 123; //expected-error{{no viable conversion from 'int' to '__attribute__((address_space(10))) MyType'}}
+MyType __attribute__((address_space(10))) m2(123);  //expected-error{{no matching constructor for initialization of '__attribute__((address_space(10))) MyType'}}
Index: test/CodeGenOpenCLCXX/addrspace-ctor.cl
===================================================================
--- /dev/null
+++ test/CodeGenOpenCLCXX/addrspace-ctor.cl
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s
+
+struct MyType {
+  MyType(int i) : i(i) {}
+  MyType(int i) __constant : i(i) {}
+  int i;
+  void bar();
+};
+
+//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1)
+__constant MyType const1 = 1;
+//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2)
+__constant MyType const2(2);
+//CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1)
+MyType glob(1);
Index: test/CodeGenCXX/address-space-of-this.cpp
===================================================================
--- test/CodeGenCXX/address-space-of-this.cpp
+++ test/CodeGenCXX/address-space-of-this.cpp
@@ -1,8 +1,11 @@
 // RUN: %clang_cc1 %s -std=c++14 -triple=spir -emit-llvm -o - | FileCheck %s
 // RUN: %clang_cc1 %s -std=c++17 -triple=spir -emit-llvm -o - | FileCheck %s
+// XFAIL: *
 
+// FIXME: We can't compile address space method qualifiers yet.
+// Therefore there is no way to check correctness of this code.
 struct MyType {
-  MyType(int i) : i(i) {}
+  MyType(int i) __attribute__((address_space(10))) : i(i) {}
   int i;
 };
 //CHECK: call void @_ZN6MyTypeC1Ei(%struct.MyType* addrspacecast (%struct.MyType addrspace(10)* @m to %struct.MyType*), i32 123)
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -3768,20 +3768,25 @@
                                      /*ExplicitArgs*/ nullptr, Args,
                                      CandidateSet, SuppressUserConversions);
     else {
-      // C++ [over.match.copy]p1:
-      //   - When initializing a temporary to be bound to the first parameter
-      //     of a constructor [for type T] that takes a reference to possibly
-      //     cv-qualified T as its first argument, called with a single
-      //     argument in the context of direct-initialization, explicit
-      //     conversion functions are also considered.
-      // FIXME: What if a constructor template instantiates to such a signature?
-      bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
-                               Args.size() == 1 &&
-                               hasCopyOrMoveCtorParam(S.Context, Info);
-      S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
-                             CandidateSet, SuppressUserConversions,
-                             /*PartialOverloading=*/false,
-                             /*AllowExplicit=*/AllowExplicitConv);
+      // Check that address space match to resolve the constructors correctly.
+      if (Info.Constructor->getMethodQualifiers().isAddressSpaceSupersetOf(
+              DestType.getQualifiers())) {
+        // C++ [over.match.copy]p1:
+        //   - When initializing a temporary to be bound to the first parameter
+        //     of a constructor [for type T] that takes a reference to possibly
+        //     cv-qualified T as its first argument, called with a single
+        //     argument in the context of direct-initialization, explicit
+        //     conversion functions are also considered.
+        // FIXME: What if a constructor template instantiates to such a
+        // signature?
+        bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
+                                 Args.size() == 1 &&
+                                 hasCopyOrMoveCtorParam(S.Context, Info);
+        S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
+                               CandidateSet, SuppressUserConversions,
+                               /*PartialOverloading=*/false,
+                               /*AllowExplicit=*/AllowExplicitConv);
+      }
     }
   }
 
@@ -5015,6 +5020,10 @@
                                            Initializer, CandidateSet,
                                            /*SuppressUserConversions=*/true);
           else
+              // Check that address space match to resolve the constructors
+              // correctly.
+              if (Info.Constructor->getMethodQualifiers()
+                      .isAddressSpaceSupersetOf(DestType.getQualifiers()))
             S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
                                    Initializer, CandidateSet,
                                    /*SuppressUserConversions=*/true);
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -8225,8 +8225,8 @@
   }
 
   DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
-  if (FTI.hasMethodTypeQualifiers()) {
-    FTI.MethodQualifiers->forEachQualifier(
+  if (FTI.hasMethodTypeCVRUQualifiers()) {
+    FTI.MethodQualifiers->forEachCVRUQualifier(
         [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) {
           Diag(SL, diag::err_invalid_qualified_constructor)
               << QualName << SourceRange(SL);
Index: include/clang/Sema/DeclSpec.h
===================================================================
--- include/clang/Sema/DeclSpec.h
+++ include/clang/Sema/DeclSpec.h
@@ -1453,6 +1453,15 @@
                                   MethodQualifiers->getAttributes().size());
     }
 
+    /// Determine whether this method has CVRU qualifiers.
+    bool hasMethodTypeCVRUQualifiers() {
+      if (!MethodQualifiers)
+        return false;
+      auto Quals = MethodQualifiers->getTypeQualifiers();
+      return Quals & DeclSpec::TQ_const || Quals & DeclSpec::TQ_volatile ||
+             Quals & DeclSpec::TQ_restrict || Quals & DeclSpec::TQ_unaligned;
+    }
+
     /// Get the type of exception specification this function has.
     ExceptionSpecificationType getExceptionSpecType() const {
       return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to