[cfe-commits] [PATCH] Don't eagerly emit a global static merged with a local extern.

Douglas Gregor dgregor at apple.com
Thu Dec 20 14:47:47 PST 2012


On Dec 19, 2012, at 7:14 PM, Rafael Ávila de Espíndola <rafael.espindola at gmail.com> wrote:

> 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.

Yeah. The fact that we represent the "extern int i;" as having "foo" as its semantic DeclContext is a longstanding problem, and this bug falls out of that damage.

> 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.

Yes, that's far better.

> 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.

That's fine. Patch looks good.

	- Doug

> Thanks to Reed Kotler for reporting this.
> ---
> lib/CodeGen/CGDecl.cpp        |  2 +-
> lib/CodeGen/CGExpr.cpp        |  5 ++---
> lib/Sema/SemaDecl.cpp         |  9 +++++++--
> test/CodeGen/linkage-redecl.c | 10 +++++++++-
> 4 files changed, 19 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
> index e01d56b..7de4637 100644
> --- a/lib/CodeGen/CGDecl.cpp
> +++ b/lib/CodeGen/CGDecl.cpp
> @@ -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:
> diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
> index daab163..0f88b3c 100644
> --- a/lib/CodeGen/CGExpr.cpp
> +++ b/lib/CodeGen/CGExpr.cpp
> @@ -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>();
> diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
> index c1afaa7..9069c21 100644
> --- a/lib/Sema/SemaDecl.cpp
> +++ b/lib/Sema/SemaDecl.cpp
> @@ -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
> diff --git a/test/CodeGen/linkage-redecl.c b/test/CodeGen/linkage-redecl.c
> index 09b51f0..14112fe 100644
> --- a/test/CodeGen/linkage-redecl.c
> +++ b/test/CodeGen/linkage-redecl.c
> @@ -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
> -- 
> 1.7.11.7
> 





More information about the cfe-commits mailing list