[cfe-commits] r130604 - /cfe/trunk/lib/Sema/SemaExprCXX.cpp

Chandler Carruth chandlerc at gmail.com
Sat Apr 30 03:07:33 PDT 2011


Author: chandlerc
Date: Sat Apr 30 05:07:32 2011
New Revision: 130604

URL: http://llvm.org/viewvc/llvm-project?rev=130604&view=rev
Log:
Extract a function to impose the completeness requirement on unary type
trait arguments. Reflow the logic to use early exit instead of a complex
condition expression. Switch to a switch for acting on different type
traits and add a bunch of the recently implemented type traits here.
This fixes one of the regressions with the new __is_standard_layout
trait to again require a complete type. It also fixes some latent bugs
in other traits that never did impose this despite the standard
requiring it. However, all these bugs were hidden for non-borland
systems where the default is to require a complete type.

It's unclear to me what the best approach here is: providing an explicit
lists for the ones requiring complete types only w/ Borland and using
a default for the rest, or forcing this switch to enumerate the traits
and make it clear which way each one goes.

I'm still working on cleaning up the tests so that they actually catch
this, a much more comprehensive update to the tests will come once I've
worked through the bugs I'm finding via inspection.

Modified:
    cfe/trunk/lib/Sema/SemaExprCXX.cpp

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=130604&r1=130603&r2=130604&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Apr 30 05:07:32 2011
@@ -2628,34 +2628,87 @@
   }
 }
 
+/// \brief Check the completeness of a type in a unary type trait.
+///
+/// If the particular type trait requires a complete type, tries to complete
+/// it. If completing the type fails, a diagnostic is emitted and false
+/// returned. If completing the type succeeds or no completion was required,
+/// returns true.
+static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S,
+                                                UnaryTypeTrait UTT,
+                                                SourceLocation Loc,
+                                                QualType ArgTy) {
+  // C++0x [meta.unary.prop]p3:
+  //   For all of the class templates X declared in this Clause, instantiating
+  //   that template with a template argument that is a class template
+  //   specialization may result in the implicit instantiation of the template
+  //   argument if and only if the semantics of X require that the argument
+  //   must be a complete type.
+  // We apply this rule to all the type trait expressions used to implement
+  // these class templates. We also try to follow any GCC documented behavior
+  // in these expressions to ensure portability of standard libraries.
+  switch (UTT) {
+    // is_complete_type somewhat obviously cannot require a complete type.
+  case UTT_IsCompleteType:
+    return true;
+
+    // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
+    // all traits except __is_class, __is_enum and __is_union require a the type
+    // to be complete, an array of unknown bound, or void.
+  case UTT_IsClass:
+  case UTT_IsEnum:
+  case UTT_IsUnion:
+    return true;
+
+  default:
+    // Apprantely Borland only wants the explicitly listed traits to complete
+    // the type.
+    if (S.LangOpts.Borland) return true;
+
+    // C++0x [meta.unary.prop] Table 49 requires the following traits to be
+    // applied to a complete type, so we enumerate theme here even though the
+    // default for non-Borland compilers is to require completeness for any
+    // other traits than the ones specifically allowed to work on incomplete
+    // types.
+    // FIXME: C++0x: This list is incomplete, and the names don't always
+    // correspond clearly to entries in the standard's table.
+  case UTT_HasNothrowAssign:
+  case UTT_HasNothrowConstructor:
+  case UTT_HasNothrowCopy:
+  case UTT_HasTrivialAssign:
+  case UTT_HasTrivialConstructor:
+  case UTT_HasTrivialCopy:
+  case UTT_HasTrivialDestructor:
+  case UTT_HasVirtualDestructor:
+  case UTT_IsAbstract:
+  case UTT_IsEmpty:
+  case UTT_IsLiteral:
+  case UTT_IsPOD:
+  case UTT_IsPolymorphic:
+  case UTT_IsStandardLayout:
+  case UTT_IsTrivial:
+    // Arrays of unknown bound are expressly allowed.
+    QualType ElTy = ArgTy;
+    if (ArgTy->isIncompleteArrayType())
+      ElTy = S.Context.getAsArrayType(ArgTy)->getElementType();
+
+    // The void type is expressly allowed.
+    if (ElTy->isVoidType())
+      return true;
+
+    return !S.RequireCompleteType(
+      Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr);
+  }
+}
+
+
 ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT,
                                      SourceLocation KWLoc,
                                      TypeSourceInfo *TSInfo,
                                      SourceLocation RParen) {
   QualType T = TSInfo->getType();
-
-  // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
-  // all traits except __is_class, __is_enum and __is_union require a the type
-  // to be complete, an array of unknown bound, or void.
-  if (UTT != UTT_IsClass && UTT != UTT_IsEnum && UTT != UTT_IsUnion &&
-      UTT != UTT_IsCompleteType) {
-    QualType E = T;
-    if (T->isIncompleteArrayType())
-      E = Context.getAsArrayType(T)->getElementType();
-    if (!T->isVoidType() &&
-        (! LangOpts.Borland ||
-         UTT == UTT_HasNothrowAssign ||
-         UTT == UTT_HasNothrowCopy ||
-         UTT == UTT_HasNothrowConstructor ||
-         UTT == UTT_HasTrivialAssign ||
-         UTT == UTT_HasTrivialCopy ||
-         UTT == UTT_HasTrivialConstructor ||
-         UTT == UTT_HasTrivialDestructor ||
-         UTT == UTT_HasVirtualDestructor) &&
-        RequireCompleteType(KWLoc, E,
-                            diag::err_incomplete_type_used_in_type_trait_expr))
-      return ExprError();
-  }
+  if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T))
+    return ExprError();
 
   bool Value = false;
   if (!T->isDependentType())





More information about the cfe-commits mailing list