diff options
-rw-r--r-- | Sema/Sema.h | 4 | ||||
-rw-r--r-- | Sema/SemaDecl.cpp | 67 | ||||
-rw-r--r-- | Sema/SemaExpr.cpp | 5 | ||||
-rw-r--r-- | test/Sema/array-init.c | 27 |
4 files changed, 95 insertions, 8 deletions
diff --git a/Sema/Sema.h b/Sema/Sema.h index 78b88b78a0..e99e332cf5 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -440,6 +440,10 @@ private: QualType CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc, IdentifierInfo &Comp, SourceLocation CmpLoc); + /// type checking declaration initializers (C99 6.7.8) + QualType CheckInitializer(Expr *simpleInit_or_initList, QualType declType); + bool CheckSingleInitializer(Expr *simpleInit, QualType declType); + /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have /// the specified width and sign. If an overflow occurs, detect it and emit /// the specified diagnostic. diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 4d2fd4d515..6d8308a882 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -239,6 +239,63 @@ Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { return 0; } +bool Sema::CheckSingleInitializer(Expr *Init, QualType DeclType) { + AssignmentCheckResult result; + SourceLocation loc = Init->getLocStart(); + // Get the type before calling CheckSingleAssignmentConstraints(), since + // it can promote the expression. + QualType rhsType = Init->getType(); + + result = CheckSingleAssignmentConstraints(DeclType, Init); + + // decode the result (notice that extensions still return a type). + switch (result) { + case Compatible: + break; + case Incompatible: + Diag(loc, diag::err_typecheck_assign_incompatible, + DeclType.getAsString(), rhsType.getAsString(), + Init->getSourceRange()); + return true; + case PointerFromInt: + // check for null pointer constant (C99 6.3.2.3p3) + if (!Init->isNullPointerConstant(Context)) { + Diag(loc, diag::ext_typecheck_assign_pointer_int, + DeclType.getAsString(), rhsType.getAsString(), + Init->getSourceRange()); + return true; + } + break; + case IntFromPointer: + Diag(loc, diag::ext_typecheck_assign_pointer_int, + DeclType.getAsString(), rhsType.getAsString(), + Init->getSourceRange()); + break; + case IncompatiblePointer: + Diag(loc, diag::ext_typecheck_assign_incompatible_pointer, + DeclType.getAsString(), rhsType.getAsString(), + Init->getSourceRange()); + break; + case CompatiblePointerDiscardsQualifiers: + Diag(loc, diag::ext_typecheck_assign_discards_qualifiers, + DeclType.getAsString(), rhsType.getAsString(), + Init->getSourceRange()); + break; + } + return false; +} + +QualType Sema::CheckInitializer(Expr *Init, QualType DeclType) { + InitListExpr *InitList = dyn_cast<InitListExpr>(Init); + if (!InitList) { + return CheckSingleInitializer(Init, DeclType) ? QualType() : DeclType; + } + // We have an InitListExpr, make sure we set the type. + Init->setType(DeclType); + // FIXME: Lot of checking still to do... + return DeclType; +} + Sema::DeclTy * Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init, DeclTy *lastDeclarator) { @@ -375,7 +432,10 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init, } } NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator); - } else { + } else { + if (Init) { + CheckInitializer(Init, R); + } // Block scope. C99 6.7p7: If an identifier for an object is declared with // no linkage (C99 6.2.2p6), the type for the object shall be complete... if (SC != VarDecl::Extern) { @@ -410,10 +470,7 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init, NewVD = MergeVarDecl(NewVD, PrevDecl); if (NewVD == 0) return 0; } - if (Init) { - AssignmentCheckResult result; - result = CheckSingleAssignmentConstraints(R, Init); - // FIXME: emit errors if appropriate. + if (Init) { // FIXME: This will likely move up above...for now, it stays. NewVD->setInit(Init); } New = NewVD; diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index daddb50c71..713ddb446d 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -642,15 +642,14 @@ ParseCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty, Action::ExprResult Sema:: ParseInitList(SourceLocation LBraceLoc, ExprTy **initlist, unsigned NumInit, SourceLocation RBraceLoc) { -// Expr **InitList = reinterpret_cast<Expr**>(initlist); + Expr **InitList = reinterpret_cast<Expr**>(initlist); // FIXME: add semantic analysis (C99 6.7.8). This involves // knowledge of the object being intialized. As a result, the code for // doing the semantic analysis will likely be located elsewhere (i.e. in // consumers of InitListExpr (e.g. ParseDeclarator, ParseCompoundLiteral). - //return new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc); - return false; // FIXME instantiate an InitListExpr. + return new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc); } Action::ExprResult Sema:: diff --git a/test/Sema/array-init.c b/test/Sema/array-init.c new file mode 100644 index 0000000000..2a26103a31 --- /dev/null +++ b/test/Sema/array-init.c @@ -0,0 +1,27 @@ +// RUN: clang -parse-ast-check -pedantic %s + +void func() { + int x = 1; + + //int x2[] = { 1, 3, 5 }; + + int x3[x] = { 1, 2 }; // gcc-error {{variable-sized object may not be initialized}} + + int x4 = { 1, 2 }; // gcc-warning {{excess elements in array initializer}} + + int y[4][3] = { + { 1, 3, 5 }, + { 2, 4, 6 }, + { 3, 5, 7 }, + }; + + int y2[4][3] = { + 1, 3, 5, 2, 4, 6, 3, 5, 7 + }; + + struct threeElements { + int a,b,c; + } z = { 1 }; + + struct threeElements *p = 7; // expected-warning{{incompatible types assigning 'int' to 'struct threeElements *'}} +} |