зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
b76a97e91d
Коммит
aa9c350386
|
@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -4383,6 +4414,9 @@ static bool Evaluate(CCValue &Result, EvalInfo &Info, const Expr *E) {
|
|||
if (!EvaluateRecord(E, LV, Info.CurrentCall->Temporaries[E], Info))
|
||||
return false;
|
||||
Result = Info.CurrentCall->Temporaries[E];
|
||||
} else if (E->getType()->isVoidType()) {
|
||||
if (!EvaluateVoid(E, Info))
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "TypeLocBuilder.h"
|
||||
#include "clang/AST/APValue.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
|
@ -3465,14 +3464,12 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
|
|||
if (VLATy->getElementType()->isVariablyModifiedType())
|
||||
return QualType();
|
||||
|
||||
Expr::EvalResult EvalResult;
|
||||
llvm::APSInt Res;
|
||||
if (!VLATy->getSizeExpr() ||
|
||||
!VLATy->getSizeExpr()->EvaluateAsRValue(EvalResult, Context) ||
|
||||
!EvalResult.Val.isInt())
|
||||
!VLATy->getSizeExpr()->EvaluateAsInt(Res, Context))
|
||||
return QualType();
|
||||
|
||||
// Check whether the array size is negative.
|
||||
llvm::APSInt &Res = EvalResult.Val.getInt();
|
||||
if (Res.isSigned() && Res.isNegative()) {
|
||||
SizeIsNegative = true;
|
||||
return QualType();
|
||||
|
|
|
@ -14,9 +14,9 @@ EVAL_EXPR(8, (_Bool)"asdf")
|
|||
EVAL_EXPR(9, !!&x)
|
||||
EVAL_EXPR(10, ((void)1, 12))
|
||||
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(13, x || 3.0)
|
||||
EVAL_EXPR(13, x || 3.0) // expected-error {{must have a constant size}}
|
||||
|
||||
unsigned int l_19 = 1;
|
||||
EVAL_EXPR(14, (1 ^ l_19) && 1); // expected-error {{fields must have a constant size}}
|
||||
|
|
Загрузка…
Ссылка в новой задаче