};
//===----------------------------------------------------------------------===//
+// Wrapper Expressions.
+//===----------------------------------------------------------------------===//
+
+/// FullExpr - Represents a "full-expression" node.
+class FullExpr : public Expr {
+protected:
+ Stmt *SubExpr;
+
+ FullExpr(StmtClass SC, Expr *subexpr)
+ : Expr(SC, subexpr->getType(),
+ subexpr->getValueKind(), subexpr->getObjectKind(),
+ subexpr->isTypeDependent(), subexpr->isValueDependent(),
+ subexpr->isInstantiationDependent(),
+ subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr) {}
+ FullExpr(StmtClass SC, EmptyShell Empty)
+ : Expr(SC, Empty) {}
+public:
+ const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+ Expr *getSubExpr() { return cast<Expr>(SubExpr); }
+
+ /// As with any mutator of the AST, be very careful when modifying an
+ /// existing AST to preserve its invariants.
+ void setSubExpr(Expr *E) { SubExpr = E; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstFullExprConstant &&
+ T->getStmtClass() <= lastFullExprConstant;
+ }
+};
+
+/// ConstantExpr - An expression that occurs in a constant context.
+struct ConstantExpr : public FullExpr {
+ ConstantExpr(Expr *subexpr)
+ : FullExpr(ConstantExprClass, subexpr) {}
+
+ /// Build an empty constant expression wrapper.
+ explicit ConstantExpr(EmptyShell Empty)
+ : FullExpr(ConstantExprClass, Empty) {}
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return SubExpr->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubExpr->getEndLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ConstantExprClass;
+ }
+
+ // Iterators
+ child_range children() { return child_range(&SubExpr, &SubExpr+1); }
+ const_child_range children() const {
+ return const_child_range(&SubExpr, &SubExpr + 1);
+ }
+};
+
+//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
/// potentially-evaluated block literal. The lifetime of a block
/// literal is the extent of the enclosing scope.
class ExprWithCleanups final
- : public Expr,
+ : public FullExpr,
private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> {
public:
/// The type of objects that are kept in the cleanup.
friend class ASTStmtReader;
friend TrailingObjects;
- Stmt *SubExpr;
-
ExprWithCleanups(EmptyShell, unsigned NumObjects);
ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> Objects);
return getObjects()[i];
}
- Expr *getSubExpr() { return cast<Expr>(SubExpr); }
- const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
-
bool cleanupsHaveSideEffects() const {
return ExprWithCleanupsBits.CleanupsHaveSideEffects;
}
- /// As with any mutator of the AST, be very careful
- /// when modifying an existing AST to preserve its invariants.
- void setSubExpr(Expr *E) { SubExpr = E; }
-
SourceLocation getBeginLoc() const LLVM_READONLY {
return SubExpr->getBeginLoc();
}
DEF_TRAVERSE_STMT(SwitchStmt, {})
DEF_TRAVERSE_STMT(WhileStmt, {})
+DEF_TRAVERSE_STMT(ConstantExpr, {})
+
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
def GenericSelectionExpr : DStmt<Expr>;
def PseudoObjectExpr : DStmt<Expr>;
+// Wrapper expressions
+def FullExpr : DStmt<Expr, 1>;
+def ConstantExpr : DStmt<FullExpr>;
+
// Atomic expressions
def AtomicExpr : DStmt<Expr>;
def CXXConstructExpr : DStmt<Expr>;
def CXXInheritedCtorInitExpr : DStmt<Expr>;
def CXXBindTemporaryExpr : DStmt<Expr>;
-def ExprWithCleanups : DStmt<Expr>;
+def ExprWithCleanups : DStmt<FullExpr>;
def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
def CXXUnresolvedConstructExpr : DStmt<Expr>;
def CXXDependentScopeMemberExpr : DStmt<Expr>;
/// A MS-style AsmStmt record.
STMT_MSASM,
+ /// A constant expression context.
+ EXPR_CONSTANT,
+
/// A PredefinedExpr record.
EXPR_PREDEFINED,
return cast<Expr>(getEssential((Stmt*)E));
}
static Stmt *getEssential(Stmt *S) {
- if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S))
- S = EWC->getSubExpr();
+ if (FullExpr *FE = dyn_cast<FullExpr>(S))
+ S = FE->getSubExpr();
if (Expr *E = dyn_cast<Expr>(S))
S = E->IgnoreParenCasts();
return S;
}
while (OuterS && (isa<ParenExpr>(OuterS) ||
isa<CastExpr>(OuterS) ||
- isa<ExprWithCleanups>(OuterS)));
+ isa<FullExpr>(OuterS)));
if (!OuterS)
return std::make_pair(prevStmt, nextStmt);
RecContainer = StmtE;
Rec = Init->IgnoreParenImpCasts();
- if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Rec))
- Rec = EWC->getSubExpr()->IgnoreParenImpCasts();
+ if (FullExpr *FE = dyn_cast<FullExpr>(Rec))
+ Rec = FE->getSubExpr()->IgnoreParenImpCasts();
RecRange = Rec->getSourceRange();
if (SM.isMacroArgExpansion(RecRange.getBegin()))
RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin()));
Stmt *parent = E;
do {
parent = StmtMap->getParentIgnoreParenImpCasts(parent);
- } while (parent && isa<ExprWithCleanups>(parent));
+ } while (parent && isa<FullExpr>(parent));
if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
std::string note = "remove the cast and change return type of function "
bool trans::isPlusOne(const Expr *E) {
if (!E)
return false;
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(E))
- E = EWC->getSubExpr();
+ if (const FullExpr *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
if (const ObjCMessageExpr *
ME = dyn_cast<ObjCMessageExpr>(E->IgnoreParenCasts()))
"Default argument is not yet instantiated!");
Expr *Arg = getInit();
- if (auto *E = dyn_cast_or_null<ExprWithCleanups>(Arg))
+ if (auto *E = dyn_cast_or_null<FullExpr>(Arg))
return E->getSubExpr();
return Arg;
// These never have a side-effect.
return false;
+ case ConstantExprClass:
+ // FIXME: Move this into the "return false;" block above.
+ return cast<ConstantExpr>(this)->getSubExpr()->HasSideEffects(
+ Ctx, IncludePossibleEffects);
+
case CallExprClass:
case CXXOperatorCallExprClass:
case CXXMemberCallExprClass:
ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
bool CleanupsHaveSideEffects,
ArrayRef<CleanupObject> objects)
- : Expr(ExprWithCleanupsClass, subexpr->getType(),
- subexpr->getValueKind(), subexpr->getObjectKind(),
- subexpr->isTypeDependent(), subexpr->isValueDependent(),
- subexpr->isInstantiationDependent(),
- subexpr->containsUnexpandedParameterPack()),
- SubExpr(subexpr) {
+ : FullExpr(ExprWithCleanupsClass, subexpr) {
ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects;
ExprWithCleanupsBits.NumObjects = objects.size();
for (unsigned i = 0, e = objects.size(); i != e; ++i)
}
ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)
- : Expr(ExprWithCleanupsClass, empty) {
+ : FullExpr(ExprWithCleanupsClass, empty) {
ExprWithCleanupsBits.NumObjects = numObjects;
}
case Expr::DesignatedInitUpdateExprClass:
return Cl::CL_PRValue;
+ case Expr::ConstantExprClass:
+ return ClassifyInternal(Ctx, cast<ConstantExpr>(E)->getSubExpr());
+
// Next come the complicated cases.
case Expr::SubstNonTypeTemplateParmExprClass:
return ClassifyInternal(Ctx,
// If we're doing a variable assignment from e.g. malloc(N), there will
// probably be a cast of some kind. In exotic cases, we might also see a
// top-level ExprWithCleanups. Ignore them either way.
- if (const auto *EC = dyn_cast<ExprWithCleanups>(E))
- E = EC->getSubExpr()->IgnoreParens();
+ if (const auto *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr()->IgnoreParens();
if (const auto *Cast = dyn_cast<CastExpr>(E))
E = Cast->getSubExpr()->IgnoreParens();
return
CheckICE(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(), Ctx);
+ case Expr::ConstantExprClass:
+ return CheckICE(cast<ConstantExpr>(E)->getSubExpr(), Ctx);
+
case Expr::ParenExprClass:
return CheckICE(cast<ParenExpr>(E)->getSubExpr(), Ctx);
case Expr::GenericSelectionExprClass:
case Expr::CXXInheritedCtorInitExprClass:
llvm_unreachable("unexpected statement kind");
+ case Expr::ConstantExprClass:
+ E = cast<ConstantExpr>(E)->getSubExpr();
+ goto recurse;
+
// FIXME: invent manglings for all these.
case Expr::BlockExprClass:
case Expr::ChooseExprClass:
// Ignore parents that don't guarantee consumption.
while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P) ||
- isa<ExprWithCleanups>(P))) {
+ isa<FullExpr>(P))) {
DirectChild = P;
P = getParent(P);
}
while (s != lasts) {
lasts = s;
- if (auto *ewc = dyn_cast<ExprWithCleanups>(s))
- s = ewc->getSubExpr();
+ if (auto *fe = dyn_cast<FullExpr>(s))
+ s = fe->getSubExpr();
if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
s = mte->GetTemporaryExpr();
// Expr printing methods.
//===----------------------------------------------------------------------===//
+void StmtPrinter::VisitConstantExpr(ConstantExpr *Node) {
+ PrintExpr(Node->getSubExpr());
+}
+
void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
if (const auto *OCED = dyn_cast<OMPCapturedExprDecl>(Node->getDecl())) {
OCED->getInit()->IgnoreImpCasts()->printPretty(OS, nullptr, Policy);
VisitStmt(S);
}
+void StmtProfiler::VisitConstantExpr(const ConstantExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitDeclRefExpr(const DeclRefExpr *S) {
VisitExpr(S);
if (!Canonical)
while (S) {
if (const Expr *Ex = dyn_cast<Expr>(S))
S = Ex->IgnoreParens();
- if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) {
- S = EWC->getSubExpr();
+ if (const FullExpr *FE = dyn_cast<FullExpr>(S)) {
+ S = FE->getSubExpr();
continue;
}
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) {
return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
else if (const auto *CE = dyn_cast<ImplicitCastExpr>(Cond))
return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
- else if (const auto *EWC = dyn_cast<ExprWithCleanups>(Cond))
- return getTrylockCallExpr(EWC->getSubExpr(), C, Negate);
+ else if (const auto *FE = dyn_cast<FullExpr>(Cond))
+ return getTrylockCallExpr(FE->getSubExpr(), C, Negate);
else if (const auto *DRE = dyn_cast<DeclRefExpr>(Cond)) {
const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
return getTrylockCallExpr(E, C, Negate);
cast<BinaryConditionalOperator>(S), Ctx);
// We treat these as no-ops
+ case Stmt::ConstantExprClass:
+ return translate(cast<ConstantExpr>(S)->getSubExpr(), Ctx);
case Stmt::ParenExprClass:
return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx);
case Stmt::ExprWithCleanupsClass:
/// Enter a full-expression with a non-trivial number of objects to
/// clean up. This is in this file because, at the moment, the only
/// kind of cleanup object is a BlockDecl*.
-void CodeGenFunction::enterNonTrivialFullExpression(const ExprWithCleanups *E) {
- assert(E->getNumObjects() != 0);
- for (const ExprWithCleanups::CleanupObject &C : E->getObjects())
- enterBlockScope(*this, C);
+void CodeGenFunction::enterNonTrivialFullExpression(const FullExpr *E) {
+ if (const auto EWC = dyn_cast<ExprWithCleanups>(E)) {
+ assert(EWC->getNumObjects() != 0);
+ for (const ExprWithCleanups::CleanupObject &C : EWC->getObjects())
+ enterBlockScope(*this, C);
+ }
}
/// Find the layout for the given block in a linked list and remove it.
// If we're emitting a value with lifetime, we have to do the
// initialization *before* we leave the cleanup scopes.
- if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(init)) {
- enterFullExpression(ewc);
- init = ewc->getSubExpr();
+ if (const FullExpr *fe = dyn_cast<FullExpr>(init)) {
+ enterFullExpression(fe);
+ init = fe->getSubExpr();
}
CodeGenFunction::RunCleanupsScope Scope(*this);
// exception to our over-conservative rules about not jumping to
// statements following block literals with non-trivial cleanups.
RunCleanupsScope cleanupScope(*this);
- if (const ExprWithCleanups *cleanups =
- dyn_cast_or_null<ExprWithCleanups>(RV)) {
- enterFullExpression(cleanups);
- RV = cleanups->getSubExpr();
+ if (const FullExpr *fe = dyn_cast_or_null<FullExpr>(RV)) {
+ enterFullExpression(fe);
+ RV = fe->getSubExpr();
}
// FIXME: Clean this up by using an LValue for ReturnTemp,
}
const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(CS))
- enterFullExpression(EWC);
+ if (const auto *FE = dyn_cast<FullExpr>(CS))
+ enterFullExpression(FE);
// Processing for statements under 'atomic capture'.
if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
for (const Stmt *C : Compound->body()) {
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(C))
- enterFullExpression(EWC);
+ if (const auto *FE = dyn_cast<FullExpr>(C))
+ enterFullExpression(FE);
}
}
void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp);
- void enterFullExpression(const ExprWithCleanups *E) {
- if (E->getNumObjects() == 0) return;
+ void enterFullExpression(const FullExpr *E) {
+ if (const auto *EWC = dyn_cast<ExprWithCleanups>(E))
+ if (EWC->getNumObjects() == 0)
+ return;
enterNonTrivialFullExpression(E);
}
- void enterNonTrivialFullExpression(const ExprWithCleanups *E);
+ void enterNonTrivialFullExpression(const FullExpr *E);
void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true);
// [Can throw] if in a potentially-evaluated context the expression would
// contain:
switch (E->getStmtClass()) {
+ case Expr::ConstantExprClass:
+ return canThrow(cast<ConstantExpr>(E)->getSubExpr());
+
case Expr::CXXThrowExprClass:
// - a potentially evaluated throw-expression
return CT_Can;
do {
Old = Init;
- if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
- Init = EWC->getSubExpr();
+ if (auto *FE = dyn_cast<FullExpr>(Init))
+ Init = FE->getSubExpr();
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
// If this is just redundant braces around an initializer, step over it.
Init = DIE->getExpr();
}
- if (auto *EWC = dyn_cast<ExprWithCleanups>(Init))
- Init = EWC->getSubExpr();
+ if (auto *FE = dyn_cast<FullExpr>(Init))
+ Init = FE->getSubExpr();
// Dig out the expression which constructs the extended temporary.
Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
} // namespace
static const Expr *getExprAsWritten(const Expr *E) {
- if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(E))
- E = ExprTemp->getSubExpr();
+ if (const auto *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
E = MTE->GetTemporaryExpr();
// we might want to make a more specific diagnostic. Check for one of these
// cases now.
unsigned DiagID = diag::warn_unused_expr;
- if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E))
+ if (const FullExpr *Temps = dyn_cast<FullExpr>(E))
E = Temps->getSubExpr();
if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
E = TempExpr->getSubExpr();
/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of
/// potentially integral-promoted expression @p expr.
static QualType GetTypeBeforeIntegralPromotion(const Expr *&E) {
- if (const auto *CleanUps = dyn_cast<ExprWithCleanups>(E))
- E = CleanUps->getSubExpr();
+ if (const auto *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
while (const auto *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
if (ImpCast->getCastKind() != CK_IntegralCast) break;
E = ImpCast->getSubExpr();
if (!Init)
return Init;
- if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
- Init = ExprTemp->getSubExpr();
+ if (auto *FE = dyn_cast<FullExpr>(Init))
+ Init = FE->getSubExpr();
if (auto *AIL = dyn_cast<ArrayInitLoopExpr>(Init))
Init = AIL->getCommonExpr();
//===----------------------------------------------------------------------===//
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformConstantExpr(ConstantExpr *E) {
+ return TransformExpr(E->getSubExpr());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return E;
"Incorrect expression field count");
}
+void ASTStmtReader::VisitConstantExpr(ConstantExpr *E) {
+ VisitExpr(E);
+ E->setSubExpr(Record.readSubExpr());
+}
+
void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
bool HasFunctionName = Record.readInt();
Context, Record[ASTStmtReader::NumStmtFields]);
break;
+ case EXPR_CONSTANT:
+ S = new (Context) ConstantExpr(Empty);
+ break;
+
case EXPR_PREDEFINED:
S = PredefinedExpr::CreateEmpty(
Context,
Record.push_back(E->getObjectKind());
}
+void ASTStmtWriter::VisitConstantExpr(ConstantExpr *E) {
+ VisitExpr(E);
+ Record.AddStmt(E->getSubExpr());
+ Code = serialization::EXPR_CONSTANT;
+}
+
void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
return;
if (const Expr *E = V->getInit()) {
- while (const ExprWithCleanups *exprClean =
- dyn_cast<ExprWithCleanups>(E))
- E = exprClean->getSubExpr();
+ while (const FullExpr *FE = dyn_cast<FullExpr>(E))
+ E = FE->getSubExpr();
// Look through transitive assignments, e.g.:
// int x = y = 0;
if (!S)
break;
- if (isa<ExprWithCleanups>(S) ||
+ if (isa<FullExpr>(S) ||
isa<CXXBindTemporaryExpr>(S) ||
isa<SubstNonTypeTemplateParmExpr>(S))
continue;
E = AE->getBase();
} else if (const auto *PE = dyn_cast<ParenExpr>(E)) {
E = PE->getSubExpr();
- } else if (const auto *EWC = dyn_cast<ExprWithCleanups>(E)) {
- E = EWC->getSubExpr();
+ } else if (const auto *FE = dyn_cast<FullExpr>(E)) {
+ E = FE->getSubExpr();
} else {
// Other arbitrary stuff.
break;
static const Expr *peelOffOuterExpr(const Expr *Ex,
const ExplodedNode *N) {
Ex = Ex->IgnoreParenCasts();
- if (const auto *EWC = dyn_cast<ExprWithCleanups>(Ex))
- return peelOffOuterExpr(EWC->getSubExpr(), N);
+ if (const auto *FE = dyn_cast<FullExpr>(Ex))
+ return peelOffOuterExpr(FE->getSubExpr(), N);
if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex))
return peelOffOuterExpr(OVE->getSourceExpr(), N);
if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) {
case Stmt::ExprWithCleanupsClass:
E = cast<ExprWithCleanups>(E)->getSubExpr();
break;
+ case Stmt::ConstantExprClass:
+ E = cast<ConstantExpr>(E)->getSubExpr();
+ break;
case Stmt::CXXBindTemporaryExprClass:
E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
break;
case Stmt::ObjCPropertyRefExprClass:
llvm_unreachable("These are handled by PseudoObjectExpr");
+ case Expr::ConstantExprClass:
+ return Visit(cast<ConstantExpr>(S)->getSubExpr(), Pred, DstTop);
+
case Stmt::GNUNullExprClass: {
// GNU __null is a pointer-width integer, not an actual pointer.
ProgramStateRef state = Pred->getState();
K = CXCursor_CharacterLiteral;
break;
+ case Stmt::ConstantExprClass:
+ return MakeCXCursor(cast<ConstantExpr>(S)->getSubExpr(),
+ Parent, TU, RegionOfInterest);
+
case Stmt::ParenExprClass:
K = CXCursor_ParenExpr;
break;