r363086 - For DR712: store on a DeclRefExpr whether it constitutes an odr-use.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 11 10:50:32 PDT 2019
Author: rsmith
Date: Tue Jun 11 10:50:32 2019
New Revision: 363086
URL: http://llvm.org/viewvc/llvm-project?rev=363086&view=rev
Log:
For DR712: store on a DeclRefExpr whether it constitutes an odr-use.
Begin restructuring to support the forms of non-odr-use reference
permitted by DR712.
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/Stmt.h
cfe/trunk/include/clang/Basic/Specifiers.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/include/clang/Sema/SemaInternal.h
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/JSONNodeDumper.cpp
cfe/trunk/lib/AST/TextNodeDumper.cpp
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
cfe/trunk/test/AST/ast-dump-color.cpp
cfe/trunk/test/AST/ast-dump-expr-json.c
cfe/trunk/test/AST/ast-dump-expr-json.cpp
cfe/trunk/test/AST/ast-dump-stmt-json.c
cfe/trunk/test/AST/ast-dump-stmt-json.cpp
cfe/trunk/test/PCH/cxx_exprs.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Jun 11 10:50:32 2019
@@ -1226,10 +1226,15 @@ public:
void setInit(Expr *I);
- /// Determine whether this variable's value can be used in a
+ /// Determine whether this variable's value might be usable in a
/// constant expression, according to the relevant language standard.
/// This only checks properties of the declaration, and does not check
/// whether the initializer is in fact a constant expression.
+ bool mightBeUsableInConstantExpressions(ASTContext &C) const;
+
+ /// Determine whether this variable's value can be used in a
+ /// constant expression, according to the relevant language standard,
+ /// including checking whether it was initialized by a constant expression.
bool isUsableInConstantExpressions(ASTContext &C) const;
EvaluatedStmt *ensureEvaluatedStmt() const;
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Jun 11 10:50:32 2019
@@ -1115,7 +1115,7 @@ class DeclRefExpr final
bool RefersToEnlosingVariableOrCapture,
const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs, QualType T,
- ExprValueKind VK);
+ ExprValueKind VK, NonOdrUseReason NOUR);
/// Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) {}
@@ -1128,14 +1128,16 @@ public:
DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture, QualType T,
ExprValueKind VK, SourceLocation L,
- const DeclarationNameLoc &LocInfo = DeclarationNameLoc());
+ const DeclarationNameLoc &LocInfo = DeclarationNameLoc(),
+ NonOdrUseReason NOUR = NOUR_None);
static DeclRefExpr *
Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc,
QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr,
- const TemplateArgumentListInfo *TemplateArgs = nullptr);
+ const TemplateArgumentListInfo *TemplateArgs = nullptr,
+ NonOdrUseReason NOUR = NOUR_None);
static DeclRefExpr *
Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
@@ -1143,7 +1145,8 @@ public:
bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
NamedDecl *FoundD = nullptr,
- const TemplateArgumentListInfo *TemplateArgs = nullptr);
+ const TemplateArgumentListInfo *TemplateArgs = nullptr,
+ NonOdrUseReason NOUR = NOUR_None);
/// Construct an empty declaration reference expression.
static DeclRefExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier,
@@ -1274,6 +1277,11 @@ public:
DeclRefExprBits.HadMultipleCandidates = V;
}
+ /// Is this expression a non-odr-use reference, and if so, why?
+ NonOdrUseReason isNonOdrUse() const {
+ return static_cast<NonOdrUseReason>(DeclRefExprBits.NonOdrUseReason);
+ }
+
/// Does this DeclRefExpr refer to an enclosing local or a captured
/// variable?
bool refersToEnclosingVariableOrCapture() const {
Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Tue Jun 11 10:50:32 2019
@@ -351,6 +351,7 @@ protected:
unsigned HasFoundDecl : 1;
unsigned HadMultipleCandidates : 1;
unsigned RefersToEnclosingVariableOrCapture : 1;
+ unsigned NonOdrUseReason : 2;
/// The location of the declaration name itself.
SourceLocation Loc;
Modified: cfe/trunk/include/clang/Basic/Specifiers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Specifiers.h (original)
+++ cfe/trunk/include/clang/Basic/Specifiers.h Tue Jun 11 10:50:32 2019
@@ -148,6 +148,20 @@ namespace clang {
OK_ObjCSubscript
};
+ /// The reason why a DeclRefExpr does not constitute an odr-use.
+ enum NonOdrUseReason {
+ /// This is an odr-use.
+ NOUR_None = 0,
+ /// This name appears in an unevaluated operand.
+ NOUR_Unevaluated,
+ /// This name appears as a potential result of an lvalue-to-rvalue
+ /// conversion that is a constant expression.
+ NOUR_Constant,
+ /// This name appears as a potential result of a discarded value
+ /// expression.
+ NOUR_Discarded,
+ };
+
/// Describes the kind of template specialization that a
/// particular template specialization declaration represents.
enum TemplateSpecializationKind {
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Jun 11 10:50:32 2019
@@ -4185,7 +4185,7 @@ public:
void MarkCaptureUsedInEnclosingContext(VarDecl *Capture, SourceLocation Loc,
unsigned CapturingScopeIndex);
- void UpdateMarkingForLValueToRValue(Expr *E);
+ ExprResult CheckLValueToRValueConversionOperand(Expr *E);
void CleanupVarDeclMarking();
enum TryCaptureKind {
Modified: cfe/trunk/include/clang/Sema/SemaInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaInternal.h?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/SemaInternal.h (original)
+++ cfe/trunk/include/clang/Sema/SemaInternal.h Tue Jun 11 10:50:32 2019
@@ -38,15 +38,6 @@ FTIHasNonVoidParameters(const Declarator
return FTI.NumParams && !FTIHasSingleVoidParameter(FTI);
}
-// This requires the variable to be non-dependent and the initializer
-// to not be value dependent.
-inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) {
- const VarDecl *DefVD = nullptr;
- return !isa<ParmVarDecl>(Var) &&
- Var->isUsableInConstantExpressions(Context) &&
- Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();
-}
-
// Helper function to check whether D's attributes match current CUDA mode.
// Decls with mismatched attributes and related diagnostics may have to be
// ignored during this CUDA compilation pass.
Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Jun 11 10:50:32 2019
@@ -6189,7 +6189,7 @@ ExpectedStmt ASTNodeImporter::VisitDeclR
auto *ToE = DeclRefExpr::Create(
Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToDecl,
E->refersToEnclosingVariableOrCapture(), ToLocation, ToType,
- E->getValueKind(), ToFoundD, ToResInfo);
+ E->getValueKind(), ToFoundD, ToResInfo, E->isNonOdrUse());
if (E->hadMultipleCandidates())
ToE->setHadMultipleCandidates(true);
return ToE;
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Jun 11 10:50:32 2019
@@ -2245,12 +2245,16 @@ void VarDecl::setInit(Expr *I) {
Init = I;
}
-bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const {
+bool VarDecl::mightBeUsableInConstantExpressions(ASTContext &C) const {
const LangOptions &Lang = C.getLangOpts();
if (!Lang.CPlusPlus)
return false;
+ // Function parameters are never usable in constant expressions.
+ if (isa<ParmVarDecl>(this))
+ return false;
+
// In C++11, any variable of reference type can be used in a constant
// expression if it is initialized by a constant expression.
if (Lang.CPlusPlus11 && getType()->isReferenceType())
@@ -2272,6 +2276,22 @@ bool VarDecl::isUsableInConstantExpressi
return Lang.CPlusPlus11 && isConstexpr();
}
+bool VarDecl::isUsableInConstantExpressions(ASTContext &Context) const {
+ // C++2a [expr.const]p3:
+ // A variable is usable in constant expressions after its initializing
+ // declaration is encountered...
+ const VarDecl *DefVD = nullptr;
+ const Expr *Init = getAnyInitializer(DefVD);
+ if (!Init || Init->isValueDependent())
+ return false;
+ // ... if it is a constexpr variable, or it is of reference type or of
+ // const-qualified integral or enumeration type, ...
+ if (!DefVD->mightBeUsableInConstantExpressions(Context))
+ return false;
+ // ... and its initializer is a constant initializer.
+ return DefVD->checkInitIsICE();
+}
+
/// Convert the initializer for this declaration to the elaborated EvaluatedStmt
/// form, which contains extra information on the evaluated value of the
/// initializer.
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Jun 11 10:50:32 2019
@@ -344,7 +344,8 @@ void DeclRefExpr::computeDependence(cons
DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture, QualType T,
ExprValueKind VK, SourceLocation L,
- const DeclarationNameLoc &LocInfo)
+ const DeclarationNameLoc &LocInfo,
+ NonOdrUseReason NOUR)
: Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
D(D), DNLoc(LocInfo) {
DeclRefExprBits.HasQualifier = false;
@@ -353,6 +354,7 @@ DeclRefExpr::DeclRefExpr(const ASTContex
DeclRefExprBits.HadMultipleCandidates = false;
DeclRefExprBits.RefersToEnclosingVariableOrCapture =
RefersToEnclosingVariableOrCapture;
+ DeclRefExprBits.NonOdrUseReason = NOUR;
DeclRefExprBits.Loc = L;
computeDependence(Ctx);
}
@@ -363,7 +365,7 @@ DeclRefExpr::DeclRefExpr(const ASTContex
bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
- QualType T, ExprValueKind VK)
+ QualType T, ExprValueKind VK, NonOdrUseReason NOUR)
: Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
D(D), DNLoc(NameInfo.getInfo()) {
DeclRefExprBits.Loc = NameInfo.getLoc();
@@ -384,6 +386,7 @@ DeclRefExpr::DeclRefExpr(const ASTContex
= (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0;
DeclRefExprBits.RefersToEnclosingVariableOrCapture =
RefersToEnclosingVariableOrCapture;
+ DeclRefExprBits.NonOdrUseReason = NOUR;
if (TemplateArgs) {
bool Dependent = false;
bool InstantiationDependent = false;
@@ -405,30 +408,27 @@ DeclRefExpr::DeclRefExpr(const ASTContex
DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *D,
+ SourceLocation TemplateKWLoc, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture,
- SourceLocation NameLoc,
- QualType T,
- ExprValueKind VK,
- NamedDecl *FoundD,
- const TemplateArgumentListInfo *TemplateArgs) {
+ SourceLocation NameLoc, QualType T,
+ ExprValueKind VK, NamedDecl *FoundD,
+ const TemplateArgumentListInfo *TemplateArgs,
+ NonOdrUseReason NOUR) {
return Create(Context, QualifierLoc, TemplateKWLoc, D,
RefersToEnclosingVariableOrCapture,
DeclarationNameInfo(D->getDeclName(), NameLoc),
- T, VK, FoundD, TemplateArgs);
+ T, VK, FoundD, TemplateArgs, NOUR);
}
DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ValueDecl *D,
+ SourceLocation TemplateKWLoc, ValueDecl *D,
bool RefersToEnclosingVariableOrCapture,
const DeclarationNameInfo &NameInfo,
- QualType T,
- ExprValueKind VK,
+ QualType T, ExprValueKind VK,
NamedDecl *FoundD,
- const TemplateArgumentListInfo *TemplateArgs) {
+ const TemplateArgumentListInfo *TemplateArgs,
+ NonOdrUseReason NOUR) {
// Filter out cases where the found Decl is the same as the value refenenced.
if (D == FoundD)
FoundD = nullptr;
@@ -443,8 +443,8 @@ DeclRefExpr *DeclRefExpr::Create(const A
void *Mem = Context.Allocate(Size, alignof(DeclRefExpr));
return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
- RefersToEnclosingVariableOrCapture,
- NameInfo, FoundD, TemplateArgs, T, VK);
+ RefersToEnclosingVariableOrCapture, NameInfo,
+ FoundD, TemplateArgs, T, VK, NOUR);
}
DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context,
Modified: cfe/trunk/lib/AST/JSONNodeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/JSONNodeDumper.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/AST/JSONNodeDumper.cpp (original)
+++ cfe/trunk/lib/AST/JSONNodeDumper.cpp Tue Jun 11 10:50:32 2019
@@ -805,6 +805,12 @@ void JSONNodeDumper::VisitDeclRefExpr(co
if (DRE->getDecl() != DRE->getFoundDecl())
JOS.attribute("foundReferencedDecl",
createBareDeclRef(DRE->getFoundDecl()));
+ switch (DRE->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::VisitPredefinedExpr(const PredefinedExpr *PE) {
Modified: cfe/trunk/lib/AST/TextNodeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TextNodeDumper.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TextNodeDumper.cpp (original)
+++ cfe/trunk/lib/AST/TextNodeDumper.cpp Tue Jun 11 10:50:32 2019
@@ -715,6 +715,12 @@ void TextNodeDumper::VisitDeclRefExpr(co
dumpBareDeclRef(Node->getFoundDecl());
OS << ")";
}
+ 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::VisitUnresolvedLookupExpr(
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Jun 11 10:50:32 2019
@@ -1783,8 +1783,8 @@ void CodeGenFunction::EmitAutoVarInit(co
}
llvm::Constant *constant = nullptr;
- if (emission.IsConstantAggregate || D.isConstexpr() ||
- D.isUsableInConstantExpressions(getContext())) {
+ if (emission.IsConstantAggregate ||
+ D.mightBeUsableInConstantExpressions(getContext())) {
assert(!capturedByInit && "constant init contains a capturing block?");
constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D);
if (constant && !constant->isZeroValue() &&
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Tue Jun 11 10:50:32 2019
@@ -1398,7 +1398,7 @@ static bool isConstantEmittableObjectTyp
/// Can we constant-emit a load of a reference to a variable of the
/// given type? This is different from predicates like
-/// Decl::isUsableInConstantExpressions because we do want it to apply
+/// Decl::mightBeUsableInConstantExpressions because we do want it to apply
/// in situations that don't necessarily satisfy the language's rules
/// for this (e.g. C++'s ODR-use rules). For example, we want to able
/// to do this with const float variables even if those variables
@@ -1492,11 +1492,17 @@ 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());
+ ME->getType(), ME->getValueKind(), nullptr, nullptr, NOUR);
}
return nullptr;
}
@@ -2462,12 +2468,11 @@ LValue CodeGenFunction::EmitDeclRefLValu
// A DeclRefExpr for a reference initialized by a constant expression can
// appear without being odr-used. Directly emit the constant initializer.
- const Expr *Init = VD->getAnyInitializer(VD);
+ VD->getAnyInitializer(VD);
const auto *BD = dyn_cast_or_null<BlockDecl>(CurCodeDecl);
- if (Init && !isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType() &&
- VD->isUsableInConstantExpressions(getContext()) &&
- VD->checkInitIsICE() &&
+ if (E->isNonOdrUse() == NOUR_Constant && VD->getType()->isReferenceType() &&
// Do not emit if it is private OpenMP variable.
+ // FIXME: This should be handled in odr-use marking, not here.
!(E->refersToEnclosingVariableOrCapture() &&
((CapturedStmtInfo &&
(LocalDeclMap.count(VD->getCanonicalDecl()) ||
@@ -2489,6 +2494,8 @@ LValue CodeGenFunction::EmitDeclRefLValu
return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl);
}
+ // FIXME: Handle other kinds of non-odr-use DeclRefExprs.
+
// Check for captured variables.
if (E->refersToEnclosingVariableOrCapture()) {
VD = VD->getCanonicalDecl();
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Tue Jun 11 10:50:32 2019
@@ -587,7 +587,7 @@ static bool ShouldRemoveFromUnused(Sema
// warn even if the variable isn't odr-used. (isReferenced doesn't
// precisely reflect that, but it's a decent approximation.)
if (VD->isReferenced() &&
- VD->isUsableInConstantExpressions(SemaRef->Context))
+ VD->mightBeUsableInConstantExpressions(SemaRef->Context))
return true;
if (VarTemplateDecl *Template = VD->getDescribedVarTemplate())
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Tue Jun 11 10:50:32 2019
@@ -5231,15 +5231,10 @@ Sema::SemaBuiltinAtomicOverloaded(ExprRe
}
// Create a new DeclRefExpr to refer to the new decl.
- DeclRefExpr* NewDRE = DeclRefExpr::Create(
- Context,
- DRE->getQualifierLoc(),
- SourceLocation(),
- NewBuiltinDecl,
- /*enclosing*/ false,
- DRE->getLocation(),
- Context.BuiltinFnTy,
- DRE->getValueKind());
+ DeclRefExpr *NewDRE = DeclRefExpr::Create(
+ Context, DRE->getQualifierLoc(), SourceLocation(), NewBuiltinDecl,
+ /*enclosing*/ false, DRE->getLocation(), Context.BuiltinFnTy,
+ DRE->getValueKind(), nullptr, nullptr, DRE->isNonOdrUse());
// Set the callee in the CallExpr.
// FIXME: This loses syntactic information.
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jun 11 10:50:32 2019
@@ -11994,7 +11994,7 @@ void Sema::CheckCompleteVariableDeclarat
for (unsigned I = 0, N = Notes.size(); I != N; ++I)
Diag(Notes[I].first, Notes[I].second);
}
- } else if (var->isUsableInConstantExpressions(Context)) {
+ } else if (var->mightBeUsableInConstantExpressions(Context)) {
// Check whether the initializer of a const variable of integral or
// enumeration type is an ICE now, since we can't tell whether it was
// initialized by a constant expression if we check later.
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 11 10:50:32 2019
@@ -625,15 +625,18 @@ ExprResult Sema::DefaultLvalueConversion
Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(E->getExprLoc(), T);
- UpdateMarkingForLValueToRValue(E);
+ ExprResult Res = CheckLValueToRValueConversionOperand(E);
+ if (Res.isInvalid())
+ return Res;
+ E = Res.get();
// Loading a __weak object implicitly retains the value, so we need a cleanup to
// balance that.
if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
Cleanup.setExprNeedsCleanups(true);
- ExprResult Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E,
- nullptr, VK_RValue);
+ Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, nullptr,
+ VK_RValue);
// C11 6.3.2.1p2:
// ... if the lvalue has atomic type, the value has the non-atomic version
@@ -1794,9 +1797,19 @@ 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);
+ VK, FoundD, TemplateArgs, NOUR);
MarkDeclRefReferenced(E);
if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
@@ -5626,7 +5639,8 @@ ExprResult Sema::BuildCallExpr(Scope *Sc
NDecl = FDecl;
Fn = DeclRefExpr::Create(
Context, FDecl->getQualifierLoc(), SourceLocation(), FDecl, false,
- SourceLocation(), FDecl->getType(), Fn->getValueKind(), FDecl);
+ SourceLocation(), FDecl->getType(), Fn->getValueKind(), FDecl,
+ nullptr, DRE->isNonOdrUse());
}
}
} else if (isa<MemberExpr>(NakedFn))
@@ -15779,59 +15793,258 @@ QualType Sema::getCapturedDeclRefType(Va
return DeclRefType;
}
+/// 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.
+///
+/// \return A new expression if we found any potential results, ExprEmpty() if
+/// not, and ExprError() if we diagnosed an error.
+static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
+ NonOdrUseReason NOUR) {
+ // Per C++11 [basic.def.odr], a variable is odr-used "unless it is
+ // an object that satisfies the requirements for appearing in a
+ // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1)
+ // is immediately applied." This function handles the lvalue-to-rvalue
+ // conversion part.
+ //
+ // If we encounter a node that claims to be an odr-use but shouldn't be, we
+ // transform it into the relevant kind of non-odr-use node and rebuild the
+ // tree of nodes leading to it.
+ //
+ // This is a mini-TreeTransform that only transforms a restricted subset of
+ // nodes (and only certain operands of them).
+ // Rebuild a subexpression.
+ auto Rebuild = [&](Expr *Sub) {
+ return rebuildPotentialResultsAsNonOdrUsed(S, Sub, NOUR);
+ };
-// If either the type of the variable or the initializer is dependent,
-// return false. Otherwise, determine whether the variable is a constant
-// expression. Use this if you need to know if a variable that might or
-// might not be dependent is truly a constant expression.
-static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var,
- ASTContext &Context) {
+ // Check whether a potential result satisfies the requirements of NOUR.
+ auto IsPotentialResultOdrUsed = [&](NamedDecl *D) {
+ // Any entity other than a VarDecl is always odr-used whenever it's named
+ // in a potentially-evaluated expression.
+ auto *VD = dyn_cast<VarDecl>(D);
+ if (!VD)
+ return true;
- if (Var->getType()->isDependentType())
- return false;
- const VarDecl *DefVD = nullptr;
- Var->getAnyInitializer(DefVD);
- if (!DefVD)
- return false;
- EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt();
- Expr *Init = cast<Expr>(Eval->Value);
- if (Init->isValueDependent())
+ // C++2a [basic.def.odr]p4:
+ // A variable x whose name appears as a potentially-evalauted expression
+ // e is odr-used by e unless
+ // -- x is a reference that is usable in constant expressions, or
+ // -- x is a variable of non-reference type that is usable in constant
+ // expressions and has no mutable subobjects, and e is an element of
+ // the set of potential results of an expression of
+ // non-volatile-qualified non-class type to which the lvalue-to-rvalue
+ // conversion is applied, or
+ // -- x is a variable of non-reference type, and e is an element of the
+ // set of potential results of a discarded-value expression to which
+ // the lvalue-to-rvalue conversion is not applied
+ //
+ // We check the first bullet and the "potentially-evaluated" condition in
+ // BuildDeclRefExpr. We check the type requirements in the second bullet
+ // in CheckLValueToRValueConversionOperand below.
+ switch (NOUR) {
+ case NOUR_None:
+ case NOUR_Unevaluated:
+ llvm_unreachable("unexpected non-odr-use-reason");
+
+ case NOUR_Constant:
+ // Constant references were handled when they were built.
+ if (VD->getType()->isReferenceType())
+ return true;
+ if (auto *RD = VD->getType()->getAsCXXRecordDecl())
+ if (RD->hasMutableFields())
+ return true;
+ if (!VD->isUsableInConstantExpressions(S.Context))
+ return true;
+ break;
+
+ case NOUR_Discarded:
+ if (VD->getType()->isReferenceType())
+ return true;
+ break;
+ }
return false;
- return IsVariableAConstantExpression(Var, Context);
-}
+ };
+ // Mark that this expression does not constitute an odr-use.
+ auto MarkNotOdrUsed = [&] {
+ S.MaybeODRUseExprs.erase(E);
+ if (LambdaScopeInfo *LSI = S.getCurLambda())
+ LSI->markVariableExprAsNonODRUsed(E);
+ };
-void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
- // Per C++11 [basic.def.odr], a variable is odr-used "unless it is
- // an object that satisfies the requirements for appearing in a
- // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1)
- // is immediately applied." This function handles the lvalue-to-rvalue
- // conversion part.
- MaybeODRUseExprs.erase(E->IgnoreParens());
+ // C++2a [basic.def.odr]p2:
+ // The set of potential results of an expression e is defined as follows:
+ switch (E->getStmtClass()) {
+ // -- If e is an id-expression, ...
+ case Expr::DeclRefExprClass: {
+ auto *DRE = cast<DeclRefExpr>(E);
+ if (DRE->isNonOdrUse() || IsPotentialResultOdrUsed(DRE->getDecl()))
+ break;
- // If we are in a lambda, check if this DeclRefExpr or MemberExpr refers
- // to a variable that is a constant expression, and if so, identify it as
- // a reference to a variable that does not involve an odr-use of that
- // variable.
- if (LambdaScopeInfo *LSI = getCurLambda()) {
- Expr *SansParensExpr = E->IgnoreParens();
- VarDecl *Var;
- ArrayRef<VarDecl *> Vars(&Var, &Var + 1);
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr))
- Var = dyn_cast<VarDecl>(DRE->getFoundDecl());
- else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr))
- Var = dyn_cast<VarDecl>(ME->getMemberDecl());
- else if (auto *FPPE = dyn_cast<FunctionParmPackExpr>(SansParensExpr))
- Vars = llvm::makeArrayRef(FPPE->begin(), FPPE->end());
- else
- Vars = None;
+ // 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);
+ }
+
+ case Expr::FunctionParmPackExprClass: {
+ auto *FPPE = cast<FunctionParmPackExpr>(E);
+ // If any of the declarations in the pack is odr-used, then the expression
+ // as a whole constitutes an odr-use.
+ for (VarDecl *D : *FPPE)
+ if (IsPotentialResultOdrUsed(D))
+ return ExprEmpty();
- for (VarDecl *VD : Vars) {
- if (VD && IsVariableNonDependentAndAConstantExpression(VD, Context))
- LSI->markVariableExprAsNonODRUsed(SansParensExpr);
+ // FIXME: Rebuild as a non-odr-use FunctionParmPackExpr? In practice,
+ // nothing cares about whether we marked this as an odr-use, but it might
+ // be useful for non-compiler tools.
+ MarkNotOdrUsed();
+ 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...
+
+ // -- If e is a class member access expression naming a static data member,
+ // ...
+ case Expr::MemberExprClass: {
+ auto *ME = cast<MemberExpr>(E);
+ if (ME->getMemberDecl()->isCXXInstanceMember())
+ // 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()))
+ break;
+
+ // FIXME: Rebuild as a non-odr-use MemberExpr.
+ MarkNotOdrUsed();
+ return ExprEmpty();
+ }
+
+ // FIXME: Implement this.
+ // -- If e is a pointer-to-member expression of the form e1 .* e2 ...
+
+ // -- If e has the form (e1)...
+ case Expr::ParenExprClass: {
+ auto *PE = dyn_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, ...
+
+ // [Clang extension]
+ // -- If e has the form __extension__ e1...
+ case Expr::UnaryOperatorClass: {
+ auto *UO = cast<UnaryOperator>(E);
+ if (UO->getOpcode() != UO_Extension)
+ break;
+ ExprResult Sub = Rebuild(UO->getSubExpr());
+ if (!Sub.isUsable())
+ return Sub;
+ return S.BuildUnaryOp(nullptr, UO->getOperatorLoc(), UO_Extension,
+ Sub.get());
+ }
+
+ // [Clang extension]
+ // -- 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);
+
+ SmallVector<Expr *, 4> AssocExprs;
+ bool AnyChanged = false;
+ for (Expr *OrigAssocExpr : GSE->getAssocExprs()) {
+ ExprResult AssocExpr = Rebuild(OrigAssocExpr);
+ if (AssocExpr.isInvalid())
+ return ExprError();
+ if (AssocExpr.isUsable()) {
+ AssocExprs.push_back(AssocExpr.get());
+ AnyChanged = true;
+ } else {
+ AssocExprs.push_back(OrigAssocExpr);
+ }
}
+
+ return AnyChanged ? S.CreateGenericSelectionExpr(
+ GSE->getGenericLoc(), GSE->getDefaultLoc(),
+ GSE->getRParenLoc(), GSE->getControllingExpr(),
+ GSE->getAssocTypeSourceInfos(), AssocExprs)
+ : ExprEmpty();
}
+
+ // [Clang extension]
+ // -- If e has the form __builtin_choose_expr(...), the set of potential
+ // 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);
+
+ ExprResult LHS = Rebuild(CE->getLHS());
+ if (LHS.isInvalid())
+ return ExprError();
+
+ ExprResult RHS = Rebuild(CE->getLHS());
+ if (RHS.isInvalid())
+ return ExprError();
+
+ if (!LHS.get() && !RHS.get())
+ return ExprEmpty();
+ if (!LHS.isUsable())
+ LHS = CE->getLHS();
+ if (!RHS.isUsable())
+ RHS = CE->getRHS();
+
+ return S.ActOnChooseExpr(CE->getBuiltinLoc(), CE->getCond(), LHS.get(),
+ RHS.get(), CE->getRParenLoc());
+ }
+
+ // Step through non-syntactic nodes.
+ case Expr::ConstantExprClass: {
+ auto *CE = dyn_cast<ConstantExpr>(E);
+ ExprResult Sub = Rebuild(CE->getSubExpr());
+ if (!Sub.isUsable())
+ return Sub;
+ return ConstantExpr::Create(S.Context, Sub.get());
+ }
+
+ default:
+ break;
+ }
+
+ // Can't traverse through this node. Nothing to do.
+ return ExprEmpty();
+}
+
+ExprResult Sema::CheckLValueToRValueConversionOperand(Expr *E) {
+ // C++2a [basic.def.odr]p4:
+ // [...] an expression of non-volatile-qualified non-class type to which
+ // the lvalue-to-rvalue conversion is applied [...]
+ if (E->getType().isVolatileQualified() || E->getType()->getAs<RecordType>())
+ return E;
+
+ ExprResult Result =
+ rebuildPotentialResultsAsNonOdrUsed(*this, E, NOUR_Constant);
+ if (Result.isInvalid())
+ return ExprError();
+ return Result.get() ? Result : E;
}
ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
@@ -15844,8 +16057,7 @@ ExprResult Sema::ActOnConstantExpression
// deciding whether it is an odr-use, just assume we will apply the
// lvalue-to-rvalue conversion. In the one case where this doesn't happen
// (a non-type template argument), we have special handling anyway.
- UpdateMarkingForLValueToRValue(Res.get());
- return Res;
+ return CheckLValueToRValueConversionOperand(Res.get());
}
void Sema::CleanupVarDeclMarking() {
@@ -15889,7 +16101,7 @@ static void DoMarkVarDeclReferenced(Sema
OdrUseContext OdrUse = isOdrUseContext(SemaRef);
bool UsableInConstantExpr =
- Var->isUsableInConstantExpressions(SemaRef.Context);
+ Var->mightBeUsableInConstantExpressions(SemaRef.Context);
// C++20 [expr.const]p12:
// A variable [...] is needed for constant evaluation if it is [...] a
@@ -15964,7 +16176,7 @@ static void DoMarkVarDeclReferenced(Sema
}
}
- // C++20 [basic.def.odr]p4:
+ // 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
@@ -15978,11 +16190,14 @@ static void DoMarkVarDeclReferenced(Sema
// lvalue-to-rvalue conversion is not applied [FIXME]
//
// We check the first part of the second bullet here, and
- // Sema::UpdateMarkingForLValueToRValue deals with the second part.
+ // 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);
switch (OdrUse) {
case OdrUseContext::None:
+ assert((!DRE || DRE->isNonOdrUse() == NOUR_Unevaluated) &&
+ "missing non-odr-use marking for unevaluated operand");
break;
case OdrUseContext::FormallyOdrUsed:
@@ -15991,19 +16206,21 @@ static void DoMarkVarDeclReferenced(Sema
break;
case OdrUseContext::Used:
- if (E && IsVariableAConstantExpression(Var, SemaRef.Context)) {
- // A reference initialized by a constant expression can never be
- // odr-used, so simply ignore it.
- if (!Var->getType()->isReferenceType() ||
- (SemaRef.LangOpts.OpenMP && SemaRef.isOpenMPCapturedDecl(Var)))
- SemaRef.MaybeODRUseExprs.insert(E);
- } else {
- MarkVarDeclODRUsed(Var, Loc, SemaRef,
- /*MaxFunctionScopeIndex ptr*/ nullptr);
- }
+ // 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))
+ SemaRef.MaybeODRUseExprs.insert(E);
+ else
+ MarkVarDeclODRUsed(Var, Loc, SemaRef);
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
@@ -16028,7 +16245,7 @@ static void DoMarkVarDeclReferenced(Sema
// FIXME: We can simplify this a lot after implementing P0588R1.
assert(E && "Capture variable should be used in an expression.");
if (!Var->getType()->isReferenceType() ||
- !IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
+ !Var->isUsableInConstantExpressions(SemaRef.Context))
LSI->addPotentialCapture(E->IgnoreParens());
}
}
@@ -16241,13 +16458,6 @@ namespace {
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
Visit(E->getExpr());
}
-
- void VisitImplicitCastExpr(ImplicitCastExpr *E) {
- Inherited::VisitImplicitCastExpr(E);
-
- if (E->getCastKind() == CK_LValueToRValue)
- S.UpdateMarkingForLValueToRValue(E->getSubExpr());
- }
};
}
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Jun 11 10:50:32 2019
@@ -7395,7 +7395,7 @@ static inline bool VariableCanNeverBeACo
return false;
}
- return !IsVariableAConstantExpression(Var, Context);
+ return !Var->isUsableInConstantExpressions(Context);
}
/// Check if the current lambda has any potential captures
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Jun 11 10:50:32 2019
@@ -285,7 +285,7 @@ static void instantiateOMPDeclareSimdDec
SmallVector<Expr *, 4> Uniforms, Aligneds, Alignments, Linears, Steps;
SmallVector<unsigned, 4> LinModifiers;
- auto &&Subst = [&](Expr *E) -> ExprResult {
+ auto SubstExpr = [&](Expr *E) -> ExprResult {
if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
Sema::ContextRAII SavedContext(S, FD);
@@ -300,6 +300,17 @@ static void instantiateOMPDeclareSimdDec
return S.SubstExpr(E, TemplateArgs);
};
+ // Substitute a single OpenMP clause, which is a potentially-evaluated
+ // full-expression.
+ auto Subst = [&](Expr *E) -> ExprResult {
+ EnterExpressionEvaluationContext Evaluated(
+ S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+ ExprResult Res = SubstExpr(E);
+ if (Res.isInvalid())
+ return Res;
+ return S.ActOnFinishFullExpr(Res.get(), false);
+ };
+
ExprResult Simdlen;
if (auto *E = Attr.getSimdlen())
Simdlen = Subst(E);
@@ -4714,8 +4725,12 @@ void Sema::InstantiateVariableDefinition
// of reference types, [...] explicit instantiation declarations
// have the effect of suppressing the implicit instantiation of the entity
// to which they refer.
+ //
+ // FIXME: That's not exactly the same as "might be usable in constant
+ // expressions", which only allows constexpr variables and const integral
+ // types, not arbitrary const literal types.
if (TSK == TSK_ExplicitInstantiationDeclaration &&
- !Var->isUsableInConstantExpressions(getASTContext()))
+ !Var->mightBeUsableInConstantExpressions(getASTContext()))
return;
// Make sure to pass the instantiated variable to the consumer at the end.
Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Jun 11 10:50:32 2019
@@ -554,6 +554,7 @@ void ASTStmtReader::VisitDeclRefExpr(Dec
E->DeclRefExprBits.HasTemplateKWAndArgsInfo = Record.readInt();
E->DeclRefExprBits.HadMultipleCandidates = Record.readInt();
E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt();
+ E->DeclRefExprBits.NonOdrUseReason = Record.readInt();
unsigned NumTemplateArgs = 0;
if (E->hasTemplateKWAndArgsInfo())
NumTemplateArgs = Record.readInt();
@@ -2524,7 +2525,7 @@ Stmt *ASTReader::ReadStmtFromStream(Modu
/*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1],
/*HasTemplateKWAndArgsInfo=*/Record[ASTStmtReader::NumExprFields + 2],
/*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ?
- Record[ASTStmtReader::NumExprFields + 5] : 0);
+ Record[ASTStmtReader::NumExprFields + 6] : 0);
break;
case EXPR_INTEGER_LITERAL:
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Jun 11 10:50:32 2019
@@ -2212,8 +2212,8 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
- 1)); // RefersToEnclosingVariableOrCapture
+ Abv->Add(BitCodeAbbrevOp(0)); // RefersToEnclosingVariableOrCapture
+ Abv->Add(BitCodeAbbrevOp(0)); // NonOdrUseReason
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv));
Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Jun 11 10:50:32 2019
@@ -456,6 +456,7 @@ void ASTStmtWriter::VisitDeclRefExpr(Dec
Record.push_back(E->hasTemplateKWAndArgsInfo());
Record.push_back(E->hadMultipleCandidates());
Record.push_back(E->refersToEnclosingVariableOrCapture());
+ Record.push_back(E->isNonOdrUse());
if (E->hasTemplateKWAndArgsInfo()) {
unsigned NumTemplateArgs = E->getNumTemplateArgs();
@@ -466,7 +467,8 @@ void ASTStmtWriter::VisitDeclRefExpr(Dec
if ((!E->hasTemplateKWAndArgsInfo()) && (!E->hasQualifier()) &&
(E->getDecl() == E->getFoundDecl()) &&
- nk == DeclarationName::Identifier) {
+ nk == DeclarationName::Identifier &&
+ !E->refersToEnclosingVariableOrCapture() && !E->isNonOdrUse()) {
AbbrevToUse = Writer.getDeclRefExprAbbrev();
}
Modified: cfe/trunk/test/AST/ast-dump-color.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/AST/ast-dump-color.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/test/AST/ast-dump-color.cpp (original)
+++ cfe/trunk/test/AST/ast-dump-color.cpp Tue Jun 11 10:50:32 2019
@@ -86,7 +86,7 @@ struct Invalid {
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:26:1[[RESET]], [[Yellow]]col:5[[RESET]]> [[Yellow]]col:5[[RESET]][[CYAN]] TestExpr[[RESET]] [[Green]]'int'[[RESET]]
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[BLUE]]GuardedByAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:29[[RESET]], [[Yellow]]col:43[[RESET]]>{{$}}
-//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]{{$}}
+//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]] non_odr_use_unevaluated{{$}}
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:28:1[[RESET]], [[Yellow]]line:30:1[[RESET]]> [[Yellow]]line:28:8[[RESET]] struct[[CYAN]] Invalid[[RESET]] definition
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit referenced struct[[CYAN]] Invalid[[RESET]]
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:29:3[[RESET]], [[Yellow]]col:42[[RESET]]> [[Yellow]]col:29[[RESET]] invalid[[CYAN]] Invalid[[RESET]] [[Green]]'void (int)'[[RESET]]
Modified: cfe/trunk/test/AST/ast-dump-expr-json.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/AST/ast-dump-expr-json.c?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/test/AST/ast-dump-expr-json.c (original)
+++ cfe/trunk/test/AST/ast-dump-expr-json.c Tue Jun 11 10:50:32 2019
@@ -3877,7 +3877,8 @@ void PrimaryExpressions(int a) {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "int"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
Modified: cfe/trunk/test/AST/ast-dump-expr-json.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/AST/ast-dump-expr-json.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/test/AST/ast-dump-expr-json.cpp (original)
+++ cfe/trunk/test/AST/ast-dump-expr-json.cpp Tue Jun 11 10:50:32 2019
@@ -1596,7 +1596,8 @@ void TestNonADLCall3() {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "int *"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
@@ -1647,7 +1648,8 @@ void TestNonADLCall3() {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "int *"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
Modified: cfe/trunk/test/AST/ast-dump-stmt-json.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/AST/ast-dump-stmt-json.c?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/test/AST/ast-dump-stmt-json.c (original)
+++ cfe/trunk/test/AST/ast-dump-stmt-json.c Tue Jun 11 10:50:32 2019
@@ -1342,7 +1342,8 @@ void TestMiscStmts(void) {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "int"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
@@ -1456,7 +1457,8 @@ void TestMiscStmts(void) {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "int"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
@@ -1596,7 +1598,8 @@ void TestMiscStmts(void) {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "int"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
@@ -1736,7 +1739,8 @@ void TestMiscStmts(void) {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "int"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
@@ -1951,7 +1955,8 @@ void TestMiscStmts(void) {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "int"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
Modified: cfe/trunk/test/AST/ast-dump-stmt-json.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/AST/ast-dump-stmt-json.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/test/AST/ast-dump-stmt-json.cpp (original)
+++ cfe/trunk/test/AST/ast-dump-stmt-json.cpp Tue Jun 11 10:50:32 2019
@@ -70,7 +70,7 @@ void TestSwitch(int i) {
}
void TestIf(bool b) {
- if (int i = 12; b)
+ if (const int i = 12; i)
;
if constexpr (sizeof(b) == 1)
@@ -2719,7 +2719,7 @@ void TestIteration() {
// CHECK-NEXT: "line": 72
// CHECK-NEXT: }
// CHECK-NEXT: },
-// CHECK-NEXT: "isUsed": true,
+// CHECK-NEXT: "isReferenced": true,
// CHECK-NEXT: "name": "b",
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "bool"
@@ -2768,7 +2768,7 @@ void TestIteration() {
// CHECK-NEXT: "line": 73
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "col": 17,
+// CHECK-NEXT: "col": 23,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 73
// CHECK-NEXT: }
@@ -2778,7 +2778,7 @@ void TestIteration() {
// CHECK-NEXT: "id": "0x{{.*}}",
// CHECK-NEXT: "kind": "VarDecl",
// CHECK-NEXT: "loc": {
-// CHECK-NEXT: "col": 11,
+// CHECK-NEXT: "col": 17,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 73
// CHECK-NEXT: },
@@ -2789,14 +2789,15 @@ void TestIteration() {
// CHECK-NEXT: "line": 73
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "col": 15,
+// CHECK-NEXT: "col": 21,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 73
// CHECK-NEXT: }
// CHECK-NEXT: },
+// CHECK-NEXT: "isReferenced": true,
// CHECK-NEXT: "name": "i",
// CHECK-NEXT: "type": {
-// CHECK-NEXT: "qualType": "int"
+// CHECK-NEXT: "qualType": "const int"
// CHECK-NEXT: },
// CHECK-NEXT: "init": "c",
// CHECK-NEXT: "inner": [
@@ -2805,12 +2806,12 @@ void TestIteration() {
// CHECK-NEXT: "kind": "IntegerLiteral",
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "col": 15,
+// CHECK-NEXT: "col": 21,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 73
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "col": 15,
+// CHECK-NEXT: "col": 21,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 73
// CHECK-NEXT: }
@@ -2830,12 +2831,12 @@ void TestIteration() {
// CHECK-NEXT: "kind": "ImplicitCastExpr",
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "col": 19,
+// CHECK-NEXT: "col": 25,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 73
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "col": 19,
+// CHECK-NEXT: "col": 25,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 73
// CHECK-NEXT: }
@@ -2844,35 +2845,59 @@ void TestIteration() {
// CHECK-NEXT: "qualType": "bool"
// CHECK-NEXT: },
// CHECK-NEXT: "valueCategory": "rvalue",
-// CHECK-NEXT: "castKind": "LValueToRValue",
+// CHECK-NEXT: "castKind": "IntegralToBoolean",
// CHECK-NEXT: "inner": [
// CHECK-NEXT: {
// CHECK-NEXT: "id": "0x{{.*}}",
-// CHECK-NEXT: "kind": "DeclRefExpr",
+// CHECK-NEXT: "kind": "ImplicitCastExpr",
// CHECK-NEXT: "range": {
// CHECK-NEXT: "begin": {
-// CHECK-NEXT: "col": 19,
+// CHECK-NEXT: "col": 25,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 73
// CHECK-NEXT: },
// CHECK-NEXT: "end": {
-// CHECK-NEXT: "col": 19,
+// CHECK-NEXT: "col": 25,
// CHECK-NEXT: "file": "{{.*}}",
// CHECK-NEXT: "line": 73
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: "type": {
-// CHECK-NEXT: "qualType": "bool"
+// CHECK-NEXT: "qualType": "int"
// CHECK-NEXT: },
-// CHECK-NEXT: "valueCategory": "lvalue",
-// CHECK-NEXT: "referencedDecl": {
-// CHECK-NEXT: "id": "0x{{.*}}",
-// CHECK-NEXT: "kind": "ParmVarDecl",
-// CHECK-NEXT: "name": "b",
-// CHECK-NEXT: "type": {
-// CHECK-NEXT: "qualType": "bool"
+// CHECK-NEXT: "valueCategory": "rvalue",
+// CHECK-NEXT: "castKind": "LValueToRValue",
+// CHECK-NEXT: "inner": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "DeclRefExpr",
+// CHECK-NEXT: "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT: "col": 25,
+// CHECK-NEXT: "file": "{{.*}}",
+// CHECK-NEXT: "line": 73
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT: "col": 25,
+// CHECK-NEXT: "file": "{{.*}}",
+// CHECK-NEXT: "line": 73
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "type": {
+// CHECK-NEXT: "qualType": "const int"
+// CHECK-NEXT: },
+// CHECK-NEXT: "valueCategory": "lvalue",
+// CHECK-NEXT: "referencedDecl": {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "VarDecl",
+// CHECK-NEXT: "name": "i",
+// CHECK-NEXT: "type": {
+// CHECK-NEXT: "qualType": "const int"
+// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "constant"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
@@ -3019,7 +3044,8 @@ void TestIteration() {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "bool"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
@@ -3217,7 +3243,8 @@ void TestIteration() {
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "bool"
// CHECK-NEXT: }
-// CHECK-NEXT: }
+// CHECK-NEXT: },
+// CHECK-NEXT: "nonOdrUseReason": "unevaluated"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
Modified: cfe/trunk/test/PCH/cxx_exprs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx_exprs.cpp?rev=363086&r1=363085&r2=363086&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx_exprs.cpp (original)
+++ cfe/trunk/test/PCH/cxx_exprs.cpp Tue Jun 11 10:50:32 2019
@@ -29,7 +29,7 @@ dynamic_cast_result derived_ptr = d;
// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'Derived *'{{$}}
// CHECK-NEXT: CXXDynamicCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'Derived *' dynamic_cast<struct Derived *> <Dynamic>{{$}}
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'Base *' <LValueToRValue> part_of_explicit_cast{{$}}
-// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'Base *' lvalue Var {{.*}} 'base_ptr' 'Base *'{{$}}
+// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'Base *' lvalue Var {{.*}} 'base_ptr' 'Base *' non_odr_use_unevaluated{{$}}
// CXXReinterpretCastExpr
reinterpret_cast_result void_ptr2 = &integer;
@@ -46,7 +46,7 @@ const_cast_result char_ptr = &character;
// CHECK-NEXT: ParenExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'char *'{{$}}
// CHECK-NEXT: CXXConstCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'char *' const_cast<char *> <NoOp>{{$}}
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'const char *' <LValueToRValue> part_of_explicit_cast{{$}}
-// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'const char *' lvalue Var {{.*}} 'const_char_ptr_value' 'const char *'{{$}}
+// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'const char *' lvalue Var {{.*}} 'const_char_ptr_value' 'const char *' non_odr_use_unevaluated{{$}}
// CXXFunctionalCastExpr
functional_cast_result *double_ptr = &floating;
@@ -56,7 +56,7 @@ functional_cast_result *double_ptr = &fl
// CHECK-NEXT: CXXFunctionalCastExpr {{.*}} <col:{{.*}}, col:{{.*}}> 'double' functional cast to double <NoOp>{{$}}
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'double' <IntegralToFloating> part_of_explicit_cast{{$}}
// CHECK-NEXT: ImplicitCastExpr {{.*}} <col:{{.*}}> 'int' <LValueToRValue> part_of_explicit_cast{{$}}
-// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue Var {{.*}} 'int_value' 'int'{{$}}
+// CHECK-NEXT: DeclRefExpr {{.*}} <col:{{.*}}> 'int' lvalue Var {{.*}} 'int_value' 'int' non_odr_use_unevaluated{{$}}
// CXXBoolLiteralExpr
bool_literal_result *bool_ptr = &boolean;
More information about the cfe-commits
mailing list