[cfe-commits] r46540 - in /cfe/trunk: Sema/SemaDecl.cpp include/clang/Basic/DiagnosticKinds.def test/Sema/tentative-decls.c

Steve Naroff snaroff at apple.com
Tue Jan 29 16:44:01 PST 2008


Author: snaroff
Date: Tue Jan 29 18:44:01 2008
New Revision: 46540

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

Many refinements to Sema::MergeVarDecl(). This routine still needs some re-work to fully handle tentative decls.

This includes a fix to bz1908.


Added:
    cfe/trunk/test/Sema/tentative-decls.c
Modified:
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def

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

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Tue Jan 29 18:44:01 2008
@@ -319,26 +319,56 @@
     Diag(OldD->getLocation(), diag::err_previous_definition);
     return New;
   }
+  // Verify the types match.
+  if (Old->getCanonicalType() != New->getCanonicalType() && 
+      !areEquivalentArrayTypes(New->getCanonicalType(), Old->getCanonicalType())) {
+    Diag(New->getLocation(), diag::err_redefinition, New->getName());
+    Diag(Old->getLocation(), diag::err_previous_definition);
+    return New;
+  }
+  // C99 6.2.2p4: Check if we have a static decl followed by a non-static.
+  if (New->getStorageClass() == VarDecl::Static &&
+      (Old->getStorageClass() == VarDecl::None ||
+       Old->getStorageClass() == VarDecl::Extern)) {
+    Diag(New->getLocation(), diag::err_static_non_static, New->getName());
+    Diag(Old->getLocation(), diag::err_previous_definition);
+    return New;
+  }
+  // C99 6.2.2p4: Check if we have a non-static decl followed by a static.
+  if (New->getStorageClass() != VarDecl::Static &&
+      Old->getStorageClass() == VarDecl::Static) {
+    Diag(New->getLocation(), diag::err_non_static_static, New->getName());
+    Diag(Old->getLocation(), diag::err_previous_definition);
+    return New;
+  }
+  // We've verified the types match, now handle "tentative" definitions.
   FileVarDecl *OldFSDecl = dyn_cast<FileVarDecl>(Old);
   FileVarDecl *NewFSDecl = dyn_cast<FileVarDecl>(New);
-  bool OldIsTentative = false;
   
-  if (OldFSDecl && NewFSDecl) { // C99 6.9.2
-    // Handle C "tentative" external object definitions. FIXME: finish!
+  if (OldFSDecl && NewFSDecl) {
+    // Handle C "tentative" external object definitions (C99 6.9.2).
+    bool OldIsTentative = false;
+    bool NewIsTentative = false;
+    
     if (!OldFSDecl->getInit() &&
         (OldFSDecl->getStorageClass() == VarDecl::None ||
          OldFSDecl->getStorageClass() == VarDecl::Static))
       OldIsTentative = true;
+      
+    // FIXME: this check doesn't work (since the initializer hasn't been
+    // attached yet). This check should be moved to FinalizeDeclaratorGroup.
+    // Unfortunately, by the time we get to FinializeDeclaratorGroup, we've 
+    // thrown out the old decl.
+    if (!NewFSDecl->getInit() &&
+        (NewFSDecl->getStorageClass() == VarDecl::None ||
+         NewFSDecl->getStorageClass() == VarDecl::Static))
+      ; // change to NewIsTentative = true; once the code is moved.
+    
+    if (NewIsTentative || OldIsTentative)
+      return New;
   }
-  // Verify the types match.
-  if (Old->getCanonicalType() != New->getCanonicalType() && 
-      !areEquivalentArrayTypes(New->getCanonicalType(), Old->getCanonicalType())) {
-    Diag(New->getLocation(), diag::err_redefinition, New->getName());
-    Diag(Old->getLocation(), diag::err_previous_definition);
-    return New;
-  }
-  // We've verified the types match, now check if Old is "extern".
-  if (Old->getStorageClass() != VarDecl::Extern) {
+  if (Old->getStorageClass() != VarDecl::Extern &&
+      New->getStorageClass() != VarDecl::Extern) {
     Diag(New->getLocation(), diag::err_redefinition, New->getName());
     Diag(Old->getLocation(), diag::err_previous_definition);
   }

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Tue Jan 29 18:44:01 2008
@@ -602,6 +602,10 @@
      "use of undeclared identifier '%0'")
 DIAG(err_redefinition, ERROR,
      "redefinition of '%0'")
+DIAG(err_static_non_static, ERROR,
+     "static declaration of '%0' follows non-static declaration")
+DIAG(err_non_static_static, ERROR,
+     "non-static declaration of '%0' follows static declaration")
 DIAG(err_redefinition_different_kind, ERROR,
      "redefinition of '%0' as different kind of symbol")
 DIAG(err_conflicting_types, ERROR,

Added: cfe/trunk/test/Sema/tentative-decls.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/tentative-decls.c?rev=46540&view=auto

==============================================================================
--- cfe/trunk/test/Sema/tentative-decls.c (added)
+++ cfe/trunk/test/Sema/tentative-decls.c Tue Jan 29 18:44:01 2008
@@ -0,0 +1,24 @@
+// RUN: clang %s -verify -fsyntax-only
+
+const int a [1] = {1};
+extern const int a[];
+
+extern const int b[];
+const int b [1] = {1};
+
+extern const int c[] = {1}; // expected-warning{{'extern' variable has an initializer}}
+const int c[];
+
+int i1 = 1; // expected-error{{previous definition is here}}
+int i1 = 2; // expected-error{{redefinition of 'i1'}} // expected-error{{previous definition is here}}
+// FIXME: the following should not be an error (see related FIXME in Sema::MergeVarDecl). 
+int i1; // expected-error{{redefinition of 'i1'}}
+int i1;
+extern int i1; // expected-error{{previous definition is here}}
+static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}} expected-error{{previous definition is here}}
+int i1 = 3; // expected-error{{non-static declaration of 'i1' follows static declaration}}
+
+void func() {
+  extern int i1; // expected-error{{previous definition is here}}
+  static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}}
+}





More information about the cfe-commits mailing list