[cfe-commits] r41672 - in /cfe/trunk: Sema/Sema.h Sema/SemaDecl.cpp include/clang/Basic/DiagnosticKinds.def test/Sema/array-init.c

Steve Naroff snaroff at apple.com
Sun Sep 2 08:34:31 PDT 2007


Author: snaroff
Date: Sun Sep  2 10:34:30 2007
New Revision: 41672

URL: http://llvm.org/viewvc/llvm-project?rev=41672&view=rev
Log:
More semantic analysis of initializers.

Added 2 errors and one warning, updated test case.

Modified:
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/test/Sema/array-init.c

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

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Sun Sep  2 10:34:30 2007
@@ -30,6 +30,7 @@
   class Preprocessor;
   class Decl;
   class Expr;
+  class InitListExpr;
   class VarDecl;
   class ParmVarDecl;
   class TypedefDecl;
@@ -441,8 +442,10 @@
                                    IdentifierInfo &Comp, SourceLocation CmpLoc);
   
   /// type checking declaration initializers (C99 6.7.8)
-  QualType CheckInitializer(Expr *simpleInit_or_initList, QualType declType);
+  QualType CheckInitializer(Expr *simpleInit_or_initList, QualType declType,
+                            bool isStatic);
   bool CheckSingleInitializer(Expr *simpleInit, QualType declType);
+  bool RequireConstantExprs(InitListExpr *IList);
   
   /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
   /// the specified width and sign.  If an overflow occurs, detect it and emit

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

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Sun Sep  2 10:34:30 2007
@@ -253,6 +253,10 @@
   case Compatible:
     break;
   case Incompatible:
+    // FIXME: tighten up this check which should allow:
+    // char s[] = "abc", which is identical to char s[] = { 'a', 'b', 'c' };
+    if (rhsType == Context.getPointerType(Context.CharTy))
+      break;
     Diag(loc, diag::err_typecheck_assign_incompatible, 
          DeclType.getAsString(), rhsType.getAsString(), 
          Init->getSourceRange());
@@ -285,13 +289,36 @@
   return false;
 }
 
-QualType Sema::CheckInitializer(Expr *Init, QualType DeclType) {
+bool Sema::RequireConstantExprs(InitListExpr *IList) {
+  bool hadError = false;
+  for (unsigned i = 0; i < IList->getNumInits(); i++) {
+    Expr *expr = IList->getInit(i);
+    
+    if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr))
+      RequireConstantExprs(InitList);
+    else {
+      SourceLocation loc;
+      // FIXME: should be isConstantExpr()...
+      if (!expr->isIntegerConstantExpr(Context, &loc)) {
+        Diag(loc, diag::err_init_element_not_constant, expr->getSourceRange());
+        hadError = true;
+      }
+    }
+  }
+  return hadError;
+}
+
+QualType Sema::CheckInitializer(Expr *Init, QualType DeclType, bool isStatic) {
   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);
+  
+  if (isStatic) // C99 6.7.8p4.
+    RequireConstantExprs(InitList);
+  
   // FIXME: Lot of checking still to do...
   return DeclType;
 }
@@ -395,6 +422,11 @@
       case DeclSpec::SCS_register:    SC = VarDecl::Register; break;
     }    
     if (S->getParent() == 0) {
+      if (Init) {
+        if (SC == VarDecl::Extern)
+          Diag(D.getIdentifierLoc(), diag::warn_extern_init);
+        CheckInitializer(Init, R, true);
+      }
       // File scope. C99 6.9.2p2: A declaration of an identifier for and 
       // object that has file scope without an initializer, and without a
       // storage-class specifier or with the storage-class specifier "static",
@@ -434,7 +466,12 @@
       NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
     } else {
       if (Init) {
-        CheckInitializer(Init, R);
+        if (SC == VarDecl::Extern) { // C99 6.7.8p5
+          Diag(D.getIdentifierLoc(), diag::err_block_extern_cant_init);
+          InvalidDecl = true;
+        } else {
+          CheckInitializer(Init, R, SC == VarDecl::Static);
+        }
       }
       // 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...

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=41672&r1=41671&r2=41672&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sun Sep  2 10:34:30 2007
@@ -542,6 +542,12 @@
      "zero size arrays are an extension")
 DIAG(err_array_size_non_int, ERROR,
      "size of array has non-integer type '%0'")
+DIAG(err_init_element_not_constant, ERROR,
+     "initializer element is not constant")
+DIAG(err_block_extern_cant_init, ERROR,
+     "'extern' variable cannot have an initializer")
+DIAG(warn_extern_init, WARNING,
+     "'extern' variable has an initializer")
 
 DIAG(err_redefinition_of_label, ERROR,
      "redefinition of label '%0'")

Modified: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=41672&r1=41671&r2=41672&view=diff

==============================================================================
--- cfe/trunk/test/Sema/array-init.c (original)
+++ cfe/trunk/test/Sema/array-init.c Sun Sep  2 10:34:30 2007
@@ -1,5 +1,12 @@
 // RUN: clang -parse-ast-check -pedantic %s
 
+static int x, y, z;
+
+static int ary[] = { x, y, z }; // expected-error{{initializer element is not constant}}
+int ary2[] = { x, y, z }; // expected-error{{initializer element is not constant}}
+
+extern int fileScopeExtern[3] = { 1, 3, 5 }; // expected-warning{{'extern' variable has an initializer}}
+
 void func() {
   int x = 1;
 
@@ -24,4 +31,6 @@
   } z = { 1 };
 
   struct threeElements *p = 7; // expected-warning{{incompatible types assigning 'int' to 'struct threeElements *'}}
+  
+  extern int blockScopeExtern[3] = { 1, 3, 5 }; // expected-error{{'extern' variable cannot have an initializer}}
 }





More information about the cfe-commits mailing list