andreybokhanko updated this revision to Diff 46908.
andreybokhanko added a comment.

John, thank you for the review!

I refactored EvaluateBuiltinClassifyType according to your comments; please 
re-review.

Yours,
Andrey


http://reviews.llvm.org/D16846

Files:
  lib/AST/ExprConstant.cpp
  test/Sema/builtin-classify-type.c
  test/SemaCXX/builtin-classify-type.cpp

Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -6185,7 +6185,8 @@
 
 /// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way
 /// as GCC.
-static int EvaluateBuiltinClassifyType(const CallExpr *E) {
+static int EvaluateBuiltinClassifyType(const CallExpr *E,
+                                       const LangOptions &LangOpts) {
   // The following enum mimics the values returned by GCC.
   // FIXME: Does GCC differ between lvalue and rvalue references here?
   enum gcc_type_class {
@@ -6205,37 +6206,88 @@
   if (E->getNumArgs() == 0)
     return no_type_class;
 
-  QualType ArgTy = E->getArg(0)->getType();
-  if (ArgTy->isVoidType())
-    return void_type_class;
-  else if (ArgTy->isEnumeralType())
-    return enumeral_type_class;
-  else if (ArgTy->isBooleanType())
-    return boolean_type_class;
-  else if (ArgTy->isCharType())
-    return string_type_class; // gcc doesn't appear to use char_type_class
-  else if (ArgTy->isIntegerType())
-    return integer_type_class;
-  else if (ArgTy->isPointerType())
+  QualType CanTy = E->getArg(0)->getType().getCanonicalType();
+  const BuiltinType *BT = dyn_cast<BuiltinType>(CanTy);
+
+  switch (CanTy->getTypeClass()) {
+  case Type::Builtin:
+    switch (BT->getKind()) {
+    case BuiltinType::Void:
+      return void_type_class;
+
+    case BuiltinType::Bool:
+      return boolean_type_class;
+
+    case BuiltinType::Char_S: // gcc doesn't appear to use char_type_class
+    case BuiltinType::Char_U:
+    case BuiltinType::SChar:
+    case BuiltinType::UChar:
+    case BuiltinType::UShort:
+    case BuiltinType::Short:
+    case BuiltinType::Half:
+    case BuiltinType::Int:
+    case BuiltinType::UInt:
+    case BuiltinType::Long:
+    case BuiltinType::ULong:
+    case BuiltinType::LongLong:
+    case BuiltinType::ULongLong:
+    case BuiltinType::Int128:
+    case BuiltinType::UInt128:
+      return integer_type_class;
+
+    case BuiltinType::NullPtr:
+      return pointer_type_class;
+
+    case BuiltinType::Float:
+    case BuiltinType::Double:
+    case BuiltinType::LongDouble:
+      return real_type_class;
+
+    default:
+      break;
+    };
+
+  case Type::Enum:
+    return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class;
+    break;
+
+  case Type::Pointer:
     return pointer_type_class;
-  else if (ArgTy->isReferenceType())
-    return reference_type_class;
-  else if (ArgTy->isRealType())
-    return real_type_class;
-  else if (ArgTy->isComplexType())
+    break;
+
+  case Type::MemberPointer:
+    if (CanTy->isMemberDataPointerType())
+      return offset_type_class;
+    else if (CanTy->isMemberFunctionPointerType())
+      return method_type_class;
+    break;
+
+  case Type::Complex:
     return complex_type_class;
-  else if (ArgTy->isFunctionType())
-    return function_type_class;
-  else if (ArgTy->isStructureOrClassType())
-    return record_type_class;
-  else if (ArgTy->isUnionType())
-    return union_type_class;
-  else if (ArgTy->isArrayType())
-    return array_type_class;
-  else if (ArgTy->isUnionType())
-    return union_type_class;
-  else  // FIXME: offset_type_class, method_type_class, & lang_type_class?
-    llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+
+  case Type::FunctionNoProto:
+  case Type::FunctionProto:
+    return LangOpts.CPlusPlus ? function_type_class : pointer_type_class;
+
+  case Type::Record:
+    if (CanTy->isStructureOrClassType())
+      return record_type_class;
+    else if (CanTy->isUnionType())
+      return union_type_class;
+    break;
+
+  case Type::ConstantArray:
+  case Type::VariableArray:
+  case Type::IncompleteArray:
+  case Type::DependentSizedArray:
+    return LangOpts.CPlusPlus ? array_type_class : pointer_type_class;
+
+  default:
+    break;
+  }
+
+  // FIXME: string_type_class & lang_type_class?
+  llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
 }
 
 /// EvaluateBuiltinConstantPForLValue - Determine the result of
@@ -6607,7 +6659,7 @@
   }
 
   case Builtin::BI__builtin_classify_type:
-    return Success(EvaluateBuiltinClassifyType(E), E);
+    return Success(EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E);
 
   // FIXME: BI__builtin_clrsb
   // FIXME: BI__builtin_clrsbl
Index: test/SemaCXX/builtin-classify-type.cpp
===================================================================
--- test/SemaCXX/builtin-classify-type.cpp
+++ test/SemaCXX/builtin-classify-type.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// expected-no-diagnostics
+
+enum gcc_type_class {
+  no_type_class = -1,
+  void_type_class, integer_type_class, char_type_class,
+  enumeral_type_class, boolean_type_class,
+  pointer_type_class, reference_type_class, offset_type_class,
+  real_type_class, complex_type_class,
+  function_type_class, method_type_class,
+  record_type_class, union_type_class,
+  array_type_class, string_type_class,
+  lang_type_class
+};
+
+class cl {
+public:
+    void bar() {}
+    int baz;
+};
+
+int builtin_result;
+
+void foo() {
+  int i;
+  char c;
+  enum { red, green, blue} enum_obj;
+  bool b;
+  int *p;
+  int &r = i;
+  double d;
+  extern void f();
+  cl cl_obj;
+  union { int a; float b; } u_obj;
+  int arr[10];
+
+  int a1[__builtin_classify_type(f()) == void_type_class ? 1 : -1];
+  int a2[__builtin_classify_type(i) == integer_type_class ? 1 : -1];
+  int a3[__builtin_classify_type(c) == integer_type_class ? 1 : -1];
+  int a4[__builtin_classify_type(enum_obj) == enumeral_type_class ? 1 : -1];
+  int a5[__builtin_classify_type(b) == boolean_type_class ? 1 : -1];
+  int a6[__builtin_classify_type(p) == pointer_type_class ? 1 : -1];
+  int a7[__builtin_classify_type(r) == integer_type_class ? 1 : -1];
+  int a8[__builtin_classify_type(&cl::baz) == offset_type_class ? 1 : -1];
+  int a9[__builtin_classify_type(d) == real_type_class ? 1 : -1];
+  int a10[__builtin_classify_type(f) == function_type_class ? 1 : -1];
+  int a11[__builtin_classify_type(&cl::bar) == method_type_class ? 1 : -1];
+  int a12[__builtin_classify_type(cl_obj) == record_type_class ? 1 : -1];
+  int a13[__builtin_classify_type(u_obj) == union_type_class ? 1 : -1];
+  int a14[__builtin_classify_type(arr) == array_type_class ? 1 : -1];
+  int a15[__builtin_classify_type("abc") == array_type_class ? 1 : -1];
+}
+
Index: test/Sema/builtin-classify-type.c
===================================================================
--- test/Sema/builtin-classify-type.c
+++ test/Sema/builtin-classify-type.c
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// expected-no-diagnostics
+
+enum gcc_type_class {
+  no_type_class = -1,
+  void_type_class, integer_type_class, char_type_class,
+  enumeral_type_class, boolean_type_class,
+  pointer_type_class, reference_type_class, offset_type_class,
+  real_type_class, complex_type_class,
+  function_type_class, method_type_class,
+  record_type_class, union_type_class,
+  array_type_class, string_type_class,
+  lang_type_class
+};
+
+void foo() {
+  int i;
+  char c;
+  enum { red, green, blue } enum_obj;
+  int *p;
+  double d;
+  _Complex double cc;
+  extern void f();
+  struct { int a; float b; } s_obj;
+  union { int a; float b; } u_obj;
+  int arr[10];
+
+  int a1[__builtin_classify_type(f()) == void_type_class ? 1 : -1];
+  int a2[__builtin_classify_type(i) == integer_type_class ? 1 : -1];
+  int a3[__builtin_classify_type(c) == integer_type_class ? 1 : -1];
+  int a4[__builtin_classify_type(enum_obj) == integer_type_class ? 1 : -1];
+  int a5[__builtin_classify_type(p) == pointer_type_class ? 1 : -1];
+  int a6[__builtin_classify_type(d) == real_type_class ? 1 : -1];
+  int a7[__builtin_classify_type(cc) == complex_type_class ? 1 : -1];
+  int a8[__builtin_classify_type(f) == pointer_type_class ? 1 : -1];
+  int a0[__builtin_classify_type(s_obj) == record_type_class ? 1 : -1];
+  int a10[__builtin_classify_type(u_obj) == union_type_class ? 1 : -1];
+  int a11[__builtin_classify_type(arr) == pointer_type_class ? 1 : -1];
+  int a12[__builtin_classify_type("abc") == pointer_type_class ? 1 : -1];
+}
+
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to