diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8419,6 +8419,12 @@ "__builtin_mul_overflow does not support 'signed _BitInt' operands of more " "than %0 bits">; +def err_int_to_float_bit_int_max_size : Error< + "cannot convert '_BitInt' operands of more than %0 bits to floating point">; + +def err_float_to_int_bit_int_max_size : Error< + "cannot convert floating point operands to a '_BitInt' of more than %0 bits">; + def err_atomic_load_store_uses_lib : Error< "atomic %select{load|store}0 requires runtime support that is not " "available for this target">; diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -31,6 +31,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Frontend/OpenMP/OMPGridValues.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Error.h" #include "llvm/Support/VersionTuple.h" @@ -595,12 +596,8 @@ // Different targets may support a different maximum width for the _BitInt // type, depending on what operations are supported. virtual size_t getMaxBitIntWidth() const { - // FIXME: this value should be llvm::IntegerType::MAX_INT_BITS, which is - // maximum bit width that LLVM claims its IR can support. However, most - // backends currently have a bug where they only support division - // operations on types that are <= 128 bits and crash otherwise. We're - // setting the max supported value to 128 to be conservative. - return 128; + // TODO: Return 128 for targets that don't link libbitint? + return llvm::IntegerType::MAX_INT_BITS; } /// Determine whether _Float16 is supported on this target. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5027,6 +5027,10 @@ /// Warn when implicitly casting 0 to nullptr. void diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E); + /// Error out when casting a floating point value to a large _BitInt + void diagnoseBitIntToFloating(CastKind Kind, const Expr *E); + void diagnoseFloatingToBitInt(CastKind Kind, QualType Ty, const Expr *E); + ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) { return DelayedDiagnostics.push(pool); } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -45,6 +45,9 @@ void linkXRayRuntimeDeps(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs); +void addBitIntRuntime(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs, + const llvm::opt::ArgList &Args); + void AddRunTimeLibs(const ToolChain &TC, const Driver &D, llvm::opt::ArgStringList &CmdArgs, const llvm::opt::ArgList &Args); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -987,6 +987,16 @@ return !StaticRuntimes.empty() || !NonWholeStaticRuntimes.empty(); } +void tools::addBitIntRuntime(const ToolChain &TC, ArgStringList &CmdArgs, + const ArgList &Args) { + std::string BitIntPath = TC.getCompilerRT(Args, "bitint"); + + // While building compiler-rt itself, this library is not available, + // so we don't try to link it. + if (TC.getVFS().exists(BitIntPath)) + CmdArgs.push_back(Args.MakeArgString(BitIntPath)); +} + bool tools::addXRayRuntime(const ToolChain&TC, const ArgList &Args, ArgStringList &CmdArgs) { if (Args.hasArg(options::OPT_shared)) return false; diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -610,6 +610,8 @@ // FIXME: Does this really make sense for all GNU toolchains? WantPthread = true; + addBitIntRuntime(getToolChain(), CmdArgs, Args); + AddRunTimeLibs(ToolChain, D, CmdArgs, Args); if (WantPthread && !isAndroid) diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -64,6 +64,8 @@ CmdArgs.push_back("-lmingwthrd"); CmdArgs.push_back("-lmingw32"); + addBitIntRuntime(getToolChain(), CmdArgs, Args); + // Make use of compiler-rt if --rtlib option is used ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args); if (RLT == ToolChain::RLT_Libgcc) { diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -1227,9 +1227,32 @@ return Val.getZExtValue() != N; } - Val = 0; const char *Ptr = DigitsBegin; + if (llvm::isPowerOf2_32(radix)) { + unsigned BitsPerDigit = llvm::Log2(radix); + unsigned BitPos = NumDigits * BitsPerDigit; + + llvm::APInt Temp(BitPos, 0); + + while (Ptr < SuffixBegin) { + if (isDigitSeparator(*Ptr)) { + ++Ptr; + continue; + } + unsigned C = llvm::hexDigitValue(*Ptr++); + BitPos -= BitsPerDigit; + Temp.insertBits(C, BitPos, BitsPerDigit); + } + + // Due to digit separators, BitPos might be greater than zero. + Temp.lshrInPlace(BitPos); + + Val = Temp.zextOrTrunc(Val.getBitWidth()); + return Temp.getActiveBits() > Val.getBitWidth(); + } + + Val = 0; llvm::APInt RadixVal(Val.getBitWidth(), radix); llvm::APInt CharVal(Val.getBitWidth(), 0); llvm::APInt OldVal = Val; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -625,6 +625,25 @@ << FixItHint::CreateReplacement(E->getSourceRange(), "nullptr"); } +void Sema::diagnoseBitIntToFloating(CastKind Kind, const Expr *E) { + if (Kind != CK_IntegralToFloating) + return; + + auto Ty = E->getType(); + if (Ty->isBitIntType() && getASTContext().getIntWidth(Ty) > 128) { + Diag(E->getBeginLoc(), diag::err_int_to_float_bit_int_max_size) << 128; + } +} + +void Sema::diagnoseFloatingToBitInt(CastKind Kind, QualType Ty, const Expr *E) { + if (Kind != CK_FloatingToIntegral) + return; + + if (Ty->isBitIntType() && getASTContext().getIntWidth(Ty) > 128) { + Diag(E->getBeginLoc(), diag::err_float_to_int_bit_int_max_size) << 128; + } +} + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. /// If there is already an implicit cast, merge into the existing one. /// The result is of the given category. @@ -656,6 +675,8 @@ diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc()); diagnoseZeroToNullptrConversion(Kind, E); + diagnoseBitIntToFloating(Kind, E); + diagnoseFloatingToBitInt(Kind, Ty, E); QualType ExprTy = Context.getCanonicalType(E->getType()); QualType TypeTy = Context.getCanonicalType(Ty); diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -3136,6 +3136,9 @@ if (SrcExpr.isInvalid()) return; + Self.diagnoseBitIntToFloating(Kind, SrcExpr.get()); + Self.diagnoseFloatingToBitInt(Kind, DestType, SrcExpr.get()); + if (Kind == CK_BitCast) checkCastAlign(); } diff --git a/clang/test/CodeGen/ext-int-cc.c b/clang/test/CodeGen/ext-int-cc.c --- a/clang/test/CodeGen/ext-int-cc.c +++ b/clang/test/CodeGen/ext-int-cc.c @@ -123,33 +123,33 @@ // are negated. This will give an error when a target does support larger // _BitInt widths to alert us to enable the test. void ParamPassing4(_BitInt(129) a) {} -// LIN64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// WIN64-NOT: define dso_local void @ParamPassing4(i129* %{{.+}}) -// LIN32-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}}) -// WIN32-NOT: define dso_local void @ParamPassing4(i129* %{{.+}}) -// NACL-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// NVPTX64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// NVPTX-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// SPARCV9-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}}) -// SPARC-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// MIPS64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// MIPS-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// SPIR64-NOT: define{{.*}} spir_func void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// SPIR-NOT: define{{.*}} spir_func void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// HEX-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// LANAI-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}}) -// R600-NOT: define{{.*}} void @ParamPassing4(i129 addrspace(5)* byval(i129) align 8 %{{.+}}) -// ARC-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}}) -// XCORE-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}}) -// RISCV64-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}}) -// RISCV32-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}}) -// WASM-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// SYSTEMZ-NOT: define{{.*}} void @ParamPassing4(i129* %{{.+}}) -// PPC64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// PPC32-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// AARCH64-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// AARCH64DARWIN-NOT: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) -// ARM-NOT: define{{.*}} arm_aapcscc void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// LIN64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// WIN64: define dso_local void @ParamPassing4(i129* %{{.+}}) +// LIN32: define{{.*}} void @ParamPassing4(i129* %{{.+}}) +// WIN32: define dso_local void @ParamPassing4(i129* %{{.+}}) +// NACL: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// NVPTX64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// NVPTX: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// SPARCV9: define{{.*}} void @ParamPassing4(i129* %{{.+}}) +// SPARC: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// MIPS64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// MIPS: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// SPIR64: define{{.*}} spir_func void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// SPIR: define{{.*}} spir_func void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// HEX: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// LANAI: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}}) +// R600: define{{.*}} void @ParamPassing4(i129 addrspace(5)* byval(i129) align 8 %{{.+}}) +// ARC: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}}) +// XCORE: define{{.*}} void @ParamPassing4(i129* byval(i129) align 4 %{{.+}}) +// RISCV64: define{{.*}} void @ParamPassing4(i129* %{{.+}}) +// RISCV32: define{{.*}} void @ParamPassing4(i129* %{{.+}}) +// WASM: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// SYSTEMZ: define{{.*}} void @ParamPassing4(i129* %{{.+}}) +// PPC64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// PPC32: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// AARCH64: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// AARCH64DARWIN: define{{.*}} void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) +// ARM: define{{.*}} arm_aapcscc void @ParamPassing4(i129* byval(i129) align 8 %{{.+}}) #endif _BitInt(63) ReturnPassing(void){} @@ -272,38 +272,38 @@ #if __BITINT_MAXWIDTH__ > 128 _BitInt(129) ReturnPassing5(void){} -// LIN64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// WIN64-NOT: define dso_local void @ReturnPassing5(i129* noalias sret -// LIN32-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// WIN32-NOT: define dso_local void @ReturnPassing5(i129* noalias sret -// NACL-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// NVPTX64-NOT: define{{.*}} i129 @ReturnPassing5( -// NVPTX-NOT: define{{.*}} i129 @ReturnPassing5( -// SPARCV9-NOT: define{{.*}} i129 @ReturnPassing5( -// SPARC-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// MIPS64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// MIPS-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// SPIR64-NOT: define{{.*}} spir_func void @ReturnPassing5(i129* noalias sret -// SPIR-NOT: define{{.*}} spir_func void @ReturnPassing5(i129* noalias sret -// HEX-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// LANAI-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// R600-NOT: define{{.*}} void @ReturnPassing5(i129 addrspace(5)* noalias sret -// ARC-NOT: define{{.*}} void @ReturnPassing5(i129* inreg noalias sret -// XCORE-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// RISCV64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// RISCV32-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// WASM-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// SYSTEMZ-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// PPC64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// PPC32-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// AARCH64-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// AARCH64DARWIN-NOT: define{{.*}} void @ReturnPassing5(i129* noalias sret -// ARM-NOT: define{{.*}} arm_aapcscc void @ReturnPassing5(i129* noalias sret +// LIN64: define{{.*}} void @ReturnPassing5(i129* noalias sret +// WIN64: define dso_local void @ReturnPassing5(i129* noalias sret +// LIN32: define{{.*}} void @ReturnPassing5(i129* noalias sret +// WIN32: define dso_local void @ReturnPassing5(i129* noalias sret +// NACL: define{{.*}} void @ReturnPassing5(i129* noalias sret +// NVPTX64: define{{.*}} i129 @ReturnPassing5( +// NVPTX: define{{.*}} i129 @ReturnPassing5( +// SPARCV9: define{{.*}} i129 @ReturnPassing5( +// SPARC: define{{.*}} void @ReturnPassing5(i129* noalias sret +// MIPS64: define{{.*}} void @ReturnPassing5(i129* noalias sret +// MIPS: define{{.*}} void @ReturnPassing5(i129* noalias sret +// SPIR64: define{{.*}} spir_func void @ReturnPassing5(i129* noalias sret +// SPIR: define{{.*}} spir_func void @ReturnPassing5(i129* noalias sret +// HEX: define{{.*}} void @ReturnPassing5(i129* noalias sret +// LANAI: define{{.*}} void @ReturnPassing5(i129* noalias sret +// R600: define{{.*}} void @ReturnPassing5(i129 addrspace(5)* noalias sret +// ARC: define{{.*}} void @ReturnPassing5(i129* inreg noalias sret +// XCORE: define{{.*}} void @ReturnPassing5(i129* noalias sret +// RISCV64: define{{.*}} void @ReturnPassing5(i129* noalias sret +// RISCV32: define{{.*}} void @ReturnPassing5(i129* noalias sret +// WASM: define{{.*}} void @ReturnPassing5(i129* noalias sret +// SYSTEMZ: define{{.*}} void @ReturnPassing5(i129* noalias sret +// PPC64: define{{.*}} void @ReturnPassing5(i129* noalias sret +// PPC32: define{{.*}} void @ReturnPassing5(i129* noalias sret +// AARCH64: define{{.*}} void @ReturnPassing5(i129* noalias sret +// AARCH64DARWIN: define{{.*}} void @ReturnPassing5(i129* noalias sret +// ARM: define{{.*}} arm_aapcscc void @ReturnPassing5(i129* noalias sret // SparcV9 is odd in that it has a return-size limit of 256, not 128 or 64 // like other platforms, so test to make sure this behavior will still work. _BitInt(256) ReturnPassing6(void) {} -// SPARCV9-NOT: define{{.*}} i256 @ReturnPassing6( +// SPARCV9: define{{.*}} i256 @ReturnPassing6( _BitInt(257) ReturnPassing7(void) {} -// SPARCV9-NOT: define{{.*}} void @ReturnPassing7(i257* noalias sret +// SPARCV9: define{{.*}} void @ReturnPassing7(i257* noalias sret #endif diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -174,7 +174,7 @@ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC-STATIC %s // CHECK-CLANG-NO-LIBGCC-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" -// CHECK-CLANG-NO-LIBGCC-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group" +// CHECK-CLANG-NO-LIBGCC-STATIC: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group" // // RUN: %clang -static-pie -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ @@ -189,7 +189,7 @@ // CHECK-CLANG-LD-STATIC-PIE: "text" // CHECK-CLANG-LD-STATIC-PIE: "-m" "elf_x86_64" // CHECK-CLANG-LD-STATIC-PIE: "{{.*}}rcrt1.o" -// CHECK-CLANG-LD-STATIC-PIE: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group" +// CHECK-CLANG-LD-STATIC-PIE: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group" // // RUN: %clang -static-pie -pie -no-canonical-prefixes %s -no-pie -### -o %t.o 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ @@ -204,7 +204,7 @@ // CHECK-CLANG-LD-STATIC-PIE-PIE: "text" // CHECK-CLANG-LD-STATIC-PIE-PIE: "-m" "elf_x86_64" // CHECK-CLANG-LD-STATIC-PIE-PIE: "{{.*}}rcrt1.o" -// CHECK-CLANG-LD-STATIC-PIE-PIE: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group" +// CHECK-CLANG-LD-STATIC-PIE-PIE: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group" // // RUN: %clang -static-pie -static -no-canonical-prefixes %s -no-pie -### -o %t.o 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ @@ -219,7 +219,7 @@ // CHECK-CLANG-LD-STATIC-PIE-STATIC: "text" // CHECK-CLANG-LD-STATIC-PIE-STATIC: "-m" "elf_x86_64" // CHECK-CLANG-LD-STATIC-PIE-STATIC: "{{.*}}rcrt1.o" -// CHECK-CLANG-LD-STATIC-PIE-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group" +// CHECK-CLANG-LD-STATIC-PIE-STATIC: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group" // // RUN: %clang -static-pie -nopie -no-canonical-prefixes %s -no-pie -### -o %t.o 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform \ @@ -318,7 +318,7 @@ // CHECK-LD-64-STATIC: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-unknown-linux/10.2.0/../../../../x86_64-unknown-linux/lib" // CHECK-LD-64-STATIC: "-L[[SYSROOT]]/lib" // CHECK-LD-64-STATIC: "-L[[SYSROOT]]/usr/lib" -// CHECK-LD-64-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group" +// CHECK-LD-64-STATIC: "--start-group" "{{[^"]*}}/libclang_rt.bitint{{[^"]*}}" "-lgcc" "-lgcc_eh" "-lc" "--end-group" // RUN: %clang -no-pie -### %s --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform -shared -static \ // RUN: --gcc-toolchain= --sysroot=%S/Inputs/basic_linux_tree 2>&1 | FileCheck --check-prefix=CHECK-LD-SHARED-STATIC %s diff --git a/clang/test/Lexer/bitint-constants.c b/clang/test/Lexer/bitint-constants.c --- a/clang/test/Lexer/bitint-constants.c +++ b/clang/test/Lexer/bitint-constants.c @@ -137,10 +137,28 @@ // the width of BITINT_MAXWIDTH. When this value changes in the future, the // test cases should pick a new value that can't be represented by a _BitInt, // but also add a test case that a 129-bit literal still behaves as-expected. - _Static_assert(__BITINT_MAXWIDTH__ <= 128, - "Need to pick a bigger constant for the test case below."); - 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1wb; // expected-error {{integer literal is too large to be represented in any signed integer type}} - 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1uwb; // expected-error {{integer literal is too large to be represented in any integer type}} + 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1wb; // 129 bits are fine + 0xFFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'FFFF'1uwb; // 129 bit unsigned are fine + + #define CONCAT(X,Y) X ## Y + #define REPEAT2(X) CONCAT(X,X) + #define REPEAT4(X) REPEAT2(REPEAT2(X)) + #define REPEAT16(X) REPEAT4(REPEAT4(X)) + #define REPEAT256(X) REPEAT16(REPEAT16(X)) + #define REPEAT65536(X) REPEAT256(REPEAT256(X)) + #define REPEAT2097152(X) REPEAT65536(REPEAT16(REPEAT2(X))) + #define _LITERAL(X, Suffix) 0x ## X ## Suffix + #define LITERAL(X, Suffix) _LITERAL(X, Suffix) + + _Static_assert(__BITINT_MAXWIDTH__ <= 8388608, + "Need to pick a bigger constant for the test case below."); + + // 8388608 bits are represented by 2097152 hex digits + LITERAL(REPEAT2097152(7), wb); // 262143 bits plus one sign bit are fine + LITERAL(REPEAT2097152(F), wb); // expected-error {{integer literal is too large to be represented in any signed integer type}} + + LITERAL(REPEAT2097152(F), uwb); // 262144 bits unsigned are fine + LITERAL(REPEAT2097152(F), 1uwb); // expected-error {{integer literal is too large to be represented in any integer type}} } void TestTypes(void) { diff --git a/clang/test/Preprocessor/init-aarch64.c b/clang/test/Preprocessor/init-aarch64.c --- a/clang/test/Preprocessor/init-aarch64.c +++ b/clang/test/Preprocessor/init-aarch64.c @@ -40,7 +40,7 @@ // AARCH64-NEXT: #define __ATOMIC_SEQ_CST 5 // AARCH64: #define __BIGGEST_ALIGNMENT__ 16 // AARCH64_BE-NEXT: #define __BIG_ENDIAN__ 1 -// AARCH64-NEXT: #define __BITINT_MAXWIDTH__ 128 +// AARCH64-NEXT: #define __BITINT_MAXWIDTH__ 8388608 // AARCH64-NEXT: #define __BOOL_WIDTH__ 8 // AARCH64_BE-NEXT: #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ // AARCH64_LE-NEXT: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -1515,7 +1515,7 @@ // WEBASSEMBLY-NEXT:#define __ATOMIC_RELEASE 3 // WEBASSEMBLY-NEXT:#define __ATOMIC_SEQ_CST 5 // WEBASSEMBLY-NEXT:#define __BIGGEST_ALIGNMENT__ 16 -// WEBASSEMBLY-NEXT:#define __BITINT_MAXWIDTH__ 128 +// WEBASSEMBLY-NEXT:#define __BITINT_MAXWIDTH__ 8388608 // WEBASSEMBLY-NEXT:#define __BOOL_WIDTH__ 8 // WEBASSEMBLY-NEXT:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ // WEBASSEMBLY-NEXT:#define __CHAR16_TYPE__ unsigned short diff --git a/clang/test/Sema/ext-int.c b/clang/test/Sema/ext-int.c --- a/clang/test/Sema/ext-int.c +++ b/clang/test/Sema/ext-int.c @@ -73,3 +73,16 @@ void FromPaper2(_BitInt(8) a1, _BitInt(24) a2) { _Static_assert(EXPR_HAS_TYPE(a1 * (_BitInt(32))a2, _BitInt(32)), ""); } + + +void LargeBitIntToFloat(_BitInt(129) a) { + float fa = a; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}} + fa = (float)a; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}} + fa = a + 0.1; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}} +} + +_BitInt(129) LargeBitIntFromFloat(float f) { + _BitInt(129) b = f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}} + b = (_BitInt(129))f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}} + return f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}} +} diff --git a/clang/test/SemaCXX/ext-int.cpp b/clang/test/SemaCXX/ext-int.cpp --- a/clang/test/SemaCXX/ext-int.cpp +++ b/clang/test/SemaCXX/ext-int.cpp @@ -17,7 +17,7 @@ unsigned _BitInt(5) e = 5; _BitInt(5) unsigned f; - _BitInt(-3) g; // expected-error{{signed _BitInt of bit sizes greater than 128 not supported}} + _BitInt(-3) g; // expected-error{{signed _BitInt of bit sizes greater than 8388608 not supported}} _BitInt(0) h; // expected-error{{signed _BitInt must have a bit size of at least 2}} _BitInt(1) i; // expected-error{{signed _BitInt must have a bit size of at least 2}} _BitInt(2) j;; @@ -29,12 +29,12 @@ constexpr _BitInt(7) o = 33; // Check imposed max size. - _BitInt(129) p; // expected-error {{signed _BitInt of bit sizes greater than 128 not supported}} - unsigned _BitInt(0xFFFFFFFFFF) q; // expected-error {{unsigned _BitInt of bit sizes greater than 128 not supported}} + _BitInt(8388609) p; // expected-error {{signed _BitInt of bit sizes greater than 8388608 not supported}} + unsigned _BitInt(0xFFFFFFFFFF) q; // expected-error {{unsigned _BitInt of bit sizes greater than 8388608 not supported}} // Ensure template params are instantiated correctly. - // expected-error@5{{signed _BitInt of bit sizes greater than 128 not supported}} - // expected-error@6{{unsigned _BitInt of bit sizes greater than 128 not supported}} + // expected-error@5{{signed _BitInt of bit sizes greater than 8388608 not supported}} + // expected-error@6{{unsigned _BitInt of bit sizes greater than 8388608 not supported}} // expected-note@+1{{in instantiation of template class }} HasExtInt<-1> r; // expected-error@5{{signed _BitInt must have a bit size of at least 2}} @@ -285,3 +285,16 @@ void FromPaper2(_BitInt(8) a1, _BitInt(24) a2) { static_assert(is_same::value, ""); } + +void LargeBitIntToFloat(_BitInt(129) a) { + float fa = a; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}} + fa = static_cast(a); // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}} + fa = a + 0.1; // expected-error {{cannot convert '_BitInt' operands of more than 128 bits to floating point}} +} + +_BitInt(129) LargeBitIntFromFloat(float f) { + _BitInt(129) a = f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}} + a = f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}} + a = static_cast<_BitInt(129)>(f); // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}} + return f; // expected-error {{cannot convert floating point operands to a '_BitInt' of more than 128 bits}} +}