summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2019-06-14 04:05:17 +0000
committerNico Weber <nicolasweber@gmx.de>2019-06-14 04:05:17 +0000
commit3d02b895eda08dda749a16c9499f3a11fd68793b (patch)
treeda36d6a87461e67af138453afafe5ffafd45d02b /clang/lib
parent5b4285d82ded14b5f486df39fbef6aacdfbd8659 (diff)
downloadbcm5719-llvm-3d02b895eda08dda749a16c9499f3a11fd68793b.tar.gz
bcm5719-llvm-3d02b895eda08dda749a16c9499f3a11fd68793b.zip
Revert 363295, it caused PR42276. Also revert follow-ups 363337, 363340.
Revert 363340 "Remove unused SK_LValueToRValue initialization step." Revert 363337 "PR23833, DR2140: an lvalue-to-rvalue conversion on a glvalue of type" Revert 363295 "C++ DR712 and others: handle non-odr-use resulting from an lvalue-to-rvalue conversion applied to a member access or similar not-quite-trivial lvalue expression." llvm-svn: 363352
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Expr.cpp5
-rw-r--r--clang/lib/CodeGen/CGDecl.cpp74
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp109
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp3
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h7
-rw-r--r--clang/lib/Sema/SemaExpr.cpp159
-rw-r--r--clang/lib/Sema/SemaInit.cpp23
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp7
9 files changed, 106 insertions, 285 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 72e1119851b..77d444151c3 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1885,11 +1885,6 @@ ImplicitCastExpr *ImplicitCastExpr::Create(const ASTContext &C, QualType T,
ExprValueKind VK) {
unsigned PathSize = (BasePath ? BasePath->size() : 0);
void *Buffer = C.Allocate(totalSizeToAlloc<CXXBaseSpecifier *>(PathSize));
- // Per C++ [conv.lval]p3, lvalue-to-rvalue conversions on class and
- // std::nullptr_t have special semantics not captured by CK_LValueToRValue.
- assert((Kind != CK_LValueToRValue ||
- !(T->isNullPtrType() || T->getAsCXXRecordDecl())) &&
- "invalid type for lvalue-to-rvalue conversion");
ImplicitCastExpr *E =
new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK);
if (PathSize)
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index f027ab941ac..db18ac49c6e 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1077,16 +1077,17 @@ static llvm::Constant *constWithPadding(CodeGenModule &CGM, IsPattern isPattern,
return constant;
}
-Address CodeGenModule::createUnnamedGlobalFrom(const VarDecl &D,
- llvm::Constant *Constant,
- CharUnits Align) {
+static Address createUnnamedGlobalFrom(CodeGenModule &CGM, const VarDecl &D,
+ CGBuilderTy &Builder,
+ llvm::Constant *Constant,
+ CharUnits Align) {
auto FunctionName = [&](const DeclContext *DC) -> std::string {
if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
if (const auto *CC = dyn_cast<CXXConstructorDecl>(FD))
return CC->getNameAsString();
if (const auto *CD = dyn_cast<CXXDestructorDecl>(FD))
return CD->getNameAsString();
- return getMangledName(FD);
+ return CGM.getMangledName(FD);
} else if (const auto *OM = dyn_cast<ObjCMethodDecl>(DC)) {
return OM->getNameAsString();
} else if (isa<BlockDecl>(DC)) {
@@ -1098,39 +1099,22 @@ Address CodeGenModule::createUnnamedGlobalFrom(const VarDecl &D,
}
};
- // Form a simple per-variable cache of these values in case we find we
- // want to reuse them.
- llvm::GlobalVariable *&CacheEntry = InitializerConstants[&D];
- if (!CacheEntry || CacheEntry->getInitializer() != Constant) {
- auto *Ty = Constant->getType();
- bool isConstant = true;
- llvm::GlobalVariable *InsertBefore = nullptr;
- unsigned AS =
- getContext().getTargetAddressSpace(getStringLiteralAddressSpace());
- llvm::GlobalVariable *GV = new llvm::GlobalVariable(
- getModule(), Ty, isConstant, llvm::GlobalValue::PrivateLinkage,
- Constant,
- "__const." + FunctionName(D.getParentFunctionOrMethod()) + "." +
- D.getName(),
- InsertBefore, llvm::GlobalValue::NotThreadLocal, AS);
- GV->setAlignment(Align.getQuantity());
- GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- CacheEntry = GV;
- } else if (CacheEntry->getAlignment() < Align.getQuantity()) {
- CacheEntry->setAlignment(Align.getQuantity());
- }
-
- return Address(CacheEntry, Align);
-}
-
-static Address createUnnamedGlobalForMemcpyFrom(CodeGenModule &CGM,
- const VarDecl &D,
- CGBuilderTy &Builder,
- llvm::Constant *Constant,
- CharUnits Align) {
- Address SrcPtr = CGM.createUnnamedGlobalFrom(D, Constant, Align);
- llvm::Type *BP = llvm::PointerType::getInt8PtrTy(CGM.getLLVMContext(),
- SrcPtr.getAddressSpace());
+ auto *Ty = Constant->getType();
+ bool isConstant = true;
+ llvm::GlobalVariable *InsertBefore = nullptr;
+ unsigned AS = CGM.getContext().getTargetAddressSpace(
+ CGM.getStringLiteralAddressSpace());
+ llvm::GlobalVariable *GV = new llvm::GlobalVariable(
+ CGM.getModule(), Ty, isConstant, llvm::GlobalValue::PrivateLinkage,
+ Constant,
+ "__const." + FunctionName(D.getParentFunctionOrMethod()) + "." +
+ D.getName(),
+ InsertBefore, llvm::GlobalValue::NotThreadLocal, AS);
+ GV->setAlignment(Align.getQuantity());
+ GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+
+ Address SrcPtr = Address(GV, Align);
+ llvm::Type *BP = llvm::PointerType::getInt8PtrTy(CGM.getLLVMContext(), AS);
if (SrcPtr.getType() != BP)
SrcPtr = Builder.CreateBitCast(SrcPtr, BP);
return SrcPtr;
@@ -1213,10 +1197,10 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D,
}
// Copy from a global.
- Builder.CreateMemCpy(Loc,
- createUnnamedGlobalForMemcpyFrom(
- CGM, D, Builder, constant, Loc.getAlignment()),
- SizeVal, isVolatile);
+ Builder.CreateMemCpy(
+ Loc,
+ createUnnamedGlobalFrom(CGM, D, Builder, constant, Loc.getAlignment()),
+ SizeVal, isVolatile);
}
static void emitStoresForZeroInit(CodeGenModule &CGM, const VarDecl &D,
@@ -1779,10 +1763,10 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur");
Cur->addIncoming(Begin.getPointer(), OriginBB);
CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize);
- Builder.CreateMemCpy(Address(Cur, CurAlign),
- createUnnamedGlobalForMemcpyFrom(
- CGM, D, Builder, Constant, ConstantAlign),
- BaseSizeInChars, isVolatile);
+ Builder.CreateMemCpy(
+ Address(Cur, CurAlign),
+ createUnnamedGlobalFrom(CGM, D, Builder, Constant, ConstantAlign),
+ BaseSizeInChars, isVolatile);
llvm::Value *Next =
Builder.CreateInBoundsGEP(Int8Ty, Cur, BaseSizeInChars, "vla.next");
llvm::Value *Done = Builder.CreateICmpEQ(Next, End, "vla-init.isdone");
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index f0d8619faa3..d5ce4870f18 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1422,11 +1422,10 @@ static ConstantEmissionKind checkVarTypeForConstantEmission(QualType type) {
}
/// Try to emit a reference to the given value without producing it as
-/// an l-value. This is just an optimization, but it avoids us needing
-/// to emit global copies of variables if they're named without triggering
-/// a formal use in a context where we can't emit a direct reference to them,
-/// for instance if a block or lambda or a member of a local class uses a
-/// const int variable or constexpr variable from an enclosing function.
+/// an l-value. This is actually more than an optimization: we can't
+/// produce an l-value for variables that we never actually captured
+/// in a block or lambda, which means const int variables or constexpr
+/// literals or similar.
CodeGenFunction::ConstantEmission
CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
ValueDecl *value = refExpr->getDecl();
@@ -2451,97 +2450,33 @@ static LValue EmitGlobalNamedRegister(const VarDecl *VD, CodeGenModule &CGM) {
return LValue::MakeGlobalReg(Address(Ptr, Alignment), VD->getType());
}
-/// Determine whether we can emit a reference to \p VD from the current
-/// context, despite not necessarily having seen an odr-use of the variable in
-/// this context.
-static bool canEmitSpuriousReferenceToVariable(CodeGenFunction &CGF,
- const DeclRefExpr *E,
- const VarDecl *VD,
- bool IsConstant) {
- // For a variable declared in an enclosing scope, do not emit a spurious
- // reference even if we have a capture, as that will emit an unwarranted
- // reference to our capture state, and will likely generate worse code than
- // emitting a local copy.
- if (E->refersToEnclosingVariableOrCapture())
- return false;
-
- // For a local declaration declared in this function, we can always reference
- // it even if we don't have an odr-use.
- if (VD->hasLocalStorage()) {
- return VD->getDeclContext() ==
- dyn_cast_or_null<DeclContext>(CGF.CurCodeDecl);
- }
-
- // For a global declaration, we can emit a reference to it if we know
- // for sure that we are able to emit a definition of it.
- VD = VD->getDefinition(CGF.getContext());
- if (!VD)
- return false;
-
- // Don't emit a spurious reference if it might be to a variable that only
- // exists on a different device / target.
- // FIXME: This is unnecessarily broad. Check whether this would actually be a
- // cross-target reference.
- if (CGF.getLangOpts().OpenMP || CGF.getLangOpts().CUDA ||
- CGF.getLangOpts().OpenCL) {
- return false;
- }
-
- // We can emit a spurious reference only if the linkage implies that we'll
- // be emitting a non-interposable symbol that will be retained until link
- // time.
- switch (CGF.CGM.getLLVMLinkageVarDefinition(VD, IsConstant)) {
- case llvm::GlobalValue::ExternalLinkage:
- case llvm::GlobalValue::LinkOnceODRLinkage:
- case llvm::GlobalValue::WeakODRLinkage:
- case llvm::GlobalValue::InternalLinkage:
- case llvm::GlobalValue::PrivateLinkage:
- return true;
- default:
- return false;
- }
-}
-
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const NamedDecl *ND = E->getDecl();
QualType T = E->getType();
- assert(E->isNonOdrUse() != NOUR_Unevaluated &&
- "should not emit an unevaluated operand");
-
if (const auto *VD = dyn_cast<VarDecl>(ND)) {
// Global Named registers access via intrinsics only
if (VD->getStorageClass() == SC_Register &&
VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())
return EmitGlobalNamedRegister(VD, CGM);
- // If this DeclRefExpr does not constitute an odr-use of the variable,
- // we're not permitted to emit a reference to it in general, and it might
- // not be captured if capture would be necessary for a use. Emit the
- // constant value directly instead.
- if (E->isNonOdrUse() == NOUR_Constant &&
- (VD->getType()->isReferenceType() ||
- !canEmitSpuriousReferenceToVariable(*this, E, VD, true))) {
- VD->getAnyInitializer(VD);
- llvm::Constant *Val = ConstantEmitter(*this).emitAbstract(
- E->getLocation(), *VD->evaluateValue(), VD->getType());
- assert(Val && "failed to emit constant expression");
-
- Address Addr = Address::invalid();
- if (!VD->getType()->isReferenceType()) {
- // Spill the constant value to a global.
- Addr = CGM.createUnnamedGlobalFrom(*VD, Val,
- getContext().getDeclAlign(VD));
- } else {
- // Should we be using the alignment of the constant pointer we emitted?
- CharUnits Alignment =
- getNaturalTypeAlignment(E->getType(),
- /* BaseInfo= */ nullptr,
- /* TBAAInfo= */ nullptr,
- /* forPointeeType= */ true);
- Addr = Address(Val, Alignment);
- }
- return MakeAddrLValue(Addr, T, AlignmentSource::Decl);
+ // A DeclRefExpr for a reference initialized by a constant expression can
+ // appear without being odr-used. Directly emit the constant initializer.
+ VD->getAnyInitializer(VD);
+ if (E->isNonOdrUse() == NOUR_Constant && VD->getType()->isReferenceType()) {
+ llvm::Constant *Val =
+ ConstantEmitter(*this).emitAbstract(E->getLocation(),
+ *VD->evaluateValue(),
+ VD->getType());
+ assert(Val && "failed to emit reference constant expression");
+ // FIXME: Eventually we will want to emit vector element references.
+
+ // Should we be using the alignment of the constant pointer we emitted?
+ CharUnits Alignment = getNaturalTypeAlignment(E->getType(),
+ /* BaseInfo= */ nullptr,
+ /* TBAAInfo= */ nullptr,
+ /* forPointeeType= */ true);
+ return MakeAddrLValue(Address(Val, Alignment), T, AlignmentSource::Decl);
}
// FIXME: Handle other kinds of non-odr-use DeclRefExprs.
@@ -2577,7 +2512,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// FIXME: We should be able to assert this for FunctionDecls as well!
// FIXME: We should be able to assert this for all DeclRefExprs, not just
// those with a valid source location.
- assert((ND->isUsed(false) || !isa<VarDecl>(ND) || E->isNonOdrUse() ||
+ assert((ND->isUsed(false) || !isa<VarDecl>(ND) ||
!E->getLocation().isValid()) &&
"Should not use decl without marking it used!");
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 3b1c5bf876e..a76058c1472 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -1352,8 +1352,7 @@ static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) {
// (int*)0 - Null pointer expressions.
if (const CastExpr *ICE = dyn_cast<CastExpr>(E))
return ICE->getCastKind() == CK_NullToPointer &&
- CGF.getTypes().isPointerZeroInitializable(E->getType()) &&
- !E->HasSideEffects(CGF.getContext());
+ CGF.getTypes().isPointerZeroInitializable(E->getType());
// '\0'
if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E))
return CL->getValue() == 0;
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index c4167537e79..267402dbef4 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -2148,14 +2148,14 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
case CK_NullToPointer:
if (MustVisitNullValue(E))
- CGF.EmitIgnoredExpr(E);
+ (void) Visit(E);
return CGF.CGM.getNullPointer(cast<llvm::PointerType>(ConvertType(DestTy)),
DestTy);
case CK_NullToMemberPointer: {
if (MustVisitNullValue(E))
- CGF.EmitIgnoredExpr(E);
+ (void) Visit(E);
const MemberPointerType *MPT = CE->getType()->getAs<MemberPointerType>();
return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT);
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 95964afed4e..8c1bc0777de 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -362,10 +362,6 @@ private:
llvm::SmallVector<std::pair<llvm::GlobalValue *, llvm::Constant *>, 8>
GlobalValReplacements;
- /// Variables for which we've emitted globals containing their constant
- /// values along with the corresponding globals, for opportunistic reuse.
- llvm::DenseMap<const VarDecl*, llvm::GlobalVariable*> InitializerConstants;
-
/// Set of global decls for which we already diagnosed mangled name conflict.
/// Required to not issue a warning (on a mangling conflict) multiple times
/// for the same decl.
@@ -627,9 +623,6 @@ public:
StaticLocalDeclGuardMap[D] = C;
}
- Address createUnnamedGlobalFrom(const VarDecl &D, llvm::Constant *Constant,
- CharUnits Align);
-
bool lookupRepresentativeDecl(StringRef MangledName,
GlobalDecl &Result) const;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a561b045f9a..d444a35be86 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -635,10 +635,8 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
Cleanup.setExprNeedsCleanups(true);
- // C++ [conv.lval]p3:
- // If T is cv std::nullptr_t, the result is a null pointer constant.
- CastKind CK = T->isNullPtrType() ? CK_NullToPointer : CK_LValueToRValue;
- Res = ImplicitCastExpr::Create(Context, T, CK, 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
@@ -15808,32 +15806,6 @@ QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
return DeclRefType;
}
-namespace {
-// Helper to copy the template arguments from a DeclRefExpr or MemberExpr.
-// The produced TemplateArgumentListInfo* points to data stored within this
-// object, so should only be used in contexts where the pointer will not be
-// used after the CopiedTemplateArgs object is destroyed.
-class CopiedTemplateArgs {
- bool HasArgs;
- TemplateArgumentListInfo TemplateArgStorage;
-public:
- template<typename RefExpr>
- CopiedTemplateArgs(RefExpr *E) : HasArgs(E->hasExplicitTemplateArgs()) {
- if (HasArgs)
- E->copyTemplateArgumentsInto(TemplateArgStorage);
- }
- operator TemplateArgumentListInfo*()
-#ifdef __has_cpp_attribute
-#if __has_cpp_attribute(clang::lifetimebound)
- [[clang::lifetimebound]]
-#endif
-#endif
- {
- return HasArgs ? &TemplateArgStorage : nullptr;
- }
-};
-}
-
/// 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.
///
@@ -15925,11 +15897,16 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
// 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(), CopiedTemplateArgs(DRE), NOUR);
+ DRE->getFoundDecl(), TemplateArgs, NOUR);
}
case Expr::FunctionParmPackExprClass: {
@@ -15947,107 +15924,52 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
break;
}
+ // FIXME: Implement these.
// -- If e is a subscripting operation with an array operand...
- case Expr::ArraySubscriptExprClass: {
- auto *ASE = cast<ArraySubscriptExpr>(E);
- Expr *OldBase = ASE->getBase()->IgnoreImplicit();
- if (!OldBase->getType()->isArrayType())
- break;
- ExprResult Base = Rebuild(OldBase);
- if (!Base.isUsable())
- return Base;
- Expr *LHS = ASE->getBase() == ASE->getLHS() ? Base.get() : ASE->getLHS();
- Expr *RHS = ASE->getBase() == ASE->getRHS() ? Base.get() : ASE->getRHS();
- SourceLocation LBracketLoc = ASE->getBeginLoc(); // FIXME: Not stored.
- return S.ActOnArraySubscriptExpr(nullptr, LHS, LBracketLoc, RHS,
- ASE->getRBracketLoc());
- }
+ // -- 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 e is a class member access expression [...] naming a non-static
- // data member...
- if (isa<FieldDecl>(ME->getMemberDecl())) {
- ExprResult Base = Rebuild(ME->getBase());
- if (!Base.isUsable())
- return Base;
- return MemberExpr::Create(
- S.Context, Base.get(), ME->isArrow(), ME->getOperatorLoc(),
- ME->getQualifierLoc(), ME->getTemplateKeywordLoc(),
- ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(),
- CopiedTemplateArgs(ME), ME->getType(), ME->getValueKind(),
- ME->getObjectKind(), ME->isNonOdrUse());
- }
-
if (ME->getMemberDecl()->isCXXInstanceMember())
+ // FIXME: Recurse to the left-hand side.
break;
- // -- If e is a class member access expression naming a static data member,
- // ...
if (ME->isNonOdrUse() || IsPotentialResultOdrUsed(ME->getMemberDecl()))
break;
// 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(), CopiedTemplateArgs(ME),
+ ME->getFoundDecl(), ME->getMemberNameInfo(), TemplateArgs,
ME->getType(), ME->getValueKind(), ME->getObjectKind(), NOUR);
return ExprEmpty();
}
- case Expr::BinaryOperatorClass: {
- auto *BO = cast<BinaryOperator>(E);
- Expr *LHS = BO->getLHS();
- Expr *RHS = BO->getRHS();
- // -- If e is a pointer-to-member expression of the form e1 .* e2 ...
- if (BO->getOpcode() == BO_PtrMemD) {
- ExprResult Sub = Rebuild(LHS);
- if (!Sub.isUsable())
- return Sub;
- LHS = Sub.get();
- // -- If e is a comma expression, ...
- } else if (BO->getOpcode() == BO_Comma) {
- ExprResult Sub = Rebuild(RHS);
- if (!Sub.isUsable())
- return Sub;
- RHS = Sub.get();
- } else {
- break;
- }
- return S.BuildBinOp(nullptr, BO->getOperatorLoc(), BO->getOpcode(),
- LHS, RHS);
- }
+ // 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 = cast<ParenExpr>(E);
+ 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, ...
- // We don't apply this to a binary conditional operator. FIXME: Should we?
- case Expr::ConditionalOperatorClass: {
- auto *CO = cast<ConditionalOperator>(E);
- ExprResult LHS = Rebuild(CO->getLHS());
- if (LHS.isInvalid())
- return ExprError();
- ExprResult RHS = Rebuild(CO->getRHS());
- if (RHS.isInvalid())
- return ExprError();
- if (!LHS.isUsable() && !RHS.isUsable())
- return ExprEmpty();
- if (!LHS.isUsable())
- LHS = CO->getLHS();
- if (!RHS.isUsable())
- RHS = CO->getRHS();
- return S.ActOnConditionalOp(CO->getQuestionLoc(), CO->getColonLoc(),
- CO->getCond(), LHS.get(), RHS.get());
- }
+ // -- If e is a comma expression, ...
// [Clang extension]
// -- If e has the form __extension__ e1...
@@ -16066,7 +15988,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
// -- 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 = cast<GenericSelectionExpr>(E);
+ auto *GSE = dyn_cast<GenericSelectionExpr>(E);
SmallVector<Expr *, 4> AssocExprs;
bool AnyChanged = false;
@@ -16094,7 +16016,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
// results is the union of the sets of potential results of the
// second and third subexpressions.
case Expr::ChooseExprClass: {
- auto *CE = cast<ChooseExpr>(E);
+ auto *CE = dyn_cast<ChooseExpr>(E);
ExprResult LHS = Rebuild(CE->getLHS());
if (LHS.isInvalid())
@@ -16117,38 +16039,13 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
// Step through non-syntactic nodes.
case Expr::ConstantExprClass: {
- auto *CE = cast<ConstantExpr>(E);
+ auto *CE = dyn_cast<ConstantExpr>(E);
ExprResult Sub = Rebuild(CE->getSubExpr());
if (!Sub.isUsable())
return Sub;
return ConstantExpr::Create(S.Context, Sub.get());
}
- // We could mostly rely on the recursive rebuilding to rebuild implicit
- // casts, but not at the top level, so rebuild them here.
- case Expr::ImplicitCastExprClass: {
- auto *ICE = cast<ImplicitCastExpr>(E);
- // Only step through the narrow set of cast kinds we expect to encounter.
- // Anything else suggests we've left the region in which potential results
- // can be found.
- switch (ICE->getCastKind()) {
- case CK_NoOp:
- case CK_DerivedToBase:
- case CK_UncheckedDerivedToBase: {
- ExprResult Sub = Rebuild(ICE->getSubExpr());
- if (!Sub.isUsable())
- return Sub;
- CXXCastPath Path(ICE->path());
- return S.ImpCastExprToType(Sub.get(), ICE->getType(), ICE->getCastKind(),
- ICE->getValueKind(), &Path);
- }
-
- default:
- break;
- }
- break;
- }
-
default:
break;
}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index d5ef5eddf3e..1a1d9347985 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -3282,6 +3282,7 @@ void InitializationSequence::Step::Destroy() {
case SK_QualificationConversionXValue:
case SK_QualificationConversionLValue:
case SK_AtomicConversion:
+ case SK_LValueToRValue:
case SK_ListInitialization:
case SK_UnwrapInitList:
case SK_RewrapInitList:
@@ -3465,6 +3466,15 @@ void InitializationSequence::AddAtomicConversionStep(QualType Ty) {
Steps.push_back(S);
}
+void InitializationSequence::AddLValueToRValueStep(QualType Ty) {
+ assert(!Ty.hasQualifiers() && "rvalues may not have qualifiers");
+
+ Step S;
+ S.Kind = SK_LValueToRValue;
+ S.Type = Ty;
+ Steps.push_back(S);
+}
+
void InitializationSequence::AddConversionSequenceStep(
const ImplicitConversionSequence &ICS, QualType T,
bool TopLevelOfInitList) {
@@ -7495,6 +7505,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
case SK_QualificationConversionXValue:
case SK_QualificationConversionRValue:
case SK_AtomicConversion:
+ case SK_LValueToRValue:
case SK_ConversionSequence:
case SK_ConversionSequenceNoNarrowing:
case SK_ListInitialization:
@@ -7766,6 +7777,14 @@ ExprResult InitializationSequence::Perform(Sema &S,
break;
}
+ case SK_LValueToRValue: {
+ assert(CurInit.get()->isGLValue() && "cannot load from a prvalue");
+ CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,
+ CK_LValueToRValue, CurInit.get(),
+ /*BasePath=*/nullptr, VK_RValue);
+ break;
+ }
+
case SK_ConversionSequence:
case SK_ConversionSequenceNoNarrowing: {
if (const auto *FromPtrType =
@@ -8987,6 +9006,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
OS << "non-atomic-to-atomic conversion";
break;
+ case SK_LValueToRValue:
+ OS << "load (lvalue to rvalue)";
+ break;
+
case SK_ConversionSequence:
OS << "implicit conversion sequence (";
S->ICS->dump(); // FIXME: use OS
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
index cc62cf1048c..df78b49130c 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -378,6 +378,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_BitCast:
case CK_AddressSpaceConversion:
case CK_BooleanToSignedIntegral:
+ case CK_NullToPointer:
case CK_IntegralToPointer:
case CK_PointerToIntegral: {
SVal V = state->getSVal(Ex, LCtx);
@@ -502,12 +503,6 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
Bldr.generateNode(CastE, Pred, state);
continue;
}
- case CK_NullToPointer: {
- SVal V = svalBuilder.makeNull();
- state = state->BindExpr(CastE, LCtx, V);
- Bldr.generateNode(CastE, Pred, state);
- continue;
- }
case CK_NullToMemberPointer: {
SVal V = svalBuilder.getMemberPointer(nullptr);
state = state->BindExpr(CastE, LCtx, V);
OpenPOWER on IntegriCloud