aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2007-10-29 05:01:08 +0000
committerAnders Carlsson <andersca@mac.com>2007-10-29 05:01:08 +0000
commit85f9bceab1542aafff012d4d28e998f4ba16e362 (patch)
treeb7fca1677fcf450c4cd1e8349873d93c14d43359
parentcd4b83cb4b4d69dbfa35ef97fe8ab88c0f2698a9 (diff)
Add (partial) support for @encode.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43439 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--AST/ASTContext.cpp100
-rw-r--r--CodeGen/CGExprScalar.cpp19
-rw-r--r--Driver/RewriteTest.cpp5
-rw-r--r--include/clang/AST/ASTContext.h3
4 files changed, 126 insertions, 1 deletions
diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp
index cf617d190e..61e2dbea06 100644
--- a/AST/ASTContext.cpp
+++ b/AST/ASTContext.cpp
@@ -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!");
diff --git a/CodeGen/CGExprScalar.cpp b/CodeGen/CGExprScalar.cpp
index 9bfd82ec0a..e443a2636a 100644
--- a/CodeGen/CGExprScalar.cpp
+++ b/CodeGen/CGExprScalar.cpp
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp
index db2c1ee70b..0c303daddf 100644
--- a/Driver/RewriteTest.cpp
+++ b/Driver/RewriteTest.cpp
@@ -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;
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 3881b6316b..9ac7b846df 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -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);