summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/Decl.cpp16
-rw-r--r--clang/lib/AST/Expr.cpp17
-rw-r--r--clang/lib/AST/ExprConstant.cpp13
-rw-r--r--clang/lib/AST/StmtIterator.cpp4
4 files changed, 43 insertions, 7 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 20fe39d0af5..6c620713f76 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -89,6 +89,15 @@ QualType ParmVarDecl::getOriginalType() const {
return getType();
}
+void VarDecl::setInit(ASTContext &C, Expr *I) {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
+ Eval->~EvaluatedStmt();
+ C.Deallocate(Eval);
+ }
+
+ Init = I;
+ }
+
bool VarDecl::isExternC(ASTContext &Context) const {
if (!Context.getLangOptions().CPlusPlus)
return (getDeclContext()->isTranslationUnit() &&
@@ -287,8 +296,13 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
void VarDecl::Destroy(ASTContext& C) {
Expr *Init = getInit();
- if (Init)
+ if (Init) {
Init->Destroy(C);
+ if (EvaluatedStmt *Eval = this->Init.dyn_cast<EvaluatedStmt *>()) {
+ Eval->~EvaluatedStmt();
+ C.Deallocate(Eval);
+ }
+ }
this->~VarDecl();
C.Deallocate((void *)this);
}
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 6711faffe74..aca5efeb163 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1210,8 +1210,21 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// type initialized by an ICE can be used in ICEs.
if (const VarDecl *Dcl =
dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())) {
- if (const Expr *Init = Dcl->getInit())
- return CheckICE(Init, Ctx);
+ if (Dcl->isInitKnownICE()) {
+ // We have already checked whether this subexpression is an
+ // integral constant expression.
+ if (Dcl->isInitICE())
+ return NoDiag();
+ else
+ return ICEDiag(2, E->getLocStart());
+ }
+
+ if (const Expr *Init = Dcl->getInit()) {
+ ICEDiag Result = CheckICE(Init, Ctx);
+ // Cache the result of the ICE test.
+ Dcl->setInitKnownICE(Ctx, Result.Val == 0);
+ return Result;
+ }
}
}
return ICEDiag(2, E->getLocStart());
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 34b01879708..7651884aa60 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -700,8 +700,17 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
// In C, they can also be folded, although they are not ICEs.
if (E->getType().getCVRQualifiers() == QualType::Const) {
if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
- if (const Expr *Init = D->getInit())
- return Visit(const_cast<Expr*>(Init));
+ if (APValue *V = D->getEvaluatedValue())
+ return Success(V->getInt(), E);
+ if (const Expr *Init = D->getInit()) {
+ if (Visit(const_cast<Expr*>(Init))) {
+ // Cache the evaluated value in the variable declaration.
+ D->setEvaluatedValue(Info.Ctx, Result);
+ return true;
+ }
+
+ return false;
+ }
}
}
diff --git a/clang/lib/AST/StmtIterator.cpp b/clang/lib/AST/StmtIterator.cpp
index 20024f513ff..5c22e28894f 100644
--- a/clang/lib/AST/StmtIterator.cpp
+++ b/clang/lib/AST/StmtIterator.cpp
@@ -140,14 +140,14 @@ Stmt*& StmtIteratorBase::GetDeclExpr() const {
if (inDeclGroup()) {
VarDecl* VD = cast<VarDecl>(*DGI);
- return VD->Init;
+ return *VD->getInitAddress();
}
assert (inDecl());
if (VarDecl* VD = dyn_cast<VarDecl>(decl)) {
assert (VD->Init);
- return VD->Init;
+ return *VD->getInitAddress();
}
EnumConstantDecl* ECD = cast<EnumConstantDecl>(decl);
OpenPOWER on IntegriCloud