summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-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
8 files changed, 107 insertions, 25 deletions
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
OpenPOWER on IntegriCloud