summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r--lib/Sema/SemaExpr.cpp153
1 files changed, 127 insertions, 26 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index a8f3ec0ba5..7b3590aeb1 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -15806,6 +15806,32 @@ QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
return DeclRefType;
}
+namespace {
+// Helper to copy the template arguments from a DeclRefExpr or MemberExpr.
+// The produced TemplateArgumentListInfo* points to data stored within this
+// object, so should only be used in contexts where the pointer will not be
+// used after the CopiedTemplateArgs object is destroyed.
+class CopiedTemplateArgs {
+ bool HasArgs;
+ TemplateArgumentListInfo TemplateArgStorage;
+public:
+ template<typename RefExpr>
+ CopiedTemplateArgs(RefExpr *E) : HasArgs(E->hasExplicitTemplateArgs()) {
+ if (HasArgs)
+ E->copyTemplateArgumentsInto(TemplateArgStorage);
+ }
+ operator TemplateArgumentListInfo*()
+#ifdef __has_cpp_attribute
+#if __has_cpp_attribute(clang::lifetimebound)
+ [[clang::lifetimebound]]
+#endif
+#endif
+ {
+ return HasArgs ? &TemplateArgStorage : nullptr;
+ }
+};
+}
+
/// Walk the set of potential results of an expression and mark them all as
/// non-odr-uses if they satisfy the side-conditions of the NonOdrUseReason.
///
@@ -15897,16 +15923,11 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
// Rebuild as a non-odr-use DeclRefExpr.
MarkNotOdrUsed();
- TemplateArgumentListInfo TemplateArgStorage, *TemplateArgs = nullptr;
- if (DRE->hasExplicitTemplateArgs()) {
- DRE->copyTemplateArgumentsInto(TemplateArgStorage);
- TemplateArgs = &TemplateArgStorage;
- }
return DeclRefExpr::Create(
S.Context, DRE->getQualifierLoc(), DRE->getTemplateKeywordLoc(),
DRE->getDecl(), DRE->refersToEnclosingVariableOrCapture(),
DRE->getNameInfo(), DRE->getType(), DRE->getValueKind(),
- DRE->getFoundDecl(), TemplateArgs, NOUR);
+ DRE->getFoundDecl(), CopiedTemplateArgs(DRE), NOUR);
}
case Expr::FunctionParmPackExprClass: {
@@ -15924,52 +15945,107 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
break;
}
- // FIXME: Implement these.
// -- If e is a subscripting operation with an array operand...
- // -- If e is a class member access expression [...] naming a non-static
- // data member...
+ case Expr::ArraySubscriptExprClass: {
+ auto *ASE = cast<ArraySubscriptExpr>(E);
+ Expr *OldBase = ASE->getBase()->IgnoreImplicit();
+ if (!OldBase->getType()->isArrayType())
+ break;
+ ExprResult Base = Rebuild(OldBase);
+ if (!Base.isUsable())
+ return Base;
+ Expr *LHS = ASE->getBase() == ASE->getLHS() ? Base.get() : ASE->getLHS();
+ Expr *RHS = ASE->getBase() == ASE->getRHS() ? Base.get() : ASE->getRHS();
+ SourceLocation LBracketLoc = ASE->getBeginLoc(); // FIXME: Not stored.
+ return S.ActOnArraySubscriptExpr(nullptr, LHS, LBracketLoc, RHS,
+ ASE->getRBracketLoc());
+ }
- // -- If e is a class member access expression naming a static data member,
- // ...
case Expr::MemberExprClass: {
auto *ME = cast<MemberExpr>(E);
+ // -- If e is a class member access expression [...] naming a non-static
+ // data member...
+ if (isa<FieldDecl>(ME->getMemberDecl())) {
+ ExprResult Base = Rebuild(ME->getBase());
+ if (!Base.isUsable())
+ return Base;
+ return MemberExpr::Create(
+ S.Context, Base.get(), ME->isArrow(), ME->getOperatorLoc(),
+ ME->getQualifierLoc(), ME->getTemplateKeywordLoc(),
+ ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(),
+ CopiedTemplateArgs(ME), ME->getType(), ME->getValueKind(),
+ ME->getObjectKind(), ME->isNonOdrUse());
+ }
+
if (ME->getMemberDecl()->isCXXInstanceMember())
- // FIXME: Recurse to the left-hand side.
break;
+ // -- If e is a class member access expression naming a static data member,
+ // ...
if (ME->isNonOdrUse() || IsPotentialResultOdrUsed(ME->getMemberDecl()))
break;
// Rebuild as a non-odr-use MemberExpr.
MarkNotOdrUsed();
- TemplateArgumentListInfo TemplateArgStorage, *TemplateArgs = nullptr;
- if (ME->hasExplicitTemplateArgs()) {
- ME->copyTemplateArgumentsInto(TemplateArgStorage);
- TemplateArgs = &TemplateArgStorage;
- }
return MemberExpr::Create(
S.Context, ME->getBase(), ME->isArrow(), ME->getOperatorLoc(),
ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), ME->getMemberDecl(),
- ME->getFoundDecl(), ME->getMemberNameInfo(), TemplateArgs,
+ ME->getFoundDecl(), ME->getMemberNameInfo(), CopiedTemplateArgs(ME),
ME->getType(), ME->getValueKind(), ME->getObjectKind(), NOUR);
return ExprEmpty();
}
- // FIXME: Implement this.
- // -- If e is a pointer-to-member expression of the form e1 .* e2 ...
+ case Expr::BinaryOperatorClass: {
+ auto *BO = cast<BinaryOperator>(E);
+ Expr *LHS = BO->getLHS();
+ Expr *RHS = BO->getRHS();
+ // -- If e is a pointer-to-member expression of the form e1 .* e2 ...
+ if (BO->getOpcode() == BO_PtrMemD) {
+ ExprResult Sub = Rebuild(LHS);
+ if (!Sub.isUsable())
+ return Sub;
+ LHS = Sub.get();
+ // -- If e is a comma expression, ...
+ } else if (BO->getOpcode() == BO_Comma) {
+ ExprResult Sub = Rebuild(RHS);
+ if (!Sub.isUsable())
+ return Sub;
+ RHS = Sub.get();
+ } else {
+ break;
+ }
+ return S.BuildBinOp(nullptr, BO->getOperatorLoc(), BO->getOpcode(),
+ LHS, RHS);
+ }
// -- If e has the form (e1)...
case Expr::ParenExprClass: {
- auto *PE = dyn_cast<ParenExpr>(E);
+ auto *PE = cast<ParenExpr>(E);
ExprResult Sub = Rebuild(PE->getSubExpr());
if (!Sub.isUsable())
return Sub;
return S.ActOnParenExpr(PE->getLParen(), PE->getRParen(), Sub.get());
}
- // FIXME: Implement these.
// -- If e is a glvalue conditional expression, ...
- // -- If e is a comma expression, ...
+ // We don't apply this to a binary conditional operator. FIXME: Should we?
+ case Expr::ConditionalOperatorClass: {
+ auto *CO = cast<ConditionalOperator>(E);
+ ExprResult LHS = Rebuild(CO->getLHS());
+ if (LHS.isInvalid())
+ return ExprError();
+ ExprResult RHS = Rebuild(CO->getRHS());
+ if (RHS.isInvalid())
+ return ExprError();
+ if (!LHS.isUsable() && !RHS.isUsable())
+ return ExprEmpty();
+ if (!LHS.isUsable())
+ LHS = CO->getLHS();
+ if (!RHS.isUsable())
+ RHS = CO->getRHS();
+ return S.ActOnConditionalOp(CO->getQuestionLoc(), CO->getColonLoc(),
+ CO->getCond(), LHS.get(), RHS.get());
+ }
// [Clang extension]
// -- If e has the form __extension__ e1...
@@ -15988,7 +16064,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
// -- If e has the form _Generic(...), the set of potential results is the
// union of the sets of potential results of the associated expressions.
case Expr::GenericSelectionExprClass: {
- auto *GSE = dyn_cast<GenericSelectionExpr>(E);
+ auto *GSE = cast<GenericSelectionExpr>(E);
SmallVector<Expr *, 4> AssocExprs;
bool AnyChanged = false;
@@ -16016,7 +16092,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
// results is the union of the sets of potential results of the
// second and third subexpressions.
case Expr::ChooseExprClass: {
- auto *CE = dyn_cast<ChooseExpr>(E);
+ auto *CE = cast<ChooseExpr>(E);
ExprResult LHS = Rebuild(CE->getLHS());
if (LHS.isInvalid())
@@ -16039,13 +16115,38 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
// Step through non-syntactic nodes.
case Expr::ConstantExprClass: {
- auto *CE = dyn_cast<ConstantExpr>(E);
+ auto *CE = cast<ConstantExpr>(E);
ExprResult Sub = Rebuild(CE->getSubExpr());
if (!Sub.isUsable())
return Sub;
return ConstantExpr::Create(S.Context, Sub.get());
}
+ // We could mostly rely on the recursive rebuilding to rebuild implicit
+ // casts, but not at the top level, so rebuild them here.
+ case Expr::ImplicitCastExprClass: {
+ auto *ICE = cast<ImplicitCastExpr>(E);
+ // Only step through the narrow set of cast kinds we expect to encounter.
+ // Anything else suggests we've left the region in which potential results
+ // can be found.
+ switch (ICE->getCastKind()) {
+ case CK_NoOp:
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase: {
+ ExprResult Sub = Rebuild(ICE->getSubExpr());
+ if (!Sub.isUsable())
+ return Sub;
+ CXXCastPath Path(ICE->path());
+ return S.ImpCastExprToType(Sub.get(), ICE->getType(), ICE->getCastKind(),
+ ICE->getValueKind(), &Path);
+ }
+
+ default:
+ break;
+ }
+ break;
+ }
+
default:
break;
}