aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-02-26 03:58:54 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-02-26 03:58:54 +0000
commitbc592e6e56f16f5d06fc70c3931f7d9d33f7b3cd (patch)
tree9b6126831719a3bdc3aa38d154dc5c02da4ee5e2
parent65100792a69a16895bd80f1d639b99e7ad903386 (diff)
Fix for PR3663/3669: use TryToFixInvalidVariablyModifiedType for
variable declarations where applicable. Also, a few fixes to TryToFixInvalidVariablyModifiedType for issues that this exposed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65500 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp70
-rw-r--r--test/Sema/vla.c4
2 files changed, 40 insertions, 34 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c312195972..981d0f9bd5 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1334,14 +1334,18 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
}
const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
- if (!VLATy) return QualType();
+ if (!VLATy)
+ return QualType();
+ // FIXME: We should probably handle this case
+ if (VLATy->getElementType()->isVariablyModifiedType())
+ return QualType();
Expr::EvalResult EvalResult;
if (!VLATy->getSizeExpr() ||
- !VLATy->getSizeExpr()->Evaluate(EvalResult, Context))
+ !VLATy->getSizeExpr()->Evaluate(EvalResult, Context) ||
+ !EvalResult.Val.isInt())
return QualType();
-
- assert(EvalResult.Val.isInt() && "Size expressions must be integers!");
+
llvm::APSInt &Res = EvalResult.Val.getInt();
if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned()))
return Context.getConstantArrayType(VLATy->getElementType(),
@@ -2731,43 +2735,43 @@ Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
if (!IDecl)
continue;
QualType T = IDecl->getType();
-
- if (T->isVariableArrayType()) {
- const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
-
- // FIXME: This won't give the correct result for
- // int a[10][n];
- SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
- if (IDecl->isFileVarDecl()) {
- Diag(IDecl->getLocation(), diag::err_vla_decl_in_file_scope) <<
- SizeRange;
-
+
+ bool isIllegalVLA = T->isVariableArrayType() && IDecl->hasGlobalStorage();
+ bool isIllegalVM = T->isVariablyModifiedType() && IDecl->hasLinkage();
+ if (isIllegalVLA || isIllegalVM) {
+ bool SizeIsNegative;
+ QualType FixedTy =
+ TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
+ if (!FixedTy.isNull()) {
+ Diag(IDecl->getLocation(), diag::warn_illegal_constant_array_size);
+ IDecl->setType(FixedTy);
+ } else if (T->isVariableArrayType()) {
IDecl->setInvalidDecl();
- } else {
- // C99 6.7.5.2p2: If an identifier is declared to be an object with
- // static storage duration, it shall not have a variable length array.
- if (IDecl->getStorageClass() == VarDecl::Static) {
+
+ const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
+ // FIXME: This won't give the correct result for
+ // int a[10][n];
+ SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange();
+
+ if (IDecl->isFileVarDecl())
+ Diag(IDecl->getLocation(), diag::err_vla_decl_in_file_scope)
+ << SizeRange;
+ else if (IDecl->getStorageClass() == VarDecl::Static)
Diag(IDecl->getLocation(), diag::err_vla_decl_has_static_storage)
<< SizeRange;
- IDecl->setInvalidDecl();
- } else if (IDecl->getStorageClass() == VarDecl::Extern) {
+ else
Diag(IDecl->getLocation(), diag::err_vla_decl_has_extern_linkage)
- << SizeRange;
- IDecl->setInvalidDecl();
- }
- }
- } else if (T->isVariablyModifiedType()) {
- if (IDecl->isFileVarDecl()) {
- Diag(IDecl->getLocation(), diag::err_vm_decl_in_file_scope);
- IDecl->setInvalidDecl();
+ << SizeRange;
} else {
- if (IDecl->getStorageClass() == VarDecl::Extern) {
+ IDecl->setInvalidDecl();
+
+ if (IDecl->isFileVarDecl())
+ Diag(IDecl->getLocation(), diag::err_vm_decl_in_file_scope);
+ else
Diag(IDecl->getLocation(), diag::err_vm_decl_has_extern_linkage);
- IDecl->setInvalidDecl();
- }
}
}
-
+
// Block scope. C99 6.7p7: If an identifier for an object is declared with
// no linkage (C99 6.2.2p6), the type for the object shall be complete...
if (IDecl->isBlockVarDecl() &&
diff --git a/test/Sema/vla.c b/test/Sema/vla.c
index 30c20bd93b..74ac134653 100644
--- a/test/Sema/vla.c
+++ b/test/Sema/vla.c
@@ -1,4 +1,4 @@
-// RUN: clang %s -verify -fsyntax-only
+// RUN: clang %s -verify -fsyntax-only -pedantic
int test1() {
typedef int x[test1()]; // vla
@@ -41,3 +41,5 @@ void f3()
static int (*d)[i];
}
+// PR3663
+static const unsigned array[((2 * (int)((((4) / 2) + 1.0/3.0) * (4) - 1e-8)) + 1)]; // expected-warning {{size of static array must be an integer constant expression}}