summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp32
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp8
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp1
-rw-r--r--clang/lib/AST/NSAPI.cpp1
-rw-r--r--clang/lib/AST/StmtPrinter.cpp1
-rw-r--r--clang/lib/AST/Type.cpp8
-rw-r--r--clang/lib/AST/TypeLoc.cpp1
-rw-r--r--clang/lib/Analysis/PrintfFormatString.cpp1
-rw-r--r--clang/lib/Basic/TargetInfo.cpp5
-rw-r--r--clang/lib/Basic/Targets.cpp27
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp6
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp14
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.cpp1
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp5
-rw-r--r--clang/lib/Format/FormatToken.cpp1
-rw-r--r--clang/lib/Index/USRGeneration.cpp2
-rw-r--r--clang/lib/Lex/LiteralSupport.cpp13
-rw-r--r--clang/lib/Parse/ParseDecl.cpp7
-rw-r--r--clang/lib/Parse/ParseExpr.cpp1
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp3
-rw-r--r--clang/lib/Parse/ParseTentative.cpp3
-rw-r--r--clang/lib/Sema/DeclSpec.cpp2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp1
-rw-r--r--clang/lib/Sema/SemaExpr.cpp69
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp6
-rw-r--r--clang/lib/Sema/SemaLookup.cpp7
-rw-r--r--clang/lib/Sema/SemaOverload.cpp30
-rw-r--r--clang/lib/Sema/SemaTemplateVariadic.cpp1
-rw-r--r--clang/lib/Sema/SemaType.cpp16
-rw-r--r--clang/lib/Serialization/ASTCommon.cpp3
-rw-r--r--clang/lib/Serialization/ASTReader.cpp3
31 files changed, 224 insertions, 55 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index f1aa16adba9..a99546cdab0 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -58,7 +58,7 @@ unsigned ASTContext::NumImplicitDestructors;
unsigned ASTContext::NumImplicitDestructorsDeclared;
enum FloatingRank {
- HalfRank, FloatRank, DoubleRank, LongDoubleRank
+ HalfRank, FloatRank, DoubleRank, LongDoubleRank, Float128Rank
};
RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const {
@@ -734,10 +734,9 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
DependentTemplateSpecializationTypes(this_()),
SubstTemplateTemplateParmPacks(this_()),
GlobalNestedNameSpecifier(nullptr), Int128Decl(nullptr),
- UInt128Decl(nullptr), Float128StubDecl(nullptr),
- BuiltinVaListDecl(nullptr), BuiltinMSVaListDecl(nullptr),
- ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr),
- ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
+ UInt128Decl(nullptr), BuiltinVaListDecl(nullptr),
+ BuiltinMSVaListDecl(nullptr), ObjCIdDecl(nullptr), ObjCSelDecl(nullptr),
+ ObjCClassDecl(nullptr), ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr),
CFConstantStringTagDecl(nullptr), CFConstantStringTypeDecl(nullptr),
ObjCInstanceTypeDecl(nullptr), FILEDecl(nullptr), jmp_bufDecl(nullptr),
sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr),
@@ -967,14 +966,6 @@ TypedefDecl *ASTContext::getUInt128Decl() const {
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 +1014,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
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 +1078,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
FloatComplexTy = getComplexType(FloatTy);
DoubleComplexTy = getComplexType(DoubleTy);
LongDoubleComplexTy = getComplexType(LongDoubleTy);
+ Float128ComplexTy = getComplexType(Float128Ty);
// Builtin types for 'id', 'Class', and 'SEL'.
InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
@@ -1341,6 +1336,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
case BuiltinType::Float: return Target->getFloatFormat();
case BuiltinType::Double: return Target->getDoubleFormat();
case BuiltinType::LongDouble: return Target->getLongDoubleFormat();
+ case BuiltinType::Float128: return Target->getFloat128Format();
}
}
@@ -1651,6 +1647,10 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
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*)
@@ -4635,6 +4635,7 @@ static FloatingRank getFloatingRank(QualType T) {
case BuiltinType::Float: return FloatRank;
case BuiltinType::Double: return DoubleRank;
case BuiltinType::LongDouble: return LongDoubleRank;
+ case BuiltinType::Float128: return Float128Rank;
}
}
@@ -4651,6 +4652,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
case FloatRank: return FloatComplexTy;
case DoubleRank: return DoubleComplexTy;
case LongDoubleRank: return LongDoubleComplexTy;
+ case Float128Rank: return Float128ComplexTy;
}
}
@@ -4660,6 +4662,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
case FloatRank: return FloatTy;
case DoubleRank: return DoubleTy;
case LongDoubleRank: return LongDoubleTy;
+ case Float128Rank: return Float128Ty;
}
llvm_unreachable("getFloatingRank(): illegal value for rank");
}
@@ -5489,6 +5492,7 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C,
case BuiltinType::LongDouble: return 'D';
case BuiltinType::NullPtr: return '*'; // like char*
+ case BuiltinType::Float128:
case BuiltinType::Half:
// FIXME: potentially need @encodes for these!
return ' ';
@@ -8695,6 +8699,8 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const {
return DoubleTy;
case TargetInfo::LongDouble:
return LongDoubleTy;
+ case TargetInfo::Float128:
+ return Float128Ty;
case TargetInfo::NoFloat:
return QualType();
}
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 62b60d7b892..8d12105c71b 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -1992,7 +1992,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
// ::= 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)
@@ -2073,6 +2073,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
? '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;
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index b63b5e5651e..c9caddbb6fc 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1751,6 +1751,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers,
Out << "$$T";
break;
+ case BuiltinType::Float128:
case BuiltinType::Half: {
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp
index 4c49e4c9f6c..ac2a8d35424 100644
--- a/clang/lib/AST/NSAPI.cpp
+++ b/clang/lib/AST/NSAPI.cpp
@@ -441,6 +441,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::Int128:
case BuiltinType::LongDouble:
case BuiltinType::UInt128:
+ case BuiltinType::Float128:
case BuiltinType::NullPtr:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCId:
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index cc383740926..0b3f9087909 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1310,6 +1310,7 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
case BuiltinType::Double: break; // no suffix.
case BuiltinType::Float: OS << 'F'; break;
case BuiltinType::LongDouble: OS << 'L'; break;
+ case BuiltinType::Float128: OS << 'Q'; break;
}
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 1c6ae2a2b9c..0262f5ba4a3 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -1777,7 +1777,7 @@ bool Type::hasUnsignedIntegerRepresentation() const {
bool Type::isFloatingType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Half &&
- BT->getKind() <= BuiltinType::LongDouble;
+ BT->getKind() <= BuiltinType::Float128;
if (const ComplexType *CT = dyn_cast<ComplexType>(CanonicalType))
return CT->getElementType()->isFloatingType();
return false;
@@ -1799,7 +1799,7 @@ bool Type::isRealFloatingType() const {
bool Type::isRealType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
- BT->getKind() <= BuiltinType::LongDouble;
+ BT->getKind() <= BuiltinType::Float128;
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped();
return false;
@@ -1808,7 +1808,7 @@ bool Type::isRealType() const {
bool Type::isArithmeticType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
- BT->getKind() <= BuiltinType::LongDouble;
+ BT->getKind() <= BuiltinType::Float128;
if (const EnumType *ET = dyn_cast<EnumType>(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 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "double";
case LongDouble:
return "long double";
+ case Float128:
+ return "__float128";
case WChar_S:
case WChar_U:
return Policy.MSWChar ? "__wchar_t" : "wchar_t";
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 05e5a627b75..78947d18f95 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -320,6 +320,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
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.
diff --git a/clang/lib/Analysis/PrintfFormatString.cpp b/clang/lib/Analysis/PrintfFormatString.cpp
index ff44a570de1..ac6cef9d084 100644
--- a/clang/lib/Analysis/PrintfFormatString.cpp
+++ b/clang/lib/Analysis/PrintfFormatString.cpp
@@ -616,6 +616,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
case BuiltinType::UInt128:
case BuiltinType::Int128:
case BuiltinType::Half:
+ case BuiltinType::Float128:
// Various types which are non-trivial to correct.
return false;
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index f6973f3942c..92f658a6a37 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -30,6 +30,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
BigEndian = true;
TLSSupported = true;
NoAsmVariants = false;
+ HasFloat128 = false;
PointerWidth = PointerAlign = 32;
BoolWidth = BoolAlign = 8;
IntWidth = IntAlign = 32;
@@ -46,6 +47,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
DoubleAlign = 64;
LongDoubleWidth = 64;
LongDoubleAlign = 64;
+ Float128Align = 128;
LargeArrayMinWidth = 0;
LargeArrayAlign = 0;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
@@ -72,6 +74,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
FloatFormat = &llvm::APFloat::IEEEsingle;
DoubleFormat = &llvm::APFloat::IEEEdouble;
LongDoubleFormat = &llvm::APFloat::IEEEdouble;
+ Float128Format = &llvm::APFloat::IEEEquad;
MCountName = "mcount";
RegParmMax = 0;
SSERegParmMax = 0;
@@ -223,6 +226,8 @@ TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble ||
&getLongDoubleFormat() == &llvm::APFloat::IEEEquad)
return LongDouble;
+ if (hasFloat128Type())
+ return Float128;
break;
}
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 6b26d14dc5a..4dac1046e67 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -427,6 +427,8 @@ protected:
Builder.defineMacro("_REENTRANT");
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
+ if (this->HasFloat128)
+ Builder.defineMacro("__FLOAT128__");
}
public:
LinuxTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
@@ -441,6 +443,11 @@ public:
case llvm::Triple::ppc64le:
this->MCountName = "_mcount";
break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ case llvm::Triple::systemz:
+ this->HasFloat128 = true;
+ break;
}
}
@@ -1096,6 +1103,8 @@ bool PPCTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
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.
@@ -1253,6 +1262,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
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");
@@ -1303,6 +1314,13 @@ static bool ppcUserFeaturesCheck(DiagnosticsEngine &Diags,
<< "-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;
@@ -1371,6 +1389,7 @@ bool PPCTargetInfo::hasFeature(StringRef Feature) const {
.Case("htm", HasHTM)
.Case("bpermd", HasBPERMD)
.Case("extdiv", HasExtDiv)
+ .Case("float128", HasFloat128)
.Default(false);
}
@@ -1380,19 +1399,19 @@ void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
// 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;
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index a98df93a042..a63f5582cd9 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -528,7 +528,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
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;
}
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 1fd79d0e0ed..8f122963a1f 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1796,15 +1796,19 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
amt = llvm::ConstantFP::get(VMContext,
llvm::APFloat(static_cast<double>(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<float>(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");
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 33e53a6cbe2..ebe55c70d81 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -449,6 +449,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case BuiltinType::Float:
case BuiltinType::Double:
case BuiltinType::LongDouble:
+ case BuiltinType::Float128:
ResultType = getTypeForFormat(getLLVMContext(),
Context.getFloatTypeSemantics(T),
/* UseNativeHalf = */ false);
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index b44e8405334..52e519f3044 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2530,6 +2530,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::Float:
case BuiltinType::Double:
case BuiltinType::LongDouble:
+ case BuiltinType::Float128:
case BuiltinType::Char16:
case BuiltinType::Char32:
case BuiltinType::Int128:
@@ -3349,8 +3350,8 @@ void ItaniumCXXABI::EmitFundamentalRTTIDescriptors() {
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);
diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp
index d6cd450d892..2ae4ddcfd08 100644
--- a/clang/lib/Format/FormatToken.cpp
+++ b/clang/lib/Format/FormatToken.cpp
@@ -53,6 +53,7 @@ bool FormatToken::isSimpleTypeSpecifier() const {
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:
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 65de75b5c4f..40283dcd686 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -618,6 +618,8 @@ void USRGenerator::VisitType(QualType T) {
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)
diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp
index 27c80b93015..e68b82fb499 100644
--- a/clang/lib/Lex/LiteralSupport.cpp
+++ b/clang/lib/Lex/LiteralSupport.cpp
@@ -525,6 +525,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
isHalf = false;
isFloat = false;
isImaginary = false;
+ isFloat128 = false;
MicrosoftInteger = 0;
hadError = false;
@@ -567,9 +568,17 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
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 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
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]) {
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 6b7ffb64fae..2171e5cfc3d 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3306,6 +3306,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
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);
@@ -4279,6 +4283,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
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:
@@ -4353,6 +4358,7 @@ bool Parser::isTypeSpecifierQualifier() {
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:
@@ -4507,6 +4513,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
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:
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 2745c337765..5b7c839454a 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1166,6 +1166,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
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:
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index afed9b1ab46..b569e7aeba1 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1928,6 +1928,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
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;
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 747d0a982cf..4d4bd806f3c 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -946,6 +946,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
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:
@@ -1426,6 +1427,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
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))
@@ -1517,6 +1519,7 @@ bool Parser::isCXXDeclarationSpecifierAType() {
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:
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 4bc1d3423b4..ddfe6257cf4 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -289,6 +289,7 @@ bool Declarator::isDeclarationOfFunction() const {
case TST_decimal32:
case TST_decimal64:
case TST_double:
+ case TST_float128:
case TST_enum:
case TST_error:
case TST_float:
@@ -457,6 +458,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T,
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";
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 058a25bf452..5360cbbc06d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -108,6 +108,7 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
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:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 66b87120b0d..a5ee8bebae7 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1155,6 +1155,48 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
/*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<ComplexType>();
+ auto *RHSComplex = RHSType->getAs<ComplexType>();
+
+ 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 {
@@ -1318,6 +1360,11 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
// 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,
@@ -3327,10 +3374,12 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
}
} 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());
@@ -6604,6 +6653,15 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
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 &&
@@ -7337,6 +7395,11 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
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())) {
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e11d9c84fea..3e950764867 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5176,6 +5176,12 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
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));
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index b2ab39aacbe..f1eed0e1565 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -681,13 +681,6 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
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());
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 0b36fef1444..4a6831d88df 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1671,6 +1671,20 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
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
+ // We of course allow this conversion if long double is really double.
+ if (&S.Context.getFloatTypeSemantics(FromType) !=
+ &S.Context.getFloatTypeSemantics(ToType)) {
+ bool Float128AndLongDouble = ((FromType == S.Context.Float128Ty &&
+ ToType == S.Context.LongDoubleTy) ||
+ (FromType == S.Context.LongDoubleTy &&
+ ToType == S.Context.Float128Ty));
+ if (Float128AndLongDouble &&
+ (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) !=
+ &llvm::APFloat::IEEEdouble))
+ return false;
+ }
// Floating point conversions (C++ 4.8).
SCS.Second = ICK_Floating_Conversion;
FromType = ToType.getUnqualifiedType();
@@ -1973,7 +1987,8 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
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.
@@ -7198,13 +7213,13 @@ class BuiltinOperatorOverloadBuilder {
// 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) {
@@ -7215,6 +7230,7 @@ class BuiltinOperatorOverloadBuilder {
&ASTContext::FloatTy,
&ASTContext::DoubleTy,
&ASTContext::LongDoubleTy,
+ &ASTContext::Float128Ty,
// Start of integral types.
&ASTContext::IntTy,
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index c23b5a2adc5..52a1ad545a5 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -727,6 +727,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
case TST_half:
case TST_float:
case TST_double:
+ case TST_float128:
case TST_bool:
case TST_decimal32:
case TST_decimal64:
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index c8c8af109b5..7fd43a87a81 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1397,7 +1397,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
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
@@ -1419,6 +1420,12 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
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
break;
case DeclSpec::TST_decimal32: // _Decimal32
@@ -7004,13 +7011,6 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
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
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index 2382f8ea4bd..792fac99e58 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -91,6 +91,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
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;
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 5d459ac9fb6..0f4a7d32667 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6040,6 +6040,9 @@ QualType ASTReader::GetType(TypeID ID) {
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;
OpenPOWER on IntegriCloud