]> granicus.if.org Git - clang/commitdiff
Variables marked as "extern" can actually have internal linkage if
authorDouglas Gregor <dgregor@apple.com>
Thu, 19 Mar 2009 22:01:50 +0000 (22:01 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 19 Mar 2009 22:01:50 +0000 (22:01 +0000)
there is a previous declaration marked "static". This fixes PR3645.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67336 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
lib/Sema/SemaDecl.cpp
test/Sema/tentative-decls.c
test/Sema/var-redecl.c

index d4d22060c83cf13b529b28db33158e2285e4c586..e4a40c6caaff54e189090fa7b006f6b4bb0a9bd5 100644 (file)
@@ -258,6 +258,7 @@ public:
   virtual void Destroy(ASTContext& C);
 
   StorageClass getStorageClass() const { return (StorageClass)SClass; }
+  void setStorageClass(StorageClass SC) { SClass = SC; }
 
   SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
 
index 99ea70776068a7da5a30e3e0f92d15548130aba4..7c80fa553e114febad93e197cad7524dc75aa112 100644 (file)
@@ -832,9 +832,20 @@ bool Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
     Diag(Old->getLocation(), diag::note_previous_definition);
     return true;
   }
-  // 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) {
+  // C99 6.2.2p4: 
+  //   For an identifier declared with the storage-class specifier
+  //   extern in a scope in which a prior declaration of that
+  //   identifier is visible,23) if the prior declaration specifies
+  //   internal or external linkage, the linkage of the identifier at
+  //   the later declaration is the same as the linkage specified at
+  //   the prior declaration. If no prior declaration is visible, or
+  //   if the prior declaration specifies no linkage, then the
+  //   identifier has external linkage.
+  if ((New->hasExternalStorage() || New->getStorageClass() == VarDecl::None) &&
+      Old->hasLinkage())
+    /* Okay */;
+  else if (New->getStorageClass() != VarDecl::Static &&
+           Old->getStorageClass() == VarDecl::Static) {
     Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
     Diag(Old->getLocation(), diag::note_previous_definition);
     return true;
index 23297f3a220621cf90f4a72bd2239cfeedb1331d..fc0d50086eaa72c87b01f076f8512c517504bf13 100644 (file)
@@ -27,7 +27,7 @@ extern int i1; // expected-note {{previous definition is here}}
 static int i1; // expected-error{{static declaration of 'i1' follows non-static declaration}}
 
 static int i2 = 5; // expected-note 1 {{previous definition is here}}
-int i2 = 3; // expected-error{{non-static declaration of 'i2' follows static declaration}}
+int i2 = 3; // expected-error{{redefinition of 'i2'}}
 
 __private_extern__ int pExtern;
 int pExtern = 0;
index 82ce58bcb9cf7fe8cca1bb0590de4a66cbb7bd06..037a8f136d898012f761e76c3241b223abb70de7 100644 (file)
@@ -54,3 +54,8 @@ void g18(void) {
   extern int g19;
 }
 int *p=&g19; // expected-error{{use of undeclared identifier 'g19'}}
+
+// PR3645
+static int a;
+extern int a;
+int a;