Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -28,6 +28,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/StringExtras.h" @@ -4041,46 +4042,56 @@ // Checks whether an argument of launch_bounds attribute is acceptable // May output an error. -static bool checkLaunchBoundsArgument(Sema &S, Expr *E, - const CUDALaunchBoundsAttr &Attr, - const unsigned Idx) { +static Expr *checkLaunchBoundsArgument(Sema &S, Expr *E, + const CUDALaunchBoundsAttr &Attr, + const unsigned Idx) { if (S.DiagnoseUnexpandedParameterPack(E)) - return false; + return nullptr; // Accept template arguments for now as they depend on something else. // We'll get to check them when they eventually get instantiated. if (E->isValueDependent()) - return true; + return E; llvm::APSInt I(64); if (!E->isIntegerConstantExpr(I, S.Context)) { S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type) << &Attr << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange(); - return false; + return nullptr; } // Make sure we can fit it in 32 bits. if (!I.isIntN(32)) { S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false) << 32 << /* Unsigned */ 1; - return false; + return nullptr; } if (I < 0) S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative) << &Attr << Idx << E->getSourceRange(); - return true; + // We may need to perform implicit conversion of the argument. + InitializedEntity Entity = InitializedEntity::InitializeParameter( + S.Context, S.Context.getConstType(S.Context.IntTy), /*consume*/ false); + ExprResult ValArg = S.PerformCopyInitialization(Entity, SourceLocation(), E); + if (ValArg.isInvalid()) + return nullptr; + + return ValArg.getAs(); } void Sema::AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads, Expr *MinBlocks, unsigned SpellingListIndex) { CUDALaunchBoundsAttr TmpAttr(AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex); - - if (!checkLaunchBoundsArgument(*this, MaxThreads, TmpAttr, 0)) + MaxThreads = checkLaunchBoundsArgument(*this, MaxThreads, TmpAttr, 0); + if (MaxThreads == nullptr) return; - if (MinBlocks && !checkLaunchBoundsArgument(*this, MinBlocks, TmpAttr, 1)) - return; + if (MinBlocks) { + MinBlocks = checkLaunchBoundsArgument(*this, MinBlocks, TmpAttr, 1); + if (MinBlocks == nullptr) + return; + } D->addAttr(::new (Context) CUDALaunchBoundsAttr( AttrRange, Context, MaxThreads, MinBlocks, SpellingListIndex)); Index: test/CodeGenCUDA/launch-bounds.cu =================================================================== --- test/CodeGenCUDA/launch-bounds.cu +++ test/CodeGenCUDA/launch-bounds.cu @@ -79,3 +79,10 @@ } // CHECK: !{{[0-9]+}} = !{void ()* @{{.*}}Kernel7{{.*}}, !"maxntidx", // CHECK-NOT: !{{[0-9]+}} = !{void ()* @{{.*}}Kernel7{{.*}}, !"minctasm", + +const int max_threads_per_block = 11; +const int min_blocks_per_mp = 12; +__global__ void __launch_bounds__(max_threads_per_block, min_blocks_per_mp) + Kernel8() {} +// CHECK: !{{[0-9]+}} = !{void ()* @{{.*}}Kernel8{{.*}}, !"maxntidx", i32 11 +// CHECK: !{{[0-9]+}} = !{void ()* @{{.*}}Kernel8{{.*}}, !"minctasm", i32 12 Index: test/SemaCUDA/pr27778.cu =================================================================== --- /dev/null +++ test/SemaCUDA/pr27778.cu @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only %s + +#include "Inputs/cuda.h" + +const int constint = 512; +__launch_bounds__(constint) void TestConstInt(void) {}