[cfe-commits] r134984 - in /cfe/trunk: include/clang/AST/Type.h lib/AST/ItaniumMangle.cpp lib/AST/Type.cpp test/CodeGenCXX/mangle.cpp

Douglas Gregor dgregor at apple.com
Tue Jul 12 08:18:55 PDT 2011


Author: dgregor
Date: Tue Jul 12 10:18:55 2011
New Revision: 134984

URL: http://llvm.org/viewvc/llvm-project?rev=134984&view=rev
Log:
Improve name mangling for instantiation-dependent types that are not
dependent. This covers an odd class of types such as

  int (&)[sizeof(sizeof(T() + T()))];

which involve template parameters but, because of some trick typically
involving a form of expression that is never type-dependent, resolve
down to a non-dependent type. Such types need to be mangled
essentially as they were written in the source code (involving
template parameters), rather than via their canonical type.

In general, instantiation-dependent types should be mangled as
they were written in the source. However, since we can't do that now
without non-trivial refactoring of the AST (see the new FIXME), I've
gone for this partial solution: only use the as-written-in-the-source
mangling for these strange types that are instantiation-dependent but
not dependent. This provides better compatibility with previous
incarnations of Clang and with GCC. In the future, we'd like to get
this right.

Fixes <rdar://problem/9663282>.


Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/test/CodeGenCXX/mangle.cpp

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=134984&r1=134983&r2=134984&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Jul 12 10:18:55 2011
@@ -757,6 +757,13 @@
     return getSplitDesugaredType(*this);
   }
 
+  /// \brief Return the specified type with one level of "sugar" removed from
+  /// the type. 
+  ///
+  /// This routine takes off the first typedef, typeof, etc. If the outer level
+  /// of the type is already concrete, it returns it unmodified.
+  QualType getSingleStepDesugaredType(const ASTContext &Context) const;
+  
   /// IgnoreParens - Returns the specified type after dropping any
   /// outer-level parentheses.
   QualType IgnoreParens() const {

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=134984&r1=134983&r2=134984&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Jul 12 10:18:55 2011
@@ -319,7 +319,7 @@
                           unsigned NumTemplateArgs);
   void mangleTemplateArgs(const TemplateParameterList &PL,
                           const TemplateArgumentList &AL);
-  void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A);
+  void mangleTemplateArg(const NamedDecl *P, TemplateArgument A);
   void mangleUnresolvedTemplateArgs(const TemplateArgument *args,
                                     unsigned numArgs);
 
@@ -1596,26 +1596,59 @@
   Context.mangleObjCMethodName(MD, Out);
 }
 
