[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