]> granicus.if.org Git - clang/commitdiff
Add some basic support for generating C++ member functions.
authorAnders Carlsson <andersca@mac.com>
Sat, 4 Apr 2009 20:47:02 +0000 (20:47 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 4 Apr 2009 20:47:02 +0000 (20:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68425 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/CodeGenModule.cpp
test/CodeGenCXX/member-functions.cpp [new file with mode: 0644]

index dc00a76ff91012ebdab59ff6f8debcad71d8c58d..5b63e6594d31ad1a130b862a9da653cb7878b846 100644 (file)
@@ -18,6 +18,7 @@
 #include "clang/AST/APValue.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "llvm/Support/CFG.h"
 #include "llvm/Target/TargetData.h"
 using namespace clang;
@@ -26,7 +27,8 @@ using namespace CodeGen;
 CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) 
   : BlockFunction(cgm, *this, Builder), CGM(cgm),
     Target(CGM.getContext().Target),
-    DebugInfo(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0) {
+    DebugInfo(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0), 
+    CXXThisDecl(0) {
   LLVMIntTy = ConvertType(getContext().IntTy);
   LLVMPointerWidth = Target.getPointerWidth(0);
 }
@@ -201,6 +203,19 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
     DebugInfo = CGM.getDebugInfo();
   
   FunctionArgList Args;
+  
+  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+    if (MD->isInstance()) {
+      // Create the implicit 'this' decl.
+      // FIXME: I'm not entirely sure I like using a fake decl just for code
+      // generation. Maybe we can come up with a better way?
+      CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0, SourceLocation(),
+                                              &getContext().Idents.get("this"), 
+                                              MD->getThisType(getContext()));
+      Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
+    }
+  }
+  
   if (FD->getNumParams()) {
     const FunctionProtoType* FProto = FD->getType()->getAsFunctionProtoType();
     assert(FProto && "Function def must have prototype!");
@@ -221,6 +236,10 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
   } else {
     FinishFunction();
   }
+    
+  // Destroy the 'this' declaration.
+  if (CXXThisDecl)
+    CXXThisDecl->Destroy(getContext());
 }
 
 /// ContainsLabel - Return true if the statement contains a label in it.  If
index 13a0e85486a6127c5d117126e7746dcb640e688e..96db4a45c77a2a683be299b18980e53c33bc060d 100644 (file)
@@ -232,6 +232,10 @@ private:
   /// BlockScopes - Map of which "cleanup scope" scope basic blocks have.
   BlockScopeMap BlockScopes;
 
+  /// CXXThisDecl - When parsing an C++ function, this will hold the implicit
+  /// 'this' declaration.
+  ImplicitParamDecl *CXXThisDecl;
+  
 public:
   CodeGenFunction(CodeGenModule &cgm);
 
index b4cf5331869de2f8773a457d0915d5a844df942e..379ff9b42407ef44b45ac13ad62ae5f2ed19f424 100644 (file)
@@ -820,18 +820,26 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
 
 
 void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
-  const llvm::FunctionType *Ty = 
-    cast<llvm::FunctionType>(getTypes().ConvertType(D->getType()));
-
-  // As a special case, make sure that definitions of K&R function
-  // "type foo()" aren't declared as varargs (which forces the backend
-  // to do unnecessary work).
-  if (D->getType()->isFunctionNoProtoType()) {
-    assert(Ty->isVarArg() && "Didn't lower type as expected");
-    // Due to stret, the lowered function could have arguments.  Just create the
-    // same type as was lowered by ConvertType but strip off the varargs bit.
-    std::vector<const llvm::Type*> Args(Ty->param_begin(), Ty->param_end());
-    Ty = llvm::FunctionType::get(Ty->getReturnType(), Args, false);
+  const llvm::FunctionType *Ty;
+
+  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+    bool isVariadic = D->getType()->getAsFunctionProtoType()->isVariadic();
+    
+    Ty = getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), isVariadic);
+  } else {
+    Ty = cast<llvm::FunctionType>(getTypes().ConvertType(D->getType()));
+    
+    // As a special case, make sure that definitions of K&R function
+    // "type foo()" aren't declared as varargs (which forces the backend
+    // to do unnecessary work).
+    if (D->getType()->isFunctionNoProtoType()) {
+      assert(Ty->isVarArg() && "Didn't lower type as expected");
+      // Due to stret, the lowered function could have arguments. 
+      // Just create the same type as was lowered by ConvertType 
+      // but strip off the varargs bit.
+      std::vector<const llvm::Type*> Args(Ty->param_begin(), Ty->param_end());
+      Ty = llvm::FunctionType::get(Ty->getReturnType(), Args, false);
+    }
   }
 
   // Get or create the prototype for teh function.
@@ -1305,6 +1313,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
     return;
 
   switch (D->getKind()) {
+  case Decl::CXXMethod:
   case Decl::Function:
   case Decl::Var:
     EmitGlobal(cast<ValueDecl>(D));
diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp
new file mode 100644 (file)
index 0000000..a6fa000
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: clang-cc -emit-llvm %s -o %t &&
+struct C {
+  void f();
+};
+
+// RUN: grep "define void @_ZN1C1fEv" %t | count 1 &&
+void C::f() {
+}
+
+// RUN: grep "call void @_ZN1C1fEv" %t | count 1
+void f() {
+  C c;
+  
+  c.f();
+}
\ No newline at end of file