Index: include/clang/Sema/Overload.h =================================================================== --- include/clang/Sema/Overload.h +++ include/clang/Sema/Overload.h @@ -873,6 +873,9 @@ unsigned NumInlineBytesUsed = 0; llvm::AlignedCharArray InlineSpace; + // Address space of the object being constructed. + LangAS DestAS = LangAS::Default; + /// If we have space, allocates from inline storage. Otherwise, allocates /// from the slab allocator. /// FIXME: It would probably be nice to have a SmallBumpPtrAllocator @@ -968,6 +971,10 @@ SourceLocation Loc = SourceLocation(), llvm::function_ref Filter = [](OverloadCandidate&) { return true; }); + + LangAS getDestAS() { return DestAS; } + + void setDestAS(LangAS AS) { DestAS = AS; } }; bool isBetterOverloadCandidate(Sema &S, Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -8226,12 +8226,15 @@ DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.hasMethodTypeQualifiers()) { + bool DiagOccured = false; FTI.MethodQualifiers->forEachQualifier( [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) { Diag(SL, diag::err_invalid_qualified_constructor) << QualName << SourceRange(SL); + DiagOccured = true; }); - D.setInvalidType(); + if (DiagOccured) + D.setInvalidType(); } // C++0x [class.ctor]p4: Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -3897,6 +3897,7 @@ // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + CandidateSet.setDestAS(DestType.getQualifiers().getAddressSpace()); // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. @@ -4989,6 +4990,7 @@ // structure, so that it will persist if we fail. OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion); + CandidateSet.setDestAS(DestType.getQualifiers().getAddressSpace()); // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -6029,8 +6029,13 @@ // A defaulted move constructor that is defined as deleted is ignored by // overload resolution. CXXConstructorDecl *Constructor = dyn_cast(Function); - if (Constructor && Constructor->isDefaulted() && Constructor->isDeleted() && - Constructor->isMoveConstructor()) + if (Constructor && ((Constructor->isDefaulted() && Constructor->isDeleted() && + Constructor->isMoveConstructor()) || + // Check that addr space of an object being constructed is + // convertible to the one ctor qualified with. + !Qualifiers::isAddressSpaceSupersetOf( + Constructor->getMethodQualifiers().getAddressSpace(), + CandidateSet.getDestAS()))) return; // Overload resolution is always an unevaluated context. 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: 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/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'}}