Fix attached.  Mostly straightforward, although the
GenerateConstantExpr bit is a little messy.  I think the fact that few
changes are required shows that the AST representation and sema are
quite flexible.

I ran this against the testsuite; it introduces some spurious failues
due to error messages changing slightly, and causes a couple of real
failures due to the broken struct initializer sema (types in struct
initializers don't get fixed up at the moment, so initializing a char*
member with a string breaks).  To work around that, we can temporarily
change the tests to work using an explicit char* cast, which will
force the introduction of the necessary implicit cast.

This change doesn't have many visible effects; here's a couple of testcases:

void b() {
int aa[sizeof "SizeNineteenString" == 19 ? 1 : -1];
char (*asdf)[19] = &"SizeNineteenString";
}

-Eli
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h      (revision 46191)
+++ include/clang/AST/ASTContext.h      (working copy)
@@ -188,6 +188,10 @@
   /// getSizeType - Return the unique type for "size_t" (C99 7.17), defined
   /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
   QualType getSizeType() const;
+
+  /// getWcharType - Return the unique type for "wchar_t" (C99 7.17), defined
+  /// in <stddef.h>. Wide strings require this (C99 6.4.5p5).
+  QualType getWcharType() const;
   
   /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
   /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
Index: Sema/SemaExpr.cpp
===================================================================
--- Sema/SemaExpr.cpp   (revision 46191)
+++ Sema/SemaExpr.cpp   (working copy)
@@ -45,12 +45,22 @@
   
   // FIXME: handle wchar_t
   QualType t;
+
+  llvm::APSInt length(32);
+  length = Literal.GetStringLength() + 1;
+  if (Literal.Pascal) {
+    t = Context.getConstantArrayType(Context.UnsignedCharTy, length, 
ArrayType::Normal, 0);
+    // FIXME: Check for wide string so we can output error
+  } else if (Literal.AnyWide) {
+    QualType wcharType = Context.getWcharType();
+    uint64_t byteWidth = Context.getTypeSize(wcharType, 
StringToks[0].getLocation()) /
+                         Context.getTypeSize(Context.CharTy, 
StringToks[0].getLocation());
+    length = (Literal.GetStringLength() + 1) / byteWidth;
+    t = Context.getConstantArrayType(wcharType, length, ArrayType::Normal, 0);
+  } else {
+    t = Context.getConstantArrayType(Context.CharTy, length, 
ArrayType::Normal, 0);
+  }
   
-  if (Literal.Pascal) 
-    t = Context.getPointerType(Context.UnsignedCharTy);
-  else
-    t = Context.getPointerType(Context.CharTy);
-  
   if (Literal.Pascal && Literal.GetStringLength() > 256)
     return Diag(StringToks[0].getLocation(), diag::err_pascal_string_too_long,
                 SourceRange(StringToks[0].getLocation(),
Index: AST/ASTContext.cpp
===================================================================
--- AST/ASTContext.cpp  (revision 46191)
+++ AST/ASTContext.cpp  (working copy)
@@ -801,6 +801,15 @@
   return UnsignedLongTy; 
 }
 
+/// getWcharType - Return the unique type for "wchar_t" (C99 7.17), the
+/// width of characters in wide strings, The value is target dependent and 
+/// needs to agree with the definition in <stddef.h>.
+QualType ASTContext::getWcharType() const {
+  // On Darwin, wchar_t is defined as a "int". 
+  // FIXME: should derive from "Target".
+  return IntTy; 
+}
+
 /// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
 /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
 QualType ASTContext::getPointerDiffType() const {
Index: CodeGen/CodeGenModule.cpp
===================================================================
--- CodeGen/CodeGenModule.cpp   (revision 46191)
+++ CodeGen/CodeGenModule.cpp   (working copy)
@@ -390,16 +390,13 @@
   // Generate constant for string literal values.
   case Stmt::StringLiteralClass: {
     const StringLiteral *String = cast<StringLiteral>(Expression);
+    assert(!String->isWide() && "Cannot codegen wide strings yet");
     const char *StrData = String->getStrData();
     unsigned Len = String->getByteLength();
 
-    // If the string has a pointer type, emit it as a global and use the 
pointer
-    // to the global as its value.
-    if (String->getType()->isPointerType()) 
-      return CGM.GetAddrOfConstantString(std::string(StrData, StrData + Len));
-
-    // 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
+    // This must be a string initializing an array in a static
+    // initializer, else we wouldn't be here.  Don't emit it as
+    // the address of the string, emit the string
     // data itself as an inline array.
     const ConstantArrayType *CAT = String->getType()->getAsConstantArrayType();
     assert(CAT && "String isn't pointer or array!");
@@ -472,6 +469,25 @@
   }
   case Stmt::ImplicitCastExprClass: {
     const ImplicitCastExpr *ICExpr = cast<ImplicitCastExpr>(Expression);
+
+    if (ICExpr->getSubExpr()->getStmtClass() == Stmt::StringLiteralClass) {
+      // FIXME: This isn't really factored correctly, but
+      // fixing that requires a GetAddrOfConstant method that
+      // takes an llvm::Constant*.
+      assert(ICExpr->getType()->isPointerType() &&
+             "Implicit cast of string to non-pointer?");
+      const StringLiteral *String = cast<StringLiteral>(ICExpr->getSubExpr());
+      assert(!String->isWide() && "Cannot codegen wide strings yet");
+      const char *StrData = String->getStrData();
+      unsigned Len = String->getByteLength();
+
+      llvm::Constant *C =
+          CGM.GetAddrOfConstantString(std::string(StrData, StrData + Len));
+      llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
+      llvm::Constant *Zeros[] = { Zero, Zero };
+      C = llvm::ConstantExpr::getGetElementPtr(C, Zeros, 2);
+      return C;
+    }
     
     // If this is due to array->pointer conversion, emit the array expression 
as
     // an l-value.
@@ -705,9 +721,7 @@
   C = new llvm::GlobalVariable(C->getType(), constant, 
                                llvm::GlobalValue::InternalLinkage,
                                C, ".str", &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;
 }
 
_______________________________________________
cfe-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

Reply via email to