-void CXXNameMangler::mangleType(QualType nonCanon) {
-  // Only operate on the canonical type!
-  QualType canon = nonCanon.getCanonicalType();
-
-  SplitQualType split = canon.split();
+void CXXNameMangler::mangleType(QualType T) {
+  // If our type is instantiation-dependent but not dependent, we mangle
+  // it as it was written in the source, removing any top-level sugar. 
+  // Otherwise, use the canonical type.
+  //
+  // FIXME: This is an approximation of the instantiation-dependent name 
+  // mangling rules, since we should really be using the type as written and
+  // augmented via semantic analysis (i.e., with implicit conversions and
+  // default template arguments) for any instantiation-dependent type. 
+  // Unfortunately, that requires several changes to our AST:
+  //   - Instantiation-dependent TemplateSpecializationTypes will need to be 
+  //     uniqued, so that we can handle substitutions properly
+  //   - Default template arguments will need to be represented in the
+  //     TemplateSpecializationType, since they need to be mangled even though
+  //     they aren't written.
+  //   - Conversions on non-type template arguments need to be expressed, since
+  //     they can affect the mangling of sizeof/alignof.
+  if (!T->isInstantiationDependentType() || T->isDependentType())
+    T = T.getCanonicalType();
+  else {
+    // Desugar any types that are purely sugar.
+    do {
+      // Don't desugar through template specialization types that aren't
+      // type aliases. We need to mangle the template arguments as written.
+      if (const TemplateSpecializationType *TST 
+                                      = dyn_cast<TemplateSpecializationType>(T))
+        if (!TST->isTypeAlias())
+          break;
+
+      QualType Desugared 
+        = T.getSingleStepDesugaredType(Context.getASTContext());
+      if (Desugared == T)
+        break;
+      
+      T = Desugared;
+    } while (true);
+  }
+  SplitQualType split = T.split();
   Qualifiers quals = split.second;
   const Type *ty = split.first;
 
-  bool isSubstitutable = quals || !isa<BuiltinType>(ty);
-  if (isSubstitutable && mangleSubstitution(canon))
+  bool isSubstitutable = quals || !isa<BuiltinType>(T);
+  if (isSubstitutable && mangleSubstitution(T))
     return;
 
   // If we're mangling a qualified array type, push the qualifiers to
   // the element type.
-  if (quals && isa<ArrayType>(ty)) {
-    ty = Context.getASTContext().getAsArrayType(canon);
+  if (quals && isa<ArrayType>(T)) {
+    ty = Context.getASTContext().getAsArrayType(T);
     quals = Qualifiers();
 
-    // Note that we don't update canon: we want to add the
-    // substitution at the canonical type.
+    // Note that we don't update T: we want to add the
+    // substitution at the original type.
   }
 
   if (quals) {
@@ -1640,7 +1673,7 @@
 
   // Add the substitution.
   if (isSubstitutable)
-    addSubstitution(canon);
+    addSubstitution(T);
 }
 
 void CXXNameMangler::mangleNameOrStandardSubstitution(const NamedDecl *ND) {
@@ -2826,12 +2859,15 @@
 }
 
 void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
-                                       const TemplateArgument &A) {
+                                       TemplateArgument A) {
   // <template-arg> ::= <type>              # type or template
   //                ::= X <expression> E    # expression
   //                ::= <expr-primary>      # simple expressions
   //                ::= J <template-arg>* E # argument pack
-  //                ::= sp <expression>     # pack expansion of (C++0x)
+  //                ::= sp <expression>     # pack expansion of (C++0x)  
+  if (!A.isInstantiationDependent() || A.isDependent())
+    A = Context.getASTContext().getCanonicalTemplateArgument(A);
+  
   switch (A.getKind()) {
   case TemplateArgument::Null:
     llvm_unreachable("Cannot mangle NULL template argument");

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=134984&r1=134983&r2=134984&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Jul 12 10:18:55 2011
@@ -180,6 +180,26 @@
   return Context.getQualifiedType(split.first, split.second);
 }
 
+QualType QualType::getSingleStepDesugaredType(const ASTContext &Context) const {
+  QualifierCollector Qs;
+  
+  const Type *CurTy = Qs.strip(*this);
+  switch (CurTy->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+  case Type::Class: { \
+    const Class##Type *Ty = cast<Class##Type>(CurTy); \
+    if (!Ty->isSugared()) \
+      return *this; \
+    return Context.getQualifiedType(Ty->desugar(), Qs); \
+    break; \
+  }
+#include "clang/AST/TypeNodes.def"
+  }
+
+  return *this;
+}
+
 SplitQualType QualType::getSplitDesugaredType(QualType T) {
   QualifierCollector Qs;
 

Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=134984&r1=134983&r2=134984&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Tue Jul 12 10:18:55 2011
@@ -825,6 +825,15 @@
 
   // CHECK: define weak_odr void @_ZN6test342f3ILy4EEEvRAplT_Ly8E_i
   template void f3<4>(int (&)[4 + sizeof(int*)]);
+
+  // Mangling for instantiation-dependent sizeof() expressions as
+  // template arguments.
+  template<unsigned> struct A { };
+
+  template<typename T> void f4(::test34::A<sizeof(sizeof(decltype(T() + T())))>) { }
+
+  // CHECK: define weak_odr void @_ZN6test342f4IiEEvNS_1AIXszstDTplcvT__EcvS2__EEEEE
+  template void f4<int>(A<sizeof(sizeof(int))>);
 }
 
 namespace test35 {





More information about the cfe-commits mailing list