]> granicus.if.org Git - clang/commitdiff
Add (partial) support for @encode.
authorAnders Carlsson <andersca@mac.com>
Mon, 29 Oct 2007 05:01:08 +0000 (05:01 +0000)
committerAnders Carlsson <andersca@mac.com>
Mon, 29 Oct 2007 05:01:08 +0000 (05:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43439 91177308-0d34-0410-b5e6-96231b3b80d8

AST/ASTContext.cpp
CodeGen/CGExprScalar.cpp
Driver/RewriteTest.cpp
include/clang/AST/ASTContext.h

index cf617d190eebd873c47843f5ee4866a452d77b0e..61e2dbea069e898afa3f1b6157e92178287cc7e3 100644 (file)
@@ -16,6 +16,8 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+
 using namespace clang;
 
 enum FloatingRank {
@@ -835,6 +837,104 @@ QualType ASTContext::getCFConstantStringType() {
   return getTagDeclType(CFConstantStringTypeDecl);
 }
 
+static bool isTypeTypedefedAsBOOL(QualType T)
+{
+  if (const PointerType *NCPT = T->getAsPointerType())
+    if (const TypedefType *TT = dyn_cast<TypedefType>(NCPT->getPointeeType()))
+      if (!strcmp(TT->getDecl()->getName(), "BOOL"))
+        return true;
+        
+  return false;
+}
+
+void ASTContext::getObjcEncodingForType(QualType T, std::string& S) const
+{
+  QualType Ty = T.getCanonicalType();
+
+  if (const BuiltinType *BT = Ty->getAsBuiltinType()) {
+    char encoding;
+    switch (BT->getKind()) {
+    case BuiltinType::Void:
+      encoding = 'v';
+      break;
+    case BuiltinType::Bool:
+      encoding = 'B';
+      break;
+    case BuiltinType::Char_U:
+    case BuiltinType::UChar:
+      encoding = 'C';
+      break;
+    case BuiltinType::UShort:
+      encoding = 'S';
+      break;
+    case BuiltinType::UInt:
+      encoding = 'I';
+      break;
+    case BuiltinType::ULong:
+      encoding = 'L';
+      break;
+    case BuiltinType::ULongLong:
+      encoding = 'Q';
+      break;
+    case BuiltinType::Char_S:
+    case BuiltinType::SChar:
+      encoding = 'c';
+      break;
+    case BuiltinType::Short:
+      encoding = 's';
+      break;
+    case BuiltinType::Int:
+      encoding = 'i';
+      break;
+    case BuiltinType::Long:
+      encoding = 'l';
+      break;
+    case BuiltinType::LongLong:
+      encoding = 'q';
+      break;
+    case BuiltinType::Float:
+      encoding = 'f';
+      break;
+    case BuiltinType::Double:
+      encoding = 'd';
+      break;
+    case BuiltinType::LongDouble:
+      encoding = 'd';
+      break;
+    default:
+      assert(0 && "Unhandled builtin type kind");          
+    }
+    
+    S += encoding;
+  } else if (const PointerType *PT = Ty->getAsPointerType()) {
+    QualType PointeeTy = PT->getPointeeType();
+    
+    if (PointeeTy->isCharType()) {
+      // char pointer types should be encoded as '*' unless it is a
+      // type that has been typedef'd to 'BOOL'.
+      if (isTypeTypedefedAsBOOL(T)) {
+        S += '*';
+        return;
+      }
+    }
+    
+    S += '^';
+    getObjcEncodingForType(PT->getPointeeType(), S);
+  } else if (const ArrayType *AT = Ty->getAsArrayType()) {
+    S += '[';
+    
+    if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
+      S += llvm::utostr(CAT->getSize().getZExtValue());
+    else
+      assert(0 && "Unhandled array type!");
+    
+    getObjcEncodingForType(AT->getElementType(), S);
+    S += ']';
+  } else
+    fprintf(stderr, "@encode for type %s not implemented!\n", 
+            Ty.getAsString().c_str());
+}
+
 void ASTContext::setBuiltinVaListType(QualType T)
 {
   assert(BuiltinVaListType.isNull() && "__builtin_va_list type already set!");
index 9bfd82ec0a0905d2aa9373e556c5d55ee6c3a0f2..e443a2636abb7ad50b71ad3f1f6d904ad01480d3 100644 (file)
@@ -16,6 +16,7 @@
 #include "clang/AST/AST.h"
 #include "llvm/Constants.h"
 #include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/Support/Compiler.h"
 using namespace clang;
@@ -262,6 +263,7 @@ public:
   Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
     return CGF.EmitObjCStringLiteral(E);
   }
+  Value *VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
 };
 }  // end anonymous namespace.
 
@@ -917,6 +919,23 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE)
   return V;
 }
 
+Value *ScalarExprEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *E)
+{
+  std::string str;
+  
+  CGF.getContext().getObjcEncodingForType(E->getEncodedType(), str);
+  
+  llvm::Constant *C = llvm::ConstantArray::get(str);
+  C = new llvm::GlobalVariable(C->getType(), true, 
+                               llvm::GlobalValue::InternalLinkage,
+                               C, ".str", &CGF.CGM.getModule());
+  llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
+  llvm::Constant *Zeros[] = { Zero, Zero };
+  C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
+  
+  return C;
+}
+
 //===----------------------------------------------------------------------===//
 //                         Entry Point into this File
 //===----------------------------------------------------------------------===//
index db2c1ee70b86724b88df8d84a17073d24925a9a6..0c303daddf2f96b94d4722d8b08ba88f6d23369f 100644 (file)
@@ -329,7 +329,10 @@ Stmt *RewriteTest::RewriteFunctionBody(Stmt *S) {
 Stmt *RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
   // Create a new string expression.
   QualType StrType = Context->getPointerType(Context->CharTy);
-  Expr *Replacement = new StringLiteral("foo", 3, false, StrType, 
+  std::string StrEncoding;
+  Context->getObjcEncodingForType(Exp->getEncodedType(), StrEncoding);
+  Expr *Replacement = new StringLiteral(StrEncoding.c_str(),
+                                        StrEncoding.length(), false, StrType, 
                                         SourceLocation(), SourceLocation());
   Rewrite.ReplaceStmt(Exp, Replacement);
   delete Exp;
index 3881b6316b475c5670fd3c244bee6f6878d4aff0..9ac7b846dfd3cb745c3b1292cabd6fa4f8d99e96 100644 (file)
@@ -171,6 +171,9 @@ public:
     return ObjcConstantStringType; 
   }
 
+  // Return the ObjC type encoding for a given type.
+  void getObjcEncodingForType(QualType t, std::string &S) const;
+    
   // This setter/getter repreents the ObjC 'id' type. It is setup lazily, by
   // Sema.
   void setObjcIdType(TypedefDecl *Decl);