aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2007-09-02 02:04:30 +0000
committerSteve Naroff <snaroff@apple.com>2007-09-02 02:04:30 +0000
commitf009063ab7e05be7781751ff9e4b42630f07a747 (patch)
tree2b44c125aa6743d63b2a1d90ae7a9fedca8ac190
parent9dcbfa450d751bd68fc4af8b75da381d4f6984b9 (diff)
Start implementing semantic analysis for C initializers.
Step 1: Start instantiating InitListExpr's. Step 2: Call newly added function Sema::CheckInitializer() from Sema::ParseDeclarator(). Step 3: Give InitListExpr's a preliminary type. Step 4: Start emitting diagnostics for simple assignments. Note: As a result of step 1, the CodeGen/mandel.c test asserts "Unimplemented agg expr!", which is expected. As a result of step 4, the test below now fails. This isn't expected and needs to be investigated (it appears type checking for C++ references is flawed in some way). ******************** TEST 'Sema/cxx-references.cpp' FAILED! ******************** Command: clang -fsyntax-only Sema/cxx-references.cpp Output: Sema/cxx-references.cpp:8:12: warning: incompatible pointer types assigning 'int &*' to 'int *' int *p = &r; ^~ Sema/cxx-references.cpp:10:20: error: incompatible types assigning 'int (int)' to 'int (&)(int)' int (&rg)(int) = g; ^ Sema/cxx-references.cpp:13:18: error: incompatible types assigning 'int [3]' to 'int (&)[3]' int (&ra)[3] = a; ^ Sema/cxx-references.cpp:16:14: error: incompatible types assigning 'int *' to 'int *&' int *& P = Q; ^ 4 diagnostics generated. ******************** TEST 'Sema/cxx-references.cpp' FAILED! ******************** git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41671 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Sema/Sema.h4
-rw-r--r--Sema/SemaDecl.cpp67
-rw-r--r--Sema/SemaExpr.cpp5
-rw-r--r--test/Sema/array-init.c27
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 *'}}
+}