forked from OSchip/llvm-project
first wave of fixes for @encode sema support. This is part of PR3648.
The big difference here is that (like string literal) @encode has array type, not pointer type. llvm-svn: 65391
This commit is contained in:
parent
9b15effcd1
commit
d7e7b8e411
|
@ -54,7 +54,9 @@ public:
|
|||
static ObjCStringLiteral* CreateImpl(llvm::Deserializer& D, ASTContext& C);
|
||||
};
|
||||
|
||||
/// ObjCEncodeExpr, used for @encode in Objective-C.
|
||||
/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type
|
||||
/// and behavior as StringLiteral except that the string initializer is obtained
|
||||
/// from ASTContext with the encoding type as an argument.
|
||||
class ObjCEncodeExpr : public Expr {
|
||||
QualType EncType;
|
||||
SourceLocation AtLoc, RParenLoc;
|
||||
|
|
|
@ -478,7 +478,8 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
|
|||
|
||||
// the type looks fine, now check the expression
|
||||
switch (getStmtClass()) {
|
||||
case StringLiteralClass: // C99 6.5.1p4
|
||||
case StringLiteralClass: // C99 6.5.1p4
|
||||
case ObjCEncodeExprClass: // @encode behaves like its string in every way.
|
||||
return LV_Valid;
|
||||
case ArraySubscriptExprClass: // C99 6.5.3p4 (e1[e2] == (*((e1)+(e2))))
|
||||
// For vectors, make sure base is an lvalue (i.e. not a function call).
|
||||
|
@ -829,6 +830,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
|
|||
switch (getStmtClass()) {
|
||||
default: break;
|
||||
case StringLiteralClass:
|
||||
case ObjCEncodeExprClass:
|
||||
return true;
|
||||
case CompoundLiteralExprClass: {
|
||||
// This handles gcc's extension that allows global initializers like
|
||||
|
|
|
@ -153,6 +153,7 @@ public:
|
|||
APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
|
||||
APValue VisitMemberExpr(MemberExpr *E);
|
||||
APValue VisitStringLiteral(StringLiteral *E) { return APValue(E, 0); }
|
||||
APValue VisitObjCEncodeExpr(ObjCEncodeExpr *E) { return APValue(E, 0); }
|
||||
APValue VisitArraySubscriptExpr(ArraySubscriptExpr *E);
|
||||
APValue VisitUnaryDeref(UnaryOperator *E);
|
||||
// FIXME: Missing: __extension__, __real__, __imag__, __builtin_choose_expr
|
||||
|
|
|
@ -148,6 +148,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
|
|||
return EmitPredefinedLValue(cast<PredefinedExpr>(E));
|
||||
case Expr::StringLiteralClass:
|
||||
return EmitStringLiteralLValue(cast<StringLiteral>(E));
|
||||
case Expr::ObjCEncodeExprClass:
|
||||
return EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E));
|
||||
|
||||
case Expr::CXXConditionDeclExprClass:
|
||||
return EmitCXXConditionDeclLValue(cast<CXXConditionDeclExpr>(E));
|
||||
|
@ -668,7 +670,8 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
|
|||
default: assert(0 && "Unknown unary operator lvalue!");
|
||||
case UnaryOperator::Deref:
|
||||
{
|
||||
QualType T = E->getSubExpr()->getType()->getAsPointerType()->getPointeeType();
|
||||
QualType T =
|
||||
E->getSubExpr()->getType()->getAsPointerType()->getPointeeType();
|
||||
LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()),
|
||||
ExprTy->getAsPointerType()->getPointeeType()
|
||||
.getCVRQualifiers(),
|
||||
|
@ -697,22 +700,27 @@ LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
|
|||
return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E), 0);
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
|
||||
return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E), 0);
|
||||
}
|
||||
|
||||
|
||||
LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) {
|
||||
std::string GlobalVarName;
|
||||
|
||||
switch (Type) {
|
||||
default:
|
||||
assert(0 && "Invalid type");
|
||||
case PredefinedExpr::Func:
|
||||
GlobalVarName = "__func__.";
|
||||
break;
|
||||
case PredefinedExpr::Function:
|
||||
GlobalVarName = "__FUNCTION__.";
|
||||
break;
|
||||
case PredefinedExpr::PrettyFunction:
|
||||
// FIXME:: Demangle C++ method names
|
||||
GlobalVarName = "__PRETTY_FUNCTION__.";
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Invalid type");
|
||||
case PredefinedExpr::Func:
|
||||
GlobalVarName = "__func__.";
|
||||
break;
|
||||
case PredefinedExpr::Function:
|
||||
GlobalVarName = "__FUNCTION__.";
|
||||
break;
|
||||
case PredefinedExpr::PrettyFunction:
|
||||
// FIXME:: Demangle C++ method names
|
||||
GlobalVarName = "__PRETTY_FUNCTION__.";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string FunctionName;
|
||||
|
|
|
@ -76,7 +76,10 @@ public:
|
|||
cast<llvm::ArrayType>(ConvertType(ILE->getType()));
|
||||
unsigned NumInitElements = ILE->getNumInits();
|
||||
// FIXME: Check for wide strings
|
||||
if (NumInitElements > 0 && isa<StringLiteral>(ILE->getInit(0)) &&
|
||||
// FIXME: Check for NumInitElements exactly equal to 1??
|
||||
if (NumInitElements > 0 &&
|
||||
(isa<StringLiteral>(ILE->getInit(0)) ||
|
||||
isa<ObjCEncodeExpr>(ILE->getInit(0))) &&
|
||||
ILE->getType()->getArrayElementTypeNoTypeQual()->isCharType())
|
||||
return Visit(ILE->getInit(0));
|
||||
const llvm::Type *ElemTy = AType->getElementType();
|
||||
|
@ -346,12 +349,26 @@ public:
|
|||
llvm::Constant *VisitStringLiteral(StringLiteral *E) {
|
||||
assert(!E->getType()->isPointerType() && "Strings are always arrays");
|
||||
|
||||
// Otherwise this must be a string initializing an array in a static
|
||||
// initializer. Don't emit it as the address of the string, emit the string
|
||||
// data itself as an inline array.
|
||||
// This must be a string initializing an array in a static initializer.
|
||||
// Don't emit it as the address of the string, emit the string data itself
|
||||
// as an inline array.
|
||||
return llvm::ConstantArray::get(CGM.GetStringForStringLiteral(E), false);
|
||||
}
|
||||
|
||||
llvm::Constant *VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
|
||||
// This must be an @encode initializing an array in a static initializer.
|
||||
// Don't emit it as the address of the string, emit the string data itself
|
||||
// as an inline array.
|
||||
std::string Str;
|
||||
CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str);
|
||||
const ConstantArrayType *CAT = cast<ConstantArrayType>(E->getType());
|
||||
|
||||
// Resize the string to the right size, adding zeros at the end, or
|
||||
// truncating as needed.
|
||||
Str.resize(CAT->getSize().getZExtValue(), '\0');
|
||||
return llvm::ConstantArray::get(Str, false);
|
||||
}
|
||||
|
||||
llvm::Constant *VisitUnaryExtension(const UnaryOperator *E) {
|
||||
return Visit(E->getSubExpr());
|
||||
}
|
||||
|
@ -398,6 +415,8 @@ public:
|
|||
}
|
||||
case Expr::StringLiteralClass:
|
||||
return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E));
|
||||
case Expr::ObjCEncodeExprClass:
|
||||
return CGM.GetAddrOfConstantStringFromObjCEncode(cast<ObjCEncodeExpr>(E));
|
||||
case Expr::ObjCStringLiteralClass: {
|
||||
ObjCStringLiteral* SL = cast<ObjCStringLiteral>(E);
|
||||
std::string S(SL->getString()->getStrData(),
|
||||
|
|
|
@ -165,6 +165,10 @@ public:
|
|||
return EmitLoadOfLValue(E);
|
||||
}
|
||||
Value *VisitStringLiteral(Expr *E) { return EmitLValue(E).getAddress(); }
|
||||
Value *VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
|
||||
return EmitLValue(E).getAddress();
|
||||
}
|
||||
|
||||
Value *VisitPredefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); }
|
||||
|
||||
Value *VisitInitListExpr(InitListExpr *E) {
|
||||
|
@ -329,7 +333,6 @@ public:
|
|||
Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
|
||||
return CGF.EmitObjCStringLiteral(E);
|
||||
}
|
||||
Value *VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
||||
|
@ -1385,22 +1388,6 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
|
|||
return Builder.CreateLoad(ArgPtr);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *BE) {
|
||||
llvm::Constant *C = CGF.BuildBlockLiteralTmp(BE);
|
||||
return C;
|
||||
|
|
|
@ -628,6 +628,7 @@ public:
|
|||
LValue EmitVAArgExprLValue(const VAArgExpr *E);
|
||||
LValue EmitDeclRefLValue(const DeclRefExpr *E);
|
||||
LValue EmitStringLiteralLValue(const StringLiteral *E);
|
||||
LValue EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E);
|
||||
LValue EmitPredefinedFunctionName(unsigned Type);
|
||||
LValue EmitPredefinedLValue(const PredefinedExpr *E);
|
||||
LValue EmitUnaryOpLValue(const UnaryOperator *E);
|
||||
|
|
|
@ -1098,6 +1098,21 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
|
|||
return GetAddrOfConstantString(GetStringForStringLiteral(S));
|
||||
}
|
||||
|
||||
/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
|
||||
/// array for the given ObjCEncodeExpr node.
|
||||
llvm::Constant *
|
||||
CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) {
|
||||
std::string Str;
|
||||
getContext().getObjCEncodingForType(E->getEncodedType(), Str);
|
||||
|
||||
llvm::Constant *C = llvm::ConstantArray::get(Str);
|
||||
C = new llvm::GlobalVariable(C->getType(), true,
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
C, ".str", &getModule());
|
||||
return C;
|
||||
}
|
||||
|
||||
|
||||
/// GenerateWritableString -- Creates storage for a string literal.
|
||||
static llvm::Constant *GenerateStringLiteral(const std::string &str,
|
||||
bool constant,
|
||||
|
@ -1107,13 +1122,10 @@ static llvm::Constant *GenerateStringLiteral(const std::string &str,
|
|||
llvm::Constant *C = llvm::ConstantArray::get(str, false);
|
||||
|
||||
// Create a global variable for this string
|
||||
C = new llvm::GlobalVariable(C->getType(), constant,
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
C,
|
||||
GlobalName ? GlobalName : ".str",
|
||||
&CGM.getModule());
|
||||
|
||||
return C;
|
||||
return new llvm::GlobalVariable(C->getType(), constant,
|
||||
llvm::GlobalValue::InternalLinkage,
|
||||
C, GlobalName ? GlobalName : ".str",
|
||||
&CGM.getModule());
|
||||
}
|
||||
|
||||
/// GetAddrOfConstantString - Returns a pointer to a character array
|
||||
|
@ -1134,7 +1146,7 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str,
|
|||
ConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]);
|
||||
|
||||
if (Entry.getValue())
|
||||
return Entry.getValue();
|
||||
return Entry.getValue();
|
||||
|
||||
// Create a global variable for this.
|
||||
llvm::Constant *C = GenerateStringLiteral(str, true, *this, GlobalName);
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace clang {
|
|||
class ObjCImplementationDecl;
|
||||
class ObjCCategoryImplDecl;
|
||||
class ObjCProtocolDecl;
|
||||
class ObjCEncodeExpr;
|
||||
class BlockExpr;
|
||||
class Decl;
|
||||
class Expr;
|
||||
|
@ -212,6 +213,10 @@ public:
|
|||
/// for the given string literal.
|
||||
llvm::Constant *GetAddrOfConstantStringFromLiteral(const StringLiteral *S);
|
||||
|
||||
/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
|
||||
/// array for the given ObjCEncodeExpr node.
|
||||
llvm::Constant *GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *);
|
||||
|
||||
/// GetAddrOfConstantString - Returns a pointer to a character array
|
||||
/// containing the literal. This contents are exactly that of the given
|
||||
/// string, i.e. it will not be null terminated automatically; see
|
||||
|
|
|
@ -1178,8 +1178,8 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
|
|||
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
|
||||
if (!InitList) {
|
||||
// FIXME: Handle wide strings
|
||||
if (StringLiteral *strLiteral = IsStringLiteralInit(Init, DeclType))
|
||||
return CheckStringLiteralInit(strLiteral, DeclType);
|
||||
if (StringLiteral *StrLiteral = IsStringLiteralInit(Init, DeclType))
|
||||
return CheckStringLiteralInit(StrLiteral, DeclType);
|
||||
|
||||
// C++ [dcl.init]p14:
|
||||
// -- If the destination type is a (possibly cv-qualified) class
|
||||
|
|
|
@ -95,8 +95,19 @@ Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
|
|||
SourceLocation RParenLoc) {
|
||||
QualType EncodedType = QualType::getFromOpaquePtr(ty);
|
||||
|
||||
QualType Ty = Context.getPointerType(Context.CharTy);
|
||||
return new (Context) ObjCEncodeExpr(Ty, EncodedType, AtLoc, RParenLoc);
|
||||
std::string Str;
|
||||
Context.getObjCEncodingForType(EncodedType, Str);
|
||||
|
||||
// The type of @encode is the same as the type of the corresponding string,
|
||||
// which is an array type.
|
||||
QualType StrTy = Context.CharTy;
|
||||
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
|
||||
if (getLangOptions().CPlusPlus)
|
||||
StrTy.addConst();
|
||||
StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1),
|
||||
ArrayType::Normal, 0);
|
||||
|
||||
return new (Context) ObjCEncodeExpr(StrTy, EncodedType, AtLoc, RParenLoc);
|
||||
}
|
||||
|
||||
Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
|
||||
|
|
|
@ -2,10 +2,13 @@
|
|||
// RUN: grep -e "\^i" %t | count 1 &&
|
||||
// RUN: grep -e "\[0i\]" %t | count 1
|
||||
|
||||
int main()
|
||||
{
|
||||
int main() {
|
||||
int n;
|
||||
|
||||
const char * inc = @encode(int[]);
|
||||
const char * vla = @encode(int[n]);
|
||||
}
|
||||
|
||||
// PR3648
|
||||
int a[sizeof(@encode(int)) == 2 ? 1 : -1]; // Type is char[2]
|
||||
char (*c)[2] = &@encode(int); // @encode is an lvalue
|
||||
|
|
Loading…
Reference in New Issue