[cfe-commits] r112577 - in /cfe/trunk: lib/AST/ExprCXX.cpp lib/Parse/ParseExpr.cpp test/SemaCXX/type-traits.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Mon Aug 30 21:59:00 PDT 2010


Author: cornedbee
Date: Mon Aug 30 23:59:00 2010
New Revision: 112577

URL: http://llvm.org/viewvc/llvm-project?rev=112577&view=rev
Log:
Implement the __has_nothrow trait family, by Steven Watanabe.

Modified:
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/test/SemaCXX/type-traits.cpp

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=112577&r1=112576&r2=112577&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Aug 30 23:59:00 2010
@@ -386,6 +386,108 @@
           C.getBaseElementType(QueriedType)->getAs<RecordType>())
       return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
     return false;
+  // TODO: Propagate nothrowness for implicitly declared special members.
+  case UTT_HasNothrowAssign:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If type is const qualified or is a reference type then the
+    //   trait is false. Otherwise if __has_trivial_assign (type)
+    //   is true then the trait is true, else if type is a cv class
+    //   or union type with copy assignment operators that are known
+    //   not to throw an exception then the trait is true, else it is
+    //   false.
+    if (C.getBaseElementType(QueriedType).isConstQualified())
+      return false;
+    if (QueriedType->isReferenceType())
+      return false;
+    if (QueriedType->isPODType())
+      return true;
+    if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
+      CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
+      if (RD->hasTrivialCopyAssignment())
+        return true;
+
+      bool FoundAssign = false;
+      bool AllNoThrow = true;
+      DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
+      DeclContext::lookup_const_iterator Op, OpEnd;
+      for (llvm::tie(Op, OpEnd) = RD->lookup(Name);
+           Op != OpEnd; ++Op) {
+        CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
+        if (Operator->isCopyAssignmentOperator()) {
+          FoundAssign = true;
+          const FunctionProtoType *CPT
+              = Operator->getType()->getAs<FunctionProtoType>();
+          if (!CPT->hasEmptyExceptionSpec()) {
+            AllNoThrow = false;
+            break;
+          }
+        }
+      }
+
+      return FoundAssign && AllNoThrow;
+    }
+    return false;
+  case UTT_HasNothrowCopy:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If __has_trivial_copy (type) is true then the trait is true, else
+    //   if type is a cv class or union type with copy constructors that are
+    //   known not to throw an exception then the trait is true, else it is
+    //   false.
+    if (QueriedType->isPODType() || QueriedType->isReferenceType())
+      return true;
+    if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+      if (RD->hasTrivialCopyConstructor())
+        return true;
+
+      bool FoundConstructor = false;
+      bool AllNoThrow = true;
+      unsigned FoundTQs;
+      DeclarationName ConstructorName
+          = C.DeclarationNames.getCXXConstructorName(
+                                          C.getCanonicalType(QueriedType));
+      DeclContext::lookup_const_iterator Con, ConEnd;
+      for (llvm::tie(Con, ConEnd) = RD->lookup(ConstructorName);
+           Con != ConEnd; ++Con) {
+        CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+        if (Constructor->isCopyConstructor(FoundTQs)) {
+          FoundConstructor = true;
+          const FunctionProtoType *CPT
+              = Constructor->getType()->getAs<FunctionProtoType>();
+          if (!CPT->hasEmptyExceptionSpec()) {
+            AllNoThrow = false;
+            break;
+          }
+        }
+      }
+
+      return FoundConstructor && AllNoThrow;
+    }
+    return false;
+  case UTT_HasNothrowConstructor:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    //   If __has_trivial_constructor (type) is true then the trait is
+    //   true, else if type is a cv class or union type (or array
+    //   thereof) with a default constructor that is known not to
+    //   throw an exception then the trait is true, else it is false.
+    if (QueriedType->isPODType())
+      return true;
+    if (const RecordType *RT =
+          C.getBaseElementType(QueriedType)->getAs<RecordType>()) {
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+      if (RD->hasTrivialConstructor())
+        return true;
+
+      if (CXXConstructorDecl *Constructor = RD->getDefaultConstructor()) {
+        const FunctionProtoType *CPT
+            = Constructor->getType()->getAs<FunctionProtoType>();
+        // TODO: check whether evaluating default arguments can throw.
+        // For now, we'll be conservative and assume that they can throw.
+        if (CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0)
+          return true;
+      }
+    }
+    return false;
   }
 }
 

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=112577&r1=112576&r2=112577&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Aug 30 23:59:00 2010
@@ -526,9 +526,9 @@
 ///                   '::'[opt] 'delete' '[' ']' cast-expression
 ///
 /// [GNU] unary-type-trait:
