[cfe-commits] r41671 - in /cfe/trunk: Sema/Sema.h Sema/SemaDecl.cpp Sema/SemaExpr.cpp test/Sema/array-init.c

Steve Naroff snaroff at apple.com
Sat Sep 1 19:04:31 PDT 2007


Author: snaroff
Date: Sat Sep  1 21:04:30 2007
New Revision: 41671

URL: http://llvm.org/viewvc/llvm-project?rev=41671&view=rev
Log:

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! ********************



Added:
    cfe/trunk/test/Sema/array-init.c
Modified:
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/Sema/SemaExpr.cpp

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=41671&r1=41670&r2=41671&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Sat Sep  1 21:04:30 2007
@@ -440,6 +440,10 @@
   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.

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=41671&r1=41670&r2=41671&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Sat Sep  1 21:04:30 2007
@@ -239,6 +239,63 @@
   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 @@
         }
       }
       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 @@
       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;

Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=41671&r1=41670&r2=41671&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Sat Sep  1 21:04:30 2007
@@ -642,15 +642,14 @@
 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::

Added: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=41671&view=auto

==============================================================================
--- cfe/trunk/test/Sema/array-init.c (added)
+++ cfe/trunk/test/Sema/array-init.c Sat Sep  1 21:04:30 2007
@@ -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 *'}}
+}





More information about the cfe-commits mailing list