handle @encode interactions with array initializers.

llvm-svn: 65401
This commit is contained in:
Chris Lattner 2009-02-24 23:10:27 +00:00
parent 94e6c4be9a
commit d8b741c85f
2 changed files with 27 additions and 17 deletions

View File

@ -18,7 +18,7 @@
#include "Sema.h"
#include "clang/Parse/Designator.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include <map>
using namespace clang;
@ -26,11 +26,13 @@ using namespace clang;
// Sema Initialization Checking
//===----------------------------------------------------------------------===//
static StringLiteral *IsStringInit(Expr *Init, QualType DeclType,
ASTContext &Context) {
static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) {
if (const ArrayType *AT = Context.getAsArrayType(DeclType))
if (AT->getElementType()->isCharType())
return dyn_cast<StringLiteral>(Init->IgnoreParens());
if (AT->getElementType()->isCharType()) {
Init = Init->IgnoreParens();
if (isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init))
return Init;
}
return 0;
}
@ -56,10 +58,13 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType,
InitType, Init, "initializing");
}
static void CheckStringInit(Expr *Str, unsigned StrLength,
QualType &DeclT, Sema &S) {
const ArrayType *AT = S.Context.getAsArrayType(DeclT);
static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {
// Get the length of the string as parsed.
uint64_t StrLength =
cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue();
const ArrayType *AT = S.Context.getAsArrayType(DeclT);
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) {
// C99 6.7.8p14. We have an array of character type with unknown size
// being initialized to a string literal.
@ -76,7 +81,7 @@ static void CheckStringInit(Expr *Str, unsigned StrLength,
// C99 6.7.8p14. We have an array of character type with known size. However,
// the size may be smaller or larger than the string we are initializing.
// FIXME: Avoid truncation for 64-bit length strings.
if (StrLength-1 > (unsigned)CAT->getSize().getZExtValue())
if (StrLength-1 > CAT->getSize().getZExtValue())
S.Diag(Str->getSourceRange().getBegin(),
diag::warn_initializer_string_for_char_array_too_long)
<< Str->getSourceRange();
@ -111,8 +116,8 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
if (!InitList) {
// FIXME: Handle wide strings
if (StringLiteral *Str = IsStringInit(Init, DeclType, Context)) {
CheckStringInit(Str, Str->getByteLength() + 1, DeclType, *this);
if (Expr *Str = IsStringInit(Init, DeclType, Context)) {
CheckStringInit(Str, DeclType, *this);
return false;
}
@ -587,9 +592,8 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
newStructuredList, newStructuredIndex);
++StructuredIndex;
++Index;
} else if (StringLiteral *Str = IsStringInit(expr, ElemType,
SemaRef.Context)) {
CheckStringInit(Str, Str->getByteLength() + 1, ElemType, SemaRef);
} else if (Expr *Str = IsStringInit(expr, ElemType, SemaRef.Context)) {
CheckStringInit(Str, ElemType, SemaRef);
UpdateStructuredListElement(StructuredList, StructuredIndex, Str);
++Index;
} else if (ElemType->isScalarType()) {
@ -773,9 +777,9 @@ void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType,
unsigned &StructuredIndex) {
// Check for the special-case of initializing an array with a string.
if (Index < IList->getNumInits()) {
if (StringLiteral *Str = IsStringInit(IList->getInit(Index), DeclType,
SemaRef.Context)) {
CheckStringInit(Str, Str->getByteLength() + 1, DeclType, SemaRef);
if (Expr *Str = IsStringInit(IList->getInit(Index), DeclType,
SemaRef.Context)) {
CheckStringInit(Str, DeclType, SemaRef);
// We place the string literal directly into the resulting
// initializer list. This is the only place where the structure
// of the structured initializer list doesn't match exactly,

View File

@ -13,3 +13,9 @@ int main() {
int a[sizeof(@encode(int)) == 2 ? 1 : -1]; // Type is char[2]
const char *B = @encode(int);
char (*c)[2] = &@encode(int); // @encode is an lvalue
char d[] = @encode(int); // infer size.
char e[1] = @encode(int); // truncate
char f[2] = @encode(int); // fits
char g[3] = @encode(int); // zero fill