From 1a86b33c1870fee08d281c9f07ac1280195a7fae Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Wed, 17 Oct 2007 00:52:43 +0000 Subject: [PATCH] Generate code for static variables that don't have initializers. Also, report an error if a static initializer is not constant. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43058 91177308-0d34-0410-b5e6-96231b3b80d8 --- AST/Expr.cpp | 3 ++- CodeGen/CGDecl.cpp | 26 +++++++++++++++++++++++++- CodeGen/CodeGenFunction.h | 1 + Sema/Sema.h | 3 ++- Sema/SemaDecl.cpp | 21 ++++++++++++++++----- test/Sema/static-init.c | 3 +++ 6 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 test/Sema/static-init.c diff --git a/AST/Expr.cpp b/AST/Expr.cpp index 5cd56ccbaf..1b989a4a61 100644 --- a/AST/Expr.cpp +++ b/AST/Expr.cpp @@ -365,7 +365,8 @@ bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const { case IntegerLiteralClass: case CharacterLiteralClass: case ImaginaryLiteralClass: - case TypesCompatibleExprClass: + case TypesCompatibleExprClass: + case CXXBoolLiteralExprClass: break; case CallExprClass: { const CallExpr *CE = cast(this); diff --git a/CodeGen/CGDecl.cpp b/CodeGen/CGDecl.cpp index 2af4127231..75a32854ab 100644 --- a/CodeGen/CGDecl.cpp +++ b/CodeGen/CGDecl.cpp @@ -12,7 +12,9 @@ //===----------------------------------------------------------------------===// #include "CodeGenFunction.h" +#include "CodeGenModule.h" #include "clang/AST/AST.h" +#include "llvm/GlobalVariable.h" #include "llvm/Type.h" using namespace clang; using namespace CodeGen; @@ -50,7 +52,7 @@ void CodeGenFunction::EmitEnumConstantDecl(const EnumConstantDecl &D) { void CodeGenFunction::EmitBlockVarDecl(const BlockVarDecl &D) { switch (D.getStorageClass()) { case VarDecl::Static: - assert(0 && "FIXME: local static vars not implemented yet"); + return EmitStaticBlockVarDecl(D); case VarDecl::Extern: assert(0 && "FIXME: should call up to codegenmodule"); default: @@ -62,6 +64,28 @@ void CodeGenFunction::EmitBlockVarDecl(const BlockVarDecl &D) { } } +void CodeGenFunction::EmitStaticBlockVarDecl(const BlockVarDecl &D) { + QualType Ty = D.getCanonicalType(); + assert(Ty->isConstantSizeType(getContext()) && "VLAs can't be static"); + + llvm::Value *&DMEntry = LocalDeclMap[&D]; + assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); + + const llvm::Type *LTy = ConvertType(Ty); + llvm::Constant *Init = 0; + if (D.getInit() == 0) { + Init = llvm::Constant::getNullValue(LTy); + } else + assert(0 && "FIXME: Support initializers"); + + + DMEntry = + new llvm::GlobalVariable(LTy, false, + llvm::GlobalValue::InternalLinkage, + Init, D.getName(), &CGM.getModule()); + +} + /// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a /// variable declaration with auto, register, or no storage class specifier. /// These turn into simple stack objects. diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h index b48280cd31..abb03ab9c0 100644 --- a/CodeGen/CodeGenFunction.h +++ b/CodeGen/CodeGenFunction.h @@ -304,6 +304,7 @@ public: void EmitEnumConstantDecl(const EnumConstantDecl &D); void EmitBlockVarDecl(const BlockVarDecl &D); void EmitLocalBlockVarDecl(const BlockVarDecl &D); + void EmitStaticBlockVarDecl(const BlockVarDecl &D); void EmitParmDecl(const ParmVarDecl &D, llvm::Value *Arg); //===--------------------------------------------------------------------===// diff --git a/Sema/Sema.h b/Sema/Sema.h index bb5d07fd6d..abe9250f04 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -623,7 +623,8 @@ private: /// type checking declaration initializers (C99 6.7.8) bool CheckInitializer(Expr *&simpleInit_or_initList, QualType &declType, bool isStatic); - bool CheckSingleInitializer(Expr *&simpleInit, QualType declType); + bool CheckSingleInitializer(Expr *&simpleInit, bool isStatic, + QualType declType); bool CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot, bool isStatic, QualType ElementType); void CheckVariableInitList(QualType DeclType, InitListExpr *IList, diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 9b2800f047..390caafdc0 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -299,9 +299,20 @@ Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { return 0; } -bool Sema::CheckSingleInitializer(Expr *&Init, QualType DeclType) { +bool Sema::CheckSingleInitializer(Expr *&Init, bool isStatic, + QualType DeclType) { + SourceLocation loc; + + // FIXME: Remove the isReferenceType check and handle assignment + // to a reference. + if (isStatic && !DeclType->isReferenceType() && + !Init->isConstantExpr(Context, &loc)) { // C99 6.7.8p4. + Diag(loc, diag::err_init_element_not_constant, Init->getSourceRange()); + return true; + } + AssignmentCheckResult result; - SourceLocation loc = Init->getLocStart(); + loc = Init->getLocStart(); // Get the type before calling CheckSingleAssignmentConstraints(), since // it can promote the expression. QualType rhsType = Init->getType(); @@ -357,7 +368,7 @@ bool Sema::CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot, if (isStatic && !expr->isConstantExpr(Context, &loc)) { // C99 6.7.8p4. Diag(loc, diag::err_init_element_not_constant, expr->getSourceRange()); return true; - } else if (CheckSingleInitializer(expr, ElementType)) { + } else if (CheckSingleInitializer(expr, isStatic, ElementType)) { return true; // types weren't compatible. } if (savExpr != expr) // The type was promoted, update initializer list. @@ -437,8 +448,8 @@ void Sema::CheckConstantInitList(QualType DeclType, InitListExpr *IList, bool Sema::CheckInitializer(Expr *&Init, QualType &DeclType, bool isStatic) { InitListExpr *InitList = dyn_cast(Init); if (!InitList) - return CheckSingleInitializer(Init, DeclType); - + return CheckSingleInitializer(Init, isStatic, DeclType); + // We have an InitListExpr, make sure we set the type. Init->setType(DeclType); diff --git a/test/Sema/static-init.c b/test/Sema/static-init.c new file mode 100644 index 0000000000..e710973700 --- /dev/null +++ b/test/Sema/static-init.c @@ -0,0 +1,3 @@ +// RUN: clang -fsyntax-only -verify %s +static int f = 10; +static int b = f; // expected-error {{initializer element is not constant}}