[cfe-commits] r65391 - in /cfe/trunk: include/clang/AST/ExprObjC.h lib/AST/Expr.cpp lib/AST/ExprConstant.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h lib/Sema/SemaDecl.cpp lib/Sema/SemaExprObjC.cpp test/CodeGenObjC/encode-test-3.m

Chris Lattner sabre at nondot.org
Tue Feb 24 14:18:40 PST 2009


Author: lattner
Date: Tue Feb 24 16:18:39 2009
New Revision: 65391

URL: http://llvm.org/viewvc/llvm-project?rev=65391&view=rev
Log:
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.

Modified:
    cfe/trunk/include/clang/AST/ExprObjC.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/CodeGenObjC/encode-test-3.m

Modified: cfe/trunk/include/clang/AST/ExprObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprObjC.h?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ExprObjC.h (original)
+++ cfe/trunk/include/clang/AST/ExprObjC.h Tue Feb 24 16:18:39 2009
@@ -54,7 +54,9 @@
   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;

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Feb 24 16:18:39 2009
@@ -478,7 +478,8 @@
 
   // 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 @@
   switch (getStmtClass()) {
   default: break;
   case StringLiteralClass:
+  case ObjCEncodeExprClass:
     return true;
   case CompoundLiteralExprClass: {
     // This handles gcc's extension that allows global initializers like

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Feb 24 16:18:39 2009
@@ -153,6 +153,7 @@
   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

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Feb 24 16:18:39 2009
@@ -148,6 +148,8 @@
     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 @@
   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 @@
   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;

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Tue Feb 24 16:18:39 2009
@@ -76,7 +76,10 @@
         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 @@
   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 @@
     }
     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(), 

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Feb 24 16:18:39 2009
@@ -165,6 +165,10 @@
     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 @@
   Value *VisitObjCStringLiteral(const ObjCStringLiteral *E) {
     return CGF.EmitObjCStringLiteral(E);
   }
-  Value *VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
 };
 }  // end anonymous namespace.
 
@@ -1385,22 +1388,6 @@
   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;

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Feb 24 16:18:39 2009
@@ -628,6 +628,7 @@
   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);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Feb 24 16:18:39 2009
@@ -1098,6 +1098,21 @@
   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 @@
   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 @@
   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);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Tue Feb 24 16:18:39 2009
@@ -41,6 +41,7 @@
   class ObjCImplementationDecl;
   class ObjCCategoryImplDecl;
   class ObjCProtocolDecl;
+  class ObjCEncodeExpr;
   class BlockExpr;
   class Decl;
   class Expr;
@@ -212,6 +213,10 @@
   /// 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

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Feb 24 16:18:39 2009
@@ -1178,8 +1178,8 @@
   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

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Feb 24 16:18:39 2009
@@ -95,8 +95,19 @@
                                                  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,

Modified: cfe/trunk/test/CodeGenObjC/encode-test-3.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/encode-test-3.m?rev=65391&r1=65390&r2=65391&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenObjC/encode-test-3.m (original)
+++ cfe/trunk/test/CodeGenObjC/encode-test-3.m Tue Feb 24 16:18:39 2009
@@ -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





More information about the cfe-commits mailing list