Index: bindings/python/clang/cindex.py =================================================================== --- bindings/python/clang/cindex.py +++ bindings/python/clang/cindex.py @@ -1685,6 +1685,7 @@ TypeKind.OBJCID = TypeKind(27) TypeKind.OBJCCLASS = TypeKind(28) TypeKind.OBJCSEL = TypeKind(29) +TypeKind.FLOAT128 = TypeKind(30) TypeKind.COMPLEX = TypeKind(100) TypeKind.POINTER = TypeKind(101) TypeKind.BLOCKPOINTER = TypeKind(102) Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -2918,6 +2918,7 @@ CXType_ObjCId = 27, CXType_ObjCClass = 28, CXType_ObjCSel = 29, + CXType_Float128 = 30, CXType_FirstBuiltin = CXType_Void, CXType_LastBuiltin = CXType_ObjCSel, Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -890,9 +890,10 @@ CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; CanQualType UnsignedLongLongTy, UnsignedInt128Ty; - CanQualType FloatTy, DoubleTy, LongDoubleTy; + CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; + CanQualType Float128ComplexTy; CanQualType VoidPtrTy, NullPtrTy; CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType BuiltinFnTy; @@ -967,9 +968,6 @@ /// \brief Retrieve the declaration for the 128-bit unsigned integer type. TypedefDecl *getUInt128Decl() const; - /// \brief Retrieve the declaration for a 128-bit float stub type. - TypeDecl *getFloat128StubType() const; - //===--------------------------------------------------------------------===// // Type Constructors //===--------------------------------------------------------------------===// Index: include/clang/AST/BuiltinTypes.def =================================================================== --- include/clang/AST/BuiltinTypes.def +++ include/clang/AST/BuiltinTypes.def @@ -133,6 +133,9 @@ // 'long double' FLOATING_TYPE(LongDouble, LongDoubleTy) +// '__float128' +FLOATING_TYPE(Float128, Float128Ty) + //===- Language-specific types --------------------------------------------===// // This is the type of C++0x 'nullptr'. Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -2050,7 +2050,7 @@ } bool isFloatingPoint() const { - return getKind() >= Half && getKind() <= LongDouble; + return getKind() >= Half && getKind() <= Float128; } /// Determines whether the given kind corresponds to a placeholder type. Index: include/clang/AST/TypeLoc.h =================================================================== --- include/clang/AST/TypeLoc.h +++ include/clang/AST/TypeLoc.h @@ -538,7 +538,7 @@ bool needsExtraLocalData() const { BuiltinType::Kind bk = getTypePtr()->getKind(); return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) - || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble) + || (bk >= BuiltinType::Short && bk <= BuiltinType::Float128) || bk == BuiltinType::UChar || bk == BuiltinType::SChar; } Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5198,8 +5198,6 @@ "arithmetic on%select{ a|}0 pointer%select{|s}0 to void">; def err_typecheck_decl_incomplete_type : Error< "variable has incomplete type %0">; -def err_typecheck_decl_incomplete_type___float128 : Error< - "support for type '__float128' is not yet implemented">; def ext_typecheck_decl_incomplete_type : ExtWarn< "tentative definition of variable with internal linkage has incomplete non-array type %0">, InGroup>; @@ -7525,8 +7523,8 @@ "feature, not permitted in C++">; def err_type_requires_extension : Error< "use of type %0 requires %1 extension to be enabled">; -def err_int128_unsupported : Error< - "__int128 is not supported on this target">; +def err_type_unsupported : Error< + "%0 is not supported on this target">; def err_nsconsumed_attribute_mismatch : Error< "overriding method has mismatched ns_consumed attribute on its" " parameter">; Index: include/clang/Basic/Specifiers.h =================================================================== --- include/clang/Basic/Specifiers.h +++ include/clang/Basic/Specifiers.h @@ -54,6 +54,7 @@ TST_half, // OpenCL half, ARM NEON __fp16 TST_float, TST_double, + TST_float128, TST_bool, // _Bool TST_decimal32, // _Decimal32 TST_decimal64, // _Decimal64 Index: include/clang/Basic/TargetInfo.h =================================================================== --- include/clang/Basic/TargetInfo.h +++ include/clang/Basic/TargetInfo.h @@ -63,7 +63,7 @@ unsigned char HalfWidth, HalfAlign; unsigned char FloatWidth, FloatAlign; unsigned char DoubleWidth, DoubleAlign; - unsigned char LongDoubleWidth, LongDoubleAlign; + unsigned char LongDoubleWidth, LongDoubleAlign, Float128Align; unsigned char LargeArrayMinWidth, LargeArrayAlign; unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; @@ -78,7 +78,7 @@ const char *UserLabelPrefix; const char *MCountName; const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat, - *LongDoubleFormat; + *LongDoubleFormat, *Float128Format; unsigned char RegParmMax, SSERegParmMax; TargetCXXABI TheCXXABI; const LangAS::Map *AddrSpaceMap; @@ -132,7 +132,8 @@ NoFloat = 255, Float = 0, Double, - LongDouble + LongDouble, + Float128 }; /// \brief The different kinds of __builtin_va_list types defined by @@ -323,6 +324,11 @@ return getPointerWidth(0) >= 64; } // FIXME + /// \brief Determine whether the __float128 type is supported on this target. + virtual bool hasFloat128Type() const { + return false; + } + /// \brief Return the alignment that is suitable for storing any /// object with a fundamental alignment requirement. unsigned getSuitableAlign() const { return SuitableAlign; } @@ -375,6 +381,14 @@ return *LongDoubleFormat; } + /// getFloat128Width/Align/Format - Return the size/align/format of + /// '__float128'. + unsigned getFloat128Width() const { return 128; } + unsigned getFloat128Align() const { return Float128Align; } + const llvm::fltSemantics &getFloat128Format() const { + return *Float128Format; + } + /// \brief Return true if the 'long double' type should be mangled like /// __float128. virtual bool useFloat128ManglingForLongDouble() const { return false; } Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -380,6 +380,7 @@ TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX) KEYWORD(__builtin_va_arg , KEYALL) KEYWORD(__extension__ , KEYALL) +KEYWORD(__float128 , KEYALL) KEYWORD(__imag , KEYALL) KEYWORD(__int128 , KEYALL) KEYWORD(__label__ , KEYALL) Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1469,6 +1469,10 @@ def mno_invariant_function_descriptors : Flag<["-"], "mno-invariant-function-descriptors">, Group; +def mfloat128: Flag<["-"], "mfloat128">, + Group; +def mno_float128 : Flag<["-"], "mno-float128">, + Group; def faltivec : Flag<["-"], "faltivec">, Group, Flags<[CC1Option]>, HelpText<"Enable AltiVec vector initializer syntax">; Index: include/clang/Lex/LiteralSupport.h =================================================================== --- include/clang/Lex/LiteralSupport.h +++ include/clang/Lex/LiteralSupport.h @@ -64,6 +64,7 @@ bool isHalf : 1; // 1.0h bool isFloat : 1; // 1.0f bool isImaginary : 1; // 1.0i + bool isFloat128 : 1; // 1.0q uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. bool isIntegerLiteral() const { Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -280,6 +280,7 @@ static const TST TST_half = clang::TST_half; static const TST TST_float = clang::TST_float; static const TST TST_double = clang::TST_double; + static const TST TST_float128 = clang::TST_float128; static const TST TST_bool = clang::TST_bool; static const TST TST_decimal32 = clang::TST_decimal32; static const TST TST_decimal64 = clang::TST_decimal64; Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -812,7 +812,9 @@ /// \brief OpenCL reserve_id type. PREDEF_TYPE_RESERVE_ID_ID = 54, /// \brief The placeholder type for OpenMP array section. - PREDEF_TYPE_OMP_ARRAY_SECTION = 55 + PREDEF_TYPE_OMP_ARRAY_SECTION = 55, + /// \brief The '__float128' type + PREDEF_TYPE_FLOAT128_ID = 56 }; /// \brief The number of predefined type IDs that are reserved for Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -58,7 +58,7 @@ unsigned ASTContext::NumImplicitDestructorsDeclared; enum FloatingRank { - HalfRank, FloatRank, DoubleRank, LongDoubleRank + HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank }; RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { @@ -967,14 +967,6 @@ return UInt128Decl; } -TypeDecl *ASTContext::getFloat128StubType() const { - assert(LangOpts.CPlusPlus && "should only be called for c++"); - if (!Float128StubDecl) - Float128StubDecl = buildImplicitRecord("__float128"); - - return Float128StubDecl; -} - void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K); R = CanQualType::CreateUnsafe(QualType(Ty, 0)); @@ -1023,6 +1015,9 @@ InitBuiltinType(DoubleTy, BuiltinType::Double); InitBuiltinType(LongDoubleTy, BuiltinType::LongDouble); + // GNU extension, __float128 for IEEE quadruple precision + InitBuiltinType(Float128Ty, BuiltinType::Float128); + // GNU extension, 128-bit integers. InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); @@ -1084,6 +1079,7 @@ FloatComplexTy = getComplexType(FloatTy); DoubleComplexTy = getComplexType(DoubleTy); LongDoubleComplexTy = getComplexType(LongDoubleTy); + Float128ComplexTy = getComplexType(Float128Ty); // Builtin types for 'id', 'Class', and 'SEL'. InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId); @@ -1351,6 +1347,7 @@ case BuiltinType::Float: return Target->getFloatFormat(); case BuiltinType::Double: return Target->getDoubleFormat(); case BuiltinType::LongDouble: return Target->getLongDoubleFormat(); + case BuiltinType::Float128: return Target->getFloat128Format(); } } @@ -1661,6 +1658,10 @@ Width = Target->getLongDoubleWidth(); Align = Target->getLongDoubleAlign(); break; + case BuiltinType::Float128: + Width = Target->getFloat128Width(); + Align = Target->getFloat128Align(); + break; case BuiltinType::NullPtr: Width = Target->getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t) Align = Target->getPointerAlign(0); // == sizeof(void*) @@ -4624,6 +4625,7 @@ case BuiltinType::Float: return FloatRank; case BuiltinType::Double: return DoubleRank; case BuiltinType::LongDouble: return LongDoubleRank; + case BuiltinType::Float128: return Float128Rank; } } @@ -4640,6 +4642,7 @@ case FloatRank: return FloatComplexTy; case DoubleRank: return DoubleComplexTy; case LongDoubleRank: return LongDoubleComplexTy; + case Float128Rank: return Float128ComplexTy; } } @@ -4649,6 +4652,7 @@ case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; case LongDoubleRank: return LongDoubleTy; + case Float128Rank: return Float128Ty; } llvm_unreachable("getFloatingRank(): illegal value for rank"); } @@ -5478,6 +5482,7 @@ case BuiltinType::LongDouble: return 'D'; case BuiltinType::NullPtr: return '*'; // like char* + case BuiltinType::Float128: case BuiltinType::Half: // FIXME: potentially need @encodes for these! return ' '; @@ -8654,6 +8659,8 @@ return DoubleTy; case TargetInfo::LongDouble: return LongDoubleTy; + case TargetInfo::Float128: + return Float128Ty; case TargetInfo::NoFloat: return QualType(); } Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -1981,7 +1981,7 @@ // ::= f # float // ::= d # double // ::= e # long double, __float80 - // UNSUPPORTED: ::= g # __float128 + // ::= g # __float128 // UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits) // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits) // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits) @@ -2061,6 +2061,12 @@ ? 'g' : 'e'); break; + case BuiltinType::Float128: + if (getASTContext().getTargetInfo().useFloat128ManglingForLongDouble()) + Out << "U10__float128"; // Match the GCC mangling + else + Out << 'g'; + break; case BuiltinType::NullPtr: Out << "Dn"; break; Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -1761,6 +1761,7 @@ Out << "$$T"; break; + case BuiltinType::Float128: case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID( Index: lib/AST/NSAPI.cpp =================================================================== --- lib/AST/NSAPI.cpp +++ lib/AST/NSAPI.cpp @@ -441,6 +441,7 @@ case BuiltinType::Int128: case BuiltinType::LongDouble: case BuiltinType::UInt128: + case BuiltinType::Float128: case BuiltinType::NullPtr: case BuiltinType::ObjCClass: case BuiltinType::ObjCId: Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1310,6 +1310,7 @@ case BuiltinType::Double: break; // no suffix. case BuiltinType::Float: OS << 'F'; break; case BuiltinType::LongDouble: OS << 'L'; break; + case BuiltinType::Float128: OS << 'Q'; break; } } Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -1777,7 +1777,7 @@ bool Type::isFloatingType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Half && - BT->getKind() <= BuiltinType::LongDouble; + BT->getKind() <= BuiltinType::Float128; if (const ComplexType *CT = dyn_cast(CanonicalType)) return CT->getElementType()->isFloatingType(); return false; @@ -1799,7 +1799,7 @@ bool Type::isRealType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::LongDouble; + BT->getKind() <= BuiltinType::Float128; if (const EnumType *ET = dyn_cast(CanonicalType)) return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); return false; @@ -1808,7 +1808,7 @@ bool Type::isArithmeticType() const { if (const BuiltinType *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && - BT->getKind() <= BuiltinType::LongDouble; + BT->getKind() <= BuiltinType::Float128; if (const EnumType *ET = dyn_cast(CanonicalType)) // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2). // If a body isn't seen by the time we get here, return false. @@ -2552,6 +2552,8 @@ return "double"; case LongDouble: return "long double"; + case Float128: + return "__float128"; case WChar_S: case WChar_U: return Policy.MSWChar ? "__wchar_t" : "wchar_t"; Index: lib/AST/TypeLoc.cpp =================================================================== --- lib/AST/TypeLoc.cpp +++ lib/AST/TypeLoc.cpp @@ -320,6 +320,7 @@ case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float128: llvm_unreachable("Builtin type needs extra local data!"); // Fall through, if the impossible happens. Index: lib/Analysis/PrintfFormatString.cpp =================================================================== --- lib/Analysis/PrintfFormatString.cpp +++ lib/Analysis/PrintfFormatString.cpp @@ -611,6 +611,7 @@ case BuiltinType::UInt128: case BuiltinType::Int128: case BuiltinType::Half: + case BuiltinType::Float128: // Various types which are non-trivial to correct. return false; Index: lib/Basic/TargetInfo.cpp =================================================================== --- lib/Basic/TargetInfo.cpp +++ lib/Basic/TargetInfo.cpp @@ -46,6 +46,7 @@ DoubleAlign = 64; LongDoubleWidth = 64; LongDoubleAlign = 64; + Float128Align = 128; LargeArrayMinWidth = 0; LargeArrayAlign = 0; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0; @@ -72,6 +73,7 @@ FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEdouble; LongDoubleFormat = &llvm::APFloat::IEEEdouble; + Float128Format = &llvm::APFloat::IEEEquad; DataLayoutString = nullptr; UserLabelPrefix = "_"; MCountName = "mcount"; @@ -225,6 +227,8 @@ if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble || &getLongDoubleFormat() == &llvm::APFloat::IEEEquad) return LongDouble; + if (hasFloat128Type()) + return Float128; break; } Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -807,6 +807,7 @@ bool HasHTM; bool HasBPERMD; bool HasExtDiv; + bool HasFloat128; protected: std::string ABI; @@ -815,7 +816,7 @@ PPCTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple), HasVSX(false), HasP8Vector(false), HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false), - HasBPERMD(false), HasExtDiv(false) { + HasBPERMD(false), HasExtDiv(false), HasFloat128(false) { BigEndian = (Triple.getArch() != llvm::Triple::ppc64le); SimdDefaultAlign = 128; LongDoubleWidth = LongDoubleAlign = 128; @@ -1059,6 +1060,9 @@ LongDoubleFormat == &llvm::APFloat::PPCDoubleDouble && getTriple().isOSBinFormatELF(); } + bool hasFloat128Type() const override { + return HasFloat128; + } }; const Builtin::Info PPCTargetInfo::BuiltinInfo[] = { @@ -1090,6 +1094,8 @@ HasQPX = true; } else if (Feature == "+htm") { HasHTM = true; + } else if (Feature == "+float128") { + HasFloat128 = true; } // TODO: Finish this list and add an assert that we've handled them // all. @@ -1247,6 +1253,8 @@ Builder.defineMacro("__CRYPTO__"); if (HasHTM) Builder.defineMacro("__HTM__"); + if (HasFloat128) + Builder.defineMacro("__FLOAT128__"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1"); Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2"); @@ -1297,6 +1305,13 @@ << "-mno-vsx"; return false; } + + if (std::find(FeaturesVec.begin(), FeaturesVec.end(), "+float128") != + FeaturesVec.end()) { + Diags.Report(diag::err_opt_not_valid_with_opt) << "-mfloat128" + << "-mno-vsx"; + return false; + } } return true; @@ -1365,6 +1380,7 @@ .Case("htm", HasHTM) .Case("bpermd", HasBPERMD) .Case("extdiv", HasExtDiv) + .Case("float128", HasFloat128) .Default(false); } @@ -1374,19 +1390,19 @@ // as well. Do the inverse if we're disabling vsx. We'll diagnose any user // incompatible options. if (Enabled) { - if (Name == "vsx") { - Features[Name] = true; - } else if (Name == "direct-move") { + if (Name == "direct-move") { Features[Name] = Features["vsx"] = true; } else if (Name == "power8-vector") { Features[Name] = Features["vsx"] = true; + } else if (Name == "float128") { + Features[Name] = Features["vsx"] = true; } else { Features[Name] = true; } } else { if (Name == "vsx") { Features[Name] = Features["direct-move"] = Features["power8-vector"] = - false; + Features["float128"] = false; } else { Features[Name] = false; } Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -545,7 +545,13 @@ case BuiltinType::Half: case BuiltinType::Float: case BuiltinType::LongDouble: + case BuiltinType::Float128: case BuiltinType::Double: + // FIXME: For targets where long double and __float128 have the same size, + // they are currently indistinguishable in the debugger without some + // special treatment. However, there is currently no consensus on encoding + // and this should be updated once a DWARF encoding exists for distinct + // floating point types of the same size. Encoding = llvm::dwarf::DW_ATE_float; break; } Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -1792,15 +1792,19 @@ amt = llvm::ConstantFP::get(VMContext, llvm::APFloat(static_cast(amount))); else { - // Remaining types are either Half or LongDouble. Convert from float. + // Remaining types are Half, LongDouble or __float128. Convert from float. llvm::APFloat F(static_cast(amount)); bool ignored; + const llvm::fltSemantics *FS; // Don't use getFloatTypeSemantics because Half isn't // necessarily represented using the "half" LLVM type. - F.convert(value->getType()->isHalfTy() - ? CGF.getTarget().getHalfFormat() - : CGF.getTarget().getLongDoubleFormat(), - llvm::APFloat::rmTowardZero, &ignored); + if (value->getType()->isFP128Ty()) + FS = &CGF.getTarget().getFloat128Format(); + else if (value->getType()->isHalfTy()) + FS = &CGF.getTarget().getHalfFormat(); + else + FS = &CGF.getTarget().getLongDoubleFormat(); + F.convert(*FS, llvm::APFloat::rmTowardZero, &ignored); amt = llvm::ConstantFP::get(VMContext, F); } value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec"); Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.cpp @@ -449,6 +449,7 @@ case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float128: ResultType = getTypeForFormat(getLLVMContext(), Context.getFloatTypeSemantics(T), /* UseNativeHalf = */ false); Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -2533,6 +2533,7 @@ case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: + case BuiltinType::Float128: case BuiltinType::Char16: case BuiltinType::Char32: case BuiltinType::Int128: @@ -3361,8 +3362,8 @@ getContext().UnsignedLongLongTy, getContext().Int128Ty, getContext().UnsignedInt128Ty, getContext().HalfTy, getContext().FloatTy, getContext().DoubleTy, - getContext().LongDoubleTy, getContext().Char16Ty, - getContext().Char32Ty, + getContext().LongDoubleTy, getContext().Float128Ty, + getContext().Char16Ty, getContext().Char32Ty }; for (const QualType &FundamentalType : FundamentalTypes) EmitFundamentalRTTIDescriptor(FundamentalType); Index: lib/Format/FormatToken.cpp =================================================================== --- lib/Format/FormatToken.cpp +++ lib/Format/FormatToken.cpp @@ -53,6 +53,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_wchar_t: case tok::kw_bool: case tok::kw___underlying_type: Index: lib/Index/USRGeneration.cpp =================================================================== --- lib/Index/USRGeneration.cpp +++ lib/Index/USRGeneration.cpp @@ -608,6 +608,8 @@ c = 'd'; break; case BuiltinType::LongDouble: c = 'D'; break; + case BuiltinType::Float128: + c = 'Q'; break; case BuiltinType::NullPtr: c = 'n'; break; #define BUILTIN_TYPE(Id, SingletonId) Index: lib/Lex/LiteralSupport.cpp =================================================================== --- lib/Lex/LiteralSupport.cpp +++ lib/Lex/LiteralSupport.cpp @@ -525,6 +525,7 @@ isHalf = false; isFloat = false; isImaginary = false; + isFloat128 = false; MicrosoftInteger = 0; hadError = false; @@ -567,9 +568,17 @@ case 'f': // FP Suffix for "float" case 'F': if (!isFPConstant) break; // Error for integer constant. - if (isHalf || isFloat || isLong) break; // HF, FF, LF invalid. + if (isHalf || isFloat || isLong || isFloat128) + break; // HF, FF, LF, QF invalid. isFloat = true; continue; // Success. + case 'q': // FP Suffix for "__float128" + case 'Q': + if (!isFPConstant) break; // Error for integer constant. + if (isHalf || isFloat || isLong || isFloat128) + break; // HQ, FQ, LQ, QQ invalid. + isFloat128 = true; + continue; // Success. case 'u': case 'U': if (isFPConstant) break; // Error for floating constant. @@ -579,7 +588,7 @@ case 'l': case 'L': if (isLong || isLongLong) break; // Cannot be repeated. - if (isHalf || isFloat) break; // LH, LF invalid. + if (isHalf || isFloat || isFloat128) break; // LH, LF, LQ invalid. // Check for long long. The L's need to be adjacent and the same case. if (s[1] == s[0]) { Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3296,6 +3296,10 @@ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw___float128: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, + DiagID, Policy); + break; case tok::kw_wchar_t: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy); @@ -4284,6 +4288,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: case tok::kw__Decimal32: @@ -4356,6 +4361,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: case tok::kw__Decimal32: @@ -4508,6 +4514,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: case tok::kw__Decimal32: Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -1166,6 +1166,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_void: case tok::kw_typename: case tok::kw_typeof: Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -1863,6 +1863,9 @@ case tok::kw_double: DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw___float128: + DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); + break; case tok::kw_wchar_t: DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy); break; Index: lib/Parse/ParseTentative.cpp =================================================================== --- lib/Parse/ParseTentative.cpp +++ lib/Parse/ParseTentative.cpp @@ -946,6 +946,7 @@ case tok::kw_char: case tok::kw_const: case tok::kw_double: + case tok::kw___float128: case tok::kw_enum: case tok::kw_half: case tok::kw_float: @@ -1424,6 +1425,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_void: case tok::annot_decltype: if (NextToken().is(tok::l_paren)) @@ -1515,6 +1517,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_void: case tok::kw___unknown_anytype: case tok::kw___auto_type: Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -289,6 +289,7 @@ case TST_decimal32: case TST_decimal64: case TST_double: + case TST_float128: case TST_enum: case TST_error: case TST_float: @@ -455,6 +456,7 @@ case DeclSpec::TST_half: return "half"; case DeclSpec::TST_float: return "float"; case DeclSpec::TST_double: return "double"; + case DeclSpec::TST_float128: return "__float128"; case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool"; case DeclSpec::TST_decimal32: return "_Decimal32"; case DeclSpec::TST_decimal64: return "_Decimal64"; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -108,6 +108,7 @@ case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw___float128: case tok::kw_wchar_t: case tok::kw_bool: case tok::kw___underlying_type: Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -1146,6 +1146,48 @@ /*convertFloat=*/!IsCompAssign); } +/// \brief Diagnose attempts to convert between __float128 and long double if +/// there is no support for such conversion. Helper function of +/// UsualArithmeticConversions(). +static bool unsupportedTypeConversion(const Sema &S, QualType LHSType, + QualType RHSType) { + /* No issue converting if at least one of the types is not a floating point + type or the two types have the same rank. + */ + if (!LHSType->isFloatingType() || !RHSType->isFloatingType() || + S.Context.getFloatingTypeOrder(LHSType, RHSType) == 0) + return false; + + assert(LHSType->isFloatingType() && RHSType->isFloatingType() && + "The remaining types must be floating point types."); + + auto *LHSComplex = LHSType->getAs(); + auto *RHSComplex = RHSType->getAs(); + + QualType LHSElemType = LHSComplex ? + LHSComplex->getElementType() : LHSType; + QualType RHSElemType = RHSComplex ? + RHSComplex->getElementType() : RHSType; + + // No issue if the two types have the same representation + if (&S.Context.getFloatTypeSemantics(LHSElemType) == + &S.Context.getFloatTypeSemantics(RHSElemType)) + return false; + + bool Float128AndLongDouble = (LHSElemType == S.Context.Float128Ty && + RHSElemType == S.Context.LongDoubleTy); + Float128AndLongDouble |= (LHSElemType == S.Context.LongDoubleTy && + RHSElemType == S.Context.Float128Ty); + + /* We've handled the situation where __float128 and long double have the same + representation. The only other allowable conversion is if long double is + really just double. + */ + return Float128AndLongDouble && + (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) != + &llvm::APFloat::IEEEdouble); +} + typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType); namespace { @@ -1309,6 +1351,11 @@ // At this point, we have two different arithmetic types. + // Diagnose attempts to convert between __float128 and long double where + // such conversions currently can't be handled. + if (unsupportedTypeConversion(*this, LHSType, RHSType)) + return QualType(); + // Handle complex types first (C99 6.3.1.8p1). if (LHSType->isComplexType() || RHSType->isComplexType()) return handleComplexFloatConversion(*this, LHS, RHS, LHSType, RHSType, @@ -3315,10 +3362,12 @@ } } else if (Literal.isFloat) Ty = Context.FloatTy; - else if (!Literal.isLong) - Ty = Context.DoubleTy; - else + else if (Literal.isLong) Ty = Context.LongDoubleTy; + else if (Literal.isFloat128) + Ty = Context.Float128Ty; + else + Ty = Context.DoubleTy; Res = BuildFloatingLiteral(*this, Literal, Ty, Tok.getLocation()); @@ -6519,6 +6568,15 @@ QualType LHSTy = LHS.get()->getType(); QualType RHSTy = RHS.get()->getType(); + // Diagnose attempts to convert between __float128 and long double where + // such conversions currently can't be handled. + if (unsupportedTypeConversion(*this, LHSTy, RHSTy)) { + Diag(QuestionLoc, + diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } + // OpenCL v2.0 s6.12.5 - Blocks cannot be used as expressions of the ternary // selection operator (?:). if (getLangOpts().OpenCL && @@ -7252,6 +7310,11 @@ return Incompatible; } + // Diagnose attempts to convert between __float128 and long double where + // such conversions currently can't be handled. + if (unsupportedTypeConversion(*this, LHSType, RHSType)) + return Incompatible; + // Arithmetic conversions. if (LHSType->isArithmeticType() && RHSType->isArithmeticType() && !(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) { Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -5048,6 +5048,12 @@ QualType ResTy = UsualArithmeticConversions(LHS, RHS); if (LHS.isInvalid() || RHS.isInvalid()) return QualType(); + if (ResTy.isNull()) { + Diag(QuestionLoc, + diag::err_typecheck_cond_incompatible_operands) << LTy << RTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy)); RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy)); Index: lib/Sema/SemaLookup.cpp =================================================================== --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -677,13 +677,6 @@ NameKind == Sema::LookupRedeclarationWithLinkage) { IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); if (II) { - if (S.getLangOpts().CPlusPlus11 && S.getLangOpts().GNUMode && - II == S.getFloat128Identifier()) { - // libstdc++4.7's type_traits expects type __float128 to exist, so - // insert a dummy type to make that header build in gnu++11 mode. - R.addDecl(S.getASTContext().getFloat128StubType()); - return true; - } if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName && II == S.getASTContext().getMakeIntegerSeqName()) { R.addDecl(S.getASTContext().getMakeIntegerSeqDecl()); Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -1655,6 +1655,16 @@ SCS.Second = ICK_Complex_Real; FromType = ToType.getUnqualifiedType(); } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) { + // FIXME: disable conversions between long double and __float128 if + // their representation is different until there is back end support + if (&S.Context.getFloatTypeSemantics(FromType) != + &S.Context.getFloatTypeSemantics(ToType)) { + if ((FromType == S.Context.Float128Ty && + ToType == S.Context.LongDoubleTy) || + (FromType == S.Context.LongDoubleTy && + ToType == S.Context.Float128Ty)) + return false; + } // Floating point conversions (C++ 4.8). SCS.Second = ICK_Floating_Conversion; FromType = ToType.getUnqualifiedType(); @@ -1958,7 +1968,8 @@ if (!getLangOpts().CPlusPlus && (FromBuiltin->getKind() == BuiltinType::Float || FromBuiltin->getKind() == BuiltinType::Double) && - (ToBuiltin->getKind() == BuiltinType::LongDouble)) + (ToBuiltin->getKind() == BuiltinType::LongDouble || + ToBuiltin->getKind() == BuiltinType::Float128)) return true; // Half can be promoted to float. @@ -7183,13 +7194,13 @@ // provided via the getArithmeticType() method below. // The "promoted arithmetic types" are the arithmetic // types are that preserved by promotion (C++ [over.built]p2). - static const unsigned FirstIntegralType = 3; - static const unsigned LastIntegralType = 20; - static const unsigned FirstPromotedIntegralType = 3, - LastPromotedIntegralType = 11; + static const unsigned FirstIntegralType = 4; + static const unsigned LastIntegralType = 21; + static const unsigned FirstPromotedIntegralType = 4, + LastPromotedIntegralType = 12; static const unsigned FirstPromotedArithmeticType = 0, - LastPromotedArithmeticType = 11; - static const unsigned NumArithmeticTypes = 20; + LastPromotedArithmeticType = 12; + static const unsigned NumArithmeticTypes = 21; /// \brief Get the canonical type for a given arithmetic type index. CanQualType getArithmeticType(unsigned index) { @@ -7200,6 +7211,7 @@ &ASTContext::FloatTy, &ASTContext::DoubleTy, &ASTContext::LongDoubleTy, + &ASTContext::Float128Ty, // Start of integral types. &ASTContext::IntTy, Index: lib/Sema/SemaTemplateVariadic.cpp =================================================================== --- lib/Sema/SemaTemplateVariadic.cpp +++ lib/Sema/SemaTemplateVariadic.cpp @@ -727,6 +727,7 @@ case TST_half: case TST_float: case TST_double: + case TST_float128: case TST_bool: case TST_decimal32: case TST_decimal64: Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1332,7 +1332,8 @@ } case DeclSpec::TST_int128: if (!S.Context.getTargetInfo().hasInt128Type()) - S.Diag(DS.getTypeSpecTypeLoc(), diag::err_int128_unsupported); + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__int128"; if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned) Result = Context.UnsignedInt128Ty; else @@ -1354,6 +1355,12 @@ declarator.setInvalidType(true); } break; + case DeclSpec::TST_float128: + if (!S.Context.getTargetInfo().hasFloat128Type()) + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__float128"; + Result = Context.Float128Ty; + break; case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool case DeclSpec::TST_decimal32: // _Decimal32 case DeclSpec::TST_decimal64: // _Decimal64 @@ -6779,13 +6786,6 @@ if (!Diagnoser) return true; - // We have an incomplete type. Produce a diagnostic. - if (Ident___float128 && - T == Context.getTypeDeclType(Context.getFloat128StubType())) { - Diag(Loc, diag::err_typecheck_decl_incomplete_type___float128); - return true; - } - Diagnoser->diagnose(*this, Loc, T); // If the type was a forward declaration of a class/struct/union Index: lib/Serialization/ASTCommon.cpp =================================================================== --- lib/Serialization/ASTCommon.cpp +++ lib/Serialization/ASTCommon.cpp @@ -91,6 +91,9 @@ case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break; + case BuiltinType::Float128: + ID = PREDEF_TYPE_FLOAT128_ID; + break; case BuiltinType::NullPtr: ID = PREDEF_TYPE_NULLPTR_ID; break; Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -6026,6 +6026,9 @@ case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break; + case PREDEF_TYPE_FLOAT128_ID: + T = Context.Float128Ty; + break; case PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break; Index: test/CodeGenCXX/float128-declarations.cpp =================================================================== --- test/CodeGenCXX/float128-declarations.cpp +++ test/CodeGenCXX/float128-declarations.cpp @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -emit-llvm -triple powerpc64-unknown-unknown \ +// RUN: -target-feature +float128 -std=c++11 %s -o - | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -triple powerpc64le-unknown-unknown \ +// RUN: -target-feature +float128 -std=c++11 %s -o - | FileCheck %s +// +/* Various contexts where type __float128 can appear. */ + +/* Namespace */ +namespace { + __float128 f1n; + __float128 f2n = 33.q; + __float128 arr1n[10]; + __float128 arr2n[] = { 1.2q, 3.0q, 3.e11q }; + const volatile __float128 func1n(const __float128 &arg) { + return arg + f2n + arr1n[4] - arr2n[1]; + } +} + +/* File */ +__float128 f1f; +__float128 f2f = 32.4q; +static __float128 f3f = f2f; +__float128 arr1f[10]; +__float128 arr2f[] = { -1.2q, -3.0q, -3.e11q }; +__float128 func1f(__float128 arg); + +/* Class */ +class C1 { + __float128 f1c; + static const __float128 f2c; + volatile __float128 f3c; +public: + C1(__float128 arg) : f1c(arg), f3c(arg) { } + __float128 func1c(__float128 arg ) { + return f1c + arg; + } + static __float128 func2c(__float128 arg) { + return arg * C1::f2c; + } +}; + +/* Template */ +template C func1t(C arg) { return arg * 2.q; } +template struct S1 { + C mem1; +}; +template <> struct S1<__float128> { + __float128 mem2; +}; + +/* Local */ +int main(void) { + __float128 f1l = 123e220q; + __float128 f2l = -0.q; + __float128 f3l = 1.189731495357231765085759326628007e4932q; + C1 c1(f1l); + S1<__float128> s1 = { 132.q }; + __float128 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + + func1t(f1l) + s1.mem2 - f1n + f2n; +#if (__cplusplus >= 201103L) + auto f5l = -1.q, *f6l = &f2l, f7l = func1t(f3l); +#endif + __float128 f8l = f4l++; + __float128 arr1l[] = { -1.q, -0.q, -11.q }; +} +// CHECK-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global fp128 0xL00000000000000000000000000000000 +// CHECK-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global fp128 0xL00000000000000004004080000000000 +// CHECK-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x fp128] +// CHECK-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x fp128] [fp128 0xL33333333333333333FFF333333333333, fp128 0xL00000000000000004000800000000000, fp128 0xL00000000000000004025176592E00000] +// CHECK-DAG: define internal fp128 @_ZN12_GLOBAL__N_16func1nERKU10__float128(fp128* +// CHECK-DAG: @f1f = global fp128 0xL00000000000000000000000000000000 +// CHECK-DAG: @f2f = global fp128 0xL33333333333333334004033333333333 +// CHECK-DAG: @arr1f = global [10 x fp128] +// CHECK-DAG: @arr2f = global [3 x fp128] [fp128 0xL3333333333333333BFFF333333333333, fp128 0xL0000000000000000C000800000000000, fp128 0xL0000000000000000C025176592E00000] +// CHECK-DAG: declare fp128 @_Z6func1fU10__float128(fp128) +// CHECK-DAG: define linkonce_odr void @_ZN2C1C2EU10__float128(%class.C1* %this, fp128 %arg) +// CHECK-DAG: define linkonce_odr fp128 @_ZN2C16func2cEU10__float128(fp128 %arg) +// CHECK-DAG: define linkonce_odr fp128 @_Z6func1tIU10__float128ET_S0_(fp128 %arg) +// CHECK-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } +// CHECK-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16 +// CHECK-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16 +// CHECK-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16 +// CHECK-DAG: store fp128 0xL0000000000000000BFFF000000000000, fp128* %f5l, align 16 +// CHECK-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l +// CHECK-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000 +// CHECK-DAG: store fp128 [[INC]], fp128* %f4l Index: test/Preprocessor/init.c =================================================================== --- test/Preprocessor/init.c +++ test/Preprocessor/init.c @@ -5819,6 +5819,9 @@ // PPCPOWER8:#define _ARCH_PWR7 1 // PPCPOWER8:#define _ARCH_PWR8 1 // +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power8 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s +// PPC-FLOAT128:#define __FLOAT128__ 1 +// // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-LINUX %s // // PPC64-LINUX:#define _ARCH_PPC 1 Index: test/Sema/128bitfloat.cpp =================================================================== --- test/Sema/128bitfloat.cpp +++ test/Sema/128bitfloat.cpp @@ -2,23 +2,23 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s #if !defined(__STRICT_ANSI__) -__float128 f; // expected-error {{support for type '__float128' is not yet implemented}} +__float128 f; // expected-error {{__float128 is not supported on this target}} // But this should work: template struct __is_floating_point_helper {}; -template<> struct __is_floating_point_helper<__float128> {}; +template<> struct __is_floating_point_helper<__float128> {}; // expected-error {{__float128 is not supported on this target}} // FIXME: This could have a better diag. -void g(int x, __float128 *y) { - x + *y; // expected-error {{invalid operands to binary expression ('int' and '__float128')}} +int g(int x, __float128 *y) { // expected-error {{__float128 is not supported on this target}} + return x + *y; } #else -__float128 f; // expected-error {{unknown type name '__float128'}} +__float128 f; // expected-error {{__float128 is not supported on this target}} template struct __is_floating_point_helper {}; -template<> struct __is_floating_point_helper<__float128> {}; // expected-error {{use of undeclared identifier '__float128'}} +template<> struct __is_floating_point_helper<__float128> {}; // expected-error {{__float128 is not supported on this target}} -void g(int x, __float128 *y) { // expected-error {{unknown type name '__float128'}} - x + *y; +int g(int x, __float128 *y) { // expected-error {{__float128 is not supported on this target}} + return x + *y; } #endif Index: test/Sema/float128-ld-incompatibility.cpp =================================================================== --- test/Sema/float128-ld-incompatibility.cpp +++ test/Sema/float128-ld-incompatibility.cpp @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 \ +// RUN: -triple powerpc64le-unknown-linux-gnu -target-cpu pwr8 \ +// RUN: -target-feature +float128 %s + +__float128 qf(); +long double ldf(); + +// FIXME: once operations between long double and __float128 are implemented for +// targets where the types are different, these next two will change +long double ld{qf()}; // expected-error {{cannot initialize a variable of type 'long double' with an rvalue of type '__float128'}} +__float128 q{ldf()}; // expected-error {{cannot initialize a variable of type '__float128' with an rvalue of type 'long double'}} + +auto test1(__float128 q, long double ld) -> decltype(q + ld) { // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}} + return q + ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}} +} + +auto test2(long double a, __float128 b) -> decltype(a + b) { // expected-error {{invalid operands to binary expression ('long double' and '__float128')}} + return a + b; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}} +} + +void test3(bool b) { + long double ld; + __float128 q; + + ld + q; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}} + q + ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}} + ld - q; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}} + q - ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}} + ld * q; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}} + q * ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}} + ld / q; // expected-error {{invalid operands to binary expression ('long double' and '__float128')}} + q / ld; // expected-error {{invalid operands to binary expression ('__float128' and 'long double')}} + ld = q; // expected-error {{assigning to 'long double' from incompatible type '__float128'}} + q = ld; // expected-error {{assigning to '__float128' from incompatible type 'long double'}} + q + b ? q : ld; // expected-error {{incompatible operand types ('__float128' and 'long double')}} +} Index: test/SemaCXX/deleted-operator.cpp =================================================================== --- test/SemaCXX/deleted-operator.cpp +++ test/SemaCXX/deleted-operator.cpp @@ -9,7 +9,7 @@ PR10757 a1; // FIXME: We get a ridiculous number of "built-in candidate" notes here... if(~a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 8 {{built-in candidate}} - if(a1==a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 121 {{built-in candidate}} + if(a1==a1) {} // expected-error {{overload resolution selected deleted operator}} expected-note 144 {{built-in candidate}} } struct DelOpDel { Index: test/SemaCXX/overloaded-builtin-operators.cpp =================================================================== --- test/SemaCXX/overloaded-builtin-operators.cpp +++ test/SemaCXX/overloaded-builtin-operators.cpp @@ -183,7 +183,7 @@ // FIXME: lots of candidates here! (void)(1.0f * a); // expected-error{{ambiguous}} \ // expected-note 4{{candidate}} \ - // expected-note {{remaining 117 candidates omitted; pass -fshow-overloads=all to show them}} + // expected-note {{remaining 140 candidates omitted; pass -fshow-overloads=all to show them}} } // pr5432 Index: tools/libclang/CXType.cpp =================================================================== --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -51,6 +51,7 @@ BTCASE(Float); BTCASE(Double); BTCASE(LongDouble); + BTCASE(Float128); BTCASE(NullPtr); BTCASE(Overload); BTCASE(Dependent); @@ -466,6 +467,7 @@ TKIND(Float); TKIND(Double); TKIND(LongDouble); + TKIND(Float128); TKIND(NullPtr); TKIND(Overload); TKIND(Dependent);