]> granicus.if.org Git - clang/commitdiff
Don't eagerly emit a global static merged with a local extern.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 21 Dec 2012 01:21:33 +0000 (01:21 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 21 Dec 2012 01:21:33 +0000 (01:21 +0000)
When we are visiting the extern declaration of 'i' in

static int i = 99;
int foo() {
  extern int i;
  return i;
}

We should not try to handle it as if it was an function static. That is, we
must consider the written storage class.

Fixing this then exposes that the assert in EmitGlobalVarDeclLValue and the
if leading to its call are not completely accurate. They were passing before
because the second decl was marked as having external storage. I changed them
to check the linkage, which I find easier to understand.

Last but not least, there is something strange going on with cuda and opencl.
My guess is that the linkage computation for these languages needs to be
audited, but I didn't want to change that in this patch so I just updated
the storage classes to keep the current behavior.

Thanks to Reed Kotler for reporting this.

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

lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGExpr.cpp
lib/Sema/SemaDecl.cpp
test/CodeGen/linkage-redecl.c

index e01d56bb296e6549bf3a43083eb2bfde6018bc88..7de46376bad8913488822f54ed3370cbb28babd0 100644 (file)
@@ -107,7 +107,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
 /// EmitVarDecl - This method handles emission of any variable declaration
 /// inside a function, including static vars etc.
 void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
-  switch (D.getStorageClass()) {
+  switch (D.getStorageClassAsWritten()) {
   case SC_None:
   case SC_Auto:
   case SC_Register:
index daab163d27ac6dc86807415e6c549aed1a3c0425..0f88b3cd40329129ab9e7c816366c4cc8da3db16 100644 (file)
@@ -1583,8 +1583,7 @@ EmitBitCastOfLValueToProperType(CodeGenFunction &CGF,
 
 static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
                                       const Expr *E, const VarDecl *VD) {
-  assert((VD->hasExternalStorage() || VD->isFileVarDecl()) &&
-         "Var decl must have external storage or be a file var decl!");
+  assert(VD->hasLinkage() && "Var decl must have linkage!");
 
   llvm::Value *V = CGF.CGM.GetAddrOfGlobalVar(VD);
   llvm::Type *RealVarTy = CGF.getTypes().ConvertTypeForMem(VD->getType());
@@ -1658,7 +1657,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
 
   if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
     // Check if this is a global variable.
-    if (VD->hasExternalStorage() || VD->isFileVarDecl()) 
+    if (VD->hasLinkage())
       return EmitGlobalVarDeclLValue(*this, E, VD);
 
     bool isBlockVariable = VD->hasAttr<BlocksAttr>();
index 96e911d17bcfab7fc9a3fb9eb145cbbafa5abb96..ebfb4b1e78c8d49263dd8f2f2e9e18f734f38781 100644 (file)
@@ -4284,8 +4284,10 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   if (getLangOpts().OpenCL) {
     // Set up the special work-group-local storage class for variables in the
     // OpenCL __local address space.
-    if (R.getAddressSpace() == LangAS::opencl_local)
+    if (R.getAddressSpace() == LangAS::opencl_local) {
       SC = SC_OpenCLWorkGroupLocal;
+      SCAsWritten = SC_OpenCLWorkGroupLocal;
+    }
   }
 
   bool isExplicitSpecialization = false;
@@ -4420,8 +4422,11 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
     // CUDA B.2.5: "__shared__ and __constant__ variables have implied static
     // storage [duration]."
     if (SC == SC_None && S->getFnParent() != 0 &&
-       (NewVD->hasAttr<CUDASharedAttr>() || NewVD->hasAttr<CUDAConstantAttr>()))
+        (NewVD->hasAttr<CUDASharedAttr>() ||
+         NewVD->hasAttr<CUDAConstantAttr>())) {
       NewVD->setStorageClass(SC_Static);
+      NewVD->setStorageClassAsWritten(SC_Static);
+    }
   }
 
   // In auto-retain/release, infer strong retension for variables of
index 09b51f02c13f229a6229666d5c55ce10266c4b5c..14112fe3a0a8a714e6e9ff69d048580c8e1a9ed4 100644 (file)
@@ -1,4 +1,11 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - |grep internal
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: @test2_i = internal global i32 99
+static int test2_i = 99;
+int test2_f() {
+  extern int test2_i;
+  return test2_i;
+}
 
 // C99 6.2.2p3
 // PR3425
@@ -9,3 +16,4 @@ void g0() {
 }
 
 extern void f(int x) { } // still has internal linkage
+// CHECK: define internal void @f