diff options
-rw-r--r-- | include/clang/AST/Decl.h | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 9 | ||||
-rw-r--r-- | test/CodeGenCXX/static-local-in-local-class.cpp | 21 |
5 files changed, 39 insertions, 0 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index d409fdb602..dcd5af5738 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -548,6 +548,12 @@ public: return getStorageClass() <= Register; } + /// isStaticLocal - Returns tru if a variable with function scope is a + /// static local variable. + bool isStaticLocal() const { + return getStorageClass() == Static && !isFileVarDecl(); + } + /// hasExternStorage - Returns true if a variable has extern or /// __private_extern__ storage. bool hasExternalStorage() const { diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 07d219f1fb..58b90929f0 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -205,6 +205,7 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D, // Store into LocalDeclMap before generating initializer to handle // circular references. DMEntry = GV; + CGM.setStaticLocalDeclMap(&D, GV); // Make sure to evaluate VLA bounds now so that we have them for later. // diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 68f09e2d29..257f2fc4f2 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1106,6 +1106,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { bool NonGCable = VD->hasLocalStorage() && !VD->hasAttr<BlocksAttr>(); llvm::Value *V = LocalDeclMap[VD]; + if (!V && VD->isStaticLocal()) + V = CGM.getStaticLocalDeclMap(VD); assert(V && "DeclRefExpr not entered in LocalDeclMap?"); Qualifiers Quals = MakeQualifiers(E->getType()); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 8db5a588d0..022360bfc5 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -133,6 +133,7 @@ class CodeGenModule : public BlockModule { llvm::StringMap<llvm::Constant*> CFConstantStringMap; llvm::StringMap<llvm::Constant*> ConstantStringMap; + llvm::DenseMap<const Decl*, llvm::Value*> StaticLocalDeclMap; /// CXXGlobalInits - Global variables with initializers that need to run /// before main. @@ -170,6 +171,14 @@ public: /// been configured. bool hasObjCRuntime() { return !!Runtime; } + llvm::Value *getStaticLocalDeclMap(const VarDecl *VD) { + return StaticLocalDeclMap[VD]; + } + void setStaticLocalDeclMap(const VarDecl *D, + llvm::GlobalVariable *GV) { + StaticLocalDeclMap[D] = GV; + } + CGDebugInfo *getDebugInfo() { return DebugInfo; } ASTContext &getContext() const { return Context; } const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } diff --git a/test/CodeGenCXX/static-local-in-local-class.cpp b/test/CodeGenCXX/static-local-in-local-class.cpp new file mode 100644 index 0000000000..d9e044ce9d --- /dev/null +++ b/test/CodeGenCXX/static-local-in-local-class.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -emit-llvm -o %t %s +// PR6769 + +struct X { + static void f(); +}; + +void X::f() { + static int *i; + { + struct Y { + static void g() { + i = new int(); + *i = 100; + (*i) = (*i) +1; + } + }; + (void)Y::g(); + } + (void)i; +} |