diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -130,6 +130,14 @@ /// Construct an empty expression. explicit Expr(StmtClass SC, EmptyShell) : ValueStmt(SC) { } + /// Each concrete expr subclass is expected to compute its dependence and call + /// this in the constructor. + void setDependence(ExprDependence Deps) { + ExprBits.Dependent = static_cast(Deps); + } + friend class ASTImporter; // Sets dependence dircetly. + friend class ASTStmtReader; // Sets dependence dircetly. + public: QualType getType() const { return TR; } void setType(QualType t) { @@ -149,18 +157,6 @@ return static_cast(ExprBits.Dependent); } - /// Each concrete expr subclass is expected to compute its dependence and call - /// this in the constructor. - void setDependence(ExprDependence Deps) { - ExprBits.Dependent = static_cast(Deps); - } - void addDependence(ExprDependence Deps) { - ExprBits.Dependent |= static_cast(Deps); - } - void removeDependence(ExprDependence Deps) { - ExprBits.Dependent &= ~static_cast(Deps); - } - /// isValueDependent - Determines whether this expression is /// value-dependent (C++ [temp.dep.constexpr]). For example, the /// array bound of "Chars" in the following example is @@ -2773,6 +2769,12 @@ /// a non-value-dependent constant parameter evaluating as false. bool isBuiltinAssumeFalse(const ASTContext &Ctx) const; + /// Used by Sema to implement MSVC-compatible delayed name lookup. + /// (Usually Exprs themselves should set dependence). + void markDependentForPostponedNameLookup() { + setDependence(getDependence() | ExprDependence::TypeValueInstantiation); + } + bool isCallToStdMove() const { const FunctionDecl *FD = getDirectCallee(); return getNumArgs() == 1 && FD && FD->isInStdNamespace() && @@ -4384,7 +4386,7 @@ InitExprs[Init] = expr; if (expr) - addDependence(expr->getDependence()); + setDependence(getDependence() | expr->getDependence()); } /// Reserve space for some number of initializers. diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -482,7 +482,25 @@ } ExprDependence clang::computeDependence(MemberExpr *E) { - return E->getBase()->getDependence(); + auto *MemberDecl = E->getMemberDecl(); + auto D = E->getBase()->getDependence(); + if (FieldDecl *FD = dyn_cast(MemberDecl)) { + DeclContext *DC = MemberDecl->getDeclContext(); + // dyn_cast_or_null is used to handle objC variables which do not + // have a declaration context. + CXXRecordDecl *RD = dyn_cast_or_null(DC); + if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC)) { + if (!E->getType()->isDependentType()) + D &= ~ExprDependence::Type; + } + + // Bitfield with value-dependent width is type-dependent. + if (FD && FD->isBitField() && FD->getBitWidth()->isValueDependent()) { + D |= ExprDependence::Type; + } + } + // FIXME: move remaining dependence computation from MemberExpr::Create() + return D; } ExprDependence clang::computeDependence(InitListExpr *E) { diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1497,28 +1497,15 @@ MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, NameInfo, T, VK, OK, NOUR); - if (isa(MemberDecl)) { - DeclContext *DC = MemberDecl->getDeclContext(); - // dyn_cast_or_null is used to handle objC variables which do not - // have a declaration context. - CXXRecordDecl *RD = dyn_cast_or_null(DC); - if (RD && RD->isDependentContext() && RD->isCurrentInstantiation(DC)) { - if (E->isTypeDependent() && !T->isDependentType()) - E->removeDependence(ExprDependence::Type); - } - // Bitfield with value-dependent width is type-dependent. - FieldDecl *FD = dyn_cast(MemberDecl); - if (FD && FD->isBitField() && FD->getBitWidth()->isValueDependent()) - E->addDependence(ExprDependence::Type); - } - + // FIXME: remove remaining dependence computation to computeDependence(). + auto Deps = E->getDependence(); if (HasQualOrFound) { // FIXME: Wrong. We should be looking at the member declaration we found. if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) - E->addDependence(ExprDependence::TypeValueInstantiation); + Deps |= ExprDependence::TypeValueInstantiation; else if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) - E->addDependence(ExprDependence::Instantiation); + Deps |= ExprDependence::Instantiation; E->MemberExprBits.HasQualifierOrFoundDecl = true; @@ -1532,16 +1519,17 @@ TemplateArgs || TemplateKWLoc.isValid(); if (TemplateArgs) { - auto Deps = TemplateArgumentDependence::None; + auto TemplateArgDeps = TemplateArgumentDependence::None; E->getTrailingObjects()->initializeFrom( TemplateKWLoc, *TemplateArgs, - E->getTrailingObjects(), Deps); - if (Deps & TemplateArgumentDependence::Instantiation) - E->addDependence(ExprDependence::Instantiation); + E->getTrailingObjects(), TemplateArgDeps); + if (TemplateArgDeps & TemplateArgumentDependence::Instantiation) + Deps |= ExprDependence::Instantiation; } else if (TemplateKWLoc.isValid()) { E->getTrailingObjects()->initializeFrom( TemplateKWLoc); } + E->setDependence(Deps); return E; } diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp --- a/clang/lib/AST/ExprConcepts.cpp +++ b/clang/lib/AST/ExprConcepts.cpp @@ -175,13 +175,13 @@ RequiresExprBits.IsSatisfied |= Dependent; // FIXME: move the computing dependency logic to ComputeDependence.h if (ContainsUnexpandedParameterPack) - addDependence(ExprDependence::UnexpandedPack); + setDependence(getDependence() | ExprDependence::UnexpandedPack); // FIXME: this is incorrect for cases where we have a non-dependent // requirement, but its parameters are instantiation-dependent. RequiresExpr // should be instantiation-dependent if it has instantiation-dependent // parameters. if (Dependent) - addDependence(ExprDependence::ValueInstantiation); + setDependence(getDependence() | ExprDependence::ValueInstantiation); } RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -12720,7 +12720,7 @@ // base classes. CallExpr *CE = CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_RValue, RParenLoc); - CE->addDependence(ExprDependence::TypeValueInstantiation); + CE->markDependentForPostponedNameLookup(); *Result = CE; return true; }