aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AST/Expr.cpp3
-rw-r--r--CodeGen/CGDecl.cpp26
-rw-r--r--CodeGen/CodeGenFunction.h1
-rw-r--r--Sema/Sema.h3
-rw-r--r--Sema/SemaDecl.cpp21
-rw-r--r--test/Sema/static-init.c3
6 files changed, 49 insertions, 8 deletions
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<CallExpr>(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<InitListExpr>(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}}