]> granicus.if.org Git - clang/commitdiff
Split out types that are non-canonical unless dependent as their own
authorJohn McCall <rjmccall@apple.com>
Mon, 1 Mar 2010 23:49:17 +0000 (23:49 +0000)
committerJohn McCall <rjmccall@apple.com>
Mon, 1 Mar 2010 23:49:17 +0000 (23:49 +0000)
category.  Use this in a few places to eliminate unnecessary TST cases and
do some future-proofing.  Provide terrible manglings for typeof.  Mangle
decltype with some hope of accuracy.

Our manglings for some of the cases covered in the testcase are different
from gcc's, which I've raised as an issue with the ABI list.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97523 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/TypeNodes.def
lib/AST/ASTContext.cpp
lib/CodeGen/CodeGenTypes.cpp
lib/CodeGen/Mangle.cpp
lib/Sema/SemaTemplateDeduction.cpp
test/CodeGenCXX/mangle.cpp

index 9cf2cb7bd7730ec17a256170c84bb36c5b3832d2..8187caddc6aa88788d353bf943e150efde470215 100644 (file)
 //    type that is always dependent. Clients that do not need to deal
 //    with uninstantiated C++ templates can ignore these types.
 //
-//  There is a fifth macro, independent of the others.  Most clients
+//    NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that
+//    is non-canonical unless it is dependent.  Defaults to TYPE because
+//    it is neither reliably dependent nor reliably non-canonical.
+//
+//  There is a sixth macro, independent of the others.  Most clients
 //  will not need to use it.
 //
 //    LEAF_TYPE(Class) - A type that never has inner types.  Clients
 #  define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
 #endif
 
+#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
+#  define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base)
+#endif
+
 TYPE(Builtin, Type)
 TYPE(Complex, Type)
 TYPE(Pointer, Type)
@@ -72,16 +80,16 @@ TYPE(FunctionProto, FunctionType)
 TYPE(FunctionNoProto, FunctionType)
 DEPENDENT_TYPE(UnresolvedUsing, Type)
 NON_CANONICAL_TYPE(Typedef, Type)
-NON_CANONICAL_TYPE(TypeOfExpr, Type)
-NON_CANONICAL_TYPE(TypeOf, Type)
-NON_CANONICAL_TYPE(Decltype, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
 ABSTRACT_TYPE(Tag, Type)
 TYPE(Record, TagType)
 TYPE(Enum, TagType)
 NON_CANONICAL_TYPE(Elaborated, Type)
 DEPENDENT_TYPE(TemplateTypeParm, Type)
 NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)
-TYPE(TemplateSpecialization, Type)
+NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)
 NON_CANONICAL_TYPE(QualifiedName, Type)
 DEPENDENT_TYPE(Typename, Type)
 TYPE(ObjCInterface, Type)
@@ -101,6 +109,7 @@ LEAF_TYPE(TemplateTypeParm)
 #undef LEAF_TYPE
 #endif
 
+#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE
 #undef DEPENDENT_TYPE
 #undef NON_CANONICAL_TYPE
 #undef ABSTRACT_TYPE
index 22871a4a68180bc0e1a9d46410feda47ec459720..5cd52396a80b643dc31f55fd05b27f0d42a75e68 100644 (file)
@@ -4522,6 +4522,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
   switch (LHSClass) {
 #define TYPE(Class, Base)
 #define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
 #define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
 #define DEPENDENT_TYPE(Class, Base) case Type::Class:
 #include "clang/AST/TypeNodes.def"
@@ -4644,9 +4645,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
 
     return QualType();
   }
-  case Type::TemplateSpecialization:
-    assert(false && "Dependent types have no size");
-    break;
   }
 
   return QualType();
index f30e03c8c9d5a98d7bb0bb59d84c929f4aef1751..4feca4dd7d3d489f3482e42b58fe44991200feef 100644 (file)
@@ -190,6 +190,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
 #define ABSTRACT_TYPE(Class, Base)
 #define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
 #define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
 #include "clang/AST/TypeNodes.def"
     assert(false && "Non-canonical or dependent types aren't possible.");
     break;
@@ -390,9 +391,6 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
                                    NULL);
     return PtrDiffTy;
   }
-
-  case Type::TemplateSpecialization:
-    assert(false && "Dependent types can't get here");
   }
 
   // FIXME: implement.
index d9a7991f78b9bcf569bc4c9c35f8a5005533e9fd..64743c7696f74b6728a2453a8cd60d63b31785a8 100644 (file)
@@ -455,7 +455,9 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) {
     mangleType(QualType(Qualifier->getAsType(), 0));
     break;
   case NestedNameSpecifier::Identifier:
-    mangleUnresolvedScope(Qualifier->getPrefix());
+    // Member expressions can have these without prefixes.
+    if (Qualifier->getPrefix())
+      mangleUnresolvedScope(Qualifier->getPrefix());
     mangleSourceName(Qualifier->getAsIdentifier());
     break;
   }
