Author: nico Date: Thu Jun 13 21:05:17 2019 New Revision: 363352 URL: http://llvm.org/viewvc/llvm-project?rev=363352&view=rev Log: 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." Removed: cfe/trunk/test/CXX/basic/basic.def.odr/p2.cpp cfe/trunk/test/CodeGenCXX/no-odr-use.cpp Modified: cfe/trunk/include/clang/Sema/Initialization.h cfe/trunk/lib/AST/Expr.cpp cfe/trunk/lib/CodeGen/CGDecl.cpp cfe/trunk/lib/CodeGen/CGExpr.cpp cfe/trunk/lib/CodeGen/CGExprAgg.cpp cfe/trunk/lib/CodeGen/CGExprScalar.cpp cfe/trunk/lib/CodeGen/CodeGenModule.h cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp cfe/trunk/test/Analysis/nullptr.cpp cfe/trunk/test/CXX/drs/dr20xx.cpp cfe/trunk/test/CXX/drs/dr21xx.cpp cfe/trunk/test/CXX/drs/dr23xx.cpp cfe/trunk/test/CXX/drs/dr6xx.cpp cfe/trunk/test/CXX/drs/dr7xx.cpp cfe/trunk/test/CodeGenCXX/nullptr.cpp cfe/trunk/www/cxx_dr_status.html Modified: cfe/trunk/include/clang/Sema/Initialization.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Initialization.h (original) +++ cfe/trunk/include/clang/Sema/Initialization.h Thu Jun 13 21:05:17 2019 @@ -821,6 +821,9 @@ public: /// Perform a conversion adding _Atomic to a type. SK_AtomicConversion, + /// Perform a load from a glvalue, producing an rvalue. + SK_LValueToRValue, + /// Perform an implicit conversion sequence. SK_ConversionSequence, @@ -1267,6 +1270,12 @@ public: /// type. void AddAtomicConversionStep(QualType Ty); + /// Add a new step that performs a load of the given type. + /// + /// Although the term "LValueToRValue" is conventional, this applies to both + /// lvalues and xvalues. + void AddLValueToRValueStep(QualType Ty); + /// Add a new step that applies an implicit conversion sequence. void AddConversionSequenceStep(const ImplicitConversionSequence &ICS, QualType T, bool TopLevelOfInitList = false); Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Thu Jun 13 21:05:17 2019 @@ -1885,11 +1885,6 @@ ImplicitCastExpr *ImplicitCastExpr::Crea 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) Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Jun 13 21:05:17 2019 @@ -1077,16 +1077,17 @@ static llvm::Constant *constWithPadding( 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::createUnnamedGlob } }; - // 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(CodeGe } // 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(co 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"); Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Jun 13 21:05:17 2019 @@ -1422,11 +1422,10 @@ static ConstantEmissionKind checkVarType } /// 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(co 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::EmitDeclRefLValu // 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!"); Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Jun 13 21:05:17 2019 @@ -1352,8 +1352,7 @@ static bool isSimpleZero(const Expr *E, // (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; Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original) +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Thu Jun 13 21:05:17 2019 @@ -2148,14 +2148,14 @@ Value *ScalarExprEmitter::VisitCastExpr( 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); Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Jun 13 21:05:17 2019 @@ -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; Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jun 13 21:05:17 2019 @@ -635,10 +635,8 @@ ExprResult Sema::DefaultLvalueConversion 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(Va 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 rebuildPotentialResult // 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 rebuildPotentialResult 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 rebuildPotentialResult // -- 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 rebuildPotentialResult // 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 rebuildPotentialResult // 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; } Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jun 13 21:05:17 2019 @@ -3282,6 +3282,7 @@ void InitializationSequence::Step::Destr 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::AddAtomicCo 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::Perfo 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::Perfo 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_os 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 Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Thu Jun 13 21:05:17 2019 @@ -378,6 +378,7 @@ void ExprEngine::VisitCast(const CastExp 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 CastExp 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); Modified: cfe/trunk/test/Analysis/nullptr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nullptr.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/test/Analysis/nullptr.cpp (original) +++ cfe/trunk/test/Analysis/nullptr.cpp Thu Jun 13 21:05:17 2019 @@ -128,10 +128,18 @@ void shouldNotCrash() { decltype(nullptr) p; // expected-note{{'p' declared without an initial value}} if (getSymbol()) // expected-note {{Assuming the condition is false}} // expected-note@-1{{Taking false branch}} + // expected-note@-2{{Assuming the condition is false}} + // expected-note@-3{{Taking false branch}} + // expected-note@-4{{Assuming the condition is true}} + // expected-note@-5{{Taking true branch}} + invokeF(p); // expected-warning{{1st function call argument is an uninitialized value}} + // expected-note@-1{{1st function call argument is an uninitialized value}} + if (getSymbol()) // expected-note {{Assuming the condition is false}} + // expected-note@-1{{Taking false branch}} // expected-note@-2{{Assuming the condition is true}} // expected-note@-3{{Taking true branch}} - invokeF(p); // expected-note {{Calling 'invokeF'}} - // expected-note@-1{{Passing null pointer value via 1st parameter 'x'}} + invokeF(nullptr); // expected-note {{Calling 'invokeF'}} + // expected-note@-1{{Passing null pointer value via 1st parameter 'x'}} if (getSymbol()) { // expected-note {{Assuming the condition is true}} // expected-note@-1{{Taking true branch}} X *xx = Type().x; // expected-note {{Null pointer value stored to field 'x'}} Removed: cfe/trunk/test/CXX/basic/basic.def.odr/p2.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.def.odr/p2.cpp?rev=363351&view=auto ============================================================================== --- cfe/trunk/test/CXX/basic/basic.def.odr/p2.cpp (original) +++ cfe/trunk/test/CXX/basic/basic.def.odr/p2.cpp (removed) @@ -1,80 +0,0 @@ -// RUN: %clang_cc1 -std=c++98 %s -Wno-unused -verify -// RUN: %clang_cc1 -std=c++11 %s -Wno-unused -verify -// RUN: %clang_cc1 -std=c++2a %s -Wno-unused -verify - -void use(int); - -void f() { - const int a = 1; // expected-note {{here}} - -#if __cplusplus >= 201103L - constexpr int arr[3] = {1, 2, 3}; // expected-note 2{{here}} - - struct S { int x; int f() const; }; - constexpr S s = {0}; // expected-note 3{{here}} - constexpr S *ps = nullptr; - S *const &psr = ps; // expected-note 2{{here}} -#endif - - struct Inner { - void test(int i) { - // id-expression - use(a); - -#if __cplusplus >= 201103L - // subscripting operation with an array operand - use(arr[i]); - use(i[arr]); - use((+arr)[i]); // expected-error {{reference to local variable}} - use(i[+arr]); // expected-error {{reference to local variable}} - - // class member access naming non-static data member - use(s.x); - use(s.f()); // expected-error {{reference to local variable}} - use((&s)->x); // expected-error {{reference to local variable}} - use(ps->x); // ok (lvalue-to-rvalue conversion applied to id-expression) - use(psr->x); // expected-error {{reference to local variable}} - - // class member access naming a static data member - // FIXME: How to test this? - - // pointer-to-member expression - use(s.*&S::x); - use((s.*&S::f)()); // expected-error {{reference to local variable}} - use(ps->*&S::x); // ok (lvalue-to-rvalue conversion applied to id-expression) - use(psr->*&S::x); // expected-error {{reference to local variable}} -#endif - - // parentheses - use((a)); -#if __cplusplus >= 201103L - use((s.x)); -#endif - - // glvalue conditional expression - use(i ? a : a); - use(i ? i : a); - - // comma expression - use((i, a)); - // FIXME: This is not an odr-use because it is a discarded-value - // expression applied to an expression whose potential result is 'a'. - use((a, a)); // expected-error {{reference to local variable}} - - // (and combinations thereof) - use(a ? (i, a) : a); -#if __cplusplus >= 201103L - use(a ? (i, a) : arr[a ? s.x : arr[a]]); -#endif - } - }; -} - -// FIXME: Test that this behaves properly. -namespace std_example { - struct S { static const int x = 0, y = 0; }; - const int &f(const int &r); - bool b; - int n = b ? (1, S::x) - : f(S::y); -} Modified: cfe/trunk/test/CXX/drs/dr20xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr20xx.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr20xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr20xx.cpp Thu Jun 13 21:05:17 2019 @@ -4,204 +4,11 @@ // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -#if __cplusplus < 201103L -#define static_assert(...) _Static_assert(__VA_ARGS__) -#endif +// expected-no-diagnostics -namespace dr2083 { // dr2083: partial -#if __cplusplus >= 201103L - void non_const_mem_ptr() { - struct A { - int x; - int y; - }; - constexpr A a = {1, 2}; - struct B { - int A::*p; - constexpr int g() const { - // OK, not an odr-use of 'a'. - return a.*p; - }; - }; - static_assert(B{&A::x}.g() == 1, ""); - static_assert(B{&A::y}.g() == 2, ""); - } -#endif - - const int a = 1; - int b; - // Note, references only get special odr-use / constant initializxer - // treatment in C++11 onwards. We continue to apply that even after DR2083. - void ref_to_non_const() { - int c; - const int &ra = a; // expected-note 0-1{{here}} - int &rb = b; // expected-note 0-1{{here}} - int &rc = c; // expected-note {{here}} - struct A { - int f() { - int a = ra; - int b = rb; #if __cplusplus < 201103L - // expected-error@-3 {{in enclosing function}} - // expected-error@-3 {{in enclosing function}} -#endif - int c = rc; // expected-error {{in enclosing function}} - return a + b + c; - } - }; - } - -#if __cplusplus >= 201103L - struct NoMut1 { int a, b; }; - struct NoMut2 { NoMut1 m; }; - struct NoMut3 : NoMut1 { - constexpr NoMut3(int a, int b) : NoMut1{a, b} {} - }; - struct Mut1 { - int a; - mutable int b; - }; - struct Mut2 { Mut1 m; }; - struct Mut3 : Mut1 { - constexpr Mut3(int a, int b) : Mut1{a, b} {} - }; - void mutable_subobjects() { - constexpr NoMut1 nm1 = {1, 2}; - constexpr NoMut2 nm2 = {1, 2}; - constexpr NoMut3 nm3 = {1, 2}; - constexpr Mut1 m1 = {1, 2}; // expected-note {{declared here}} - constexpr Mut2 m2 = {1, 2}; // expected-note {{declared here}} - constexpr Mut3 m3 = {1, 2}; // expected-note {{declared here}} - struct A { - void f() { - static_assert(nm1.a == 1, ""); - static_assert(nm2.m.a == 1, ""); - static_assert(nm3.a == 1, ""); - // Can't even access a non-mutable member of a variable containing mutable fields. - static_assert(m1.a == 1, ""); // expected-error {{enclosing function}} - static_assert(m2.m.a == 1, ""); // expected-error {{enclosing function}} - static_assert(m3.a == 1, ""); // expected-error {{enclosing function}} - } - }; - } -#endif - - void ellipsis() { - void ellipsis(...); - struct A {}; - const int n = 0; -#if __cplusplus >= 201103L - constexpr -#endif - A a = {}; // expected-note {{here}} - struct B { - void f() { - ellipsis(n); - // Even though this is technically modelled as an lvalue-to-rvalue - // conversion, it calls a constructor and binds 'a' to a reference, so - // it results in an odr-use. - ellipsis(a); // expected-error {{enclosing function}} - } - }; - } - -#if __cplusplus >= 201103L - void volatile_lval() { - struct A { int n; }; - constexpr A a = {0}; // expected-note {{here}} - struct B { - void f() { - // An lvalue-to-rvalue conversion of a volatile lvalue always results - // in odr-use. - int A::*p = &A::n; - int x = a.*p; - volatile int A::*q = p; - int y = a.*q; // expected-error {{enclosing function}} - } - }; - } -#endif - - void discarded_lval() { - struct A { int x; mutable int y; volatile int z; }; - A a; // expected-note 1+{{here}} - int &r = a.x; // expected-note {{here}} - struct B { - void f() { - a.x; // expected-warning {{unused}} - a.*&A::x; // expected-warning {{unused}} - true ? a.x : a.y; // expected-warning {{unused}} - (void)a.x; - a.x, discarded_lval(); // expected-warning {{unused}} -#if 1 // FIXME: These errors are all incorrect; the above code is valid. - // expected-error@-6 {{enclosing function}} - // expected-error@-6 {{enclosing function}} - // expected-error@-6 2{{enclosing function}} - // expected-error@-6 {{enclosing function}} - // expected-error@-6 {{enclosing function}} -#endif - - // 'volatile' qualifier triggers an lvalue-to-rvalue conversion. - a.z; // expected-error {{enclosing function}} -#if __cplusplus < 201103L - // expected-warning@-2 {{assign into a variable}} -#endif - - // References always get "loaded" to determine what they reference, - // even if the result is discarded. - r; // expected-error {{enclosing function}} expected-warning {{unused}} - } - }; - } - - namespace dr_example_1 { - extern int globx; - int main() { - const int &x = globx; - struct A { -#if __cplusplus < 201103L - // expected-error@+2 {{enclosing function}} expected-note@-3 {{here}} -#endif - const int *foo() { return &x; } - } a; - return *a.foo(); - } - } - -#if __cplusplus >= 201103L - namespace dr_example_2 { - struct A { - int q; - constexpr A(int q) : q(q) {} - constexpr A(const A &a) : q(a.q * 2) {} // (note, not called) - }; - - int main(void) { - constexpr A a(42); - constexpr int aq = a.q; - struct Q { - int foo() { return a.q; } - } q; - return q.foo(); - } - - // Checking odr-use does not invent an lvalue-to-rvalue conversion (and - // hence copy construction) on the potential result variable. - struct B { - int b = 42; - constexpr B() {} - constexpr B(const B&) = delete; - }; - void f() { - constexpr B b; - struct Q { - constexpr int foo() const { return b.b; } - }; - static_assert(Q().foo() == 42, ""); - } - } +#define static_assert(...) _Static_assert(__VA_ARGS__) #endif -} namespace dr2094 { // dr2094: 5 struct A { int n; }; Modified: cfe/trunk/test/CXX/drs/dr21xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr21xx.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr21xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr21xx.cpp Thu Jun 13 21:05:17 2019 @@ -8,19 +8,6 @@ #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) #endif -namespace dr2103 { // dr2103: yes - void f() { - int a; - int &r = a; // expected-note {{here}} - struct Inner { - void f() { - int &s = r; // expected-error {{enclosing function}} - (void)s; - } - }; - } -} - namespace dr2120 { // dr2120: 7 struct A {}; struct B : A {}; @@ -32,29 +19,6 @@ namespace dr2120 { // dr2120: 7 static_assert(!__is_standard_layout(E), ""); } -namespace dr2140 { // dr2140: 9 -#if __cplusplus >= 201103L - union U { int a; decltype(nullptr) b; }; - constexpr int *test(U u) { - return u.b; - } - static_assert(!test({123}), "u.b should be valid even when b is inactive"); -#endif -} - -namespace dr2170 { // dr2170: 9 -#if __cplusplus >= 201103L - void f() { - constexpr int arr[3] = {1, 2, 3}; // expected-note {{here}} - struct S { - int get(int n) { return arr[n]; } - const int &get_ref(int n) { return arr[n]; } // expected-error {{enclosing function}} - // FIXME: expected-warning@-1 {{reference to stack}} - }; - } -#endif -} - namespace dr2180 { // dr2180: yes class A { A &operator=(const A &); // expected-note 0-2{{here}} Modified: cfe/trunk/test/CXX/drs/dr23xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr23xx.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr23xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr23xx.cpp Thu Jun 13 21:05:17 2019 @@ -1,45 +1,13 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s -// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors +// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors #if __cplusplus <= 201103L // expected-no-diagnostics #endif -namespace dr2353 { // dr2353: 9 - struct X { - static const int n = 0; - }; - - // CHECK: FunctionDecl {{.*}} use - int use(X x) { - // CHECK: MemberExpr {{.*}} .n - // CHECK-NOT: non_odr_use - // CHECK: DeclRefExpr {{.*}} 'x' - // CHECK-NOT: non_odr_use - return *&x.n; - } -#pragma clang __debug dump use - - // CHECK: FunctionDecl {{.*}} not_use - int not_use(X x) { - // CHECK: MemberExpr {{.*}} .n {{.*}} non_odr_use_constant - // CHECK: DeclRefExpr {{.*}} 'x' - return x.n; - } -#pragma clang __debug dump not_use - - // CHECK: FunctionDecl {{.*}} not_use_2 - int not_use_2(X *x) { - // CHECK: MemberExpr {{.*}} ->n {{.*}} non_odr_use_constant - // CHECK: DeclRefExpr {{.*}} 'x' - return x->n; - } -#pragma clang __debug dump not_use_2 -} - namespace dr2387 { // dr2387: 9 #if __cplusplus >= 201402L template<int> int a = 0; Modified: cfe/trunk/test/CXX/drs/dr6xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr6xx.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr6xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr6xx.cpp Thu Jun 13 21:05:17 2019 @@ -1132,20 +1132,3 @@ namespace dr692 { // dr692: no template void f(int*); // expected-error {{ambiguous}} } } - -namespace dr696 { // dr696: yes - void f(const int*); - void g() { - const int N = 10; // expected-note 1+{{here}} - struct A { - void h() { - int arr[N]; (void)arr; - f(&N); // expected-error {{declared in enclosing}} - } - }; -#if __cplusplus >= 201103L - (void) [] { int arr[N]; (void)arr; }; - (void) [] { f(&N); }; // expected-error {{cannot be implicitly captured}} expected-note {{here}} -#endif - } -} Modified: cfe/trunk/test/CXX/drs/dr7xx.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr7xx.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/test/CXX/drs/dr7xx.cpp (original) +++ cfe/trunk/test/CXX/drs/dr7xx.cpp Thu Jun 13 21:05:17 2019 @@ -17,42 +17,6 @@ namespace dr705 { // dr705: yes } } -namespace dr712 { // dr712: partial - void use(int); - void f() { - const int a = 0; // expected-note 5{{here}} - struct X { - void g(bool cond) { - use(a); - use((a)); - use(cond ? a : a); - use((cond, a)); // expected-warning 2{{unused}} FIXME: should only warn once - - (void)a; // FIXME: expected-error {{declared in enclosing}} - (void)(a); // FIXME: expected-error {{declared in enclosing}} - (void)(cond ? a : a); // FIXME: expected-error 2{{declared in enclosing}} - (void)(cond, a); // FIXME: expected-error {{declared in enclosing}} expected-warning {{unused}} - } - }; - } - -#if __cplusplus >= 201103L - void g() { - struct A { int n; }; - constexpr A a = {0}; // expected-note 2{{here}} - struct X { - void g(bool cond) { - use(a.n); - use(a.*&A::n); - - (void)a.n; // FIXME: expected-error {{declared in enclosing}} - (void)(a.*&A::n); // FIXME: expected-error {{declared in enclosing}} - } - }; - } -#endif -} - namespace dr727 { // dr727: partial struct A { template<typename T> struct C; // expected-note 6{{here}} Removed: cfe/trunk/test/CodeGenCXX/no-odr-use.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/no-odr-use.cpp?rev=363351&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/no-odr-use.cpp (original) +++ cfe/trunk/test/CodeGenCXX/no-odr-use.cpp (removed) @@ -1,27 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm -o - -triple x86_64-linux-gnu %s | FileCheck %s - -// CHECK: @__const._Z1fi.a = private unnamed_addr constant {{.*}} { i32 1, [2 x i32] [i32 2, i32 3], [3 x i32] [i32 4, i32 5, i32 6] } - -struct A { int x, y[2]; int arr[3]; }; -// CHECK-LABEL: define i32 @_Z1fi( -int f(int i) { - // CHECK: call void {{.*}}memcpy{{.*}}({{.*}}, {{.*}} @__const._Z1fi.a - constexpr A a = {1, 2, 3, 4, 5, 6}; - - // CHECK-LABEL: define {{.*}}@"_ZZ1fiENK3$_0clEiM1Ai"( - return [] (int n, int A::*p) { - // CHECK: br i1 - return (n >= 0 - // CHECK: getelementptr inbounds [3 x i32], [3 x i32]* getelementptr inbounds ({{.*}} @__const._Z1fi.a, i32 0, i32 2), i64 0, i64 % - ? a.arr[n] - // CHECK: br i1 - : (n == -1 - // CHECK: getelementptr inbounds i8, i8* bitcast ({{.*}} @__const._Z1fi.a to i8*), i64 % - // CHECK: bitcast i8* %{{.*}} to i32* - // CHECK: load i32 - ? a.*p - // CHECK: getelementptr inbounds [2 x i32], [2 x i32]* getelementptr inbounds ({{.*}} @__const._Z1fi.a, i32 0, i32 1), i64 0, i64 % - // CHECK: load i32 - : a.y[2 - n])); - }(i, &A::x); -} Modified: cfe/trunk/test/CodeGenCXX/nullptr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/nullptr.cpp?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/nullptr.cpp (original) +++ cfe/trunk/test/CodeGenCXX/nullptr.cpp Thu Jun 13 21:05:17 2019 @@ -22,50 +22,3 @@ void g() { const std::type_info& f2() { return typeid(nullptr_t); } - -union U { - int n; - nullptr_t b; -}; -// CHECK-LABEL: define {{.*}}pr23833_a -// CHECK: store -// CHECK: load -// CHECK-NOT: load -// CHECK: ret i1 false -bool pr23833_a(U &u) { return u.b; } - -// CHECK-LABEL: define {{.*}}pr23833_b -// CHECK: store -// CHECK: load -// CHECK-NOT: load -// CHECK: ret i8* null -nullptr_t pr23833_b(nullptr_t &n) { return n; } - -struct X1 { operator int*(); }; -struct X2 { operator const nullptr_t&(); }; - -// CHECK-LABEL: define {{.*}}pr23833_c -// CHECK: call {{.*}}X1 -// CHECK: call {{.*}}X2 -// CHECK-NOT: load -// CHECK: ret i32 -int pr23833_c() { - return X1() != X2(); -} - -// CHECK-LABEL: define {{.*}}pr23833_d -// CHECK: call {{.*}}X2 -// CHECK-NOT: load -// CHECK: store -// CHECK: load -// CHECK: ret i32* -int *pr23833_d() { - int *p = X2(); - return p; -} - -namespace PR39528 { - constexpr nullptr_t null = nullptr; - void f(nullptr_t); - void g() { f(null); } -} Modified: cfe/trunk/www/cxx_dr_status.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=363352&r1=363351&r2=363352&view=diff ============================================================================== --- cfe/trunk/www/cxx_dr_status.html (original) +++ cfe/trunk/www/cxx_dr_status.html Thu Jun 13 21:05:17 2019 @@ -4219,7 +4219,7 @@ and <I>POD class</I></td> <td><a href="http://wg21.link/cwg696">696</a></td> <td>C++11</td> <td>Use of block-scope constants in local classes</td> - <td class="full" align="center">Yes</td> + <td class="none" align="center">Unknown</td> </tr> <tr class="open" id="697"> <td><a href="http://wg21.link/cwg697">697</a></td> @@ -4315,7 +4315,7 @@ and <I>POD class</I></td> <td><a href="http://wg21.link/cwg712">712</a></td> <td>CD3</td> <td>Are integer constant operands of a <I>conditional-expression</I> “used?”</td> - <td class="partial" align="center">Partial</td> + <td class="none" align="center">Unknown</td> </tr> <tr id="713"> <td><a href="http://wg21.link/cwg713">713</a></td> @@ -12313,7 +12313,7 @@ and <I>POD class</I></td> <td><a href="http://wg21.link/cwg2083">2083</a></td> <td>DR</td> <td>Incorrect cases of odr-use</td> - <td class="partial" align="center">Partial</td> + <td class="none" align="center">Unknown</td> </tr> <tr id="2084"> <td><a href="http://wg21.link/cwg2084">2084</a></td> @@ -12433,7 +12433,7 @@ and <I>POD class</I></td> <td><a href="http://wg21.link/cwg2103">2103</a></td> <td>DR</td> <td>Lvalue-to-rvalue conversion is irrelevant in odr-use of a reference</td> - <td class="full" align="center">Yes</td> + <td class="none" align="center">Unknown</td> </tr> <tr id="2104"> <td><a href="http://wg21.link/cwg2104">2104</a></td> @@ -12655,7 +12655,7 @@ and <I>POD class</I></td> <td><a href="http://wg21.link/cwg2140">2140</a></td> <td>CD4</td> <td>Lvalue-to-rvalue conversion of <TT>std::nullptr_t</TT></td> - <td class="svn" align="center">SVN</td> + <td class="none" align="center">Unknown</td> </tr> <tr id="2141"> <td><a href="http://wg21.link/cwg2141">2141</a></td> @@ -12835,7 +12835,7 @@ and <I>POD class</I></td> <td><a href="http://wg21.link/cwg2170">2170</a></td> <td>DR</td> <td>Unclear definition of odr-use for arrays</td> - <td class="svn" align="center">SVN</td> + <td class="none" align="center">Unknown</td> </tr> <tr id="2171"> <td><a href="http://wg21.link/cwg2171">2171</a></td> @@ -13933,7 +13933,7 @@ and <I>POD class</I></td> <td><a href="http://wg21.link/cwg2353">2353</a></td> <td>DR</td> <td>Potential results of a member access expression for a static data member</td> - <td class="svn" align="center">SVN</td> + <td class="none" align="center">Unknown</td> </tr> <tr id="2354"> <td><a href="http://wg21.link/cwg2354">2354</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits