Author: rsmith Date: Tue Jun 11 10:50:36 2019 New Revision: 363087 URL: http://llvm.org/viewvc/llvm-project?rev=363087&view=rev Log: For DR712: store on a MemberExpr whether it constitutes an odr-use.
Modified: cfe/trunk/include/clang/AST/Expr.h cfe/trunk/include/clang/AST/Stmt.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/ASTImporter.cpp cfe/trunk/lib/AST/Expr.cpp cfe/trunk/lib/AST/JSONNodeDumper.cpp cfe/trunk/lib/AST/TextNodeDumper.cpp cfe/trunk/lib/Analysis/BodyFarm.cpp cfe/trunk/lib/CodeGen/CGExpr.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaExprMember.cpp cfe/trunk/lib/Serialization/ASTReaderStmt.cpp cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Modified: cfe/trunk/include/clang/AST/Expr.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Expr.h (original) +++ cfe/trunk/include/clang/AST/Expr.h Tue Jun 11 10:50:36 2019 @@ -2780,7 +2780,8 @@ class MemberExpr final MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo, - QualType T, ExprValueKind VK, ExprObjectKind OK); + QualType T, ExprValueKind VK, ExprObjectKind OK, + NonOdrUseReason NOUR); MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty), Base(), MemberDecl() {} @@ -2792,10 +2793,11 @@ public: DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK, ExprObjectKind OK); + QualType T, ExprValueKind VK, ExprObjectKind OK, + NonOdrUseReason NOUR); /// Create an implicit MemberExpr, with no location, qualifier, template - /// arguments, and so on. + /// arguments, and so on. Suitable only for non-static member access. static MemberExpr *CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, @@ -2803,7 +2805,7 @@ public: return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(), SourceLocation(), MemberDecl, DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()), - DeclarationNameInfo(), nullptr, T, VK, OK); + DeclarationNameInfo(), nullptr, T, VK, OK, NOUR_None); } static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier, @@ -2957,6 +2959,12 @@ public: return LO.AppleKext || !hasQualifier(); } + /// Is this expression a non-odr-use reference, and if so, why? + /// This is only meaningful if the named member is a static member. + NonOdrUseReason isNonOdrUse() const { + return static_cast<NonOdrUseReason>(MemberExprBits.NonOdrUseReason); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == MemberExprClass; } Modified: cfe/trunk/include/clang/AST/Stmt.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/Stmt.h (original) +++ cfe/trunk/include/clang/AST/Stmt.h Tue Jun 11 10:50:36 2019 @@ -479,6 +479,11 @@ protected: /// was resolved from an overloaded set having size greater than 1. unsigned HadMultipleCandidates : 1; + /// Value of type NonOdrUseReason indicating why this MemberExpr does + /// not constitute an odr-use of the named declaration. Meaningful only + /// when naming a static member. + unsigned NonOdrUseReason : 2; + /// This is the location of the -> or . in the expression. SourceLocation OperatorLoc; }; Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Tue Jun 11 10:50:36 2019 @@ -4305,6 +4305,10 @@ public: bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs); + /// If \p D cannot be odr-used in the current expression evaluation context, + /// return a reason explaining why. Otherwise, return NOUR_None. + NonOdrUseReason getNonOdrUseReasonInCurrentContext(ValueDecl *D); + DeclRefExpr *BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS = nullptr); Modified: cfe/trunk/lib/AST/ASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp (original) +++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Jun 11 10:50:36 2019 @@ -7113,10 +7113,11 @@ ExpectedStmt ASTNodeImporter::VisitMembe ResInfo = &ToTAInfo; } - return MemberExpr::Create( - Importer.getToContext(), ToBase, E->isArrow(), ToOperatorLoc, - ToQualifierLoc, ToTemplateKeywordLoc, ToMemberDecl, ToFoundDecl, - ToMemberNameInfo, ResInfo, ToType, E->getValueKind(), E->getObjectKind()); + return MemberExpr::Create(Importer.getToContext(), ToBase, E->isArrow(), + ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc, + ToMemberDecl, ToFoundDecl, ToMemberNameInfo, + ResInfo, ToType, E->getValueKind(), + E->getObjectKind(), E->isNonOdrUse()); } ExpectedStmt Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Tue Jun 11 10:50:36 2019 @@ -1541,7 +1541,8 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTyp MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo, QualType T, - ExprValueKind VK, ExprObjectKind OK) + ExprValueKind VK, ExprObjectKind OK, + NonOdrUseReason NOUR) : Expr(MemberExprClass, T, VK, OK, Base->isTypeDependent(), Base->isValueDependent(), Base->isInstantiationDependent(), Base->containsUnexpandedParameterPack()), @@ -1553,6 +1554,7 @@ MemberExpr::MemberExpr(Expr *Base, bool MemberExprBits.HasQualifierOrFoundDecl = false; MemberExprBits.HasTemplateKWAndArgsInfo = false; MemberExprBits.HadMultipleCandidates = false; + MemberExprBits.NonOdrUseReason = NOUR; MemberExprBits.OperatorLoc = OperatorLoc; } @@ -1561,7 +1563,7 @@ MemberExpr *MemberExpr::Create( NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, DeclAccessPair FoundDecl, DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK, ExprObjectKind OK) { + QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) { bool HasQualOrFound = QualifierLoc || FoundDecl.getDecl() != MemberDecl || FoundDecl.getAccess() != MemberDecl->getAccess(); bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); @@ -1572,8 +1574,8 @@ MemberExpr *MemberExpr::Create( TemplateArgs ? TemplateArgs->size() : 0); void *Mem = C.Allocate(Size, alignof(MemberExpr)); - MemberExpr *E = new (Mem) - MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, NameInfo, T, VK, OK); + MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, + NameInfo, T, VK, OK, NOUR); if (HasQualOrFound) { // FIXME: Wrong. We should be looking at the member declaration we found. Modified: cfe/trunk/lib/AST/JSONNodeDumper.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/JSONNodeDumper.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/AST/JSONNodeDumper.cpp (original) +++ cfe/trunk/lib/AST/JSONNodeDumper.cpp Tue Jun 11 10:50:36 2019 @@ -843,6 +843,12 @@ void JSONNodeDumper::VisitMemberExpr(con JOS.attribute("name", VD && VD->getDeclName() ? VD->getNameAsString() : ""); JOS.attribute("isArrow", ME->isArrow()); JOS.attribute("referencedMemberDecl", createPointerRepresentation(VD)); + switch (ME->isNonOdrUse()) { + case NOUR_None: break; + case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break; + case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break; + case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break; + } } void JSONNodeDumper::VisitCXXNewExpr(const CXXNewExpr *NE) { Modified: cfe/trunk/lib/AST/TextNodeDumper.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TextNodeDumper.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/AST/TextNodeDumper.cpp (original) +++ cfe/trunk/lib/AST/TextNodeDumper.cpp Tue Jun 11 10:50:36 2019 @@ -825,6 +825,12 @@ void TextNodeDumper::VisitUnaryExprOrTyp void TextNodeDumper::VisitMemberExpr(const MemberExpr *Node) { OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl(); dumpPointer(Node->getMemberDecl()); + switch (Node->isNonOdrUse()) { + case NOUR_None: break; + case NOUR_Unevaluated: OS << " non_odr_use_unevaluated"; break; + case NOUR_Constant: OS << " non_odr_use_constant"; break; + case NOUR_Discarded: OS << " non_odr_use_discarded"; break; + } } void TextNodeDumper::VisitExtVectorElementExpr( Modified: cfe/trunk/lib/Analysis/BodyFarm.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/BodyFarm.cpp (original) +++ cfe/trunk/lib/Analysis/BodyFarm.cpp Tue Jun 11 10:50:36 2019 @@ -220,7 +220,7 @@ MemberExpr *ASTMaker::makeMemberExpressi SourceLocation(), MemberDecl, FoundDecl, DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()), /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind, - OK_Ordinary); + OK_Ordinary, NOUR_None); } ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) { Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Jun 11 10:50:36 2019 @@ -1492,17 +1492,11 @@ CodeGenFunction::tryEmitAsConstant(DeclR static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction &CGF, const MemberExpr *ME) { if (auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) { - // FIXME: Copy this from the MemberExpr once we store it there. - NonOdrUseReason NOUR = NOUR_None; - if (VD->getType()->isReferenceType() && - VD->isUsableInConstantExpressions(CGF.getContext())) - NOUR = NOUR_Constant; - // Try to emit static variable member expressions as DREs. return DeclRefExpr::Create( CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD, /*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(), - ME->getType(), ME->getValueKind(), nullptr, nullptr, NOUR); + ME->getType(), ME->getValueKind(), nullptr, nullptr, ME->isNonOdrUse()); } return nullptr; } Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 11 10:50:36 2019 @@ -1785,6 +1785,27 @@ Sema::BuildDeclRefExpr(ValueDecl *D, Qua TemplateArgs); } +NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) { + // A declaration named in an unevaluated operand never constitutes an odr-use. + if (isUnevaluatedContext()) + return NOUR_Unevaluated; + + // C++2a [basic.def.odr]p4: + // A variable x whose name appears as a potentially-evaluated expression e + // is odr-used by e unless [...] x is a reference that is usable in + // constant expressions. + if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (VD->getType()->isReferenceType() && + !(getLangOpts().OpenMP && isOpenMPCapturedDecl(D)) && + VD->isUsableInConstantExpressions(Context)) + return NOUR_Constant; + } + + // All remaining non-variable cases constitute an odr-use. For variables, we + // need to wait and see how the expression is used. + return NOUR_None; +} + /// BuildDeclRefExpr - Build an expression that references a /// declaration that does not require a closure capture. DeclRefExpr * @@ -1797,19 +1818,9 @@ Sema::BuildDeclRefExpr(ValueDecl *D, Qua isa<VarDecl>(D) && NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc()); - NonOdrUseReason NOUR; - if (isUnevaluatedContext()) - NOUR = NOUR_Unevaluated; - else if (isa<VarDecl>(D) && D->getType()->isReferenceType() && - !(getLangOpts().OpenMP && isOpenMPCapturedDecl(D)) && - cast<VarDecl>(D)->isUsableInConstantExpressions(Context)) - NOUR = NOUR_Constant; - else - NOUR = NOUR_None; - - DeclRefExpr *E = DeclRefExpr::Create(Context, NNS, TemplateKWLoc, D, - RefersToCapturedVariable, NameInfo, Ty, - VK, FoundD, TemplateArgs, NOUR); + DeclRefExpr *E = DeclRefExpr::Create( + Context, NNS, TemplateKWLoc, D, RefersToCapturedVariable, NameInfo, Ty, + VK, FoundD, TemplateArgs, getNonOdrUseReasonInCurrentContext(D)); MarkDeclRefReferenced(E); if (getLangOpts().ObjCWeak && isa<VarDecl>(D) && @@ -15924,13 +15935,21 @@ static ExprResult rebuildPotentialResult // FIXME: Recurse to the left-hand side. break; - // FIXME: Track whether a MemberExpr constitutes an odr-use; bail out here - // if we've already marked it. - if (IsPotentialResultOdrUsed(ME->getMemberDecl())) + if (ME->isNonOdrUse() || IsPotentialResultOdrUsed(ME->getMemberDecl())) break; - // FIXME: Rebuild as a non-odr-use MemberExpr. + // 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->getType(), ME->getValueKind(), ME->getObjectKind(), NOUR); return ExprEmpty(); } @@ -16193,11 +16212,19 @@ static void DoMarkVarDeclReferenced(Sema // Sema::CheckLValueToRValueConversionOperand deals with the second part. // FIXME: To get the third bullet right, we need to delay this even for // variables that are not usable in constant expressions. - DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E); + + // If we already know this isn't an odr-use, there's nothing more to do. + if (DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(E)) + if (DRE->isNonOdrUse()) + return; + if (MemberExpr *ME = dyn_cast_or_null<MemberExpr>(E)) + if (ME->isNonOdrUse()) + return; + switch (OdrUse) { case OdrUseContext::None: - assert((!DRE || DRE->isNonOdrUse() == NOUR_Unevaluated) && - "missing non-odr-use marking for unevaluated operand"); + assert((!E || isa<FunctionParmPackExpr>(E)) && + "missing non-odr-use marking for unevaluated decl ref"); break; case OdrUseContext::FormallyOdrUsed: @@ -16206,9 +16233,6 @@ static void DoMarkVarDeclReferenced(Sema break; case OdrUseContext::Used: - // If we already know this isn't an odr-use, there's nothing more to do. - if (DRE && DRE->isNonOdrUse()) - break; // If we might later find that this expression isn't actually an odr-use, // delay the marking. if (E && Var->isUsableInConstantExpressions(SemaRef.Context)) @@ -16218,9 +16242,6 @@ static void DoMarkVarDeclReferenced(Sema break; case OdrUseContext::Dependent: - // If we already know this isn't an odr-use, there's nothing more to do. - if (DRE && DRE->isNonOdrUse()) - break; // If this is a dependent context, we don't need to mark variables as // odr-used, but we may still need to track them for lambda capture. // FIXME: Do we also need to do this inside dependent typeid expressions Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprMember.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprMember.cpp Tue Jun 11 10:50:36 2019 @@ -913,9 +913,10 @@ MemberExpr *Sema::BuildMemberExpr( QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs) { assert((!IsArrow || Base->isRValue()) && "-> base must be a pointer rvalue"); - MemberExpr *E = MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, - TemplateKWLoc, Member, FoundDecl, - MemberNameInfo, TemplateArgs, Ty, VK, OK); + MemberExpr *E = + MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc, + Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty, + VK, OK, getNonOdrUseReasonInCurrentContext(Member)); E->setHadMultipleCandidates(HadMultipleCandidates); MarkMemberReferenced(E); return E; Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Jun 11 10:50:36 2019 @@ -768,6 +768,7 @@ void ASTStmtReader::VisitMemberExpr(Memb E->MemberExprBits.HasQualifierOrFoundDecl = HasQualifier || HasFoundDecl; E->MemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo; E->MemberExprBits.HadMultipleCandidates = Record.readInt(); + E->MemberExprBits.NonOdrUseReason = Record.readInt(); E->MemberExprBits.OperatorLoc = Record.readSourceLocation(); if (HasQualifier || HasFoundDecl) { Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=363087&r1=363086&r2=363087&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Jun 11 10:50:36 2019 @@ -686,6 +686,7 @@ void ASTStmtWriter::VisitMemberExpr(Memb Record.AddSourceLocation(E->getMemberLoc()); Record.push_back(E->isArrow()); Record.push_back(E->hadMultipleCandidates()); + Record.push_back(E->isNonOdrUse()); Record.AddSourceLocation(E->getOperatorLoc()); if (HasFoundDecl) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits