зеркало из 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.
|
// 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}}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче