]> granicus.if.org Git - clang/commitdiff
Bug fix, __private_extern__ globals were always introducing a definition.
authorDaniel Dunbar <daniel@zuster.org>
Tue, 13 Jan 2009 02:25:00 +0000 (02:25 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Tue, 13 Jan 2009 02:25:00 +0000 (02:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62139 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
test/CodeGen/private-extern.c [new file with mode: 0644]

index ff8acde99510d0a02013541fbe6a46be3bda0124..39611a08deb7f59cb3976da2aec1b00abbe0f99a 100644 (file)
@@ -150,14 +150,14 @@ static void setGlobalVisibility(llvm::GlobalValue *GV,
 /// AddGlobalCtor - Add a function to the list that will be called before
 /// main() runs.
 void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor, int Priority) {
-  // TODO: Type coercion of void()* types.
+  // FIXME: Type coercion of void()* types.
   GlobalCtors.push_back(std::make_pair(Ctor, Priority));
 }
 
 /// AddGlobalDtor - Add a function to the list that will be called
 /// when the module is unloaded.
 void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) {
-  // TODO: Type coercion of void()* types.
+  // FIXME: Type coercion of void()* types.
   GlobalDtors.push_back(std::make_pair(Dtor, Priority));
 }
 
@@ -214,7 +214,7 @@ static void SetGlobalValueAttributes(const Decl *D,
                                      bool IsInline,
                                      llvm::GlobalValue *GV,
                                      bool ForDefinition) {
-  // TODO: Set up linkage and many other things.  Note, this is a simple 
+  // FIXME: Set up linkage and many other things.  Note, this is a simple 
   // approximation of what we really want.
   if (!ForDefinition) {
     // Only a few attributes are set on declarations.
@@ -247,6 +247,8 @@ static void SetGlobalValueAttributes(const Decl *D,
     }
   }
 
+  // FIXME: Figure out the relative priority of the attribute,
+  // -fvisibility, and private_extern.
   if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>())
     setGlobalVisibility(GV, attr->getVisibility());
   // FIXME: else handle -fvisibility
@@ -451,7 +453,9 @@ void CodeGenModule::EmitGlobal(const ValueDecl *Global) {
   } else if (const VarDecl *VD = cast<VarDecl>(Global)) {
     assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
 
-    isDef = !(VD->getStorageClass() == VarDecl::Extern && VD->getInit() == 0);
+    isDef = !((VD->getStorageClass() == VarDecl::Extern ||
+               VD->getStorageClass() == VarDecl::PrivateExtern) && 
+              VD->getInit() == 0);
     isStatic = VD->getStorageClass() == VarDecl::Static;
   } else {
     assert(0 && "Invalid argument to EmitGlobal");
@@ -492,11 +496,24 @@ void CodeGenModule::EmitGlobalDefinition(const ValueDecl *D) {
 
   // Lookup the entry, lazily creating it if necessary.
   llvm::GlobalValue *&Entry = GlobalDeclMap[D->getIdentifier()];
-  if (!Entry)
-    Entry = new llvm::GlobalVariable(Ty, false, 
-                                     llvm::GlobalValue::ExternalLinkage,
-                                     0, D->getNameAsString(), &getModule(), 0,
-                                     ASTTy.getAddressSpace());
+  if (!Entry) {
+    llvm::GlobalVariable *GV = 
+      new llvm::GlobalVariable(Ty, false, 
+                               llvm::GlobalValue::ExternalLinkage,
+                               0, D->getNameAsString(), &getModule(), 0,
+                               ASTTy.getAddressSpace());
+    Entry = GV;
+
+    // Handle things which are present even on external declarations.
+
+    // FIXME: This code is overly simple and should be merged with
+    // other global handling.
+
+    GV->setConstant(D->getType().isConstant(Context));
+
+    if (D->getStorageClass() == VarDecl::PrivateExtern)
+      setGlobalVisibility(GV, VisibilityAttr::HiddenVisibility);
+  }
   
   // Make sure the result is of the correct type.
   return llvm::ConstantExpr::getBitCast(Entry, PTy);
@@ -626,8 +643,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
         GV->setLinkage(llvm::GlobalVariable::ExternalLinkage);
       break;
     case VarDecl::Extern:
+      // FIXME: common
+      break;
+      
     case VarDecl::PrivateExtern:
-      // todo: common
+      GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+      // FIXME: common
       break;
     }
   }
diff --git a/test/CodeGen/private-extern.c b/test/CodeGen/private-extern.c
new file mode 100644 (file)
index 0000000..8cf963d
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: clang -emit-llvm -o %t %s &&
+// RUN: grep '@g0 = external hidden constant i32' %t &&
+// RUN: grep '@g1 = hidden constant i32 1' %t
+
+__private_extern__ const int g0;
+__private_extern__ const int g1 = 1;
+
+int f0(void) {
+  return g0;
+}