[llvm/f16] clang++: Backport C++0x patches from the 3.0 branch (#729308)

Michel Alexandre Salim salimma at fedoraproject.org
Mon Mar 26 10:54:48 UTC 2012


commit 4e1a1955b0e2cd2597eb244cd79eaeac619e072e
Author: Michel Alexandre Salim <salimma at fedoraproject.org>
Date:   Mon Mar 26 17:54:44 2012 +0700

    clang++: Backport C++0x patches from the 3.0 branch (#729308)

 clang-2.9-PR9472_is_trivial.patch |  286 +++++++++++++++++++++++++++++++++++++
 clang-2.9-PR9585_decltype.patch   |   54 +++++++
 llvm.spec                         |   12 ++-
 3 files changed, 351 insertions(+), 1 deletions(-)
---
diff --git a/clang-2.9-PR9472_is_trivial.patch b/clang-2.9-PR9472_is_trivial.patch
new file mode 100644
index 0000000..51054b8
--- /dev/null
+++ b/clang-2.9-PR9472_is_trivial.patch
@@ -0,0 +1,286 @@
+From 96fdb1843b17f4acad796229b53793da328ea476 Mon Sep 17 00:00:00 2001
+From: Michel Alexandre Salim <salimma at fedoraproject.org>
+Date: Mon, 26 Mar 2012 15:34:11 +0700
+Subject: [PATCH] Implement basic __is_trivial type-trait support, enough to
+ close PR9472. This introduces a few APIs on the AST to
+ bundle up the standard-based logic so that programmatic
+ clients have access to exactly the same behavior.
+
+There is only one serious FIXME here: checking for non-trivial move
+constructors and move assignment operators. Those bits need to be added
+to the declaration and accessors provided.
+
+This implementation should be enough for the uses of __is_trivial in
+libstdc++ 4.6's C++98 library implementation.
+
+Ideas for more thorough test cases or any edge cases missing would be
+appreciated. =D
+
+git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130057 91177308-0d34-0410-b5e6-96231b3b80d8
+(cherry picked from commit b7e9589bce9852b4db9575f55ac9137572147eb5)
+
+Conflicts:
+
+	include/clang/Basic/TypeTraits.h
+	lib/Parse/ParseExpr.cpp
+---
+ include/clang/AST/DeclCXX.h        |    4 ++++
+ include/clang/AST/Type.h           |    4 ++++
+ include/clang/Basic/TokenKinds.def |    1 +
+ include/clang/Basic/TypeTraits.h   |    1 +
+ lib/AST/DeclCXX.cpp                |   17 +++++++++++++++++
+ lib/AST/StmtPrinter.cpp            |    1 +
+ lib/AST/Type.cpp                   |   27 +++++++++++++++++++++++++++
+ lib/Lex/PPMacroExpansion.cpp       |    1 +
+ lib/Parse/ParseExpr.cpp            |    2 ++
+ lib/Parse/ParseExprCXX.cpp         |    1 +
+ lib/Parse/ParseTentative.cpp       |    1 +
+ lib/Sema/SemaExprCXX.cpp           |    1 +
+ test/SemaCXX/type-traits.cpp       |   34 ++++++++++++++++++++++++++++++++++
+ 13 files changed, 95 insertions(+)
+
+diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
+index 0473ae0..b36b35b 100644
+--- a/include/clang/AST/DeclCXX.h
++++ b/include/clang/AST/DeclCXX.h
+@@ -743,6 +743,10 @@ public:
+   // (C++ [class.dtor]p3)
+   bool hasTrivialDestructor() const { return data().HasTrivialDestructor; }
+ 
++  // isTriviallyCopyable - Whether this class is considered trivially copyable
++  // (C++0x [class]p5).
++  bool isTriviallyCopyable() const;
++
+   /// \brief If this record is an instantiation of a member class,
+   /// retrieves the member class from which it was instantiated.
+   ///
+diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
+index c071056..8270530 100644
+--- a/include/clang/AST/Type.h
++++ b/include/clang/AST/Type.h
+@@ -1163,6 +1163,10 @@ public:
+   /// (C++0x [basic.types]p10)
+   bool isLiteralType() const;
+ 
++  /// isTrivialType - Return true if this is a literal type
++  /// (C++0x [basic.types]p9)
++  bool isTrivialType() const;
++
+   /// Helper methods to distinguish type categories. All type predicates
+   /// operate on the canonical type, ignoring typedefs and qualifiers.
+ 
+diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
+index 96a817b..bc1a97e 100644
+--- a/include/clang/Basic/TokenKinds.def
++++ b/include/clang/Basic/TokenKinds.def
+@@ -331,6 +331,7 @@ KEYWORD(__is_empty                  , KEYCXX)
+ KEYWORD(__is_enum                   , KEYCXX)
+ KEYWORD(__is_pod                    , KEYCXX)
+ KEYWORD(__is_polymorphic            , KEYCXX)
++KEYWORD(__is_trivial                , KEYCXX)
+ KEYWORD(__is_union                  , KEYCXX)
+ // Tentative name - there's no implementation of std::is_literal_type yet.
+ KEYWORD(__is_literal                , KEYCXX)
+diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
+index 00c6e9e..d39ddf9 100644
+--- a/include/clang/Basic/TypeTraits.h
++++ b/include/clang/Basic/TypeTraits.h
+@@ -32,6 +32,7 @@ namespace clang {
+     UTT_IsEnum,
+     UTT_IsPOD,
+     UTT_IsPolymorphic,
++    UTT_IsTrivial,
+     UTT_IsUnion,
+     UTT_IsLiteral
+   };
+diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
+index b6cba0a..6c80d00 100644
+--- a/lib/AST/DeclCXX.cpp
++++ b/lib/AST/DeclCXX.cpp
+@@ -218,6 +218,23 @@ bool CXXRecordDecl::hasConstCopyConstructor(const ASTContext &Context) const {
+   return getCopyConstructor(Context, Qualifiers::Const) != 0;
+ }
+ 
++bool CXXRecordDecl::isTriviallyCopyable() const {
++  // C++0x [class]p5:
++  //   A trivially copyable class is a class that:
++  //   -- has no non-trivial copy constructors,
++  if (!hasTrivialCopyConstructor()) return false;
++  //   -- has no non-trivial move constructors,
++  // FIXME: C++0x: Track and check trivial move constructors.
++  //   -- has no non-trivial copy assignment operators,
++  if (!hasTrivialCopyAssignment()) return false;
++  //   -- has no non-trivial move assignment operators, and
++  // FIXME: C++0x: Track and check trivial move assignment operators.
++  //   -- has a trivial destructor.
++  if (!hasTrivialDestructor()) return false;
++
++  return true;
++}
++
+ /// \brief Perform a simplistic form of overload resolution that only considers
+ /// cv-qualifiers on a single parameter, and return the best overload candidate
+ /// (if there is one).
+diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
+index 1cdd220..2f35b62 100644
+--- a/lib/AST/StmtPrinter.cpp
++++ b/lib/AST/StmtPrinter.cpp
+@@ -1227,6 +1227,7 @@ static const char *getTypeTraitName(UnaryTypeTrait UTT) {
+   case UTT_IsEnum:                return "__is_enum";
+   case UTT_IsPOD:                 return "__is_pod";
+   case UTT_IsPolymorphic:         return "__is_polymorphic";
++  case UTT_IsTrivial:             return "__is_trivial";
+   case UTT_IsUnion:               return "__is_union";
+   }
+   return "";
+diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
+index cde865f..07b90e5 100644
+--- a/lib/AST/Type.cpp
++++ b/lib/AST/Type.cpp
+@@ -891,6 +891,33 @@ bool Type::isLiteralType() const {
+   }
+ }
+ 
++bool Type::isTrivialType() const {
++  if (isIncompleteType())
++    return false;
++
++  // C++0x [basic.types]p9:
++  //   Scalar types, trivial class types, arrays of such types, and
++  //   cv-qualified versions of these types are collectively called trivial
++  //   types.
++  const Type *BaseTy = getBaseElementTypeUnsafe();
++  assert(BaseTy && "NULL element type");
++  if (BaseTy->isScalarType()) return true;
++  if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
++    const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
++
++    // C++0x [class]p5:
++    //   A trivial class is a class that has a trivial default constructor
++    if (!ClassDecl->hasTrivialConstructor()) return false;
++    //   and is trivially copyable.
++    if (!ClassDecl->isTriviallyCopyable()) return false;
++
++    return true;
++  }
++
++  // No other types can match.
++  return false;
++}
++
+ bool Type::isPromotableIntegerType() const {
+   if (const BuiltinType *BT = getAs<BuiltinType>())
+     switch (BT->getKind()) {
+diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
+index 10abfb4..5ac8661 100644
+--- a/lib/Lex/PPMacroExpansion.cpp
++++ b/lib/Lex/PPMacroExpansion.cpp
+@@ -584,6 +584,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
+            .Case("is_enum", LangOpts.CPlusPlus)
+            .Case("is_pod", LangOpts.CPlusPlus)
+            .Case("is_polymorphic", LangOpts.CPlusPlus)
++           .Case("is_trivial", LangOpts.CPlusPlus)
+            .Case("is_union", LangOpts.CPlusPlus)
+            .Case("is_literal", LangOpts.CPlusPlus)
+            .Case("tls", PP.getTargetInfo().isTLSSupported())
+diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
+index 03b3417..d663da4 100644
+--- a/lib/Parse/ParseExpr.cpp
++++ b/lib/Parse/ParseExpr.cpp
+@@ -535,6 +535,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+ ///                   '__is_enum'
+ ///                   '__is_pod'
+ ///                   '__is_polymorphic'
++///                   '__is_trivial'
+ ///                   '__is_union'
+ ///
+ ///       binary-type-trait:
+@@ -981,6 +982,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+   case tok::kw___is_pod: // [GNU] unary-type-trait
+   case tok::kw___is_class:
+   case tok::kw___is_enum:
++  case tok::kw___is_trivial:
+   case tok::kw___is_union:
+   case tok::kw___is_empty:
+   case tok::kw___is_polymorphic:
+diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
+index d09f20e..d94cac6 100644
+--- a/lib/Parse/ParseExprCXX.cpp
++++ b/lib/Parse/ParseExprCXX.cpp
+@@ -1825,6 +1825,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
+   case tok::kw___is_enum:                 return UTT_IsEnum;
+   case tok::kw___is_pod:                  return UTT_IsPOD;
+   case tok::kw___is_polymorphic:          return UTT_IsPolymorphic;
++  case tok::kw___is_trivial:              return UTT_IsTrivial;
+   case tok::kw___is_union:                return UTT_IsUnion;
+   case tok::kw___is_literal:              return UTT_IsLiteral;
+   }
+diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
+index 1099327..93122b3 100644
+--- a/lib/Parse/ParseTentative.cpp
++++ b/lib/Parse/ParseTentative.cpp
+@@ -660,6 +660,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
+   case tok::kw___is_enum:
+   case tok::kw___is_pod:
+   case tok::kw___is_polymorphic:
++  case tok::kw___is_trivial:
+   case tok::kw___is_union:
+   case tok::kw___is_literal:
+   case tok::kw___uuidof:
+diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
+index 884011e..e8220ff 100644
+--- a/lib/Sema/SemaExprCXX.cpp
++++ b/lib/Sema/SemaExprCXX.cpp
+@@ -2310,6 +2310,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T,
+   default: assert(false && "Unknown type trait or not implemented");
+   case UTT_IsPOD: return T->isPODType();
+   case UTT_IsLiteral: return T->isLiteralType();
++  case UTT_IsTrivial: return T->isTrivialType();
+   case UTT_IsClass: // Fallthrough
+   case UTT_IsUnion:
+     if (const RecordType *Record = T->getAs<RecordType>()) {
+diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
+index ff9a6bf..cbb3549 100644
+--- a/test/SemaCXX/type-traits.cpp
++++ b/test/SemaCXX/type-traits.cpp
+@@ -548,3 +548,37 @@ void is_convertible_to() {
+   int t22[F(__is_convertible_to(PrivateCopy, PrivateCopy))];
+   int t23[T(__is_convertible_to(X0<int>, X0<float>))];
+ }
++
++void is_trivial()
++{
++  int t01[T(__is_trivial(int))];
++  int t02[T(__is_trivial(Enum))];
++  int t03[T(__is_trivial(POD))];
++  int t04[T(__is_trivial(Int))];
++  int t05[T(__is_trivial(IntAr))];
++  int t06[T(__is_trivial(Statics))];
++  int t07[T(__is_trivial(Empty))];
++  int t08[T(__is_trivial(EmptyUnion))];
++  int t09[T(__is_trivial(Union))];
++  int t10[T(__is_trivial(HasFunc))];
++  int t11[T(__is_trivial(HasOp))];
++  int t12[T(__is_trivial(HasConv))];
++  int t13[T(__is_trivial(HasAssign))];
++  int t15[T(__is_trivial(HasAnonymousUnion))];
++  int t16[T(__is_trivial(Derives))];
++  int t17[T(__is_trivial(DerivesEmpty))];
++  int t18[T(__is_trivial(NonPODAr))];
++  int t19[T(__is_trivial(HasPriv))];
++  int t20[T(__is_trivial(HasProt))];
++
++  int f01[F(__is_trivial(IntArNB))];
++  int f02[F(__is_trivial(HasCons))];
++  int f03[F(__is_trivial(HasCopyAssign))];
++  int f04[F(__is_trivial(HasDest))];
++  int f05[F(__is_trivial(HasRef))];
++  int f06[F(__is_trivial(HasNonPOD))];
++  int f07[F(__is_trivial(HasVirt))];
++  int f08[F(__is_trivial(void))];
++  int f09[F(__is_trivial(cvoid))];
++  int f10[F(__is_trivial(NonPODArNB))];
++}
+-- 
+1.7.9.3
+
diff --git a/clang-2.9-PR9585_decltype.patch b/clang-2.9-PR9585_decltype.patch
new file mode 100644
index 0000000..a514c5e
--- /dev/null
+++ b/clang-2.9-PR9585_decltype.patch
@@ -0,0 +1,54 @@
+From ddd23feca95aa2341654f225010675ea873ea38f Mon Sep 17 00:00:00 2001
+From: Eli Friedman <eli.friedman at gmail.com>
+Date: Mon, 4 Apr 2011 07:19:40 +0000
+Subject: [PATCH] PR9585: add __decltype as a keyword.  While I'm here,
+ alphabetize the list.
+
+git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128809 91177308-0d34-0410-b5e6-96231b3b80d8
+(cherry picked from commit cccc02ac215ffc16fc4b3ebfee5ee87c40e30505)
+---
+ include/clang/Basic/TokenKinds.def |    9 +++++----
+ test/SemaCXX/decltype-98.cpp       |    3 +++
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+ create mode 100644 test/SemaCXX/decltype-98.cpp
+
+diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
+index bc1a97e..df67d13 100644
+--- a/include/clang/Basic/TokenKinds.def
++++ b/include/clang/Basic/TokenKinds.def
+@@ -360,18 +360,19 @@ KEYWORD(__pixel                     , KEYALTIVEC)
+ 
+ // Alternate spelling for various tokens.  There are GCC extensions in all
+ // languages, but should not be disabled in strict conformance mode.
+-ALIAS("__attribute__", __attribute, KEYALL)
+-ALIAS("__const"      , const      , KEYALL)
+-ALIAS("__const__"    , const      , KEYALL)
+ ALIAS("__alignof__"  , __alignof  , KEYALL)
+ ALIAS("__asm"        , asm        , KEYALL)
+ ALIAS("__asm__"      , asm        , KEYALL)
++ALIAS("__attribute__", __attribute, KEYALL)
+ ALIAS("__complex"    , _Complex   , KEYALL)
+ ALIAS("__complex__"  , _Complex   , KEYALL)
++ALIAS("__const"      , const      , KEYALL)
++ALIAS("__const__"    , const      , KEYALL)
++ALIAS("__decltype"   , decltype   , KEYCXX)
+ ALIAS("__imag__"     , __imag     , KEYALL)
+ ALIAS("__inline"     , inline     , KEYALL)
+ ALIAS("__inline__"   , inline     , KEYALL)
+-ALIAS("__nullptr"    , nullptr      , KEYCXX)
++ALIAS("__nullptr"    , nullptr    , KEYCXX)
+ ALIAS("__real__"     , __real     , KEYALL)
+ ALIAS("__restrict"   , restrict   , KEYALL)
+ ALIAS("__restrict__" , restrict   , KEYALL)
+diff --git a/test/SemaCXX/decltype-98.cpp b/test/SemaCXX/decltype-98.cpp
+new file mode 100644
+index 0000000..db52565
+--- /dev/null
++++ b/test/SemaCXX/decltype-98.cpp
+@@ -0,0 +1,3 @@
++// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s
++extern int x;
++__decltype(1) x = 3;
+-- 
+1.7.9.3
+
diff --git a/llvm.spec b/llvm.spec
index 6bbb0e8..4de17fb 100644
--- a/llvm.spec
+++ b/llvm.spec
@@ -19,7 +19,7 @@
 
 Name:           llvm
 Version:        2.9
-Release:        9%{?dist}
+Release:        10%{?dist}
 Summary:        The Low Level Virtual Machine
 
 Group:          Development/Languages
@@ -39,6 +39,11 @@ Patch1:         clang-2.9-add_gcc_vers.patch
 # Operator.h incompatibility with GCC 4.6 in C++0x mode
 # http://llvm.org/bugs/show_bug.cgi?id=9869
 Patch2:         llvm-2.9-PR9869_operator_destructor.patch
+# Backports from clang 3.0 needed for libstdc++ 4.6.x
+# __is_trivial implementation 
+Patch3:         clang-2.9-PR9472_is_trivial.patch
+# __decltype
+Patch4:         clang-2.9-PR9585_decltype.patch
 
 BuildRequires:  bison
 BuildRequires:  chrpath
@@ -226,6 +231,8 @@ mv clang-%{version}%{?prerel} tools/clang
 # clang patches
 pushd tools/clang
 %patch1 -p1 -b .add_gcc_ver
+%patch3 -p1 -b .is_trivial
+%patch4 -p1 -b .decltype
 popd
 
 # Encoding fix
@@ -476,6 +483,9 @@ exit 0
 
 
 %changelog
+* Mon Mar 26 2012 Michel Salim <salimma at fedoraproject.org> - 2.9-10
+- clang++: Backport C++0x patches from the 3.0 branch (#729308)
+
 * Fri Mar 23 2012 Michel Salim <salimma at fedoraproject.org> - 2.9-9
 - Actually rebuild against GCC 4.6.3 (BR override expired when building -8)
 


More information about the scm-commits mailing list