[cfe-commits] r84265 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp test/CodeGenCXX/derived-to-base-conv.cpp

Fariborz Jahanian fjahanian at apple.com
Fri Oct 16 12:20:59 PDT 2009


Author: fjahanian
Date: Fri Oct 16 14:20:59 2009
New Revision: 84265

URL: http://llvm.org/viewvc/llvm-project?rev=84265&view=rev
Log:
Implement derived-to-base AST/code gen. There is a
FIXME in CGCXX.cpp that I would like Anders to
take a look at.

Added:
    cfe/trunk/test/CodeGenCXX/derived-to-base-conv.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprCXX.cpp

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=84265&r1=84264&r2=84265&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Oct 16 14:20:59 2009
@@ -566,6 +566,10 @@
       assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
              "EmitCXXConstructorCall - user declared copy constructor");
       const Expr *E = (*ArgBeg);
+      // FIXME. This may not be correct. But till now, we were skipping
+      // code gen of trivial copy constructors regardless of their arguments.
+      if (isa<CXXZeroInitValueExpr>(E))
+        return;
       QualType Ty = E->getType();
       llvm::Value *Src = EmitLValue(E).getAddress();
       EmitAggregateCopy(This, Src, Ty);
@@ -590,12 +594,15 @@
 CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
                                       const CXXConstructExpr *E) {
   assert(Dest && "Must have a destination!");
-
-  const CXXRecordDecl *RD =
-  cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
-  if (RD->hasTrivialConstructor())
+  const CXXConstructorDecl *CD = E->getConstructor();
+  // For a copy constructor, even if it is trivial, must fall thru so
+  // its argument is code-gen'ed.
+  if (!CD->isCopyConstructor(getContext())) {
+    const CXXRecordDecl *RD =
+      cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
+    if (RD->hasTrivialConstructor())
     return;
-
+  }
   // Code gen optimization to eliminate copy constructor and return
   // its first argument instead.
   if (getContext().getLangOptions().ElideConstructors && E->isElidable()) {
@@ -604,7 +611,7 @@
     return;
   }
   // Call the constructor.
-  EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest,
+  EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
                          E->arg_begin(), E->arg_end());
 }
 

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=84265&r1=84264&r2=84265&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Oct 16 14:20:59 2009
@@ -3552,6 +3552,10 @@
   bool PerformImplicitConversion(Expr *&From, QualType ToType,
                                  const StandardConversionSequence& SCS,
                                  const char *Flavor);
+  
+  bool BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind,
+                                 const ImplicitConversionSequence& ICS,
+                                 const char *Flavor);
 
   /// the following "Check" methods will return a valid/converted QualType
   /// or a null QualType (indicating an error diagnostic was issued).

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=84265&r1=84264&r2=84265&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Oct 16 14:20:59 2009
@@ -1043,6 +1043,40 @@
   return PerformImplicitConversion(From, ToType, ICS, Flavor);
 }
 
+/// BuildCXXDerivedToBaseExpr - This routine generates the suitable AST
+/// for the derived to base conversion of the expression 'From'. All
+/// necessary information is passed in ICS.
+bool 
+Sema::BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind,
+                                     const ImplicitConversionSequence& ICS,
+                                     const char *Flavor) {
+  QualType  BaseType = 
+    QualType::getFromOpaquePtr(ICS.UserDefined.After.ToTypePtr);
+  // Must do additional defined to base conversion.
+  QualType  DerivedType = 
+    QualType::getFromOpaquePtr(ICS.UserDefined.After.FromTypePtr);
+
+  From = new (Context) ImplicitCastExpr(
+                                        DerivedType.getNonReferenceType(),
+                                        CastKind, 
+                                        From, 
+                                        DerivedType->isLValueReferenceType());
+  From = new (Context) ImplicitCastExpr(BaseType.getNonReferenceType(),
+                                        CastExpr::CK_DerivedToBase, From, 
+                                        BaseType->isLValueReferenceType());
+  ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+  OwningExprResult FromResult =
+  BuildCXXConstructExpr(
+                        ICS.UserDefined.After.CopyConstructor->getLocation(),
+                        BaseType,
+                        ICS.UserDefined.After.CopyConstructor,
+                        MultiExprArg(*this, (void **)&From, 1));
+  if (FromResult.isInvalid())
+    return true;
+  From = FromResult.takeAs<Expr>();
+  return false;
+}
+
 /// PerformImplicitConversion - Perform an implicit conversion of the
 /// expression From to the type ToType using the pre-computed implicit
 /// conversion sequence ICS. Returns true if there was an error, false
@@ -1095,13 +1129,19 @@
 
       if (CastArg.isInvalid())
         return true;
+    
+      if (ICS.UserDefined.After.Second == ICK_Derived_To_Base &&
+          ICS.UserDefined.After.CopyConstructor) {
+        From = CastArg.takeAs<Expr>();
+        return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor);
+      }
       
       From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(),
-                                            CastKind, CastArg.takeAs<Expr>(), 
+                                            CastKind, CastArg.takeAs<Expr>(),
                                             ToType->isLValueReferenceType());
       return false;
-    }
-
+  }
+      
   case ImplicitConversionSequence::EllipsisConversion:
     assert(false && "Cannot perform an ellipsis conversion");
     return false;

Added: cfe/trunk/test/CodeGenCXX/derived-to-base-conv.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/derived-to-base-conv.cpp?rev=84265&view=auto

==============================================================================
--- cfe/trunk/test/CodeGenCXX/derived-to-base-conv.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/derived-to-base-conv.cpp Fri Oct 16 14:20:59 2009
@@ -0,0 +1,51 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
+// RUN: true
+
+extern "C" int printf(...);
+
+struct A {
+ A (const A&) { printf("A::A(const A&)\n"); }
+ A() {};
+}; 
+
+struct B : public A {
+  B() {};
+}; 
+
+struct C : public B {
+  C() {};
+}; 
+
+struct X {
+	operator B&() {printf("X::operator B&()\n"); return b; }
+	operator C&() {printf("X::operator C&()\n"); return c; }
+ 	X (const X&) { printf("X::X(const X&)\n"); }
+ 	X () { printf("X::X()\n"); }
+	B b;
+	C c;
+};
+
+void f(A) {
+  printf("f(A)\n");
+}
+
+
+void func(X x) 
+{
+  f (x);
+}
+
+int main()
+{
+    X x;
+    func(x);
+}
+
+// CHECK-LP64: call     __ZN1XcvR1BEv
+// CHECK-LP64: call     __ZN1AC1ERKS_
+
+// CHECK-LP32: call     L__ZN1XcvR1BEv
+// CHECK-LP32: call     L__ZN1AC1ERKS_





More information about the cfe-commits mailing list