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