parent
3692dbe492
commit
d849982e84
|
@ -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!");
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue