Revert "PR45083: Mark statement expressions as being dependent if they contain"

This reverts commit 2669e41b7b, which was
pushed by mistake.
This commit is contained in:
Richard Smith 2020-03-09 17:03:56 -07:00
parent 51fab8f36f
commit 6333cc2a12
3 changed files with 10 additions and 89 deletions

View File

@ -3959,8 +3959,14 @@ class StmtExpr : public Expr {
Stmt *SubStmt;
SourceLocation LParenLoc, RParenLoc;
public:
StmtExpr(CompoundStmt *SubStmt, QualType T,
SourceLocation LParen, SourceLocation RParen);
// FIXME: Does type-dependence need to be computed differently?
// FIXME: Do we need to compute instantiation instantiation-dependence for
// statements? (ugh!)
StmtExpr(CompoundStmt *substmt, QualType T,
SourceLocation lp, SourceLocation rp) :
Expr(StmtExprClass, T, VK_RValue, OK_Ordinary,
T->isDependentType(), false, false, false),
SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
/// Build an empty statement expression.
explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { }

View File

@ -4101,53 +4101,6 @@ void ExtVectorElementExpr::getEncodedElementAccess(
}
}
StmtExpr::StmtExpr(CompoundStmt *SubStmt, QualType T, SourceLocation LParen,
SourceLocation RParen)
: Expr(StmtExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(),
false, false, false),
SubStmt(SubStmt), LParenLoc(LParen), RParenLoc(RParen) {
llvm::SmallVector<Stmt*, 16> Queue(1, SubStmt);
while (!Queue.empty()) {
Stmt *S = Queue.pop_back_val();
if (!S)
continue;
// If any subexpression is dependent, the statement expression is dependent
// in the same way.
if (Expr *E = dyn_cast<Expr>(S)) {
addDependence(E->getDependence());
continue;
}
// FIXME: Need to properly compute whether DeclStmts contain unexpanded
// parameter packs.
if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
for (Decl *D : DS->decls()) {
// If any contained declaration is in a dependent context, then it
// needs to be instantiated, so the statement expression itself is
// instantiation-dependent.
//
// Note that we don't need to worry about the case where the context is
// non-dependent but contains dependent entities here (eg, inside a
// variable template or alias template): that can only happen at file
// scope, where statement expressions are prohibited.
if (D->getLexicalDeclContext()->isDependentContext())
addDependence(ExprDependence::Instantiation);
// If any contained variable declaration has a dependent type, we can't
// evaluate that declaration.
if (auto *VD = dyn_cast<VarDecl>(D))
if (VD->getType()->isDependentType())
addDependence(ExprDependence::Value);
}
}
// Recurse to substatements.
// FIXME: Should we skip the unchosen side of 'if constexpr' if known?
Queue.insert(Queue.end(), S->child_begin(), S->child_end());
}
}
ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args,
QualType Type, SourceLocation BLoc,
SourceLocation RP)

View File

@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s
// RUN: %clang_cc1 -fsyntax-only -verify %s
// expected-no-diagnostics
// PR5908
template <typename Iterator>
@ -107,42 +108,3 @@ namespace PR18152 {
};
template struct A<0>;
}
template<typename T> void stmt_expr_1() {
// GCC doesn't check this: it appears to treat statement-expressions as being
// value-dependent if they appear in a dependent context, regardless of their
// contents.
static_assert( ({ false; }), "" ); // expected-error {{failed}}
}
void stmt_expr_2() {
static_assert( ({ false; }), "" ); // expected-error {{failed}}
}
namespace PR45083 {
struct A { bool x; };
template<typename> struct B : A {
void f() {
const int n = ({ if (x) {} 0; });
}
};
template void B<int>::f();
template<typename> void f() {
decltype(({})) x; // expected-error {{incomplete type}}
}
template void f<int>();
template<typename> auto g() {
auto c = [](auto, int) -> decltype(({})) {};
using T = decltype(c(0.0, 0));
using T = void;
return c(0, 0);
}
using U = decltype(g<int>()); // expected-note {{previous}}
using U = float; // expected-error {{different types ('float' vs 'decltype(g<int>())' (aka 'void'))}}
void h(auto a, decltype(g<char>())*) {} // expected-note {{previous}}
void h(auto a, void*) {} // expected-error {{redefinition}}
}