When folding the size of a global scope VLA to a constant, require the array

bound to not have side effects(!). Add constant-folding support for expressions
of void type, to ensure that we can still fold ((void)0, 1) as an array bound.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146000 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Smith 2011-12-07 00:43:50 +00:00
Родитель b76a97e91d
Коммит aa9c350386
3 изменённых файлов: 38 добавлений и 7 удалений

Просмотреть файл

@ -4332,6 +4332,37 @@ bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
} }
} }
//===----------------------------------------------------------------------===//
// Void expression evaluation, primarily for a cast to void on the LHS of a
// comma operator
//===----------------------------------------------------------------------===//
namespace {
class VoidExprEvaluator
: public ExprEvaluatorBase<VoidExprEvaluator, bool> {
public:
VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {}
bool Success(const CCValue &V, const Expr *e) { return true; }
bool Error(const Expr *E) { return false; }
bool VisitCastExpr(const CastExpr *E) {
switch (E->getCastKind()) {
default:
return ExprEvaluatorBaseTy::VisitCastExpr(E);
case CK_ToVoid:
VisitIgnoredValue(E->getSubExpr());
return true;
}
}
};
} // end anonymous namespace
static bool EvaluateVoid(const Expr *E, EvalInfo &Info) {
assert(E->isRValue() && E->getType()->isVoidType());
return VoidExprEvaluator(Info).Visit(E);
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Top level Expr::EvaluateAsRValue method. // Top level Expr::EvaluateAsRValue method.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -4383,6 +4414,9 @@ static bool Evaluate(CCValue &Result, EvalInfo &Info, const Expr *E) {
if (!EvaluateRecord(E, LV, Info.CurrentCall->Temporaries[E], Info)) if (!EvaluateRecord(E, LV, Info.CurrentCall->Temporaries[E], Info))
return false; return false;
Result = Info.CurrentCall->Temporaries[E]; Result = Info.CurrentCall->Temporaries[E];
} else if (E->getType()->isVoidType()) {
if (!EvaluateVoid(E, Info))
return false;
} else } else
return false; return false;

Просмотреть файл

@ -18,7 +18,6 @@
#include "clang/Sema/Scope.h" #include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/ScopeInfo.h"
#include "TypeLocBuilder.h" #include "TypeLocBuilder.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h" #include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h" #include "clang/AST/CXXInheritance.h"
@ -3465,14 +3464,12 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
if (VLATy->getElementType()->isVariablyModifiedType()) if (VLATy->getElementType()->isVariablyModifiedType())
return QualType(); return QualType();
Expr::EvalResult EvalResult; llvm::APSInt Res;
if (!VLATy->getSizeExpr() || if (!VLATy->getSizeExpr() ||
!VLATy->getSizeExpr()->EvaluateAsRValue(EvalResult, Context) || !VLATy->getSizeExpr()->EvaluateAsInt(Res, Context))
!EvalResult.Val.isInt())
return QualType(); return QualType();
// Check whether the array size is negative. // Check whether the array size is negative.
llvm::APSInt &Res = EvalResult.Val.getInt();
if (Res.isSigned() && Res.isNegative()) { if (Res.isSigned() && Res.isNegative()) {
SizeIsNegative = true; SizeIsNegative = true;
return QualType(); return QualType();

Просмотреть файл

@ -14,9 +14,9 @@ EVAL_EXPR(8, (_Bool)"asdf")
EVAL_EXPR(9, !!&x) EVAL_EXPR(9, !!&x)
EVAL_EXPR(10, ((void)1, 12)) EVAL_EXPR(10, ((void)1, 12))
void g0(void); void g0(void);
EVAL_EXPR(11, (g0(), 12)) // FIXME: This should give an error EVAL_EXPR(11, (g0(), 12)) // expected-error {{must have a constant size}}
EVAL_EXPR(12, 1.0&&2.0) EVAL_EXPR(12, 1.0&&2.0)
EVAL_EXPR(13, x || 3.0) EVAL_EXPR(13, x || 3.0) // expected-error {{must have a constant size}}
unsigned int l_19 = 1; unsigned int l_19 = 1;
EVAL_EXPR(14, (1 ^ l_19) && 1); // expected-error {{fields must have a constant size}} EVAL_EXPR(14, (1 ^ l_19) && 1); // expected-error {{fields must have a constant size}}