@@ -1123,6 +1125,42 @@ void CXXNameMangler::mangleType(const TypenameType *T) {
   Out << 'E';
 }
 
+void CXXNameMangler::mangleType(const TypeOfType *T) {
+  // FIXME: this is pretty unsatisfactory, but there isn't an obvious
+  // "extension with parameters" mangling.
+  Out << "u6typeof";
+}
+
+void CXXNameMangler::mangleType(const TypeOfExprType *T) {
+  // FIXME: this is pretty unsatisfactory, but there isn't an obvious
+  // "extension with parameters" mangling.
+  Out << "u6typeof";
+}
+
+void CXXNameMangler::mangleType(const DecltypeType *T) {
+  Expr *E = T->getUnderlyingExpr();
+  
+  // type ::= Dt <expression> E  # decltype of an id-expression
+  //                             #   or class member access
+  //      ::= DT <expression> E  # decltype of an expression
+
+  // This purports to be an exhaustive list of id-expressions and
+  // class member accesses.  Note that we do not ignore parentheses;
+  // parentheses change the semantics of decltype for these
+  // expressions (and cause the mangler to use the other form).
+  if (isa<DeclRefExpr>(E) ||
+      isa<MemberExpr>(E) ||
+      isa<UnresolvedLookupExpr>(E) ||
+      isa<DependentScopeDeclRefExpr>(E) ||
+      isa<CXXDependentScopeMemberExpr>(E) ||
+      isa<UnresolvedMemberExpr>(E))
+    Out << "Dt";
+  else
+    Out << "DT";
+  mangleExpression(E);
+  Out << 'E';
+}
+
 void CXXNameMangler::mangleIntegerLiteral(QualType T, 
                                           const llvm::APSInt &Value) {
   //  <expr-primary> ::= L <type> <value number> E # integer literal
index df4d4a828d4803637e0dd57945cf7cfb18d6df46..7f16400aea8d87217de5625293cc7007e2d458e2 100644 (file)
@@ -2419,6 +2419,27 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T,
                                  OnlyDeduced, Depth, Used);
     break;
 
+  case Type::TypeOf:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(SemaRef,
+                                 cast<TypeOfType>(T)->getUnderlyingType(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::TypeOfExpr:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(SemaRef,
+                                 cast<TypeOfExprType>(T)->getUnderlyingExpr(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
+  case Type::Decltype:
+    if (!OnlyDeduced)
+      MarkUsedTemplateParameters(SemaRef,
+                                 cast<DecltypeType>(T)->getUnderlyingExpr(),
+                                 OnlyDeduced, Depth, Used);
+    break;
+
   // None of these types have any template parameters in them.
   case Type::Builtin:
   case Type::VariableArray:
index d00579155c2e2657bebc40c5ec7f6334d4cb2a35..e18ca03d1be28a80a4dea0b12babe8d628a65b93 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks -std=c++0x | FileCheck %s
 struct X { };
 struct Y { };
 
@@ -376,3 +376,41 @@ namespace test1 {
 // CHECK: define internal void @_Z27functionWithInternalLinkagev()
 static void functionWithInternalLinkage() {  }
 void g() { functionWithInternalLinkage(); }
+
+namespace test2 {
+  template <class T> decltype(((T*) 0)->member) read_member(T& obj) {
+    return obj.member;
+  }
+
+  struct A { int member; } obj;
+  int test() {
+    return read_member(obj);
+  }
+
+  // CHECK: define linkonce_odr i32 @_ZN5test211read_memberINS_1AEEEDtptcvPT_Li0E6memberERS2_(
+}
+
+namespace test3 {
+  struct AmbiguousBase { int ab; };
+  struct Path1 : AmbiguousBase { float p; };
+  struct Path2 : AmbiguousBase { double p; };
+  struct Derived : Path1, Path2 { };
+
+  //template <class T> decltype(((T*) 0)->Path1::ab) get_ab_1(T &ref) { return ref.Path1::ab; }
+  //template <class T> decltype(((T*) 0)->Path2::ab) get_ab_2(T &ref) { return ref.Path2::ab; }
+
+  // define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path11pERS2_(
+  template <class T> decltype(((T*) 0)->Path1::p) get_p_1(T &ref) { return ref.Path1::p; }
+
+  // define linkonce_odr double @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path21pERS2_(
+  template <class T> decltype(((T*) 0)->Path2::p) get_p_2(T &ref) { return ref.Path2::p; }
+
+  Derived obj;
+  void test() {
+    // FIXME: uncomment these when we support diamonds competently
+    //get_ab_1(obj);
+    //get_ab_2(obj);
+    get_p_1(obj);
+    get_p_2(obj);
+  }
+}