Index: cfe/trunk/include/clang/AST/ASTContext.h =================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h +++ cfe/trunk/include/clang/AST/ASTContext.h @@ -1348,6 +1348,8 @@ return getFunctionTypeInternal(ResultTy, Args, EPI, false); } + QualType adjustStringLiteralBaseType(QualType StrLTy) const; + private: /// Return a normal function type with a typed argument list. QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef Args, Index: cfe/trunk/lib/AST/ASTContext.cpp =================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp +++ cfe/trunk/lib/AST/ASTContext.cpp @@ -3621,6 +3621,12 @@ return QualType(New, 0); } +QualType ASTContext::adjustStringLiteralBaseType(QualType Ty) const { + // OpenCL v1.1 s6.5.3: a string literal is in the constant address space. + return LangOpts.OpenCL ? getAddrSpaceQualType(Ty, LangAS::opencl_constant) + : Ty; +} + QualType ASTContext::getReadPipeType(QualType T) const { return getPipeType(T, true); } Index: cfe/trunk/lib/AST/Expr.cpp =================================================================== --- cfe/trunk/lib/AST/Expr.cpp +++ cfe/trunk/lib/AST/Expr.cpp @@ -881,7 +881,8 @@ void *Mem = C.Allocate(sizeof(StringLiteral) + sizeof(SourceLocation) * (NumStrs - 1), alignof(StringLiteral)); - StringLiteral *SL = new (Mem) StringLiteral(QualType()); + StringLiteral *SL = + new (Mem) StringLiteral(C.adjustStringLiteralBaseType(QualType())); SL->CharByteWidth = 0; SL->Length = 0; SL->NumConcatenated = NumStrs; Index: cfe/trunk/lib/Sema/SemaExpr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp +++ cfe/trunk/lib/Sema/SemaExpr.cpp @@ -1554,17 +1554,14 @@ if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings) CharTyConst.addConst(); + CharTyConst = Context.adjustStringLiteralBaseType(CharTyConst); + // Get an array type for the string, according to C99 6.4.5. This includes // the nul terminator character as well as the string length for pascal // strings. - QualType StrTy = Context.getConstantArrayType(CharTyConst, - llvm::APInt(32, Literal.GetNumStringChars()+1), - ArrayType::Normal, 0); - - // OpenCL v1.1 s6.5.3: a string literal is in the constant address space. - if (getLangOpts().OpenCL) { - StrTy = Context.getAddrSpaceQualType(StrTy, LangAS::opencl_constant); - } + QualType StrTy = Context.getConstantArrayType( + CharTyConst, llvm::APInt(32, Literal.GetNumStringChars() + 1), + ArrayType::Normal, 0); // Pass &StringTokLocs[0], StringTokLocs.size() to factory! StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(), @@ -3046,7 +3043,8 @@ llvm::APInt LengthI(32, Length + 1); if (IT == PredefinedExpr::LFunction) { - ResTy = Context.WideCharTy.withConst(); + ResTy = + Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst()); SmallString<32> RawChars; ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(), Str, RawChars); @@ -3055,7 +3053,7 @@ SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide, /*Pascal*/ false, ResTy, Loc); } else { - ResTy = Context.CharTy.withConst(); + ResTy = Context.adjustStringLiteralBaseType(Context.CharTy.withConst()); ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, /*IndexTypeQuals*/ 0); SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii, @@ -3294,8 +3292,8 @@ // operator "" X ("n") unsigned Length = Literal.getUDSuffixOffset(); QualType StrTy = Context.getConstantArrayType( - Context.CharTy.withConst(), llvm::APInt(32, Length + 1), - ArrayType::Normal, 0); + Context.adjustStringLiteralBaseType(Context.CharTy.withConst()), + llvm::APInt(32, Length + 1), ArrayType::Normal, 0); Expr *Lit = StringLiteral::Create( Context, StringRef(TokSpelling.data(), Length), StringLiteral::Ascii, /*Pascal*/false, StrTy, &TokLoc, 1); @@ -13675,7 +13673,6 @@ DiagKind = diag::err_typecheck_incompatible_address_space; break; - } else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) { DiagKind = diag::err_typecheck_incompatible_ownership; break; Index: cfe/trunk/test/CodeGenOpenCL/str_literals.cl =================================================================== --- cfe/trunk/test/CodeGenOpenCL/str_literals.cl +++ cfe/trunk/test/CodeGenOpenCL/str_literals.cl @@ -1,9 +1,15 @@ // RUN: %clang_cc1 %s -cl-opt-disable -emit-llvm -o - -ffake-address-space-map | FileCheck %s -__constant char * __constant x = "hello world"; -__constant char * __constant y = "hello world"; +__constant char *__constant x = "hello world"; +__constant char *__constant y = "hello world"; -// CHECK: unnamed_addr addrspace(2) constant +// CHECK: unnamed_addr addrspace(2) constant{{.*}}"hello world\00" // CHECK-NOT: addrspace(2) unnamed_addr constant // CHECK: @x = {{(dso_local )?}}addrspace(2) constant i8 addrspace(2)* // CHECK: @y = {{(dso_local )?}}addrspace(2) constant i8 addrspace(2)* +// CHECK: unnamed_addr addrspace(2) constant{{.*}}"f\00" + +void f() { + //CHECK: store i8 addrspace(2)* {{.*}}, i8 addrspace(2)** + constant const char *f3 = __func__; +} Index: cfe/trunk/test/SemaOpenCL/predefined-expr.cl =================================================================== --- cfe/trunk/test/SemaOpenCL/predefined-expr.cl +++ cfe/trunk/test/SemaOpenCL/predefined-expr.cl @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 %s -verify +// RUN: %clang_cc1 %s -verify -cl-std=CL2.0 + +void f() { + char *f1 = __func__; //expected-error-re{{initializing '{{__generic char|char}} *' with an expression of type 'const __constant char *' changes address space of pointer}} + constant char *f2 = __func__; //expected-warning{{initializing '__constant char *' with an expression of type 'const __constant char [2]' discards qualifiers}} + constant const char *f3 = __func__; +}