aboutsummaryrefslogtreecommitdiff
path: root/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2008-01-30 00:44:01 +0000
committerSteve Naroff <snaroff@apple.com>2008-01-30 00:44:01 +0000
commitb7b032ecb23e5a2ebff89d62478f93313c04d367 (patch)
treef240461fb61075931e74fa191f8ce8177b03deed /Sema/SemaDecl.cpp
parent52a16499df87730c0252b431abdf2b2e32d756a6 (diff)
Many refinements to Sema::MergeVarDecl(). This routine still needs some re-work to fully handle tentative decls.
This includes a fix to bz1908. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46540 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Sema/SemaDecl.cpp')
-rw-r--r--Sema/SemaDecl.cpp54
1 files changed, 42 insertions, 12 deletions
diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp
index 9dd306944d..68177e03c8 100644
--- a/Sema/SemaDecl.cpp
+++ b/Sema/SemaDecl.cpp
@@ -319,26 +319,56 @@ VarDecl *Sema::MergeVarDecl(VarDecl *New, ScopedDecl *OldD) {
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);
}