r363087 - For DR712: store on a MemberExpr whether it constitutes an odr-use.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 11 10:50:36 PDT 2019
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) {
More information about the cfe-commits
mailing list