-///                   '__has_nothrow_assign'                  [TODO]
-///                   '__has_nothrow_copy'                    [TODO]
-///                   '__has_nothrow_constructor'             [TODO]
+///                   '__has_nothrow_assign'
+///                   '__has_nothrow_copy'
+///                   '__has_nothrow_constructor'
 ///                   '__has_trivial_assign'                  [TODO]
 ///                   '__has_trivial_copy'                    [TODO]
 ///                   '__has_trivial_constructor'
@@ -900,6 +900,9 @@
   case tok::kw___has_trivial_copy:
   case tok::kw___has_trivial_assign:
   case tok::kw___has_trivial_destructor:
+  case tok::kw___has_nothrow_assign:
+  case tok::kw___has_nothrow_copy:
+  case tok::kw___has_nothrow_constructor:
     return ParseUnaryTypeTrait();
 
   case tok::at: {

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=112577&r1=112576&r2=112577&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Mon Aug 30 23:59:00 2010
@@ -34,6 +34,33 @@
 typedef HasVirt VirtAr[10];
 union NonPODUnion { int i; Derives n; };
 
+struct HasNoThrowCopyAssign {
+  void operator =(const HasNoThrowCopyAssign&) throw();
+};
+struct HasMultipleCopyAssign {
+  void operator =(const HasMultipleCopyAssign&) throw();
+  void operator =(volatile HasMultipleCopyAssign&);
+};
+struct HasMultipleNoThrowCopyAssign {
+  void operator =(const HasMultipleNoThrowCopyAssign&) throw();
+  void operator =(volatile HasMultipleNoThrowCopyAssign&) throw();
+};
+
+struct HasNoThrowConstructor { HasNoThrowConstructor() throw(); };
+struct HasNoThrowConstructorWithArgs {
+  HasNoThrowConstructorWithArgs(HasCons i = HasCons(0)) throw();
+};
+
+struct HasNoThrowCopy { HasNoThrowCopy(const HasNoThrowCopy&) throw(); };
+struct HasMultipleCopy {
+  HasMultipleCopy(const HasMultipleCopy&) throw();
+  HasMultipleCopy(volatile HasMultipleCopy&);
+};
+struct HasMultipleNoThrowCopy {
+  HasMultipleNoThrowCopy(const HasMultipleNoThrowCopy&) throw();
+  HasMultipleNoThrowCopy(volatile HasMultipleNoThrowCopy&) throw();
+};
+
 void is_pod()
 {
   int t01[T(__is_pod(int))];
@@ -258,3 +285,77 @@
   int t01[T(!__has_trivial_destructor(A))];
   int t02[T(!__has_trivial_destructor(B<int>))];
 }
+
+void has_nothrow_assign() {
+  int t01[T(__has_nothrow_assign(Int))];
+  int t02[T(__has_nothrow_assign(IntAr))];
+  int t03[T(__has_nothrow_assign(Union))];
+  int t04[T(__has_nothrow_assign(UnionAr))];
+  int t05[T(__has_nothrow_assign(POD))];
+  int t06[T(__has_nothrow_assign(Derives))];
+  int t07[F(__has_nothrow_assign(ConstIntAr))];
+  int t08[F(__has_nothrow_assign(ConstIntArAr))];
+  int t09[T(__has_nothrow_assign(HasDest))];
+  int t10[T(__has_nothrow_assign(HasPriv))];
+  int t11[T(__has_nothrow_assign(HasCons))];
+  int t12[T(__has_nothrow_assign(HasRef))];
+  int t13[T(__has_nothrow_assign(HasCopy))];
+  int t14[F(__has_nothrow_assign(IntRef))];
+  int t15[F(__has_nothrow_assign(HasCopyAssign))];
+  int t16[F(__has_nothrow_assign(const Int))];
+  int t17[F(__has_nothrow_assign(NonPODAr))];
+  int t18[F(__has_nothrow_assign(VirtAr))];
+
+  int t19[T(__has_nothrow_assign(HasNoThrowCopyAssign))];
+  int t20[F(__has_nothrow_assign(HasMultipleCopyAssign))];
+  int t21[T(__has_nothrow_assign(HasMultipleNoThrowCopyAssign))];
+}
+
+void has_nothrow_copy() {
+  int t01[T(__has_nothrow_copy(Int))];
+  int t02[T(__has_nothrow_copy(IntAr))];
+  int t03[T(__has_nothrow_copy(Union))];
+  int t04[T(__has_nothrow_copy(UnionAr))];
+  int t05[T(__has_nothrow_copy(POD))];
+  int t06[T(__has_nothrow_copy(Derives))];
+  int t07[T(__has_nothrow_copy(ConstIntAr))];
+  int t08[T(__has_nothrow_copy(ConstIntArAr))];
+  int t09[T(__has_nothrow_copy(HasDest))];
+  int t10[T(__has_nothrow_copy(HasPriv))];
+  int t11[T(__has_nothrow_copy(HasCons))];
+  int t12[T(__has_nothrow_copy(HasRef))];
+  int t13[F(__has_nothrow_copy(HasCopy))];
+  int t14[T(__has_nothrow_copy(IntRef))];
+  int t15[T(__has_nothrow_copy(HasCopyAssign))];
+  int t16[T(__has_nothrow_copy(const Int))];
+  int t17[F(__has_nothrow_copy(NonPODAr))];
+  int t18[F(__has_nothrow_copy(VirtAr))];
+
+  int t19[T(__has_nothrow_copy(HasNoThrowCopy))];
+  int t20[F(__has_nothrow_copy(HasMultipleCopy))];
+  int t21[T(__has_nothrow_copy(HasMultipleNoThrowCopy))];
+}
+
+void has_nothrow_constructor() {
+  int t01[T(__has_nothrow_constructor(Int))];
+  int t02[T(__has_nothrow_constructor(IntAr))];
+  int t03[T(__has_nothrow_constructor(Union))];
+  int t04[T(__has_nothrow_constructor(UnionAr))];
+  int t05[T(__has_nothrow_constructor(POD))];
+  int t06[T(__has_nothrow_constructor(Derives))];
+  int t07[T(__has_nothrow_constructor(ConstIntAr))];
+  int t08[T(__has_nothrow_constructor(ConstIntArAr))];
+  int t09[T(__has_nothrow_constructor(HasDest))];
+  int t10[T(__has_nothrow_constructor(HasPriv))];
+  int t11[F(__has_nothrow_constructor(HasCons))];
+  int t12[F(__has_nothrow_constructor(HasRef))];
+  int t13[F(__has_nothrow_constructor(HasCopy))];
+  int t14[F(__has_nothrow_constructor(IntRef))];
+  int t15[T(__has_nothrow_constructor(HasCopyAssign))];
+  int t16[T(__has_nothrow_constructor(const Int))];
+  int t17[T(__has_nothrow_constructor(NonPODAr))];
+  // int t18[T(__has_nothrow_constructor(VirtAr))]; // not implemented
+
+  int t19[T(__has_nothrow_constructor(HasNoThrowConstructor))];
+  int t20[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))];
+}





More information about the cfe-commits mailing list